diff --git a/.mega-linter.yml b/.mega-linter.yml index 1a62e65e25c..838c5454d14 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -26,7 +26,7 @@ DISABLE_ERRORS_LINTERS: # If errors are found by these linters, they will be con SHOW_ELAPSED_TIME: true FILEIO_REPORTER: false GITHUB_COMMENT_REPORTER: false -UPDATED_SOURCES_REPORTER: false +UPDATED_SOURCES_REPORTER: true PRINT_ALPACA: false # Don't print ASCII alpaca in the log PRINT_ALL_FILES: true # Print all processed files FLAVOR_SUGGESTIONS: false # Don't show suggestions about different MegaLinter flavors diff --git a/CODEOWNERS b/CODEOWNERS index c25eb7141bc..0094c1c0e55 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -36,7 +36,7 @@ /PWGEM @alibuild @mikesas @rbailhac @feisenhu /PWGEM/Dilepton @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu /PWGEM/PhotonMeson @alibuild @mikesas @rbailhac @m-c-danisch @novitzky @mhemmer-cern @dsekihat -/PWGHF @alibuild @vkucera @fcolamar @fgrosa @fcatalan92 @mfaggin @mmazzilli @deepathoms @nzardosh @NicoleBastid +/PWGHF @alibuild @vkucera @fcolamar @fgrosa @fcatalan92 @mfaggin @mmazzilli @deepathoms @nzardosh @NicoleBastid @hahassan7 /PWGLF @alibuild @ercolessi @fmazzasc @chiarapinto @BongHwi @smaff92 @mbombara @ChiaraDeMartin95 @njacazio @skundu692 /PWGMM @alibuild @aalkin /PWGMM/Lumi @alibuild @aalkin diff --git a/Common/TableProducer/eventSelection.cxx b/Common/TableProducer/eventSelection.cxx index e741959960f..6632a5cb22b 100644 --- a/Common/TableProducer/eventSelection.cxx +++ b/Common/TableProducer/eventSelection.cxx @@ -240,9 +240,9 @@ struct BcSelectionTask { // access orbitShift, ITSROF and TF border margins EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", ts); mITSROFrameStartBorderMargin = confITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : confITSROFrameStartBorderMargin; - mITSROFrameEndBorderMargin = confITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : confITSROFrameStartBorderMargin; - mTimeFrameStartBorderMargin = confITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : confITSROFrameStartBorderMargin; - mTimeFrameEndBorderMargin = confITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : confITSROFrameStartBorderMargin; + mITSROFrameEndBorderMargin = confITSROFrameEndBorderMargin < 0 ? par->fITSROFrameEndBorderMargin : confITSROFrameEndBorderMargin; + mTimeFrameStartBorderMargin = confTimeFrameStartBorderMargin < 0 ? par->fTimeFrameStartBorderMargin : confTimeFrameStartBorderMargin; + mTimeFrameEndBorderMargin = confTimeFrameEndBorderMargin < 0 ? par->fTimeFrameEndBorderMargin : confTimeFrameEndBorderMargin; // access orbit-reset timestamp auto ctpx = ccdb->getForTimeStamp>("CTP/Calib/OrbitReset", ts); int64_t tsOrbitReset = (*ctpx)[0]; // us diff --git a/DPG/Tasks/AOTTrack/V0Cascades/perfK0sResolution.cxx b/DPG/Tasks/AOTTrack/V0Cascades/perfK0sResolution.cxx index 3a2ae760ddc..7fb981a271b 100644 --- a/DPG/Tasks/AOTTrack/V0Cascades/perfK0sResolution.cxx +++ b/DPG/Tasks/AOTTrack/V0Cascades/perfK0sResolution.cxx @@ -35,10 +35,12 @@ using SelectedCollisions = soa::Join; struct perfK0sResolution { // Configurable bins ConfigurableAxis mBins{"mBins", {200, 0.4f, 0.6f}, "Mass binning"}; - ConfigurableAxis pTBins{"pTBins", {200, 0.f, 10.f}, "pT binning"}; + ConfigurableAxis pTBins{"pTBins", {240, 0.f, 12.f}, "pT binning"}; + ConfigurableAxis invpTBins{"invpTBins", {240, 0.f, 12.f}, "inverse pT binning"}; ConfigurableAxis pTResBins{"pTResBins", {200, -1.2f, 1.2f}, "pT resolution binning"}; ConfigurableAxis pTResRelBins{"pTResRelBins", {200, -0.2f, 0.2f}, "pT relative resolution binning"}; ConfigurableAxis invpTResBins{"invpTResBins", {200, -1.2f, 1.2f}, "inv pT resolution binning"}; + ConfigurableAxis invpTResNormBins{"invpTResNormBins", {200, -4.f, 4.f}, "inv pT normalised resolution binning"}; ConfigurableAxis etaBins{"etaBins", {2, -1.f, 1.f}, "eta binning"}; ConfigurableAxis etaBinsDauthers{"etaBinsDauthers", {100, -1.f, 1.f}, "eta binning for daughters"}; ConfigurableAxis phiBins{"phiBins", {100, 0.f, 6.28f}, "phi binning"}; @@ -99,9 +101,11 @@ struct perfK0sResolution { const AxisSpec statAxis{5, 0, 5, ""}; const AxisSpec mAxis{mBins, "#it{m} (GeV/#it{c}^{2})"}; const AxisSpec pTAxis{pTBins, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec invpTAxis{invpTBins, "1/#it{p}_{T}^{MC} (GeV/#it{c})^{-1}"}; const AxisSpec pTResAxis{pTResBins, "#Delta#it{p}_{T} (GeV/#it{c})"}; const AxisSpec pTResRelAxis{pTResRelBins, "(#it{p}_{T}^{rec} - #it{p}_{T}^{MC})/#it{p}_{T}^{MC}"}; const AxisSpec invpTResAxis{invpTResBins, "1/#it{p}_{T}-1/#it{p}_{T}^{MC} (GeV/#it{c})^{-1}"}; + const AxisSpec invpTResNormAxis{invpTResNormBins, "(1/#it{p}_{T}-1/#it{p}_{T}^{MC})/#sigma_{1/#it{p}_{T}}"}; const AxisSpec relpTResAxis{relpTResBins, "#sigma(#it{p}_{T})/#it{p}_{T}"}; const AxisSpec etaAxis{etaBins, "#eta"}; const AxisSpec etaAxisPosD{etaBinsDauthers, "#eta pos."}; @@ -119,15 +123,28 @@ struct perfK0sResolution { rK0sDauResolution.add("h2_massPosPtRes", "h2_massPosPtRes", {HistType::kTH2F, {mAxis, pTResAxis}}); rK0sDauResolution.add("h2_massNegPtRes", "h2_massNegPtRes", {HistType::kTH2F, {mAxis, pTResAxis}}); - rK0sDauResolution.add("h2_genPtPosPtRes", "h2_genPtPosPtRes", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); - rK0sDauResolution.add("h2_genPxPosPxRes", "h2_genPxPosPxRes", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); - rK0sDauResolution.add("h2_genPyPosPyRes", "h2_genPyPosPyRes", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); - rK0sDauResolution.add("h2_genPzPosPzRes", "h2_genPzPosPzRes", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPtPosPtResNorm", "h2_genPtPosPtResNorm", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPxPosPxResNorm", "h2_genPxPosPxResNorm", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPyPosPyResNorm", "h2_genPyPosPyResNorm", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPzPosPzResNorm", "h2_genPzPosPzResNorm", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); - rK0sDauResolution.add("h2_genPtNegPtRes", "h2_genPtNegPtRes", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); - rK0sDauResolution.add("h2_genPxNegPxRes", "h2_genPxNegPxRes", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); - rK0sDauResolution.add("h2_genPyNegPyRes", "h2_genPyNegPyRes", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); - rK0sDauResolution.add("h2_genPzNegPzRes", "h2_genPzNegPzRes", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPtNegPtResNorm", "h2_genPtNegPtResNorm", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPxNegPxResNorm", "h2_genPxNegPxResNorm", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPyNegPyResNorm", "h2_genPyNegPyResNorm", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPzNegPzResNorm", "h2_genPzNegPzResNorm", {HistType::kTH2F, {pTResRelAxis, pTAxis}}); + + rK0sDauResolution.add("h2_genPtPosPtRes", "h2_genPtPosPtRes", {HistType::kTH2F, {pTResAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPxPosPxRes", "h2_genPxPosPxRes", {HistType::kTH2F, {pTResAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPyPosPyRes", "h2_genPyPosPyRes", {HistType::kTH2F, {pTResAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPzPosPzRes", "h2_genPzPosPzRes", {HistType::kTH2F, {pTResAxis, pTAxis}}); + + rK0sDauResolution.add("h2_genPtNegPtRes", "h2_genPtNegPtRes", {HistType::kTH2F, {pTResAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPxNegPxRes", "h2_genPxNegPxRes", {HistType::kTH2F, {pTResAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPyNegPyRes", "h2_genPyNegPyRes", {HistType::kTH2F, {pTResAxis, pTAxis}}); + rK0sDauResolution.add("h2_genPzNegPzRes", "h2_genPzNegPzRes", {HistType::kTH2F, {pTResAxis, pTAxis}}); + + rK0sDauResolution.add("h2_genPtPosPulls", "h2_GenPtPosPulls", {HistType::kTH2F, {invpTResNormAxis, invpTAxis}}); + rK0sDauResolution.add("h2_genPtNegPulls", "h2_GenPtNegPulls", {HistType::kTH2F, {invpTResNormAxis, invpTAxis}}); rK0sDauResolution.add("h2_PosRelPtRes", "h2_PosRelPtRes", {HistType::kTH2F, {pTAxis, relpTResAxis}}); rK0sDauResolution.add("h2_NegRelPtRes", "h2_NegRelPtRes", {HistType::kTH2F, {pTAxis, relpTResAxis}}); @@ -434,9 +451,6 @@ struct perfK0sResolution { o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, mTrackParCovNeg, 2.f, matCorr, &mDcaInfoCovNeg); } - bool daughtersHaveMCParticles = false; - bool daughtersCorrRec = false; - void processMC(soa::Filtered::iterator const& collision, soa::Filtered> const& fullV0s, PIDTracksIUMC const&, @@ -445,6 +459,8 @@ struct perfK0sResolution { { rK0sResolution.fill(HIST("h1_stats"), 0.5); for (auto& v0 : fullV0s) { + bool daughtersHaveMCParticles = false; + bool daughtersCorrRec = false; rK0sResolution.fill(HIST("h1_stats"), 1.5); const auto& posTrack = v0.posTrack_as(); const auto& negTrack = v0.negTrack_as(); @@ -489,18 +505,32 @@ struct perfK0sResolution { // QA of correctly reconstructed V0 daughters if (daughtersCorrRec) { - rK0sDauResolution.fill(HIST("h2_genPtPosPtRes"), (v0.positivept() - posTrack.mcParticle().pt()) / posTrack.mcParticle().pt(), posTrack.mcParticle().pt()); - rK0sDauResolution.fill(HIST("h2_genPxPosPxRes"), (v0.pxpos() - posTrack.mcParticle().px()) / posTrack.mcParticle().px(), posTrack.mcParticle().px()); - rK0sDauResolution.fill(HIST("h2_genPyPosPyRes"), (v0.pypos() - posTrack.mcParticle().py()) / posTrack.mcParticle().py(), posTrack.mcParticle().py()); - rK0sDauResolution.fill(HIST("h2_genPzPosPzRes"), (v0.pzpos() - posTrack.mcParticle().pz()) / posTrack.mcParticle().pz(), posTrack.mcParticle().pz()); - - rK0sDauResolution.fill(HIST("h2_genPtNegPtRes"), (v0.negativept() - negTrack.mcParticle().pt()) / negTrack.mcParticle().pt(), negTrack.mcParticle().pt()); - rK0sDauResolution.fill(HIST("h2_genPxNegPxRes"), (v0.pxneg() - negTrack.mcParticle().px()) / negTrack.mcParticle().px(), negTrack.mcParticle().px()); - rK0sDauResolution.fill(HIST("h2_genPyNegPyRes"), (v0.pyneg() - negTrack.mcParticle().py()) / negTrack.mcParticle().py(), negTrack.mcParticle().py()); - rK0sDauResolution.fill(HIST("h2_genPzNegPzRes"), (v0.pzneg() - negTrack.mcParticle().pz()) / negTrack.mcParticle().pz(), negTrack.mcParticle().pz()); + rK0sDauResolution.fill(HIST("h2_genPtPosPtResNorm"), (v0.positivept() - posTrack.mcParticle().pt()) / posTrack.mcParticle().pt(), posTrack.mcParticle().pt()); + rK0sDauResolution.fill(HIST("h2_genPxPosPxResNorm"), (v0.pxpos() - posTrack.mcParticle().px()) / posTrack.mcParticle().px(), posTrack.mcParticle().px()); + rK0sDauResolution.fill(HIST("h2_genPyPosPyResNorm"), (v0.pypos() - posTrack.mcParticle().py()) / posTrack.mcParticle().py(), posTrack.mcParticle().py()); + rK0sDauResolution.fill(HIST("h2_genPzPosPzResNorm"), (v0.pzpos() - posTrack.mcParticle().pz()) / posTrack.mcParticle().pz(), posTrack.mcParticle().pz()); + + rK0sDauResolution.fill(HIST("h2_genPtNegPtResNorm"), (v0.negativept() - negTrack.mcParticle().pt()) / negTrack.mcParticle().pt(), negTrack.mcParticle().pt()); + rK0sDauResolution.fill(HIST("h2_genPxNegPxResNorm"), (v0.pxneg() - negTrack.mcParticle().px()) / negTrack.mcParticle().px(), negTrack.mcParticle().px()); + rK0sDauResolution.fill(HIST("h2_genPyNegPyResNorm"), (v0.pyneg() - negTrack.mcParticle().py()) / negTrack.mcParticle().py(), negTrack.mcParticle().py()); + rK0sDauResolution.fill(HIST("h2_genPzNegPzResNorm"), (v0.pzneg() - negTrack.mcParticle().pz()) / negTrack.mcParticle().pz(), negTrack.mcParticle().pz()); + + rK0sDauResolution.fill(HIST("h2_genPtPosPtRes"), (v0.positivept() - posTrack.mcParticle().pt()), posTrack.mcParticle().pt()); + rK0sDauResolution.fill(HIST("h2_genPxPosPxRes"), (v0.pxpos() - posTrack.mcParticle().px()), posTrack.mcParticle().px()); + rK0sDauResolution.fill(HIST("h2_genPyPosPyRes"), (v0.pypos() - posTrack.mcParticle().py()), posTrack.mcParticle().py()); + rK0sDauResolution.fill(HIST("h2_genPzPosPzRes"), (v0.pzpos() - posTrack.mcParticle().pz()), posTrack.mcParticle().pz()); + + rK0sDauResolution.fill(HIST("h2_genPtNegPtRes"), (v0.negativept() - negTrack.mcParticle().pt()), negTrack.mcParticle().pt()); + rK0sDauResolution.fill(HIST("h2_genPxNegPxRes"), (v0.pxneg() - negTrack.mcParticle().px()), negTrack.mcParticle().px()); + rK0sDauResolution.fill(HIST("h2_genPyNegPyRes"), (v0.pyneg() - negTrack.mcParticle().py()), negTrack.mcParticle().py()); + rK0sDauResolution.fill(HIST("h2_genPzNegPzRes"), (v0.pzneg() - negTrack.mcParticle().pz()), negTrack.mcParticle().pz()); rK0sDauResolution.fill(HIST("h2_massPosPtRes"), mass, v0.positivept() - posTrack.mcParticle().pt()); rK0sDauResolution.fill(HIST("h2_massNegPtRes"), mass, v0.negativept() - negTrack.mcParticle().pt()); + + rK0sDauResolution.fill(HIST("h2_genPtPosPulls"), (1. / v0.positivept() - 1. / posTrack.mcParticle().pt()) / (RecoDecay::sqrtSumOfSquares(v0.covMatPosDau()[9], v0.covMatPosDau()[14]) / RecoDecay::sq(v0.positivept())), 1. / posTrack.mcParticle().pt()); + rK0sDauResolution.fill(HIST("h2_genPtNegPulls"), (1. / v0.negativept() - 1. / negTrack.mcParticle().pt()) / (RecoDecay::sqrtSumOfSquares(v0.covMatNegDau()[9], v0.covMatNegDau()[14]) / RecoDecay::sq(v0.negativept())), 1. / negTrack.mcParticle().pt()); + if (useMultidimHisto) { rK0sResolution.fill(HIST("thn_mass"), mass, v0.pt(), v0.eta(), v0.phi(), posTrack.eta(), negTrack.eta(), 1. / v0.positivept() - 1. / posTrack.mcParticle().pt(), @@ -510,8 +540,8 @@ struct perfK0sResolution { } // QA of seleted V0s - rK0sDauResolution.fill(HIST("h2_PosRelPtRes"), v0.positivept(), RecoDecay::sqrtSumOfSquares(v0.covMatPosDau()[9], v0.covMatPosDau()[14]), v0.positivept()); - rK0sDauResolution.fill(HIST("h2_NegRelPtRes"), v0.negativept(), RecoDecay::sqrtSumOfSquares(v0.covMatNegDau()[9], v0.covMatNegDau()[14]), v0.positivept()); + rK0sDauResolution.fill(HIST("h2_PosRelPtRes"), v0.positivept(), RecoDecay::sqrtSumOfSquares(v0.covMatPosDau()[9], v0.covMatPosDau()[14]) / v0.positivept()); + rK0sDauResolution.fill(HIST("h2_NegRelPtRes"), v0.negativept(), RecoDecay::sqrtSumOfSquares(v0.covMatNegDau()[9], v0.covMatNegDau()[14]) / v0.negativept()); rK0sResolution.fill(HIST("h2_masspT"), mass, v0.pt()); rK0sResolution.fill(HIST("h2_masseta"), mass, v0.eta()); rK0sResolution.fill(HIST("h2_massphi"), mass, v0.phi()); diff --git a/DPG/Tasks/AOTTrack/qaEventTrack.cxx b/DPG/Tasks/AOTTrack/qaEventTrack.cxx index c19a8494492..b2aa6f71c64 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrack.cxx +++ b/DPG/Tasks/AOTTrack/qaEventTrack.cxx @@ -77,6 +77,11 @@ struct qaEventTrack { Configurable minPhi{"minPhi", -1.f, "Minimum phi of accepted tracks"}; Configurable maxPhi{"maxPhi", 10.f, "Maximum phi of accepted tracks"}; + // option to check PID for tracking before filling resolution histogras + Configurable checkPIDforTracking{"checkPIDforTracking", false, "check for PID in tracking"}; + Configurable PartIdentifier{"PartIdentifier", 2, "Particle identifier for selected particle; 0: electron, 1: muon, 2: pion, 3: kaon, 4: proton, 5: deuteron, 6: triton, 7: helium3, 8: alpha"}; + Configurable doExtraPIDqa{"doExtraPIDqa", false, "do extra QA for tracks with wrong PID in tracking"}; + // options to check the track variables only for PV contributors Configurable checkOnlyPVContributor{"checkOnlyPVContributor", false, "check the track variables only for primary vertex contributors"}; @@ -257,6 +262,9 @@ struct qaEventTrack { histos.add("Tracks/Kine/pullInvPtVsInvPtmc", "", kTH2D, {axisPullInvPt, axisInvPt}); histos.add("Tracks/Kine/pullInvPtVsInvPtmcEtaPlus", "", kTH2D, {axisPullInvPt, axisInvPt}); histos.add("Tracks/Kine/pullInvPtVsInvPtmcEtaMinus", "", kTH2D, {axisPullInvPt, axisInvPt}); + histos.add("Tracks/Kine/pullInvPtVsPtmc", "", kTH2D, {axisPullInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/pullInvPtVsPtmcEtaPlus", "", kTH2D, {axisPullInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/pullInvPtVsPtmcEtaMinus", "", kTH2D, {axisPullInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); histos.add("Tracks/Kine/resoInvPtVsPt", "", kTH2D, {axisDeltaInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); histos.add("Tracks/Kine/resoInvPtVsPtEtaPlus", "", kTH2D, {axisDeltaInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); histos.add("Tracks/Kine/resoInvPtVsPtEtaMinus", "", kTH2D, {axisDeltaInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); @@ -266,6 +274,22 @@ struct qaEventTrack { histos.add("Tracks/Kine/ptVsptmc", "", kTH2D, {axisPt, axisPt})->GetXaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); histos.add("Tracks/Kine/resoEta", "", kTH2D, {axisDeltaEta, axisEta})->GetYaxis()->SetTitle("#eta_{rec}"); histos.add("Tracks/Kine/resoPhi", "", kTH2D, {axisDeltaPhi, axisPhi})->GetYaxis()->SetTitle("#varphi_{rec}"); + + histos.add("Tracks/Kine/resoPtVsptmcWrongPIDinTrk", "", kTH2D, {axisDeltaPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/resoPtVsptmcEtaPlusWrongPIDinTrk", "", kTH2D, {axisDeltaPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/resoPtVsptmcEtaMinusWrongPIDinTrk", "", kTH2D, {axisDeltaPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/pullInvPtVsInvPtmcWrongPIDinTrk", "", kTH2D, {axisPullInvPt, axisInvPt}); + histos.add("Tracks/Kine/pullInvPtVsInvPtmcEtaPlusWrongPIDinTrk", "", kTH2D, {axisPullInvPt, axisInvPt}); + histos.add("Tracks/Kine/pullInvPtVsInvPtmcEtaMinusWrongPIDinTrk", "", kTH2D, {axisPullInvPt, axisInvPt}); + histos.add("Tracks/Kine/pullInvPtVsPtmcWrongPIDinTrk", "", kTH2D, {axisPullInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/pullInvPtVsPtmcEtaPlusWrongPIDinTrk", "", kTH2D, {axisPullInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/pullInvPtVsPtmcEtaMinusWrongPIDinTrk", "", kTH2D, {axisPullInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/resoInvPtVsPtWrongPIDinTrk", "", kTH2D, {axisDeltaInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/resoInvPtVsPtEtaPlusWrongPIDinTrk", "", kTH2D, {axisDeltaInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/resoInvPtVsPtEtaMinusWrongPIDinTrk", "", kTH2D, {axisDeltaInvPt, axisPt})->GetYaxis()->SetTitle("#it{p}_{T, gen} [GeV/c]"); + histos.add("Tracks/Kine/resoInvPtWrongPIDinTrk", "", kTH2D, {axisDeltaInvPt, axisInvPt}); + histos.add("Tracks/Kine/resoInvPtEtaPlusWrongPIDinTrk", "", kTH2D, {axisDeltaInvPt, axisInvPt}); + histos.add("Tracks/Kine/resoInvPtEtaMinusWrongPIDinTrk", "", kTH2D, {axisDeltaInvPt, axisInvPt}); } histos.add("Tracks/Kine/relativeResoPt", "relative #it{p}_{T} resolution; #it{p}_{T}; #sigma(#it{p}_{T})/#it{p}_{T}", kTH2D, {{axisPt, {100, 0., 0.3}}}); histos.add("Tracks/Kine/relativeResoPtEtaPlus", "relative #it{p}_{T} resolution positive #eta; #it{p}_{T}; #sigma(#it{p}_{T})/#it{p}_{T} (#eta>0)", kTH2D, {{axisPt, {100, 0., 0.3}}}); @@ -1524,12 +1548,47 @@ void qaEventTrack::fillRecoHistogramsGroupedTracks(const C& collision, const T& if constexpr (IS_MC) { if (track.has_mcParticle()) { - // resolution plots auto particle = track.mcParticle(); + // resolution plots + if (doExtraPIDqa && track.pidForTracking() != std::abs(PartIdentifier)) { + // full eta range + histos.fill(HIST("Tracks/Kine/resoPtVsptmcWrongPIDinTrk"), track.pt() - particle.pt(), particle.pt()); + histos.fill(HIST("Tracks/Kine/pullInvPtVsInvPtmcWrongPIDinTrk"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), 1.f / particle.pt()); + histos.fill(HIST("Tracks/Kine/pullInvPtVsPtmcWrongPIDinTrk"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), particle.pt()); + if (particle.pt() > 0.f) { + histos.fill(HIST("Tracks/Kine/resoInvPtWrongPIDinTrk"), std::abs(track.signed1Pt()) - 1.f / particle.pt(), 1.f / particle.pt()); + } + histos.fill(HIST("Tracks/Kine/resoInvPtVsPtWrongPIDinTrk"), track.signed1Pt() - 1.f / particle.pt(), particle.pt()); + // split eta range + if (eta > 0) { // positive eta + histos.fill(HIST("Tracks/Kine/resoPtVsptmcEtaPlusWrongPIDinTrk"), track.pt() - particle.pt(), particle.pt()); + histos.fill(HIST("Tracks/Kine/pullInvPtVsInvPtmcEtaPlusWrongPIDinTrk"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), 1.f / particle.pt()); + histos.fill(HIST("Tracks/Kine/pullInvPtVsPtmcEtaPlusWrongPIDinTrk"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), particle.pt()); + if (particle.pt() > 0.f) { + histos.fill(HIST("Tracks/Kine/resoInvPtEtaPlusWrongPIDinTrk"), std::abs(track.signed1Pt()) - 1.f / particle.pt(), 1.f / particle.pt()); + } + histos.fill(HIST("Tracks/Kine/resoInvPtVsPtEtaPlusWrongPIDinTrk"), track.signed1Pt() - 1.f / particle.pt(), particle.pt()); + } else { // negative eta + histos.fill(HIST("Tracks/Kine/resoPtVsptmcEtaMinusWrongPIDinTrk"), track.pt() - particle.pt(), particle.pt()); // + histos.fill(HIST("Tracks/Kine/pullInvPtVsInvPtmcEtaMinusWrongPIDinTrk"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), 1.f / particle.pt()); + histos.fill(HIST("Tracks/Kine/pullInvPtVsPtmcEtaMinusWrongPIDinTrk"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), particle.pt()); + if (particle.pt() > 0.f) { + histos.fill(HIST("Tracks/Kine/resoInvPtEtaMinusWrongPIDinTrk"), std::abs(track.signed1Pt()) - 1.f / particle.pt(), 1.f / particle.pt()); + } + histos.fill(HIST("Tracks/Kine/resoInvPtVsPtEtaMinusWrongPIDinTrk"), track.signed1Pt() - 1.f / particle.pt(), particle.pt()); + } + } + + // optionally check for PID in tracking + if (checkPIDforTracking && track.pidForTracking() != std::abs(PartIdentifier)) { + continue; + } + // full eta range histos.fill(HIST("Tracks/Kine/resoPt"), track.pt() - particle.pt(), track.pt()); histos.fill(HIST("Tracks/Kine/resoPtVsptmc"), track.pt() - particle.pt(), particle.pt()); histos.fill(HIST("Tracks/Kine/pullInvPtVsInvPtmc"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), 1.f / particle.pt()); + histos.fill(HIST("Tracks/Kine/pullInvPtVsPtmc"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), particle.pt()); if (particle.pt() > 0.f) { histos.fill(HIST("Tracks/Kine/resoInvPt"), std::abs(track.signed1Pt()) - 1.f / particle.pt(), 1.f / particle.pt()); } @@ -1538,18 +1597,20 @@ void qaEventTrack::fillRecoHistogramsGroupedTracks(const C& collision, const T& histos.fill(HIST("Tracks/Kine/resoEta"), track.eta() - particle.eta(), track.eta()); histos.fill(HIST("Tracks/Kine/resoPhi"), track.phi() - particle.phi(), track.phi()); // split eta range - if (eta > 0) { // positive eta - histos.fill(HIST("Tracks/Kine/resoPtEtaPlus"), track.pt() - particle.pt(), track.pt()); // - histos.fill(HIST("Tracks/Kine/resoPtVsptmcEtaPlus"), track.pt() - particle.pt(), particle.pt()); // + if (eta > 0) { // positive eta + histos.fill(HIST("Tracks/Kine/resoPtEtaPlus"), track.pt() - particle.pt(), track.pt()); + histos.fill(HIST("Tracks/Kine/resoPtVsptmcEtaPlus"), track.pt() - particle.pt(), particle.pt()); histos.fill(HIST("Tracks/Kine/pullInvPtVsInvPtmcEtaPlus"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), 1.f / particle.pt()); + histos.fill(HIST("Tracks/Kine/pullInvPtVsPtmcEtaPlus"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), particle.pt()); if (particle.pt() > 0.f) { histos.fill(HIST("Tracks/Kine/resoInvPtEtaPlus"), std::abs(track.signed1Pt()) - 1.f / particle.pt(), 1.f / particle.pt()); } histos.fill(HIST("Tracks/Kine/resoInvPtVsPtEtaPlus"), track.signed1Pt() - 1.f / particle.pt(), particle.pt()); } else { // negative eta histos.fill(HIST("Tracks/Kine/resoPtEtaMinus"), track.pt() - particle.pt(), track.pt()); - histos.fill(HIST("Tracks/Kine/resoPtVsptmcEtaMinus"), track.pt() - particle.pt(), particle.pt()); // + histos.fill(HIST("Tracks/Kine/resoPtVsptmcEtaMinus"), track.pt() - particle.pt(), particle.pt()); histos.fill(HIST("Tracks/Kine/pullInvPtVsInvPtmcEtaMinus"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), 1.f / particle.pt()); + histos.fill(HIST("Tracks/Kine/pullInvPtVsPtmcEtaMinus"), (std::abs(track.signed1Pt()) - 1.f / particle.pt()) / std::sqrt(track.c1Pt21Pt2()), particle.pt()); if (particle.pt() > 0.f) { histos.fill(HIST("Tracks/Kine/resoInvPtEtaMinus"), std::abs(track.signed1Pt()) - 1.f / particle.pt(), 1.f / particle.pt()); } diff --git a/DPG/Tasks/AOTTrack/qaMatchEff.cxx b/DPG/Tasks/AOTTrack/qaMatchEff.cxx index 4338f0eba20..4c9d29e8cb4 100644 --- a/DPG/Tasks/AOTTrack/qaMatchEff.cxx +++ b/DPG/Tasks/AOTTrack/qaMatchEff.cxx @@ -71,15 +71,15 @@ struct qaMatchEff { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // // Track selections - Configurable b_useTrackSelections{"b_useTrackSelections", false, "Boolean to switch the track selections on/off."}; - Configurable filterbitTrackSelections{"filterbitTrackSelections", 0, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; + Configurable isUseTrackSelections{"isUseTrackSelections", false, "Boolean to switch the track selections on/off."}; + Configurable isUseAnalysisTrackSelections{"isUseAnalysisTrackSelections", false, "Boolean to switch if the analysis track selections are used. If true, all the Explicit track cuts are ignored."}; // kinematics Configurable ptMinCutInnerWallTPC{"ptMinCutInnerWallTPC", 0.1f, "Minimum transverse momentum calculated at the inner wall of TPC (GeV/c)"}; Configurable ptMinCut{"ptMinCut", 0.1f, "Minimum transverse momentum (GeV/c)"}; Configurable ptMaxCut{"ptMaxCut", 100.f, "Maximum transverse momentum (GeV/c)"}; Configurable etaMinCut{"etaMinCut", -2.0f, "Minimum pseudorapidity"}; Configurable etaMaxCut{"etaMaxCut", 2.0f, "Maximum pseudorapidity"}; - Configurable b_useTPCinnerWallPt{"b_useTPCinnerWallPt", false, "Boolean to switch the usage of pt calculated at the inner wall of TPC on/off."}; + Configurable isUseTPCinnerWallPt{"isUseTPCinnerWallPt", false, "Boolean to switch the usage of pt calculated at the inner wall of TPC on/off."}; // DCA and PID cuts Configurable> dcaMaxCut{"dcaMaxCut", {parTableDCA[0], nParDCA, nParVaDCA, parClassDCA, parNameDCA}, "Track DCA cuts"}; Configurable> nSigmaPID{"nSigmaPID", {parTablePID[0], nParPID, nParVaPID, parClassPID, parNamePID}, "PID nSigma cuts TPC and TOF"}; @@ -186,12 +186,6 @@ struct qaMatchEff { // ****** BE VERY CAREFUL! -- FILTERS !!! ***** // Filter zPrimVtxLim = nabs(aod::collision::posZ) < zPrimVtxMax; - Filter trackFilter = (filterbitTrackSelections.node() == 0) || - ((filterbitTrackSelections.node() == 1) && requireGlobalTrackInFilter()) || /// filterbit 4 track selections + tight DCA cuts - ((filterbitTrackSelections.node() == 2) && requireGlobalTrackWoPtEtaInFilter()) || - ((filterbitTrackSelections.node() == 3) && requireGlobalTrackWoDCAInFilter()) || - ((filterbitTrackSelections.node() == 4) && requireQualityTracksInFilter()) || - ((filterbitTrackSelections.node() == 5) && requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks)); // // // @@ -208,9 +202,9 @@ struct qaMatchEff { else initData(); - if ((!isitMC && (doprocessMCFilteredTracks || doprocessMC || doprocessMCNoColl || doprocessTrkIUMC)) || (isitMC && (doprocessDataFilteredTracks || doprocessData || doprocessDataNoColl || doprocessTrkIUMC))) + if ((!isitMC && (doprocessMC || doprocessMCNoColl || doprocessTrkIUMC)) || (isitMC && (doprocessData || doprocessDataNoColl || doprocessTrkIUMC))) LOGF(fatal, "Initialization set for MC and processData function flagged (or viceversa)! Fix the configuration."); - if ((doprocessMCFilteredTracks && doprocessMC && doprocessMCNoColl && doprocessTrkIUMC) || (doprocessDataFilteredTracks && doprocessData && doprocessDataNoColl && doprocessTrkIUData)) + if ((doprocessMC && doprocessMCNoColl && doprocessTrkIUMC) || (doprocessData && doprocessDataNoColl && doprocessTrkIUData)) LOGF(fatal, "Cannot process for both without collision tag and with collision tag at the same time! Fix the configuration."); if (doprocessTrkIUMC && makethn) { LOGF(fatal, "No DCA for IU tracks. Put makethn = false."); @@ -220,7 +214,7 @@ struct qaMatchEff { } // /// initialize the track selections - if (b_useTrackSelections) { + if (isUseTrackSelections) { // kinematics cutObject.SetEtaRange(etaMinCut, etaMaxCut); cutObject.SetPtRange(ptMinCut, ptMaxCut); @@ -249,6 +243,12 @@ struct qaMatchEff { } LOG(info) << "############"; cutObject.SetRequireHitsInITSLayers(customMinITShits, set_customITShitmap); + + if (isUseAnalysisTrackSelections) { + LOG(info) << "### Using analysis track selections"; + cutObject = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, 0); + LOG(info) << "### Analysis track selections set"; + } } } // end Init function @@ -1251,11 +1251,11 @@ struct qaMatchEff { template bool isTrackSelectedKineCuts(T& track) { - if (!b_useTrackSelections) + if (!isUseTrackSelections && !isUseAnalysisTrackSelections) return true; // no track selections applied if (!cutObject.IsSelected(track, TrackSelection::TrackCuts::kPtRange)) return false; - if (b_useTPCinnerWallPt && computePtInParamTPC(track) < ptMinCutInnerWallTPC) { + if (isUseTPCinnerWallPt && computePtInParamTPC(track) < ptMinCutInnerWallTPC) { return false; // pt selection active only if the required pt is that calculated at the inner wall of TPC } if (!cutObject.IsSelected(track, TrackSelection::TrackCuts::kEtaRange)) @@ -1271,7 +1271,7 @@ struct qaMatchEff { template bool isTrackSelectedTPCCuts(T& track) { - if (!b_useTrackSelections) + if (!isUseTrackSelections && !isUseAnalysisTrackSelections) return true; // no track selections applied if (!cutObject.IsSelected(track, TrackSelection::TrackCuts::kTPCNCls)) return false; @@ -1287,7 +1287,7 @@ struct qaMatchEff { template bool isTrackSelectedITSCuts(T& track) { - if (!b_useTrackSelections) + if (!isUseTrackSelections && !isUseAnalysisTrackSelections) return true; // no track selections applied if (!cutObject.IsSelected(track, TrackSelection::TrackCuts::kITSChi2NDF)) return false; @@ -1377,7 +1377,7 @@ struct qaMatchEff { /// Using pt calculated at the inner wall of TPC /// Caveat: tgl still from tracking: this is not the value of tgl at the /// inner wall of TPC - if (b_useTPCinnerWallPt) + if (isUseTPCinnerWallPt) trackPt = tpcinner_pt; else trackPt = reco_pt; @@ -1394,7 +1394,7 @@ struct qaMatchEff { // Using pt calculated at the inner wall of TPC // Caveat: tgl still from tracking: this is not the value of tgl at the // inner wall of TPC - // if (b_useTPCinnerWallPtForITS) + // if (isUseTPCinnerWallPtForITS) // ITStrackPt = tpcinner_pt; // else // ITStrackPt = reco_pt; @@ -3018,13 +3018,6 @@ struct qaMatchEff { } PROCESS_SWITCH(qaMatchEff, processMC, "process MC", false); - void processMCFilteredTracks(soa::Filtered::iterator const& collision, soa::Filtered> const& tracks, aod::McParticles const& mcParticles) - { - fillHistograms(tracks, mcParticles, mcParticles); /// 3rd argument non-sense in this case - fillGeneralHistos(collision); - } - PROCESS_SWITCH(qaMatchEff, processMCFilteredTracks, "process MC with filtered tracks with filterbit selections", false); - //////////////////////////////////////////////////////////// /// Process MC with collision grouping and IU tracks /// //////////////////////////////////////////////////////////// @@ -3058,17 +3051,6 @@ struct qaMatchEff { } PROCESS_SWITCH(qaMatchEff, processData, "process data", true); - void processDataFilteredTracks(soa::Filtered::iterator const& collision, soa::Filtered> const& tracks, BCsWithTimeStamp const& bcs) - { - if (enableMonitorVsTime) { - // tracks.rawIteratorAt(0).collision().bc_as().timestamp(); /// NB: in ms - setUpTimeMonitoring(bcs); - } - fillHistograms(tracks, tracks, bcs); // 2nd argument not used in this case - fillGeneralHistos(collision); - } - PROCESS_SWITCH(qaMatchEff, processDataFilteredTracks, "process data with filtered tracks with filterbit selections", false); - ///////////////////////////////////////////////////////////// /// Process data with collision grouping and IU tracks /// ///////////////////////////////////////////////////////////// diff --git a/EventFiltering/PWGHF/HFFilter.cxx b/EventFiltering/PWGHF/HFFilter.cxx index 700be2ca896..5e39b455c6c 100644 --- a/EventFiltering/PWGHF/HFFilter.cxx +++ b/EventFiltering/PWGHF/HFFilter.cxx @@ -182,7 +182,7 @@ struct HfFilter { // Main struct for HF triggers if (iBin < 2) hProcessedEvents->GetXaxis()->SetBinLabel(iBin + 1, eventTitles[iBin].data()); else - hProcessedEvents->GetXaxis()->SetBinLabel(iBin + 1, Form("o2::aod::filtering::%s::columnLabel()", hfTriggerNames[iBin - 2].data())); + hProcessedEvents->GetXaxis()->SetBinLabel(iBin + 1, hfTriggerNames[iBin - 2].data()); } if (activateQA) { diff --git a/EventFiltering/PWGHF/HFFilterHelpers.h b/EventFiltering/PWGHF/HFFilterHelpers.h index 21ec3af21c2..52a6b49bb22 100644 --- a/EventFiltering/PWGHF/HFFilterHelpers.h +++ b/EventFiltering/PWGHF/HFFilterHelpers.h @@ -50,6 +50,7 @@ #include "Common/Core/trackUtilities.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "EventFiltering/filterTables.h" namespace o2::aod { @@ -124,7 +125,7 @@ static const std::array charmParticleNames{"D0", static const std::array beautyParticleNames{"Bplus", "B0toDStar", "B0", "Bs", "Lb", "Xib"}; static const std::array pdgCodesCharm{421, 411, 431, 4122, 4232}; static const std::array eventTitles = {"all", "rejected"}; -static const std::array hfTriggerNames{"kHighPt2P", "kHighPt3P", "kBeauty3P", "kBeauty4P", "kFemto2P", "kFemto3P", "kDoubleCharm2P", "kDoubleCharm3P", "kDoubleCharmMix", "kV0Charm2P", "kV0Charm3P", "kCharmBarToXiBach"}; +static const std::array hfTriggerNames{filtering::HfHighPt2P::columnLabel(), filtering::HfHighPt3P::columnLabel(), filtering::HfBeauty3P::columnLabel(), filtering::HfBeauty4P::columnLabel(), filtering::HfFemto2P::columnLabel(), filtering::HfFemto3P::columnLabel(), filtering::HfDoubleCharm2P::columnLabel(), filtering::HfDoubleCharm3P::columnLabel(), filtering::HfDoubleCharmMix::columnLabel(), filtering::HfV0Charm2P::columnLabel(), filtering::HfV0Charm3P::columnLabel(), filtering::HfCharmBarToXiBach::columnLabel()}; static const std::array v0Labels{"#gamma", "K_{S}^{0}", "#Lambda", "#bar{#Lambda}"}; static const std::array v0Names{"Photon", "K0S", "Lambda", "AntiLambda"}; diff --git a/EventFiltering/PWGJE/jetFilter.cxx b/EventFiltering/PWGJE/jetFilter.cxx index 347508a7916..f3d3ed3fc6c 100644 --- a/EventFiltering/PWGJE/jetFilter.cxx +++ b/EventFiltering/PWGJE/jetFilter.cxx @@ -44,15 +44,17 @@ using namespace o2::framework::expressions; struct jetFilter { enum { kJetChLowPt = 0, kJetChHighPt = 1, - kTrackPt = 2, - kTriggerObjects = 3 + kTrackLowPt = 2, + kTrackHighPt = 3, + kTriggerObjects = 4 }; enum { kBinAllEvents = 0, kBinJetChLowPt = 1, kBinJetChHighPt = 2, - kBinTrackPt = 3, - kBins = 4 + kBinTrackLowPt = 3, + kBinTrackHighPt = 4, + kBins = 5 }; Produces tags; @@ -62,7 +64,8 @@ struct jetFilter { Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; Configurable trackPtMin{"trackPtMin", 0.15, "min track pT in filter"}; - Configurable trackPtTriggerThreshold{"trackPtThreshold", 25.0, "pT threshold for track trigger"}; + Configurable trackLowPtTriggerThreshold{"trackLowPtThreshold", 10.0, "low pT track trigger threshold"}; + Configurable trackHighPtTriggerThreshold{"trackHighPtThreshold", 25.0, "high pT track trigger threshold"}; Configurable jetPtLowThreshold{"jetPtLowThreshold", 30.0, "threshold for low pT jet trigger"}; Configurable jetPtHighThreshold{"jetPtHighThreshold", 50.0, "threshold for high pT jet trigger"}; @@ -107,7 +110,11 @@ struct jetFilter { {{150, 0., +150., "charged jet #it{p}_{T} (GeV/#it{c})"}, {60, 0, TMath::TwoPi(), "#varphi"}}); - spectra.add("ptphiTrackSelected_trackpttrigger", "#it{p}_{T} of selected high pT tracks vs #varphi", HistType::kTH2F, + spectra.add("ptphiTrackSelected_lowtrackpttrigger", "#it{p}_{T} of selected low pT tracks vs #varphi", HistType::kTH2F, + {{150, 0., +150., "track #it{p}_{T} (GeV/#it{c})"}, + {60, 0, TMath::TwoPi(), "#varphi"}}); + + spectra.add("ptphiTrackSelected_hightrackpttrigger", "#it{p}_{T} of selected high pT tracks vs #varphi", HistType::kTH2F, {{150, 0., +150., "track #it{p}_{T} (GeV/#it{c})"}, {60, 0, TMath::TwoPi(), "#varphi"}}); @@ -119,7 +126,11 @@ struct jetFilter { {{150, 0., +150., "charged jet #it{p}_{T} (GeV/#it{c})"}, {40, -1.0, 1.0, "#eta"}}); - spectra.add("ptetaTrackSelected_trackpttrigger", "#it{p}_{T} of selected high pT tracks vs #eta", HistType::kTH2F, + spectra.add("ptetaTrackSelected_lowtrackpttrigger", "#it{p}_{T} of selected low pT tracks vs #eta", HistType::kTH2F, + {{150, 0., +150., "track #it{p}_{T} (GeV/#it{c})"}, + {40, -1.0, 1.0, "#eta"}}); + + spectra.add("ptetaTrackSelected_hightrackpttrigger", "#it{p}_{T} of selected high pT tracks vs #eta", HistType::kTH2F, {{150, 0., +150., "track #it{p}_{T} (GeV/#it{c})"}, {40, -1.0, 1.0, "#eta"}}); @@ -134,12 +145,18 @@ struct jetFilter { jetRFidVolume.push_back(cfgEtaTPC - jetRadiiAxis.binEdges[ir]); jetIntR.push_back(TMath::Nint(100 * jetRadiiAxis.binEdges[ir])); } + spectra.add("hLeadingTrackPt", "Leading track pT in |#eta| < 0.9;", + {HistType::kTH1F, {axisTrackPt}}); + spectra.add("hEtaVsPtTracksInclusive", "#eta of tracks |#eta| < 0.9;", {HistType::kTH2F, {axisTrackPt, axisEta}}); spectra.add("hPhiVsPtTracksInclusive", "#varphi of tracks |#eta| < 0.9;", {HistType::kTH2F, {axisTrackPt, axisPhi}}); + spectra.add("hLeadingAKTJetR06Pt", "#it{p}_{T} of AKT R=0.6 charged jets in |#eta| < 0.9;", + {HistType::kTH1F, {axisJetPt}}); + spectra.add("hPtAKTJetsInclusive", "#it{p}_{T} of AKT charged jets in |#eta| < 0.9 - #it{R};", {HistType::kTH2F, {jetRadiiAxis, axisJetPt}}); @@ -157,8 +174,9 @@ struct jetFilter { hProcessedEvents->GetXaxis()->SetBinLabel(kBinAllEvents + 1, "Processed events"); hProcessedEvents->GetXaxis()->SetBinLabel(kBinJetChLowPt + 1, o2::aod::filtering::JetChLowPt::columnLabel()); - hProcessedEvents->GetXaxis()->SetBinLabel(kBinJetChHighPt + 1, o2::aod::filtering::JetChLowPt::columnLabel()); - hProcessedEvents->GetXaxis()->SetBinLabel(kBinTrackPt + 1, o2::aod::filtering::TrackHighPt::columnLabel()); + hProcessedEvents->GetXaxis()->SetBinLabel(kBinJetChHighPt + 1, o2::aod::filtering::JetChHighPt::columnLabel()); + hProcessedEvents->GetXaxis()->SetBinLabel(kBinTrackLowPt + 1, o2::aod::filtering::TrackLowPt::columnLabel()); + hProcessedEvents->GetXaxis()->SetBinLabel(kBinTrackHighPt + 1, o2::aod::filtering::TrackHighPt::columnLabel()); } template @@ -168,7 +186,7 @@ struct jetFilter { // collision process loop bool keepEvent[kTriggerObjects]{false}; if (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - tags(keepEvent[kJetChLowPt], keepEvent[kJetChHighPt], keepEvent[kTrackPt]); + tags(keepEvent[kJetChLowPt], keepEvent[kJetChHighPt], keepEvent[kTrackLowPt], keepEvent[kTrackHighPt]); return; } @@ -204,6 +222,7 @@ struct jetFilter { for (const auto& jet : jets) { // jets are ordered by pT if (jet.r() != triggerJetR) continue; + spectra.fill(HIST("hLeadingAKTJetR06Pt"), jet.pt()); if (jet.pt() >= jetPtLowThreshold) { spectra.fill(HIST("ptphiJetChSelected_lowptjettrigger"), jet.pt(), jet.phi()); // charged jet pT vs phi @@ -234,20 +253,29 @@ struct jetFilter { leadingTrackEta = track.eta(); } } - if (leadingTrackPt > trackPtTriggerThreshold) { - keepEvent[kTrackPt] = true; - spectra.fill(HIST("ptphiTrackSelected_trackpttrigger"), leadingTrackPt, leadingTrackPhi); - spectra.fill(HIST("ptetaTrackSelected_trackpttrigger"), leadingTrackPt, leadingTrackEta); + spectra.fill(HIST("hLeadingTrackPt"), leadingTrackPt); + + if (leadingTrackPt > trackLowPtTriggerThreshold) { + keepEvent[kTrackLowPt] = true; + spectra.fill(HIST("ptphiTrackSelected_lowtrackpttrigger"), leadingTrackPt, leadingTrackPhi); + spectra.fill(HIST("ptetaTrackSelected_lowtrackpttrigger"), leadingTrackPt, leadingTrackEta); + } + if (leadingTrackPt > trackHighPtTriggerThreshold) { + keepEvent[kTrackHighPt] = true; + spectra.fill(HIST("ptphiTrackSelected_hightrackpttrigger"), leadingTrackPt, leadingTrackPhi); + spectra.fill(HIST("ptetaTrackSelected_hightrackpttrigger"), leadingTrackPt, leadingTrackEta); } if (keepEvent[kJetChLowPt]) hProcessedEvents->Fill(static_cast(kBinJetChLowPt) + 0.1f); if (keepEvent[kJetChHighPt]) hProcessedEvents->Fill(static_cast(kBinJetChHighPt) + 0.1f); - if (keepEvent[kTrackPt]) - hProcessedEvents->Fill(static_cast(kBinTrackPt) + 0.1f); + if (keepEvent[kTrackLowPt]) + hProcessedEvents->Fill(static_cast(kBinTrackLowPt) + 0.1f); + if (keepEvent[kTrackHighPt]) + hProcessedEvents->Fill(static_cast(kBinTrackHighPt) + 0.1f); - tags(keepEvent[kJetChLowPt], keepEvent[kJetChHighPt], keepEvent[kTrackPt]); + tags(keepEvent[kJetChLowPt], keepEvent[kJetChHighPt], keepEvent[kTrackLowPt], keepEvent[kTrackHighPt]); } void processWithoutRho(soa::Join::iterator const& collision, o2::aod::ChargedJets const& jets, soa::Filtered const& tracks) diff --git a/EventFiltering/filterTables.h b/EventFiltering/filterTables.h index c02b43d3eef..e22afdde898 100644 --- a/EventFiltering/filterTables.h +++ b/EventFiltering/filterTables.h @@ -66,6 +66,7 @@ DECLARE_SOA_COLUMN(LLL, hasLLL, bool); //! has L-L-L tripletD // jets DECLARE_SOA_COLUMN(JetChLowPt, hasJetChLowPt, bool); //! low-pT charged jet DECLARE_SOA_COLUMN(JetChHighPt, hasJetChHighPt, bool); //! high-pT charged jet +DECLARE_SOA_COLUMN(TrackLowPt, hasTrackLowPt, bool); //! low-pT track DECLARE_SOA_COLUMN(TrackHighPt, hasTrackHighPt, bool); //! high-pT track // hf-jets @@ -179,6 +180,7 @@ using CfFilter = CFFilters::iterator; DECLARE_SOA_TABLE(JetFilters, "AOD", "JetFilters", //! filtering::JetChLowPt, filtering::JetChHighPt, + filtering::TrackLowPt, filtering::TrackHighPt); using JetFilter = JetFilters::iterator; diff --git a/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt b/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt index 01dcb26ed35..8e8bfbd4cc6 100644 --- a/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt +++ b/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt @@ -32,4 +32,9 @@ o2physics_add_dpl_workflow(identified-meanpt-fluctuations o2physics_add_dpl_workflow(robust-fluctuation-observables SOURCES RobustFluctuationObservables.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(v0pt-pp-task + SOURCES Diff_pT_fluct_PID.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGCF/EbyEFluctuations/Tasks/Diff_pT_fluct_PID.cxx b/PWGCF/EbyEFluctuations/Tasks/Diff_pT_fluct_PID.cxx new file mode 100644 index 00000000000..5710ab1e864 --- /dev/null +++ b/PWGCF/EbyEFluctuations/Tasks/Diff_pT_fluct_PID.cxx @@ -0,0 +1,760 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief This task provides the parameters required to calculate the observable +/// v0(pT) along with its statistical uncertainity using subsampling technique. +/// \author Anna Binoy (anna.binoy@niser.ac.in) + +#include +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/HistogramSpec.h" +#include "Framework/StaticFor.h" + +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" + +#include "TDatabasePDG.h" +#include "TLorentzVector.h" +#include "TList.h" +#include "TProfile.h" +#include "TProfile2D.h" +#include "TH2D.h" +#include "TH1D.h" +#include "TRandom3.h" +#include "TMath.h" +#include "TF1.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace std; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + +double massPi = TDatabasePDG::Instance()->GetParticle(211)->Mass(); +double massKa = TDatabasePDG::Instance()->GetParticle(321)->Mass(); +double massPr = TDatabasePDG::Instance()->GetParticle(2212)->Mass(); + +struct Diff_pT_fluct_PID { + // Histogram registry: an object to hold your histograms + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + std::vector>> Subsample; + TRandom3* fRndm = new TRandom3(0); + + Configurable nPtBins_qa{"nBinsPt_qa", 280, "N bins in pT histo qualitative analysis"}; + + Configurable nPtBins{"nBinsPt", 14, "N bins in pT histo"}; + Configurable nEtaBins{"nEtaBins", 100, ""}; + + Configurable ptMax{"ptMax", 3.0, "maximum pT"}; + Configurable ptMin{"ptMin", 0.2, "minimum pT"}; + + Configurable etaMin{"etaMin", 0.4, "Eta min"}; + Configurable etaCut{"etaCut", 0.8, "Eta cut"}; + Configurable rapCut{"rapCut", 0.5, "Rapidity Cut"}; + + Configurable cfgCutPtUpperTPC{"cfgCutPtUpperTPC", 0.6f, "Upper pT cut for PID using TPC only"}; + Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; + Configurable cfgnSigmaCut{"cfgnSigmaCut", 2.0f, "PID nSigma cut"}; + + Configurable cfgnSigmaCut_TPC_pi{"cfgnSigmaCut_TPC_pi", 2.0f, "PID nSigma cut for TPC for pion"}; + Configurable cfgnSigmaCut_TOF_pi{"cfgnSigmaCut_TOF_pi", 3.0f, "PID nSigma cut for TOF for pion"}; + Configurable cfgnSigmaCut_TPC_ka{"cfgnSigmaCut_TPC_ka", 2.0f, "PID nSigma cut for TPC for kaon"}; + Configurable cfgnSigmaCut_TOF_ka{"cfgnSigmaCut_TOF_ka", 3.0f, "PID nSigma cut for TOF for kaon"}; + Configurable cfgnSigmaCut_TPC_pr{"cfgnSigmaCut_TPC_pr", 2.0f, "PID nSigma cut for TPC for proton"}; + Configurable cfgnSigmaCut_TOF_pr{"cfgnSigmaCut_TOF_pr", 3.0f, "PID nSigma cut for TOF for proton"}; + + // QualityCuts + + Configurable dcaXYCut{"dcaXYCut", 0.2, "DCAxy cut"}; + Configurable dcaZCut{"dcaZCut", 2.0, "DCAz cut"}; + Configurable posZCut{"posZCut", 10.0, "cut for vertex Z"}; + + Configurable TPCNCrossedRowsCut{"TPCNCrossedRowsCut", 2.5, "n_TPC crossed rows Cut"}; + Configurable chi2TPCperClstrCut{"chi2TPCperClstrCut", 4, "Chi2 TPC per Cluster Cut"}; + Configurable chi2ITSperClstrCut{"chi2ITSperClstrCut", 36, "Chi2 ITS per Cluster Cut"}; + + ConfigurableAxis dcaXYBins{"dcaXYBins", {100, -0.15, 0.15}, "dcaXY bins"}; + ConfigurableAxis dcaZBins{"dcaZBins", {100, -1.2, 1.2}, "dcaZ bins"}; + + O2_DEFINE_CONFIGURABLE(cfgUse22sEventCut, bool, true, "Use 22s event cut on mult correlations") + + // Connect to ccdb + Service ccdb; + Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + + // for the sub-sampling + Configurable cfgNSubsample{"cfgNSubsample", 10, "Number of subsamples"}; + + // Event selection cuts - Alex + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + TF1* fMultMultPVCut = nullptr; + + // This is an example of a convenient declaration of "using" + using MyAllTracks = soa::Join; + using MyRun2Collisions = soa::Join; + using MyRun3Collisions = soa::Join; + + void init(InitContext const&) + { + + const AxisSpec axisEvents{5, 0, 5, "Counts"}; + const AxisSpec axisEta{nEtaBins, -1., +1., "#eta"}; + const AxisSpec axisY{nEtaBins, -1., +1., "Rapidity"}; + const AxisSpec axisPt{nPtBins, 0.2, 3., "p_{T} (GeV/c)"}; + const AxisSpec axisPt_qa{nPtBins_qa, 0.2, 3., "p_{T} (GeV/c)"}; + const AxisSpec axisP{nPtBins, 0.2, 3., "p (GeV/c)"}; + const AxisSpec axisCent{100, 0., 100, ""}; + const AxisSpec axis1Bin{1, 0., 1, ""}; + + const AxisSpec axisNumberOfHadronEtaLess0{3000, 0, 3000, "Number of proton eta less than 0"}; + const AxisSpec axisNumberOfProtonEtaLess0{3000, 0, 3000, "Number of proton eta less than 0"}; + const AxisSpec axisNumberOfPionEtaLess0{3000, 0, 3000, "Number of pion eta less than 0"}; + const AxisSpec axisNumberOfKaonEtaLess0{3000, 0, 3000, "Number of kaon eta less than 0"}; + + const AxisSpec axisVtxZ{80, -20., 20., "V_{Z} (cm)"}; + const AxisSpec axisDCAz{dcaZBins, "DCA_{Z} (cm)"}; + const AxisSpec axisDCAxy{dcaXYBins, "DCA_{XY} (cm)"}; + const AxisSpec axisTPCNsigma{500, -5., 5., "n #sigma_{TPC}"}; + const AxisSpec axisTOFNsigma{500, -5., 5., "n #sigma_{TOF}"}; + const AxisSpec axisTPCTOFNsigma{800, -8., 8., "n #sigma_{TOF+TPC}"}; + const AxisSpec axisTPCSignal{720, 20., 200., "#frac{dE}{dx}"}; + const AxisSpec axisTOFSignal{400, 0.2, 1.2, "TOF #beta"}; + const AxisSpec axisChi2{50, 0., 50., "Chi2"}; + const AxisSpec axisCrossedTPC{500, 0, 500, "Crossed TPC"}; + + HistogramConfigSpec TOFnSigmaHist({HistType::kTH2D, {axisPt_qa, axisTOFNsigma}}); + HistogramConfigSpec TOFSignalHist({HistType::kTH2D, {axisPt_qa, axisTOFSignal}}); + HistogramConfigSpec TPCnSigmaHist({HistType::kTH2D, {axisPt_qa, axisTPCNsigma}}); + HistogramConfigSpec TPCSignalHist({HistType::kTH2D, {axisPt_qa, axisTPCSignal}}); + HistogramConfigSpec TPCTOFHist({HistType::kTH2D, {axisTPCNsigma, axisTOFNsigma}}); + HistogramConfigSpec TPCTOFnSigmaHist({HistType::kTH2D, {axisPt_qa, axisTPCTOFNsigma}}); + + histos.add("fA_hadron", "", kTProfile2D, {axisCent, axisPt}); + histos.add("fA_pion", "", kTProfile2D, {axisCent, axisPt}); + histos.add("fA_kaon", "", kTProfile2D, {axisCent, axisPt}); + histos.add("fA_proton", "", kTProfile2D, {axisCent, axisPt}); + + histos.add("fB1_hadron", "", kTProfile2D, {axisCent, axis1Bin}); + histos.add("fB1_pion", "", kTProfile2D, {axisCent, axis1Bin}); + histos.add("fB1_kaon", "", kTProfile2D, {axisCent, axis1Bin}); + histos.add("fB1_proton", "", kTProfile2D, {axisCent, axis1Bin}); + + histos.add("fB2_hadron", "", kTProfile2D, {axisCent, axis1Bin}); + histos.add("fB2_pion", "", kTProfile2D, {axisCent, axis1Bin}); + histos.add("fB2_kaon", "", kTProfile2D, {axisCent, axis1Bin}); + histos.add("fB2_proton", "", kTProfile2D, {axisCent, axis1Bin}); + + histos.add("fC_hadron", "", kTProfile2D, {axisCent, axisPt}); + histos.add("fC_pion", "", kTProfile2D, {axisCent, axisPt}); + histos.add("fC_kaon", "", kTProfile2D, {axisCent, axisPt}); + histos.add("fC_proton", "", kTProfile2D, {axisCent, axisPt}); + + histos.add("fD_hadron", "", kTProfile2D, {axisCent, axis1Bin}); + histos.add("fD_pion", "", kTProfile2D, {axisCent, axis1Bin}); + histos.add("fD_kaon", "", kTProfile2D, {axisCent, axis1Bin}); + histos.add("fD_proton", "", kTProfile2D, {axisCent, axis1Bin}); + + // QA Plots: + histos.add("QA/before/h_VtxZ", "V_{Z}", kTH1D, {axisVtxZ}); + histos.add("QA/before/h_TPCChi2perCluster", "TPC #Chi^{2}/Cluster", kTH1D, {axisChi2}); + histos.add("QA/before/h_ITSChi2perCluster", "ITS #Chi^{2}/Cluster", kTH1D, {axisChi2}); + histos.add("QA/before/h_crossedTPC", "Crossed TPC", kTH1D, {axisCrossedTPC}); + histos.add("QA/before/h2_DcaZ", "DCA_{Z}", kTH1D, {axisDCAz}); + histos.add("QA/before/h2_DcaXY", "DCA_{XY}", kTH1D, {axisDCAxy}); + histos.add("QA/before/h2_TPCSignal", "TPC Signal", TPCSignalHist); + histos.add("QA/before/h2_TOFSignal", "TOF Signal", TOFSignalHist); + + histos.addClone("QA/before/", "QA/after/"); + + histos.add("QA/Pion/h_Pt", "p_{T} (TPC & TPC+TOF)", kTH1D, {axisPt_qa}); + histos.add("QA/Pion/h_rap", "y (TPC & TPC+TOF)", kTH1D, {axisY}); + histos.add("QA/Pion/h2_Pt_rap", "p_{T} vs y", kTH2D, {{axisY}, {axisPt_qa}}); + histos.add("QA/Pion/h2_DcaZ", "DCA_{z}", kTH2D, {{axisPt_qa}, {axisDCAz}}); + histos.add("QA/Pion/h2_DcaXY", "DCA_{xy}", kTH2D, {{axisPt_qa}, {axisDCAxy}}); + + histos.add("QA/Pion/before/h2_TPCNsigma", "n #sigma_{TPC}", TPCnSigmaHist); + histos.add("QA/Pion/before/h2_TOFNsigma", "n #sigma_{TOF}", TOFnSigmaHist); + histos.add("QA/Pion/before/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", TPCTOFHist); + histos.add("QA/Pion/before/h2_TpcTofNsigma1", "n #sigma_{TPC+TOF}", TPCTOFnSigmaHist); + + histos.add("QA/Pion/h2_TPCNsigma", "n #sigma_{TPC}", TPCnSigmaHist); + histos.add("QA/Pion/h2_TOFNsigma", "n #sigma_{TOF}", TOFnSigmaHist); + histos.add("QA/Pion/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", TPCTOFHist); + histos.add("QA/Pion/h2_TpcTofNsigma1", "n #sigma_{TPC+TOF}", TPCTOFnSigmaHist); + + histos.add("QA/Pion/h2_TPCSignal", "TPC Signal vs pT", TPCSignalHist); + histos.add("QA/Pion/h2_TOFSignal", "TOF Signal vs pT", TOFSignalHist); + histos.add("QA/Pion/h2_ExpTPCSignal", "Expected TPC Signal vs pT", TPCSignalHist); + + histos.addClone("QA/Pion/", "QA/Kaon/"); + histos.addClone("QA/Pion/", "QA/Proton/"); + + // Define Subsamples + Subsample.resize(cfgNSubsample); + for (int i = 0; i < cfgNSubsample; i++) { + Subsample[i].resize(20); + } + for (int i = 0; i < cfgNSubsample; i++) { + Subsample[i][0] = std::get>(histos.add(Form("Subsample_%d/fA_hadron", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); + Subsample[i][1] = std::get>(histos.add(Form("Subsample_%d/fA_pion", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); + Subsample[i][2] = std::get>(histos.add(Form("Subsample_%d/fA_kaon", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); + Subsample[i][3] = std::get>(histos.add(Form("Subsample_%d/fA_proton", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); + + Subsample[i][4] = std::get>(histos.add(Form("Subsample_%d/fB1_hadron", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + Subsample[i][5] = std::get>(histos.add(Form("Subsample_%d/fB1_pion", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + Subsample[i][6] = std::get>(histos.add(Form("Subsample_%d/fB1_kaon", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + Subsample[i][7] = std::get>(histos.add(Form("Subsample_%d/fB1_proton", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + + Subsample[i][8] = std::get>(histos.add(Form("Subsample_%d/fB2_hadron", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + Subsample[i][9] = std::get>(histos.add(Form("Subsample_%d/fB2_pion", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + Subsample[i][10] = std::get>(histos.add(Form("Subsample_%d/fB2_kaon", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + Subsample[i][11] = std::get>(histos.add(Form("Subsample_%d/fB2_proton", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + + Subsample[i][12] = std::get>(histos.add(Form("Subsample_%d/fC_hadron", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); + Subsample[i][13] = std::get>(histos.add(Form("Subsample_%d/fC_pion", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); + Subsample[i][14] = std::get>(histos.add(Form("Subsample_%d/fC_kaon", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); + Subsample[i][15] = std::get>(histos.add(Form("Subsample_%d/fC_proton", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); + + Subsample[i][16] = std::get>(histos.add(Form("Subsample_%d/fD_hadron", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + Subsample[i][17] = std::get>(histos.add(Form("Subsample_%d/fD_pion", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + Subsample[i][18] = std::get>(histos.add(Form("Subsample_%d/fD_kaon", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + Subsample[i][19] = std::get>(histos.add(Form("Subsample_%d/fD_proton", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); + } + } + + template + bool selRun2Col(T const& col) + { + if (std::abs(col.posZ()) > posZCut) + return false; + + if (!col.sel7()) + return false; + + if (!col.alias_bit(kINT7)) + return false; + + return true; + } + + template + bool selRun3Col(T const& col) + { + if (std::abs(col.posZ()) > posZCut) + return false; + + if (!col.sel8()) + return false; + + return true; + } + + template + bool selTrack(T const& track) + { + + // kinematic cuts + + if (track.pt() < ptMin) + return false; + + if (track.pt() > ptMax) + return false; + + if (std::abs(track.eta()) > etaCut) + return false; + + if (std::abs(track.dcaZ()) > dcaZCut) + return false; + + if (std::abs(track.dcaXY()) > dcaXYCut) + return false; + + if (track.tpcChi2NCl() > chi2TPCperClstrCut) + return false; + + if (track.itsChi2NCl() > chi2ITSperClstrCut) + return false; + + if (track.tpcNClsCrossedRows() > TPCNCrossedRowsCut) + return false; + + if (!track.isGlobalTrack()) + return false; + + return true; + } + + template + bool selPions(T const& track) + { + const float combNSigmaPi = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); + const float combNSigmaKa = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); + const float combNSigmaPr = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); + + if (track.pt() <= cfgCutPtUpperTPC) { + Int_t flag = 0; + if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cfgnSigmaCut_TPC_pi) + flag += 1; + if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cfgnSigmaCut_TPC_pi) + flag += 1; + if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cfgnSigmaCut_TPC_pi) + flag += 1; + if (flag > 1) + return false; + else if (flag == 1 && std::abs(track.tpcNSigmaPi()) < cfgnSigmaCut_TPC_pi) + return true; + + } else if (track.pt() > cfgCutPtUpperTPC) { + Int_t flag = 0; + if (track.hasTOF() && track.hasTPC() && combNSigmaPi < cfgnSigmaCut_TOF_pi) + flag += 1; + if (track.hasTOF() && track.hasTPC() && combNSigmaKa < cfgnSigmaCut_TOF_pi) + flag += 1; + if (track.hasTOF() && track.hasTPC() && combNSigmaPr < cfgnSigmaCut_TOF_pi) + flag += 1; + if (flag > 1) + return false; + else if (flag == 1 && combNSigmaPi < cfgnSigmaCut_TOF_pi) + return true; + } + + return false; + } + + template + bool selKaons(T const& track) + { + const float combNSigmaPi = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); + const float combNSigmaKa = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); + const float combNSigmaPr = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); + + if (track.pt() <= cfgCutPtUpperTPC) { + Int_t flag = 0; + if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cfgnSigmaCut_TPC_ka) + flag += 1; + if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cfgnSigmaCut_TPC_ka) + flag += 1; + if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cfgnSigmaCut_TPC_ka) + flag += 1; + if (flag > 1) + return false; + else if (flag == 1 && std::abs(track.tpcNSigmaKa()) < cfgnSigmaCut_TPC_ka) + return true; + + } else if (track.pt() > cfgCutPtUpperTPC) { + Int_t flag = 0; + if (track.hasTOF() && track.hasTPC() && combNSigmaPi < cfgnSigmaCut_TOF_ka) + flag += 1; + if (track.hasTOF() && track.hasTPC() && combNSigmaKa < cfgnSigmaCut_TOF_ka) + flag += 1; + if (track.hasTOF() && track.hasTPC() && combNSigmaPr < cfgnSigmaCut_TOF_ka) + flag += 1; + if (flag > 1) + return false; + else if (flag == 1 && combNSigmaKa < cfgnSigmaCut_TOF_ka) + return true; + } + + return false; + } + + template + bool selProtons(T const& track) + { + const float combNSigmaPi = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); + const float combNSigmaKa = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); + const float combNSigmaPr = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); + + // if (abs(track.rapidity(massPr)) < 0.5) + // return true; + if (track.pt() <= cfgCutPtUpperTPC && track.pt() > 0.4) { + Int_t flag = 0; + if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cfgnSigmaCut_TPC_pr) + flag += 1; + if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cfgnSigmaCut_TPC_pr) + flag += 1; + if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cfgnSigmaCut_TPC_pr) + flag += 1; + if (flag > 1) + return false; + else if (flag == 1 && std::abs(track.tpcNSigmaPr()) < cfgnSigmaCut_TPC_pr) + return true; + + } else if (track.pt() > cfgCutPtUpperTPC) { + Int_t flag = 0; + if (track.hasTOF() && track.hasTPC() && combNSigmaPi < cfgnSigmaCut_TOF_pr) + flag += 1; + if (track.hasTOF() && track.hasTPC() && combNSigmaKa < cfgnSigmaCut_TOF_pr) + flag += 1; + if (track.hasTOF() && track.hasTPC() && combNSigmaPr < cfgnSigmaCut_TOF_pr) + flag += 1; + if (flag > 1) + return false; + else if (flag == 1 && combNSigmaPr < cfgnSigmaCut_TOF_pr) + return true; + } + + return false; + } + + void process(MyRun3Collisions::iterator const& col, MyAllTracks const& tracks) + { + double Cent_FT0M = 0; + + if (selRun3Col(col)) { + + Cent_FT0M = col.centFT0M(); + + Double_t pT_bin[14] = {0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9}; + + Double_t N_Pi_eta_less_0 = 0; + Double_t N_Ka_eta_less_0 = 0; + Double_t N_Pr_eta_less_0 = 0; + Double_t Nch_eta_less_0 = 0; + + Double_t pT_sum_etaLess0 = 0; + Double_t pT_sum_etaGreaterEtamin = 0; + Double_t N_sum_etaGreaterEtamin = 0; + + Double_t pt_Ch = 0, pt_Pi = 0, pt_Ka = 0, pt_Pr = 0; + + Double_t fA_hadron[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + Double_t fA_pion[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + Double_t fA_kaon[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + Double_t fA_proton[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + Double_t fB1_hadron = 0; + Double_t fB1_pion = 0; + Double_t fB1_kaon = 0; + Double_t fB1_proton = 0; + + Double_t fB2_hadron = 0; + Double_t fB2_pion = 0; + Double_t fB2_kaon = 0; + Double_t fB2_proton = 0; + + Double_t fC_hadron[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + Double_t fC_pion[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + Double_t fC_kaon[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + Double_t fC_proton[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + Double_t fD_hadron = 0; + Double_t fD_pion = 0; + Double_t fD_kaon = 0; + Double_t fD_proton = 0; + + // normal creation of a histogram + TH1D* fPt_profile = new TH1D("fPt_profile", "fPt_profile", 14, 0.2, 3); + TH1D* fPt_profile_pion = new TH1D("fPt_profile_pion", "fPt_profile_pion", 14, 0.2, 3); + TH1D* fPt_profile_kaon = new TH1D("fPt_profile_kaon", "fPt_profile_kaon", 14, 0.2, 3); + TH1D* fPt_profile_proton = new TH1D("fPt_profile_proton", "fPt_profile_proton", 14, 0.2, 3); + + for (auto& track : tracks) { + + histos.fill(HIST("QA/before/h2_DcaXY"), track.dcaXY()); + histos.fill(HIST("QA/before/h2_DcaZ"), track.dcaZ()); + histos.fill(HIST("QA/before/h_VtxZ"), col.posZ()); + + histos.fill(HIST("QA/before/h_TPCChi2perCluster"), track.tpcChi2NCl()); + histos.fill(HIST("QA/before/h_ITSChi2perCluster"), track.itsChi2NCl()); + histos.fill(HIST("QA/before/h_crossedTPC"), track.tpcNClsCrossedRows()); + + if (selTrack(track)) + continue; + + histos.fill(HIST("QA/after/h2_DcaXY"), track.dcaXY()); + histos.fill(HIST("QA/after/h2_DcaZ"), track.dcaZ()); + + histos.fill(HIST("QA/after/h_TPCChi2perCluster"), track.tpcChi2NCl()); + histos.fill(HIST("QA/after/h_ITSChi2perCluster"), track.itsChi2NCl()); + histos.fill(HIST("QA/after/h_crossedTPC"), track.tpcNClsCrossedRows()); + + histos.fill(HIST("QA/before/h2_TOFSignal"), track.pt(), track.beta()); + histos.fill(HIST("QA/before/h2_TPCSignal"), track.pt(), track.tpcSignal()); + + histos.fill(HIST("QA/Pion/before/h2_TPCNsigma"), track.pt(), track.tpcNSigmaPi()); + histos.fill(HIST("QA/Pion/before/h2_TOFNsigma"), track.pt(), track.tofNSigmaPi()); + histos.fill(HIST("QA/Pion/before/h2_TpcTofNsigma"), track.tpcNSigmaPi(), track.tofNSigmaPi()); + + histos.fill(HIST("QA/Proton/before/h2_TPCNsigma"), track.pt(), track.tpcNSigmaPr()); + histos.fill(HIST("QA/Proton/before/h2_TOFNsigma"), track.pt(), track.tofNSigmaPr()); + histos.fill(HIST("QA/Proton/before/h2_TpcTofNsigma"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + + histos.fill(HIST("QA/Kaon/before/h2_TPCNsigma"), track.pt(), track.tpcNSigmaKa()); + histos.fill(HIST("QA/Kaon/before/h2_TOFNsigma"), track.pt(), track.tofNSigmaKa()); + histos.fill(HIST("QA/Kaon/before/h2_TpcTofNsigma"), track.tpcNSigmaKa(), track.tofNSigmaKa()); + + const float combNSigmaPi1 = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); + const float combNSigmaKa1 = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); + const float combNSigmaPr1 = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); + + histos.fill(HIST("QA/Pion/before/h2_TpcTofNsigma1"), track.pt(), combNSigmaPi1); + histos.fill(HIST("QA/Kaon/before/h2_TpcTofNsigma1"), track.pt(), combNSigmaKa1); + histos.fill(HIST("QA/Proton/before/h2_TpcTofNsigma1"), track.pt(), combNSigmaPr1); + + if (track.eta() < 0) { + Nch_eta_less_0++; + pt_Ch = track.pt(); + + pT_sum_etaLess0 += pt_Ch; + fPt_profile->Fill(pt_Ch); + + // For Pions: + if (selPions(track)) { + N_Pi_eta_less_0++; + pt_Pi = track.pt(); + + fPt_profile_pion->Fill(pt_Pi); + + // QA + histos.fill(HIST("QA/Pion/h_Pt"), track.pt()); + histos.fill(HIST("QA/Pion/h_rap"), track.rapidity(massPi)); + histos.fill(HIST("QA/Pion/h2_Pt_rap"), track.rapidity(massPi), track.pt()); + histos.fill(HIST("QA/Pion/h2_DcaXY"), track.pt(), track.dcaXY()); + histos.fill(HIST("QA/Pion/h2_DcaZ"), track.pt(), track.dcaZ()); + + histos.fill(HIST("QA/Pion/h2_TPCNsigma"), track.pt(), track.tpcNSigmaPi()); + histos.fill(HIST("QA/Pion/h2_TOFNsigma"), track.pt(), track.tofNSigmaPi()); + histos.fill(HIST("QA/Pion/h2_TpcTofNsigma"), track.tpcNSigmaPi(), track.tofNSigmaPi()); + histos.fill(HIST("QA/Pion/h2_TOFSignal"), track.pt(), track.beta()); + histos.fill(HIST("QA/Pion/h2_TPCSignal"), track.pt(), track.tpcSignal()); + histos.fill(HIST("QA/Pion/h2_ExpTPCSignal"), track.pt(), track.tpcExpSignalPi(track.tpcSignal())); + + histos.fill(HIST("QA/after/h2_TOFSignal"), track.pt(), track.beta()); + histos.fill(HIST("QA/after/h2_TPCSignal"), track.pt(), track.tpcSignal()); + + const float combNSigmaPi2 = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); + + histos.fill(HIST("QA/Pion/h2_TpcTofNsigma1"), track.pt(), combNSigmaPi2); + } + + // For Kaons: + if (selKaons(track)) { + N_Ka_eta_less_0++; + pt_Ka = track.pt(); + + fPt_profile_kaon->Fill(pt_Ka); + + // QA + + histos.fill(HIST("QA/Kaon/h_Pt"), track.pt()); + histos.fill(HIST("QA/Kaon/h_rap"), track.rapidity(massKa)); + histos.fill(HIST("QA/Kaon/h2_Pt_rap"), track.rapidity(massKa), track.pt()); + histos.fill(HIST("QA/Kaon/h2_DcaXY"), track.pt(), track.dcaXY()); + histos.fill(HIST("QA/Kaon/h2_DcaZ"), track.pt(), track.dcaZ()); + + histos.fill(HIST("QA/Kaon/h2_TPCNsigma"), track.pt(), track.tpcNSigmaKa()); + histos.fill(HIST("QA/Kaon/h2_TOFNsigma"), track.pt(), track.tofNSigmaKa()); + histos.fill(HIST("QA/Kaon/h2_TpcTofNsigma"), track.tpcNSigmaKa(), track.tofNSigmaKa()); + histos.fill(HIST("QA/Kaon/h2_TOFSignal"), track.pt(), track.beta()); + histos.fill(HIST("QA/Kaon/h2_TPCSignal"), track.pt(), track.tpcSignal()); + histos.fill(HIST("QA/Kaon/h2_ExpTPCSignal"), track.pt(), track.tpcExpSignalKa(track.tpcSignal())); + histos.fill(HIST("QA/after/h2_TOFSignal"), track.pt(), track.beta()); + histos.fill(HIST("QA/after/h2_TPCSignal"), track.pt(), track.tpcSignal()); + + const float combNSigmaKa2 = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); + + histos.fill(HIST("QA/Kaon/h2_TpcTofNsigma1"), track.pt(), combNSigmaKa2); + } + + // For Protons: + if (selProtons(track)) { + N_Pr_eta_less_0++; + pt_Pr = track.pt(); + + fPt_profile_proton->Fill(pt_Pr); + + // QA + + histos.fill(HIST("QA/Proton/h_Pt"), track.pt()); + histos.fill(HIST("QA/Proton/h_rap"), track.rapidity(massPr)); + histos.fill(HIST("QA/Proton/h2_Pt_rap"), track.rapidity(massPr), track.pt()); + histos.fill(HIST("QA/Proton/h2_DcaZ"), track.pt(), track.dcaZ()); + histos.fill(HIST("QA/Proton/h2_DcaXY"), track.pt(), track.dcaXY()); + + histos.fill(HIST("QA/Proton/h2_TPCNsigma"), track.pt(), track.tpcNSigmaPr()); + histos.fill(HIST("QA/Proton/h2_TOFNsigma"), track.pt(), track.tofNSigmaPr()); + histos.fill(HIST("QA/Proton/h2_TpcTofNsigma"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + histos.fill(HIST("QA/Proton/h2_TPCSignal"), track.pt(), track.tpcSignal()); + histos.fill(HIST("QA/Proton/h2_TOFSignal"), track.pt(), track.beta()); + histos.fill(HIST("QA/Proton/h2_ExpTPCSignal"), track.pt(), track.tpcExpSignalPr(track.tpcSignal())); + histos.fill(HIST("QA/after/h2_TPCSignal"), track.pt(), track.tpcSignal()); + histos.fill(HIST("QA/after/h2_TOFSignal"), track.pt(), track.beta()); + + const float combNSigmaPr2 = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); + + histos.fill(HIST("QA/Proton/h2_TpcTofNsigma1"), track.pt(), combNSigmaPr2); + } + + } else if (track.eta() > etaMin) { + pT_sum_etaGreaterEtamin += pt_Ch; + N_sum_etaGreaterEtamin++; + } + } + + // selecting subsample and filling profiles + float l_Random = fRndm->Rndm(); + int SampleIndex = static_cast(cfgNSubsample * l_Random); + + // B1, B2, and D Calculation for hadrons + if (N_sum_etaGreaterEtamin != 0 && Nch_eta_less_0 != 0) { + fB1_hadron = pT_sum_etaLess0 / Nch_eta_less_0; + histos.fill(HIST("fB1_hadron"), Cent_FT0M, 0.5, fB1_hadron); + Subsample[SampleIndex][4]->Fill(Cent_FT0M, 0.5, fB1_hadron); + + fB2_hadron = pT_sum_etaGreaterEtamin / N_sum_etaGreaterEtamin; + histos.fill(HIST("fB2_hadron"), Cent_FT0M, 0.5, fB2_hadron); + Subsample[SampleIndex][8]->Fill(Cent_FT0M, 0.5, fB2_hadron); + + fD_hadron = fB1_hadron * fB2_hadron; + histos.fill(HIST("fD_hadron"), Cent_FT0M, 0.5, fD_hadron); + Subsample[SampleIndex][16]->Fill(Cent_FT0M, 0.5, fD_hadron); + } + + // B1, B2, and D Calculation for pions + if (N_sum_etaGreaterEtamin != 0 && Nch_eta_less_0 != 0 && N_Pi_eta_less_0 != 0) { + fB1_pion = pT_sum_etaLess0 / Nch_eta_less_0; + histos.fill(HIST("fB1_pion"), Cent_FT0M, 0.5, fB1_pion); + Subsample[SampleIndex][5]->Fill(Cent_FT0M, 0.5, fB1_pion); + + fB2_pion = pT_sum_etaGreaterEtamin / N_sum_etaGreaterEtamin; + histos.fill(HIST("fB2_pion"), Cent_FT0M, 0.5, fB2_pion); + Subsample[SampleIndex][9]->Fill(Cent_FT0M, 0.5, fB2_pion); + + fD_pion = fB1_pion * fB2_pion; + histos.fill(HIST("fD_pion"), Cent_FT0M, 0.5, fD_pion); + Subsample[SampleIndex][17]->Fill(Cent_FT0M, 0.5, fD_pion); + } + + // B1, B2, and D Calculation for kaons + if (N_sum_etaGreaterEtamin != 0 && Nch_eta_less_0 != 0 && N_Ka_eta_less_0 != 0) { + fB1_kaon = pT_sum_etaLess0 / Nch_eta_less_0; + histos.fill(HIST("fB1_kaon"), Cent_FT0M, 0.5, fB1_kaon); + Subsample[SampleIndex][6]->Fill(Cent_FT0M, 0.5, fB1_kaon); + + fB2_kaon = pT_sum_etaGreaterEtamin / N_sum_etaGreaterEtamin; + histos.fill(HIST("fB2_kaon"), Cent_FT0M, 0.5, fB2_kaon); + Subsample[SampleIndex][10]->Fill(Cent_FT0M, 0.5, fB2_kaon); + + fD_kaon = fB1_kaon * fB2_kaon; + histos.fill(HIST("fD_kaon"), Cent_FT0M, 0.5, fD_kaon); + Subsample[SampleIndex][18]->Fill(Cent_FT0M, 0.5, fD_kaon); + } + + // B1, B2, and D Calculation for protons + if (N_sum_etaGreaterEtamin != 0 && Nch_eta_less_0 != 0 && N_Pr_eta_less_0 != 0) { + fB1_proton = pT_sum_etaLess0 / Nch_eta_less_0; + histos.fill(HIST("fB1_proton"), Cent_FT0M, 0.5, fB1_proton); + Subsample[SampleIndex][7]->Fill(Cent_FT0M, 0.5, fB1_proton); + + fB2_proton = pT_sum_etaGreaterEtamin / N_sum_etaGreaterEtamin; + histos.fill(HIST("fB2_proton"), Cent_FT0M, 0.5, fB2_proton); + Subsample[SampleIndex][11]->Fill(Cent_FT0M, 0.5, fB2_proton); + + fD_proton = fB1_proton * fB2_proton; + histos.fill(HIST("fD_proton"), Cent_FT0M, 0.5, fD_proton); + Subsample[SampleIndex][19]->Fill(Cent_FT0M, 0.5, fD_proton); + } + + for (int i = 0; i < 14; i++) { + // A_hadrone Calculation + if (Nch_eta_less_0 != 0) { + fA_hadron[i] = fPt_profile->GetBinContent(i + 1) / Nch_eta_less_0; + histos.fill(HIST("fA_hadron"), Cent_FT0M, pT_bin[i], fA_hadron[i]); + Subsample[SampleIndex][0]->Fill(Cent_FT0M, pT_bin[i], fA_hadron[i]); + } + + // A_pion Calculation + if (N_Pi_eta_less_0 != 0) { + fA_pion[i] = fPt_profile_pion->GetBinContent(i + 1) / N_Pi_eta_less_0; + histos.fill(HIST("fA_pion"), Cent_FT0M, pT_bin[i], fA_pion[i]); + Subsample[SampleIndex][1]->Fill(Cent_FT0M, pT_bin[i], fA_pion[i]); + } + + // A_kaon Calculation + if (N_Ka_eta_less_0 != 0) { + fA_kaon[i] = fPt_profile_kaon->GetBinContent(i + 1) / N_Ka_eta_less_0; + histos.fill(HIST("fA_kaon"), Cent_FT0M, pT_bin[i], fA_kaon[i]); + Subsample[SampleIndex][2]->Fill(Cent_FT0M, pT_bin[i], fA_kaon[i]); + } + + // A_proton Calculation + if (N_Pr_eta_less_0 != 0) { + fA_proton[i] = fPt_profile_proton->GetBinContent(i + 1) / N_Pr_eta_less_0; + histos.fill(HIST("fA_proton"), Cent_FT0M, pT_bin[i], fA_proton[i]); + Subsample[SampleIndex][3]->Fill(Cent_FT0M, pT_bin[i], fA_proton[i]); + } + + // C_hadron Calculation + if (Nch_eta_less_0 != 0 && N_sum_etaGreaterEtamin != 0) { + fC_hadron[i] = fA_hadron[i] * fB2_hadron; + histos.fill(HIST("fC_hadron"), Cent_FT0M, pT_bin[i], fC_hadron[i]); + Subsample[SampleIndex][12]->Fill(Cent_FT0M, pT_bin[i], fC_hadron[i]); + } + + // C_pion Calculation + if (N_Pi_eta_less_0 != 0 && N_sum_etaGreaterEtamin != 0) { + fC_pion[i] = fA_pion[i] * fB2_pion; + histos.fill(HIST("fC_pion"), Cent_FT0M, pT_bin[i], fC_pion[i]); + Subsample[SampleIndex][13]->Fill(Cent_FT0M, pT_bin[i], fC_pion[i]); + } + + // A_kaon Calculation + if (N_Ka_eta_less_0 != 0 && N_sum_etaGreaterEtamin != 0) { + fC_kaon[i] = fA_kaon[i] * fB2_kaon; + histos.fill(HIST("fC_kaon"), Cent_FT0M, pT_bin[i], fC_kaon[i]); + Subsample[SampleIndex][14]->Fill(Cent_FT0M, pT_bin[i], fC_kaon[i]); + } + + // A_proton Calculation + if (N_Pr_eta_less_0 != 0 && N_sum_etaGreaterEtamin != 0) { + fC_proton[i] = fA_proton[i] * fB2_proton; + histos.fill(HIST("fC_proton"), Cent_FT0M, pT_bin[i], fC_proton[i]); + Subsample[SampleIndex][15]->Fill(Cent_FT0M, pT_bin[i], fC_proton[i]); + } + } + + fPt_profile->Delete(); + fPt_profile_pion->Delete(); + fPt_profile_kaon->Delete(); + fPt_profile_proton->Delete(); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx b/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx index 12418407c49..f9b85d33978 100755 --- a/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx +++ b/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx @@ -254,7 +254,8 @@ struct FemtoCorrelations { SEhistos_1D[multBin][kTbin]->Fill(Pair->GetKstar()); // close pair rejection and fillig the SE histo if (_fill3dCF) { - TVector3 qLCMS = Pair->GetQLCMS(); + std::mt19937 mt(std::chrono::steady_clock::now().time_since_epoch().count()); + TVector3 qLCMS = std::pow(-1, (mt() % 2)) * Pair->GetQLCMS(); // introducing randomness to the pair order ([first, second]); important only for 3D because if there are any sudden order/correlation in the tables, it could couse unwanted asymmetries in the final 3d rel. momentum distributions; irrelevant in 1D case because the absolute value of the rel.momentum is taken SEhistos_3D[multBin][kTbin]->Fill(qLCMS.X(), qLCMS.Y(), qLCMS.Z()); } } @@ -301,14 +302,16 @@ struct FemtoCorrelations { mThistos[multBin][kTbin]->Fill(Pair->GetMt()); // test if (_fill3dCF) { - TVector3 qLCMS = Pair->GetQLCMS(); + std::mt19937 mt(std::chrono::steady_clock::now().time_since_epoch().count()); + TVector3 qLCMS = std::pow(-1, (mt() % 2)) * Pair->GetQLCMS(); // introducing randomness to the pair order ([first, second]); important only for 3D because if there are any sudden order/correlation in the tables, it could couse unwanted asymmetries in the final 3d rel. momentum distributions; irrelevant in 1D case because the absolute value of the rel.momentum is taken SEhistos_3D[multBin][kTbin]->Fill(qLCMS.X(), qLCMS.Y(), qLCMS.Z()); } } else { MEhistos_1D[multBin][kTbin]->Fill(Pair->GetKstar()); if (_fill3dCF) { - TVector3 qLCMS = Pair->GetQLCMS(); + std::mt19937 mt(std::chrono::steady_clock::now().time_since_epoch().count()); + TVector3 qLCMS = std::pow(-1, (mt() % 2)) * Pair->GetQLCMS(); // introducing randomness to the pair order ([first, second]); important only for 3D because if there are any sudden order/correlation in the tables, it could couse unwanted asymmetries in the final 3d rel. momentum distributions; irrelevant in 1D case because the absolute value of the rel.momentum is taken MEhistos_3D[multBin][kTbin]->Fill(qLCMS.X(), qLCMS.Y(), qLCMS.Z()); qLCMSvskStar[multBin][kTbin]->Fill(qLCMS.X(), qLCMS.Y(), qLCMS.Z(), Pair->GetKstar()); } @@ -412,11 +415,6 @@ struct FemtoCorrelations { int centBin = std::floor((i->first).second); MultHistos[centBin]->Fill(col1->mult()); - if (_fill3dCF) { // shuffling is important only for 3D because if there are any sudden order/correlation in the tables, it could couse unwanted asymmetries in the final 3d rel. momentum distributions; irrelevant in 1D case because the absolute value of the rel.momentum is taken - std::mt19937 gen(std::chrono::steady_clock::now().time_since_epoch().count()); - std::shuffle(selectedtracks_1[col1->index()].begin(), selectedtracks_1[col1->index()].end(), gen); - } - mixTracks(selectedtracks_1[col1->index()], centBin); // mixing SE identical for (int indx2 = indx1 + 1; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin @@ -449,11 +447,6 @@ struct FemtoCorrelations { int centBin = std::floor((i->first).second); MultHistos[centBin]->Fill(col1->mult()); - if (_fill3dCF) { - std::mt19937 gen(std::chrono::steady_clock::now().time_since_epoch().count()); - std::shuffle(selectedtracks_1[col1->index()].begin(), selectedtracks_1[col1->index()].end(), gen); - } - mixTracks<0>(selectedtracks_1[col1->index()], selectedtracks_2[col1->index()], centBin); // mixing SE non-identical, in <> brackets: 0 -- SE; 1 -- ME for (int indx2 = indx1 + 1; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin diff --git a/PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h b/PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h index c75c897d0d2..dcb4b1ab645 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h +++ b/PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h @@ -177,13 +177,9 @@ class FemtoDreamContainerThreeBody /// \param part3 Particle three /// \param mult Multiplicity of the event template - void setTriplet(T const& part1, T const& part2, T const& part3, const int mult) + void setTriplet(T const& part1, T const& part2, T const& part3, const int mult, const float femtoObs) { - float femtoObs, femtoObsMC; - // Calculate femto observable and the mT with reconstructed information - if constexpr (mFemtoObs == femtoDreamContainerThreeBody::Observable::Q3) { - femtoObs = FemtoDreamMath::getQ3(part1, mMassOne, part2, mMassTwo, part3, mMassThree); - } + float femtoObsMC; if (mHistogramRegistry) { setTriplet_base(femtoObs, part1, part2, part3, mult); diff --git a/PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h b/PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h index 371487d70df..c65fbbb221a 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h +++ b/PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h @@ -41,32 +41,33 @@ class FemtoDreamDetaDphiStar /// Destructor virtual ~FemtoDreamDetaDphiStar() = default; /// Initialization of the histograms and setting required values - void init(HistogramRegistry* registry, HistogramRegistry* registryQA, float ldeltaPhiMax, float ldeltaEtaMax, bool lplotForEveryRadii) + void init(HistogramRegistry* registry, HistogramRegistry* registryQA, float ldeltaPhiMax, float ldeltaEtaMax, bool lplotForEveryRadii, int meORse = 0, bool oldversion = true) { deltaPhiMax = ldeltaPhiMax; deltaEtaMax = ldeltaEtaMax; plotForEveryRadii = lplotForEveryRadii; + runOldVersion = oldversion; mHistogramRegistry = registry; mHistogramRegistryQA = registryQA; if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kTrack) { std::string dirName = static_cast(dirNames[0]); - histdetadpi[0][0] = mHistogramRegistry->add((dirName + static_cast(histNames[0][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpi[0][1] = mHistogramRegistry->add((dirName + static_cast(histNames[1][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpi[0][0] = mHistogramRegistry->add((dirName + static_cast(histNames[0][0]) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpi[0][1] = mHistogramRegistry->add((dirName + static_cast(histNames[1][0]) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{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}}); + histdetadpiRadii[0][i] = mHistogramRegistryQA->add((dirName + static_cast(histNamesRadii[0][i]) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); } } } if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kV0) { for (int i = 0; i < 2; i++) { std::string dirName = static_cast(dirNames[1]); - histdetadpi[i][0] = mHistogramRegistry->add((dirName + static_cast(histNames[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpi[i][1] = mHistogramRegistry->add((dirName + static_cast(histNames[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpi[i][0] = mHistogramRegistry->add((dirName + static_cast(histNames[0][i]) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpi[i][1] = mHistogramRegistry->add((dirName + static_cast(histNames[1][i]) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); if (plotForEveryRadii) { for (int j = 0; j < 9; j++) { - histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(histNamesRadii[i][j])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(histNamesRadii[i][j]) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); } } } @@ -128,6 +129,8 @@ class FemtoDreamDetaDphiStar HistogramRegistry* mHistogramRegistryQA = nullptr; ///< For QA output static constexpr std::string_view dirNames[2] = {"kTrack_kTrack/", "kTrack_kV0/"}; + static constexpr std::string_view histNameSEorME[3] = {"_SEandME", "_SE", "_ME"}; + static constexpr std::string_view histNames[2][2] = {{"detadphidetadphi0Before_0", "detadphidetadphi0Before_1"}, {"detadphidetadphi0After_0", "detadphidetadphi0After_1"}}; static constexpr std::string_view histNamesRadii[2][9] = {{"detadphidetadphi0Before_0_0", "detadphidetadphi0Before_0_1", "detadphidetadphi0Before_0_2", @@ -150,6 +153,9 @@ class FemtoDreamDetaDphiStar float deltaEtaMax; float magfield; bool plotForEveryRadii = false; + // a possible bug was found, but this must be tested on hyperloop with larger statistics + // possiboility to run old code is turned on so a proper comparison of both code versions can be done + bool runOldVersion = true; std::array, 2>, 2> histdetadpi{}; std::array, 9>, 2> histdetadpiRadii{}; @@ -175,7 +181,18 @@ class FemtoDreamDetaDphiStar // End: Get the charge from cutcontainer using masks float pt = part.pt(); for (size_t i = 0; i < 9; i++) { - tmpVec.push_back(phi0 - std::asin(0.3 * charge * 0.1 * magfield * tmpRadiiTPC[i] * 0.01 / (2. * pt))); + if (runOldVersion) { + tmpVec.push_back(phi0 - std::asin(0.3 * charge * 0.1 * magfield * tmpRadiiTPC[i] * 0.01 / (2. * pt))); + } + if (!runOldVersion) { + auto arg = 0.3 * charge * magfield * tmpRadiiTPC[i] * 0.01 / (2. * pt); + // for very low pT particles, this value goes outside of range -1 to 1 at at large tpc radius; asin fails + if (abs(arg) < 1) { + tmpVec.push_back(phi0 - std::asin(0.3 * charge * magfield * tmpRadiiTPC[i] * 0.01 / (2. * pt))); + } else { + tmpVec.push_back(999); + } + } } } @@ -188,16 +205,23 @@ class FemtoDreamDetaDphiStar PhiAtRadiiTPC(part1, tmpVec1); PhiAtRadiiTPC(part2, tmpVec2); int num = tmpVec1.size(); + int meaningfulEntries = num; float dPhiAvg = 0; + float dphi; for (int i = 0; i < num; i++) { - float dphi = tmpVec1.at(i) - tmpVec2.at(i); + if (tmpVec1.at(i) != 999 && tmpVec2.at(i) != 999) { + dphi = tmpVec1.at(i) - tmpVec2.at(i); + } else { + dphi = 0; + meaningfulEntries = meaningfulEntries - 1; + } dphi = TVector2::Phi_mpi_pi(dphi); dPhiAvg += dphi; if (plotForEveryRadii) { histdetadpiRadii[iHist][i]->Fill(part1.eta() - part2.eta(), dphi); } } - return dPhiAvg / num; + return dPhiAvg / static_cast(meaningfulEntries); } }; diff --git a/PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h b/PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h index a2f3c6538fb..709864bc02a 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h +++ b/PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h @@ -582,11 +582,11 @@ class FemtoDreamParticleHisto } private: - HistogramRegistry* mHistogramRegistry; ///< For QA output - static constexpr o2::aod::femtodreamparticle::ParticleType mParticleType = particleType; ///< Type of the particle under analysis - static constexpr int mFolderSuffixType = suffixType; ///< Counter for the folder suffix specified below - static constexpr std::string_view mFolderSuffix[5] = {"", "_one", "_two", "_pos", "_neg"}; ///< Suffix for the folder name in case of analyses of pairs of the same kind (T-T, V-V, C-C) - int mPDG = 0; ///< PDG code of the selected particle + HistogramRegistry* mHistogramRegistry; ///< For QA output + static constexpr o2::aod::femtodreamparticle::ParticleType mParticleType = particleType; ///< Type of the particle under analysis + static constexpr int mFolderSuffixType = suffixType; ///< Counter for the folder suffix specified below + static constexpr std::string_view mFolderSuffix[8] = {"", "_one", "_two", "_pos", "_neg", "_allSelected", "_allSelected_pos", "_allSelected_neg"}; ///< Suffix for the folder name in case of analyses of pairs of the same kind (T-T, V-V, C-C) + int mPDG = 0; ///< PDG code of the selected particle }; } // namespace o2::analysis::femtoDream diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx index 7e7e1352c8d..d57bd9b5cc3 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx @@ -220,6 +220,8 @@ struct femoDreamCollisionMasker { TrackPIDThreshold.at(CollisionMasks::kPartOne).push_back(option.defaultValue.get()); } else if (option.name.compare(std::string("ConfMaxpT")) == 0) { FilterPtMax.at(CollisionMasks::kPartOne).push_back(option.defaultValue.get()); + } else if (option.name.compare(std::string("ConfMinpT")) == 0) { + FilterPtMin.at(CollisionMasks::kPartOne).push_back(option.defaultValue.get()); } } } else if (device.name.find("femto-dream-triplet-task-track-track-v0") != std::string::npos) { @@ -236,6 +238,8 @@ struct femoDreamCollisionMasker { TrackPIDThreshold.at(CollisionMasks::kPartOne).push_back(option.defaultValue.get()); } else if (option.name.compare(std::string("ConfMaxpT")) == 0) { FilterPtMax.at(CollisionMasks::kPartOne).push_back(option.defaultValue.get()); + } else if (option.name.compare(std::string("ConfMinpT")) == 0) { + FilterPtMin.at(CollisionMasks::kPartOne).push_back(option.defaultValue.get()); } else if (option.name.compare(std::string("ConfCutV0")) == 0) { V0CutBits.at(CollisionMasks::kPartThree).push_back(option.defaultValue.get()); } else if (option.name.compare(std::string("Conf_ChildPos_CutV0")) == 0) { @@ -325,7 +329,7 @@ struct femoDreamCollisionMasker { continue; } // check filter cuts - if (track.pt() > FilterPtMax.at(P).at(index)) { + if (track.pt() < FilterPtMin.at(P).at(index) || track.pt() > FilterPtMax.at(P).at(index)) { // if they are not passed, skip the particle continue; } diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrack.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrack.cxx index 2ef196642eb..93bf384bc26 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrack.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrack.cxx @@ -47,12 +47,17 @@ struct femtoDreamTripletTaskTrackTrackTrack { 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 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"}; @@ -67,14 +72,17 @@ struct femtoDreamTripletTaskTrackTrackTrack { 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 < ConfMaxpT) && + (aod::femtodreamparticle::pt > ConfMinpT); 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 < ConfMaxpT) && + (aod::femtodreamparticle::pt > ConfMinpT); /// Histogramming of Selected Particles FemtoDreamParticleHisto trackHistoSelectedParts; + FemtoDreamParticleHisto trackHistoALLSelectedParts; /// Histogramming for Event FemtoDreamEventHisto eventHisto; @@ -91,6 +99,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { 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 ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; @@ -101,7 +110,8 @@ struct femtoDreamTripletTaskTrackTrackTrack { FemtoDreamContainerThreeBody sameEventCont; FemtoDreamContainerThreeBody mixedEventCont; FemtoDreamPairCleaner pairCleaner; - FemtoDreamDetaDphiStar pairCloseRejection; + FemtoDreamDetaDphiStar pairCloseRejectionSE; + FemtoDreamDetaDphiStar pairCloseRejectionME; /// Histogram output HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -112,9 +122,12 @@ struct femtoDreamTripletTaskTrackTrackTrack { eventHisto.init(&qaRegistry); trackHistoSelectedParts.init(&qaRegistry, ConfBinmultTempFit, ConfDummy, ConfTempFitVarpTBins, ConfDummy, ConfDummy, ConfTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePart); + trackHistoALLSelectedParts.init(&qaRegistry, ConfBinmultTempFit, ConfDummy, ConfTempFitVarpTBins, ConfDummy, ConfDummy, ConfTempFitVarBins, 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}}); @@ -125,9 +138,15 @@ struct femtoDreamTripletTaskTrackTrackTrack { mixedEventCont.setPDGCodes(ConfPDGCodePart, ConfPDGCodePart, ConfPDGCodePart); pairCleaner.init(&qaRegistry); // SERKSNYTE : later check if init should be updated to have 3 separate histos if (ConfIsCPR.value) { - pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); + pairCloseRejectionSE.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 1, ConfUseOLD_possiblyWrong_CPR); + pairCloseRejectionME.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 2, ConfUseOLD_possiblyWrong_CPR); } + // 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; @@ -138,7 +157,8 @@ struct femtoDreamTripletTaskTrackTrackTrack { 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, "ConfMaxpT", ConfMaxpT.value) && + containsNameValuePair(device.options, "ConfMinpT", ConfMinpT.value)) { mask.set(index); MaskBit = static_cast(mask.to_ulong()); LOG(info) << "Device name matched: " << device.name; @@ -184,13 +204,13 @@ struct femtoDreamTripletTaskTrackTrackTrack { /// Now build the combinations for (auto& [p1, p2, p3] : combinations(CombinationsStrictlyUpperIndexPolicy(groupSelectedParts, groupSelectedParts, groupSelectedParts))) { if (ConfIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + if (pairCloseRejectionSE.isClosePair(p1, p2, parts, magFieldTesla)) { continue; } - if (pairCloseRejection.isClosePair(p2, p3, parts, magFieldTesla)) { + if (pairCloseRejectionSE.isClosePair(p2, p3, parts, magFieldTesla)) { continue; } - if (pairCloseRejection.isClosePair(p1, p3, parts, magFieldTesla)) { + if (pairCloseRejectionSE.isClosePair(p1, p3, parts, magFieldTesla)) { continue; } } @@ -205,7 +225,10 @@ struct femtoDreamTripletTaskTrackTrackTrack { if (!pairCleaner.isCleanPair(p1, p3, parts)) { continue; } - sameEventCont.setTriplet(p1, p2, p3, multCol); + // fill pT of all three particles as a function of Q3 for lambda calculations + auto Q3 = FemtoDreamMath::getQ3(p1, mMassOne, p2, mMassTwo, p3, mMassThree); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_SE"), p1.pt(), p2.pt(), p3.pt(), Q3); + sameEventCont.setTriplet(p1, p2, p3, multCol, Q3); } } @@ -217,6 +240,10 @@ struct femtoDreamTripletTaskTrackTrackTrack { { 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; } @@ -231,6 +258,9 @@ struct femtoDreamTripletTaskTrackTrackTrack { { 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; } @@ -248,6 +278,9 @@ struct femtoDreamTripletTaskTrackTrackTrack { { 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()); + } if (thegroupSelectedParts.size() < 3) { return; } @@ -265,6 +298,9 @@ struct femtoDreamTripletTaskTrackTrackTrack { { 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()); + } if (thegroupSelectedParts.size() < 3) { return; } @@ -287,18 +323,21 @@ struct femtoDreamTripletTaskTrackTrackTrack { { for (auto& [p1, p2, p3] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo, groupPartsThree))) { if (ConfIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + if (pairCloseRejectionME.isClosePair(p1, p2, parts, magFieldTesla)) { continue; } - if (pairCloseRejection.isClosePair(p2, p3, parts, magFieldTesla)) { + if (pairCloseRejectionME.isClosePair(p2, p3, parts, magFieldTesla)) { continue; } - if (pairCloseRejection.isClosePair(p1, p3, parts, magFieldTesla)) { + if (pairCloseRejectionME.isClosePair(p1, p3, parts, magFieldTesla)) { continue; } } - mixedEventCont.setTriplet(p1, p2, p3, multCol); + // fill pT of all three particles as a function of Q3 for lambda calculations + auto Q3 = FemtoDreamMath::getQ3(p1, mMassOne, p2, mMassTwo, p3, mMassThree); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_ME"), p1.pt(), p2.pt(), p3.pt(), Q3); + mixedEventCont.setTriplet(p1, p2, p3, multCol, Q3); } } diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackV0.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackV0.cxx index 05ba4ee37d3..3f5036fdb1e 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackV0.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackV0.cxx @@ -45,17 +45,22 @@ struct femtoDreamTripletTaskTrackTrackV0 { using MaskedCollisions = soa::Join; using MaskedCollision = MaskedCollisions::iterator; aod::femtodreamcollision::BitMaskType MaskBit = -1; + float mMassOne = -999, mMassTwo = -999, mMassThree = -999; Configurable ConfMixIfTripletPresent{"ConfMixIfTripletPresent", true, "Use for mixing only events which have a TTV0 triplet"}; Configurable ConfMixIfTVOPairPresent{"ConfMixIfTVOPairPresent", false, "Use for mixing only events which have a TV0 pair (at least one track and one V0)"}; Configurable ConfMixIfTOrVOPartsPresent{"ConfMixIfTOrVOPartsPresent", false, "Use for mixing only events which have at least one particle of interest"}; + // 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."}; + /// Track selection Configurable ConfPDGCodePart{"ConfPDGCodePart", 2212, "Particle PDG code"}; Configurable ConfCutPart{"ConfCutPart", 5542474, "Track - Selection bit from cutCulator"}; Configurable ConfTPCPIDBit{"ConfTPCPIDBit", 16, "PID TPC bit from cutCulator "}; Configurable ConfTPCTOFPIDBit{"ConfTPCTOFPIDBit", 8, "PID TPCTOF bit from cutCulator"}; Configurable ConfMaxpT{"ConfMaxpT", 4.05f, "Maximum transverse momentum of the particles"}; + Configurable ConfMinpT{"ConfMinpT", 0.3f, "Minimum transverse momentum of the particles"}; Configurable ConfPIDthrMom{"ConfPIDthrMom", 1.f, "Momentum threshold from which TPC and TOF are required for PID"}; 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"}; @@ -64,14 +69,17 @@ struct femtoDreamTripletTaskTrackTrackV0 { 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 < ConfMaxpT) && + (aod::femtodreamparticle::pt > ConfMinpT); 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 < ConfMaxpT) && + (aod::femtodreamparticle::pt > ConfMinpT); /// Histogramming of selected tracks FemtoDreamParticleHisto trackHistoSelectedParts; + FemtoDreamParticleHisto trackHistoALLSelectedParts; /// V0 selection Configurable ConfPDGCodeV0{"ConfPDGCodeV0", 3122, "V0 PDG code"}; @@ -111,6 +119,9 @@ struct femtoDreamTripletTaskTrackTrackV0 { FemtoDreamParticleHisto particleHistoSelectedV0s; FemtoDreamParticleHisto particleHistoPosChild; FemtoDreamParticleHisto particleHistoNegChild; + FemtoDreamParticleHisto particleHistoALLSelectedV0s; + FemtoDreamParticleHisto particleHistoALLPosChild; + FemtoDreamParticleHisto particleHistoALLNegChild; /// Histogramming for Event FemtoDreamEventHisto eventHisto; @@ -120,8 +131,8 @@ struct femtoDreamTripletTaskTrackTrackV0 { ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (track)"}; ConfigurableAxis ConfTempFitVarBinsV0{"ConfTempFitVarBinsV0", {300, 0.9, 1}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0)"}; ConfigurableAxis ConfTempFitVarBinsV0Child{"ConfTempFitVarBinsV0Child", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0 child)"}; - ConfigurableAxis ConfTempFitVarpTV0Bins{"ConfTempFitVarpTV0Bins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0)"}; - ConfigurableAxis ConfTempFitVarpTV0Child{"ConfTempFitVarpTV0Child", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0 child)"}; + ConfigurableAxis ConfTempFitVarpTV0Bins{"ConfTempFitVarpTV0Bins", {35, 0, 6}, "pT binning of the pT vs. TempFitVar plot (V0)"}; + ConfigurableAxis ConfTempFitVarpTV0Child{"ConfTempFitVarpTV0Child", {35, 0, 6}, "pT binning of the pT vs. TempFitVar plot (V0 child)"}; ConfigurableAxis ConfInvMassBins{"ConfInvMassBins", {200, 1, 1.2}, "InvMass binning"}; /// Correlations @@ -131,6 +142,7 @@ struct femtoDreamTripletTaskTrackTrackV0 { 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 ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; @@ -142,8 +154,10 @@ struct femtoDreamTripletTaskTrackTrackV0 { FemtoDreamContainerThreeBody mixedEventCont; FemtoDreamPairCleaner pairCleanerTrackTrack; FemtoDreamPairCleaner pairCleanerTrackV0; - FemtoDreamDetaDphiStar pairCloseRejectionTrackTrack; - FemtoDreamDetaDphiStar pairCloseRejectionTrackV0; + FemtoDreamDetaDphiStar pairCloseRejectionTrackTrackSE; + FemtoDreamDetaDphiStar pairCloseRejectionTrackV0SE; + FemtoDreamDetaDphiStar pairCloseRejectionTrackTrackME; + FemtoDreamDetaDphiStar pairCloseRejectionTrackV0ME; /// Histogram output HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -154,12 +168,20 @@ struct femtoDreamTripletTaskTrackTrackV0 { eventHisto.init(&qaRegistry); trackHistoSelectedParts.init(&qaRegistry, ConfDummy, ConfDummy, ConfTempFitVarpTBins, ConfDummy, ConfDummy, ConfTempFitVarBinsTrack, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePart); + trackHistoALLSelectedParts.init(&qaRegistry, ConfDummy, ConfDummy, ConfTempFitVarpTBins, ConfDummy, ConfDummy, ConfTempFitVarBinsTrack, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePart); particleHistoSelectedV0s.init(&qaRegistry, ConfDummy, ConfDummy, ConfTempFitVarpTV0Bins, ConfDummy, ConfDummy, ConfTempFitVarBinsV0, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfInvMassBins, ConfIsMC, ConfPDGCodeV0); particleHistoPosChild.init(&qaRegistry, ConfDummy, ConfDummy, ConfTempFitVarpTV0Child, ConfDummy, ConfDummy, ConfTempFitVarBinsV0Child, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, 0); particleHistoNegChild.init(&qaRegistry, ConfDummy, ConfDummy, ConfTempFitVarpTV0Child, ConfDummy, ConfDummy, ConfTempFitVarBinsV0Child, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, 0); + particleHistoALLSelectedV0s.init(&qaRegistry, ConfDummy, ConfDummy, ConfTempFitVarpTV0Bins, ConfDummy, ConfDummy, ConfTempFitVarBinsV0, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfInvMassBins, ConfIsMC, ConfPDGCodeV0); + particleHistoALLPosChild.init(&qaRegistry, ConfDummy, ConfDummy, ConfTempFitVarpTV0Child, ConfDummy, ConfDummy, ConfTempFitVarBinsV0Child, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, 0); + particleHistoALLNegChild.init(&qaRegistry, ConfDummy, ConfDummy, ConfTempFitVarpTV0Child, ConfDummy, ConfDummy, ConfTempFitVarBinsV0Child, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, 0); 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/hMinvSE", ";Q_{3};M_{inv}", kTH2F, {ConfQ3Bins, ConfInvMassBins}); + ThreeBodyQARegistry.add("TripletTaskQA/hMinvME", ";Q_{3};M_{inv}", kTH2F, {ConfQ3Bins, ConfInvMassBins}); + ThreeBodyQARegistry.add("TripletTaskQA/particle_pT_in_Triplet_SE", "; p_{T1} ; p_{T2} ; p_{T3} ; Q_{3}", kTHnSparseF, {ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfTempFitVarpTV0Bins, ConfQ3BinsFor4D}); + ThreeBodyQARegistry.add("TripletTaskQA/particle_pT_in_Triplet_ME", "; p_{T1} ; p_{T2} ; p_{T3} ; Q_{3}", kTHnSparseF, {ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfTempFitVarpTV0Bins, ConfQ3BinsFor4D}); std::vector tmpVecMult = ConfMultBins; framework::AxisSpec multAxis = {tmpVecMult, "Multiplicity"}; ThreeBodyQARegistry.add("TripletTaskQA/hSEMultVSGoodTracks", ";Mult;GoodT", kTH2F, {multAxis, {100, 0, 100}}); @@ -172,10 +194,17 @@ struct femtoDreamTripletTaskTrackTrackV0 { pairCleanerTrackTrack.init(&qaRegistry); pairCleanerTrackV0.init(&qaRegistry); if (ConfIsCPR.value) { - pairCloseRejectionTrackTrack.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); - pairCloseRejectionTrackV0.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); + pairCloseRejectionTrackTrackSE.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 1, ConfUseOLD_possiblyWrong_CPR); + pairCloseRejectionTrackV0SE.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 1, ConfUseOLD_possiblyWrong_CPR); + pairCloseRejectionTrackTrackME.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 2, ConfUseOLD_possiblyWrong_CPR); + pairCloseRejectionTrackV0ME.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 2, ConfUseOLD_possiblyWrong_CPR); } + // get masses + mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePart)->Mass(); + mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePart)->Mass(); + mMassThree = TDatabasePDG::Instance()->GetParticle(ConfPDGCodeV0)->Mass(); + // get bit for the collision mask std::bitset<8 * sizeof(aod::femtodreamcollision::BitMaskType)> mask; int index = 0; @@ -187,6 +216,7 @@ struct femtoDreamTripletTaskTrackTrackV0 { 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, "ConfCutV0", ConfCutV0.value) && containsNameValuePair(device.options, "Conf_ChildPos_CutV0", Conf_ChildPos_CutV0.value) && containsNameValuePair(device.options, "Conf_ChildPos_TPCBitV0", Conf_ChildPos_TPCBitV0.value) && @@ -250,10 +280,6 @@ struct femtoDreamTripletTaskTrackTrackV0 { const auto& posChild = parts.iteratorAt(V0.index() - 2); const auto& negChild = parts.iteratorAt(V0.index() - 1); - particleHistoSelectedV0s.fillQA(V0, aod::femtodreamparticle::kPt, multCol, centCol); - particleHistoPosChild.fillQA(posChild, aod::femtodreamparticle::kPt, multCol, centCol); - particleHistoNegChild.fillQA(negChild, aod::femtodreamparticle::kPt, multCol, centCol); - if (((posChild.cut() & Conf_ChildPos_CutV0) == Conf_ChildPos_CutV0 && (posChild.pidcut() & Conf_ChildPos_TPCBitV0) == Conf_ChildPos_TPCBitV0 && (negChild.cut() & Conf_ChildNeg_CutV0) == Conf_ChildNeg_CutV0 && @@ -279,13 +305,13 @@ struct femtoDreamTripletTaskTrackTrackV0 { // Close pair rejection if (ConfIsCPR.value) { - if (pairCloseRejectionTrackTrack.isClosePair(T1, T2, parts, magFieldTesla)) { + if (pairCloseRejectionTrackTrackSE.isClosePair(T1, T2, parts, magFieldTesla)) { continue; } - if (pairCloseRejectionTrackV0.isClosePair(T1, V0, parts, magFieldTesla)) { + if (pairCloseRejectionTrackV0SE.isClosePair(T1, V0, parts, magFieldTesla)) { continue; } - if (pairCloseRejectionTrackV0.isClosePair(T2, V0, parts, magFieldTesla)) { + if (pairCloseRejectionTrackV0SE.isClosePair(T2, V0, parts, magFieldTesla)) { continue; } } @@ -300,7 +326,11 @@ struct femtoDreamTripletTaskTrackTrackV0 { if (!pairCleanerTrackV0.isCleanPair(T1, V0, parts)) { continue; } - sameEventCont.setTriplet(T1, T2, V0, multCol); + // fill inv Mass as a function of Q3 for purity fits + auto Q3 = FemtoDreamMath::getQ3(T1, mMassOne, T2, mMassTwo, V0, mMassThree); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMinvSE"), Q3, V0.mLambda()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_SE"), T1.pt(), T2.pt(), V0.pt(), Q3); + sameEventCont.setTriplet(T1, T2, V0, multCol, Q3); } } } @@ -313,7 +343,23 @@ struct femtoDreamTripletTaskTrackTrackV0 { { fillCollision(col); auto thegroupSelectedTracks = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupSelectedV0s = SelectedV0s->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedTracks) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + auto thegroupSelectedV0s = SelectedV0s->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); /// Histograming V0s + for (auto& V0 : thegroupSelectedV0s) { + const auto& posChild = parts.iteratorAt(V0.index() - 2); + const auto& negChild = parts.iteratorAt(V0.index() - 1); + + if (((posChild.cut() & Conf_ChildPos_CutV0) == Conf_ChildPos_CutV0 && + (posChild.pidcut() & Conf_ChildPos_TPCBitV0) == Conf_ChildPos_TPCBitV0 && + (negChild.cut() & Conf_ChildNeg_CutV0) == Conf_ChildNeg_CutV0 && + (negChild.pidcut() & Conf_ChildNeg_TPCBitV0) == Conf_ChildNeg_TPCBitV0)) { + particleHistoALLSelectedV0s.fillQA(V0, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + particleHistoALLPosChild.fillQA(posChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + particleHistoALLNegChild.fillQA(negChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + } if (thegroupSelectedTracks.size() < 2 || thegroupSelectedV0s.size() < 1) { return; } @@ -328,7 +374,23 @@ struct femtoDreamTripletTaskTrackTrackV0 { { fillCollision(col); auto thegroupSelectedTracks = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedTracks) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } auto thegroupSelectedV0s = SelectedV0s->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& V0 : thegroupSelectedV0s) { + const auto& posChild = parts.iteratorAt(V0.index() - 2); + const auto& negChild = parts.iteratorAt(V0.index() - 1); + + if (((posChild.cut() & Conf_ChildPos_CutV0) == Conf_ChildPos_CutV0 && + (posChild.pidcut() & Conf_ChildPos_TPCBitV0) == Conf_ChildPos_TPCBitV0 && + (negChild.cut() & Conf_ChildNeg_CutV0) == Conf_ChildNeg_CutV0 && + (negChild.pidcut() & Conf_ChildNeg_TPCBitV0) == Conf_ChildNeg_TPCBitV0)) { + particleHistoALLSelectedV0s.fillQA(V0, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + particleHistoALLPosChild.fillQA(posChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + particleHistoALLNegChild.fillQA(negChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + } if (thegroupSelectedTracks.size() < 2 || thegroupSelectedV0s.size() < 1) { return; } @@ -346,7 +408,23 @@ struct femtoDreamTripletTaskTrackTrackV0 { { fillCollision(col); auto thegroupSelectedTracks = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedTracks) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } auto thegroupSelectedV0s = SelectedV0sMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& V0 : thegroupSelectedV0s) { + const auto& posChild = parts.iteratorAt(V0.index() - 2); + const auto& negChild = parts.iteratorAt(V0.index() - 1); + + if (((posChild.cut() & Conf_ChildPos_CutV0) == Conf_ChildPos_CutV0 && + (posChild.pidcut() & Conf_ChildPos_TPCBitV0) == Conf_ChildPos_TPCBitV0 && + (negChild.cut() & Conf_ChildNeg_CutV0) == Conf_ChildNeg_CutV0 && + (negChild.pidcut() & Conf_ChildNeg_TPCBitV0) == Conf_ChildNeg_TPCBitV0)) { + particleHistoALLSelectedV0s.fillQA(V0, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + particleHistoALLPosChild.fillQA(posChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + particleHistoALLNegChild.fillQA(negChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + } if (thegroupSelectedTracks.size() < 2 || thegroupSelectedV0s.size() < 1) { return; } @@ -364,7 +442,23 @@ struct femtoDreamTripletTaskTrackTrackV0 { { fillCollision(col); auto thegroupSelectedTracks = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedTracks) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } auto thegroupSelectedV0s = SelectedV0sMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& V0 : thegroupSelectedV0s) { + const auto& posChild = parts.iteratorAt(V0.index() - 2); + const auto& negChild = parts.iteratorAt(V0.index() - 1); + + if (((posChild.cut() & Conf_ChildPos_CutV0) == Conf_ChildPos_CutV0 && + (posChild.pidcut() & Conf_ChildPos_TPCBitV0) == Conf_ChildPos_TPCBitV0 && + (negChild.cut() & Conf_ChildNeg_CutV0) == Conf_ChildNeg_CutV0 && + (negChild.pidcut() & Conf_ChildNeg_TPCBitV0) == Conf_ChildNeg_TPCBitV0)) { + particleHistoALLSelectedV0s.fillQA(V0, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + particleHistoALLPosChild.fillQA(posChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + particleHistoALLNegChild.fillQA(negChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + } if (thegroupSelectedTracks.size() < 2 || thegroupSelectedV0s.size() < 1) { return; } @@ -398,17 +492,21 @@ struct femtoDreamTripletTaskTrackTrackV0 { // Close pair rejection if (ConfIsCPR.value) { - if (pairCloseRejectionTrackTrack.isClosePair(T1, T2, parts, magFieldTesla)) { + if (pairCloseRejectionTrackTrackME.isClosePair(T1, T2, parts, magFieldTesla)) { continue; } - if (pairCloseRejectionTrackV0.isClosePair(T1, V0, parts, magFieldTesla)) { + if (pairCloseRejectionTrackV0ME.isClosePair(T1, V0, parts, magFieldTesla)) { continue; } - if (pairCloseRejectionTrackV0.isClosePair(T2, V0, parts, magFieldTesla)) { + if (pairCloseRejectionTrackV0ME.isClosePair(T2, V0, parts, magFieldTesla)) { continue; } } - mixedEventCont.setTriplet(T1, T2, V0, multCol); + // fill inv Mass as a function of Q3 for purity fits + auto Q3 = FemtoDreamMath::getQ3(T1, mMassOne, T2, mMassTwo, V0, mMassThree); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMinvME"), Q3, V0.mLambda()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_ME"), T1.pt(), T2.pt(), V0.pt(), Q3); + mixedEventCont.setTriplet(T1, T2, V0, multCol, Q3); } } diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h index 1297f1034c3..f35642ad2e8 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h @@ -291,7 +291,7 @@ class FemtoUniverseDetaDphiStar auto indexOfDaughter = part2.index() - 2 + i; auto daughter = particles.begin() + indexOfDaughter; auto deta = part1.eta() - daughter.eta(); - auto dphiAvg = CalculateDphiStar(part1, *daughter); + auto dphiAvg = AveragePhiStar(part1, *daughter, i); // CalculateDphiStar(part1, *daughter); dphiAvg = TVector2::Phi_mpi_pi(dphiAvg); if (ChosenEventType == femtoUniverseContainer::EventType::same) { histdetadpisame[i][0]->Fill(deta, dphiAvg); diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx index e911d95d81a..c9e4b4e9f7c 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx @@ -61,6 +61,12 @@ struct femtoUniversePairTaskTrackPhi { SliceCache cache; Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiCut{"ConfCPRdeltaPhiCut", 0.01, "Delta Phi cut for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaCut{"ConfCPRdeltaEtaCut", 0.004, "Delta Eta cut for Close Pair Rejection"}; + Configurable ConfCPRChosenRadii{"ConfCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; + /// Table for both particles struct : o2::framework::ConfigurableGroup { Configurable ConfNsigmaCombinedProton{"ConfNsigmaCombinedProton", 3.0, "TPC and TOF Proton Sigma (combined) for momentum > 0.5"}; @@ -81,7 +87,6 @@ struct femtoUniversePairTaskTrackPhi { struct : o2::framework::ConfigurableGroup { Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; Configurable ConfPDGCodeTrack{"ConfPDGCodeTrack", 2212, "Particle 2 - PDG code"}; - // Configurable ConfCutTrack{"ConfCutTrack", 5542474, "Particle 2 - Selection bit"}; Configurable ConfPIDTrack{"ConfPIDTrack", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> Configurable ConfTrackSign{"ConfTrackSign", 1, "Track sign"}; Configurable ConfIsTrackIdentified{"ConfIsTrackIdentified", true, "Enable PID for the track"}; @@ -90,10 +95,7 @@ struct femtoUniversePairTaskTrackPhi { /// Particle 2 --- PHI struct : o2::framework::ConfigurableGroup { Configurable ConfPDGCodePhi{"ConfPDGCodePhi", 333, "Phi meson - PDG code"}; - // Configurable ConfCutPhi{"ConfCutPhi", 5542474, "Phi meson - Selection bit from cutCulator"}; Configurable ConfPIDPhi{"ConfPIDPhi", 2, "Phi meson - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> - // Configurable ConfPtLowPhi{"ConfPtLowPhi", 0.5, "Lower limit for Pt for the Phi meson"}; // change according to wrzesa cuts - // Configurable ConfPtHighPhi{"ConfPtHighPhi", 1.5, "Higher limit for Pt for the Phi meson"}; } ConfPhi; /// Partitions for particle 1 @@ -128,7 +130,6 @@ struct femtoUniversePairTaskTrackPhi { /// Correlation part ConfigurableAxis ConfMultBins{"ConfMultBins", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; // \todo to be obtained from the hash task - // ConfigurableAxis ConfMultBins{"CfgMultBins", {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"}; 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)"}; 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)"}; @@ -138,11 +139,6 @@ struct femtoUniversePairTaskTrackPhi { ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; - Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; - Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; - Configurable ConfCPRdeltaPhiCut{"ConfCPRdeltaPhiCut", 0.01, "Delta Phi cut for Close Pair Rejection"}; - Configurable ConfCPRdeltaEtaCut{"ConfCPRdeltaEtaCut", 0.004, "Delta Eta cut for Close Pair Rejection"}; - Configurable ConfCPRChosenRadii{"ConfCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; FemtoUniverseFemtoContainer sameEventFemtoCont; FemtoUniverseFemtoContainer mixedEventFemtoCont; @@ -160,13 +156,6 @@ struct femtoUniversePairTaskTrackPhi { // PID for protons bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx { - //|nsigma_TPC| < 3 for p < 0.5 GeV/c - //|nsigma_combined| < 3 for p > 0.5 - - // using configurables: - // ConfNsigmaTPCProton -> TPC Kaon Sigma for momentum < 0.5 - // ConfNsigmaCombinedProton -> TPC and TOF Kaon Sigma (combined) for momentum > 0.5 - if (mom < 0.5) { if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaTPCProton) { return true; @@ -175,7 +164,6 @@ struct femtoUniversePairTaskTrackPhi { } } else if (mom > 0.4) { if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfNsigmaCombinedProton) { - // if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaCombinedProton) { return true; } else { return false; @@ -225,12 +213,6 @@ struct femtoUniversePairTaskTrackPhi { bool IsPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) { - //|nsigma_TPC| < 3 for p < 0.5 GeV/c - //|nsigma_combined| < 3 for p > 0.5 - - // using configurables: - // ConfNsigmaTPCPion -> TPC Kaon Sigma for momentum < 0.5 - // ConfNsigmaCombinedPion -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 if (true) { if (mom < 0.5) { if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfNsigmaTPCPion) { @@ -240,7 +222,6 @@ struct femtoUniversePairTaskTrackPhi { } } else if (mom > 0.5) { if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfNsigmaCombinedPion) { - // if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfNsigmaCombinedPion) { return true; } else { return false; diff --git a/PWGCF/TableProducer/dptdptfilter.cxx b/PWGCF/TableProducer/dptdptfilter.cxx index 9907c3be9d3..7d980b3f542 100644 --- a/PWGCF/TableProducer/dptdptfilter.cxx +++ b/PWGCF/TableProducer/dptdptfilter.cxx @@ -518,7 +518,7 @@ struct DptDptFilterTracks { Configurable cfgTrackType{"trktype", 4, "Type of selected tracks: 0 = no selection;1 = Run2 global tracks FB96;3 = Run3 tracks;4 = Run3 tracks MM sel;5 = Run2 TPC only tracks;7 = Run 3 TPC only tracks;30-33 = any/two on 3 ITS,any/all in 7 ITS;40-43 same as 30-33 w tighter DCAxy;50-53 w tighter pT DCAz. Default 4"}; Configurable cfgTraceDCAOutliers{"trackdcaoutliers", {false, 0.0, 0.0}, "Track the generator level DCAxy outliers: false/true, low dcaxy, up dcaxy. Default {false,0.0,0.0}"}; Configurable cfgTraceOutOfSpeciesParticles{"trackoutparticles", false, "Track the particles which are not e,mu,pi,K,p: false/true. Default false"}; - Configurable cfgRecoIdMethod{"recoidmethod", 0, "Method for identifying reconstructed tracks: 0 No PID, 1 PID, 2 mcparticle, 3 mcparticle only primaries. Default 0"}; + Configurable cfgRecoIdMethod{"recoidmethod", 0, "Method for identifying reconstructed tracks: 0 No PID, 1 PID, 2 mcparticle, 3 mcparticle only primaries, 4 mcparticle only sec, 5 mcparicle only sec from decays, 6 mcparticle only sec from material. Default 0"}; Configurable cfgTuneTrackSelection{"tunetracksel", {}, "Track selection: {useit: true/false, tpccls-useit, tpcxrws-useit, tpcxrfc-useit, dcaxy-useit, dcaz-useit}. Default {false,0.70,false,0.8,false,2.4,false,3.2,false}"}; Configurable cfgPionPIDSelection{"pipidsel", {}, @@ -838,6 +838,12 @@ struct DptDptFilterTracks { int8_t identifyParticle(ParticleObject const& particle); template int8_t identifyPrimaryParticle(ParticleObject const& particle); + template + int8_t identifySecondaryParticle(ParticleObject const& particle); + template + int8_t identifySecFromDecayParticle(ParticleObject const& particle); + template + int8_t identifySecFromMaterialParticle(ParticleObject const& particle); template int8_t selectParticle(ParticleObject const& particle, MCCollisionObject const& mccollision); template @@ -1048,12 +1054,26 @@ int8_t DptDptFilterTracks::trackIdentification(TrackObject const& track) } else { LOGF(fatal, "Track identification required but PID information not present"); } - } else if (recoIdMethod == 2 || recoIdMethod == 3) { + } else { if constexpr (framework::has_type_v) { - if (recoIdMethod == 2) { - sp = identifyParticle(track.template mcParticle_as()); - } else { - sp = identifyPrimaryParticle(track.template mcParticle_as()); + switch (recoIdMethod) { + case 2: + sp = identifyParticle(track.template mcParticle_as()); + break; + case 3: + sp = identifyPrimaryParticle(track.template mcParticle_as()); + break; + case 4: + sp = identifySecondaryParticle(track.template mcParticle_as()); + break; + case 5: + sp = identifySecFromDecayParticle(track.template mcParticle_as()); + break; + case 6: + sp = identifySecFromMaterialParticle(track.template mcParticle_as()); + break; + default: + LOGF(fatal, "Track identification method %d not recognized. Fix it!", recoIdMethod); } } else { LOGF(fatal, "Track identification required from MC particle but MC information not present"); @@ -1200,6 +1220,27 @@ inline int8_t DptDptFilterTracks::identifyPrimaryParticle(ParticleObject const& return pidselector.whichTruthPrimarySpecies(particle); } +template +inline int8_t DptDptFilterTracks::identifySecondaryParticle(ParticleObject const& particle) +{ + using namespace dptdptfilter; + return pidselector.whichTruthSecondarySpecies(particle); +} + +template +inline int8_t DptDptFilterTracks::identifySecFromDecayParticle(ParticleObject const& particle) +{ + using namespace dptdptfilter; + return pidselector.whichTruthSecFromDecaySpecies(particle); +} + +template +inline int8_t DptDptFilterTracks::identifySecFromMaterialParticle(ParticleObject const& particle) +{ + using namespace dptdptfilter; + return pidselector.whichTruthSecFromMaterialSpecies(particle); +} + template inline int8_t DptDptFilterTracks::selectParticle(ParticleObject const& particle, MCCollisionObject const& mccollision) { @@ -1212,6 +1253,7 @@ inline int8_t DptDptFilterTracks::selectParticle(ParticleObject const& particle, /* track selection */ if (AcceptParticle(particle, mccollision)) { /* the particle has been accepted */ + /* the particle is only accepted if it is a primary particle */ /* let's identify the particle */ sp = identifyParticle(particle); if (!(sp < 0)) { diff --git a/PWGCF/TableProducer/dptdptfilter.h b/PWGCF/TableProducer/dptdptfilter.h index 957abc93c6e..128ebc94596 100644 --- a/PWGCF/TableProducer/dptdptfilter.h +++ b/PWGCF/TableProducer/dptdptfilter.h @@ -1158,6 +1158,36 @@ struct PIDSpeciesSelection { } } + template + int8_t whichTruthSecondarySpecies(ParticleObject part) + { + if (!(part.isPhysicalPrimary())) { + return whichTruthSpecies(part); + } else { + return -127; + } + } + + template + int8_t whichTruthSecFromDecaySpecies(ParticleObject part) + { + if (!(part.isPhysicalPrimary()) && (part.getProcess() == 4)) { + return whichTruthSpecies(part); + } else { + return -127; + } + } + + template + int8_t whichTruthSecFromMaterialSpecies(ParticleObject part) + { + if (!(part.isPhysicalPrimary()) && (part.getProcess() != 4)) { + return whichTruthSpecies(part); + } else { + return -127; + } + } + std::vector config; ///< the PID selection configuration of the species to include in the analysis std::vector species; ///< the species index of the species to include in the analysis std::vector configexclude; ///< the PID selection configuration of the species to exclude from the analysis diff --git a/PWGDQ/TableProducer/tableMaker.cxx b/PWGDQ/TableProducer/tableMaker.cxx index 908043b33e3..b5b52144b46 100644 --- a/PWGDQ/TableProducer/tableMaker.cxx +++ b/PWGDQ/TableProducer/tableMaker.cxx @@ -797,7 +797,7 @@ struct TableMaker { if (grpmag != nullptr) { o2::base::Propagator::initFieldFromGRP(grpmag); } - if (fPropMuon) { + if constexpr (static_cast(TMuonFillMap)) { VarManager::SetupMuonMagField(); } } @@ -1110,12 +1110,6 @@ struct TableMaker { muon.matchScoreMCHMFT(), muon.mchBitMap(), muon.midBitMap(), muon.midBoards(), muon.trackType(), VarManager::fgValues[VarManager::kMuonDCAx], VarManager::fgValues[VarManager::kMuonDCAy], muon.trackTime(), muon.trackTimeRes()); - } - - muonCov(VarManager::fgValues[VarManager::kX], VarManager::fgValues[VarManager::kY], VarManager::fgValues[VarManager::kZ], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kTgl], muon.sign() / VarManager::fgValues[VarManager::kPt], - VarManager::fgValues[VarManager::kMuonCXX], VarManager::fgValues[VarManager::kMuonCXY], VarManager::fgValues[VarManager::kMuonCYY], VarManager::fgValues[VarManager::kMuonCPhiX], VarManager::fgValues[VarManager::kMuonCPhiY], VarManager::fgValues[VarManager::kMuonCPhiPhi], - VarManager::fgValues[VarManager::kMuonCTglX], VarManager::fgValues[VarManager::kMuonCTglY], VarManager::fgValues[VarManager::kMuonCTglPhi], VarManager::fgValues[VarManager::kMuonCTglTgl], VarManager::fgValues[VarManager::kMuonC1Pt2X], VarManager::fgValues[VarManager::kMuonC1Pt2Y], - VarManager::fgValues[VarManager::kMuonC1Pt2Phi], VarManager::fgValues[VarManager::kMuonC1Pt2Tgl], VarManager::fgValues[VarManager::kMuonC1Pt21Pt2]); } else { muonExtra(muon.nClusters(), muon.pDca(), muon.rAtAbsorberEnd(), muon.chi2(), muon.chi2MatchMCHMID(), muon.chi2MatchMCHMFT(), @@ -1123,6 +1117,12 @@ struct TableMaker { muon.midBoards(), muon.trackType(), muon.fwdDcaX(), muon.fwdDcaY(), muon.trackTime(), muon.trackTimeRes()); } + + muonCov(VarManager::fgValues[VarManager::kX], VarManager::fgValues[VarManager::kY], VarManager::fgValues[VarManager::kZ], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kTgl], muon.sign() / VarManager::fgValues[VarManager::kPt], + VarManager::fgValues[VarManager::kMuonCXX], VarManager::fgValues[VarManager::kMuonCXY], VarManager::fgValues[VarManager::kMuonCYY], VarManager::fgValues[VarManager::kMuonCPhiX], VarManager::fgValues[VarManager::kMuonCPhiY], VarManager::fgValues[VarManager::kMuonCPhiPhi], + VarManager::fgValues[VarManager::kMuonCTglX], VarManager::fgValues[VarManager::kMuonCTglY], VarManager::fgValues[VarManager::kMuonCTglPhi], VarManager::fgValues[VarManager::kMuonCTglTgl], VarManager::fgValues[VarManager::kMuonC1Pt2X], VarManager::fgValues[VarManager::kMuonC1Pt2Y], + VarManager::fgValues[VarManager::kMuonC1Pt2Phi], VarManager::fgValues[VarManager::kMuonC1Pt2Tgl], VarManager::fgValues[VarManager::kMuonC1Pt21Pt2]); + } } } // end if constexpr (TMuonFillMap) } // end fullSkimming() diff --git a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx index 1db788266cb..204cb96bc42 100644 --- a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx +++ b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx @@ -465,7 +465,7 @@ DalitzEECut* o2::aod::pwgem::photon::dalitzeecuts::GetCut(const char* cutName) cut->SetMaxDcaZ(1.0); // for PID - cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly_lowB); + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly); cut->SetTOFbetaRange(true, 0.0, 0.95); cut->SetTPCNsigmaElRange(-3, +3); cut->SetTPCNsigmaPiRange(0, 0); @@ -540,14 +540,14 @@ DalitzEECut* o2::aod::pwgem::photon::dalitzeecuts::GetCut(const char* cutName) if (nameStr.find("mee") != std::string::npos) { // for electron if (nameStr.find("tpchadrejortofreq_lowB") != std::string::npos) { // for PID - cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq_lowB); + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); cut->SetTOFbetaRange(true, 0.0, 0.95); cut->SetTPCNsigmaElRange(-2, +3); - cut->SetTOFNsigmaElRange(-3, +3); cut->SetTPCNsigmaMuRange(-2, +2); cut->SetTPCNsigmaPiRange(-3, +3); cut->SetTPCNsigmaKaRange(-3, +3); cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetTOFNsigmaElRange(-3, +3); cut->SetMuonExclusionTPC(true); return cut; } else if (nameStr.find("tpchadrejortofreq") != std::string::npos) { @@ -562,7 +562,7 @@ DalitzEECut* o2::aod::pwgem::photon::dalitzeecuts::GetCut(const char* cutName) return cut; } else if (nameStr.find("tpconly_lowB") != std::string::npos) { // for PID - cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly_lowB); + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly); cut->SetTOFbetaRange(true, 0.0, 0.95); cut->SetTPCNsigmaElRange(-2, +3); cut->SetTPCNsigmaPiRange(-3, +3); @@ -574,6 +574,13 @@ DalitzEECut* o2::aod::pwgem::photon::dalitzeecuts::GetCut(const char* cutName) cut->SetTPCNsigmaElRange(-2, +3); cut->SetTPCNsigmaPiRange(-1e+10, +3); return cut; + } else if (nameStr.find("tpcelonly") != std::string::npos) { + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(0, 0); + return cut; } else { // not match electron cut LOGF(info, Form("Did not find electron ID cut %s", cutName)); return cut; diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.h b/PWGEM/PhotonMeson/Core/DalitzEECut.h index f79cda030eb..bd9ae51598e 100644 --- a/PWGEM/PhotonMeson/Core/DalitzEECut.h +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.h @@ -69,18 +69,11 @@ class DalitzEECut : public TNamed enum class PIDSchemes : int { kUnDef = -1, - // for nominal B analysis kTOFreq = 0, kTPChadrej = 1, kTPChadrejORTOFreq = 2, kTPConly = 3, - - // for low B analysis - kTOFreq_lowB = 4, - kTPChadrej_lowB = 5, - kTPChadrejORTOFreq_lowB = 6, - kTPConly_lowB = 7, - kMuon_lowB = 8, + kMuon_lowB = 4, }; template @@ -223,18 +216,6 @@ class DalitzEECut : public TNamed case PIDSchemes::kTPConly: return PassTPConly(track); - case PIDSchemes::kTOFreq_lowB: - return PassTOFreq(track); - - case PIDSchemes::kTPChadrej_lowB: - return PassTPChadrej_lowB(track); - - case PIDSchemes::kTPChadrejORTOFreq_lowB: - return PassTPChadrej_lowB(track) || PassTOFreq_lowB(track); - - case PIDSchemes::kTPConly_lowB: - return PassTPConly_lowB(track); - case PIDSchemes::kMuon_lowB: return PassMuon_lowB(track); @@ -274,34 +255,6 @@ class DalitzEECut : public TNamed return is_el_included_TPC && is_pi_excluded_TPC; } - template - bool PassTOFreq_lowB(T const& track) const - { - bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; - bool is_pi_excluded_TPC = track.tpcInnerParam() < 0.4 ? true : (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()); - bool is_el_included_TOF = mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl; - return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; - } - - template - bool PassTPChadrej_lowB(T const& track) const - { - bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; - bool is_mu_excluded_TPC = mMuonExclusionTPC ? track.tpcNSigmaMu() < mMinTPCNsigmaMu || mMaxTPCNsigmaMu < track.tpcNSigmaMu() : true; - bool is_pi_excluded_TPC = track.tpcInnerParam() < 0.4 ? true : (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()); - bool is_ka_excluded_TPC = track.tpcNSigmaKa() < mMinTPCNsigmaKa || mMaxTPCNsigmaKa < track.tpcNSigmaKa(); - bool is_pr_excluded_TPC = track.tpcNSigmaPr() < mMinTPCNsigmaPr || mMaxTPCNsigmaPr < track.tpcNSigmaPr(); - return is_el_included_TPC && is_mu_excluded_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC; - } - - template - bool PassTPConly_lowB(T const& track) const - { - bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; - bool is_pi_excluded_TPC = track.tpcInnerParam() < 0.4 ? true : (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()); - return is_el_included_TPC && is_pi_excluded_TPC; - } - template bool PassMuon_lowB(T const& track) const { diff --git a/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx b/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx index 020b2631d33..ec8f4376cdc 100644 --- a/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx +++ b/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx @@ -42,9 +42,10 @@ void o2::aod::pwgem::photon::histogram::DefineHistograms(THashList* list, const reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(4, "No Same Bunch Pileup"); reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(5, "Is Vertex ITSTPC"); reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(6, "Is Good Zvtx FT0vsPV"); - reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(7, "sel8"); - reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(8, "|Z_{vtx}| < 10 cm"); - reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(9, "accepted"); + reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(7, "FT0AND"); + reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(8, "sel8"); + reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(9, "|Z_{vtx}| < 10 cm"); + reinterpret_cast(list->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(10, "accepted"); list->Add(new TH1F("hZvtx", "vertex z; Z_{vtx} (cm)", 100, -50, +50)); list->Add(new TH1F("hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", 6001, -0.5, 6000.5)); @@ -403,12 +404,12 @@ void o2::aod::pwgem::photon::histogram::DefineHistograms(THashList* list, const } const int nmgg = 401; - float mgg[nmgg] = {}; + double mgg[nmgg] = {}; for (int i = 0; i < nmgg; i++) { mgg[i] = 0.002 * i; } const int npTgg = 71; - float pTgg[npTgg] = {}; + double pTgg[npTgg] = {}; for (int i = 0; i < 50; i++) { pTgg[i] = 0.1 * (i - 0) + 0.0; // from 0 to 5 GeV/c, every 0.1 GeV/c } @@ -527,12 +528,12 @@ void o2::aod::pwgem::photon::histogram::DefineHistograms(THashList* list, const } const int nmgg04 = 201; - float mgg04[nmgg04] = {}; + double mgg04[nmgg04] = {}; for (int i = 0; i < nmgg04; i++) { mgg04[i] = 0.002 * i; } const int npTgg10 = 61; - float pTgg10[npTgg10] = {}; + double pTgg10[npTgg10] = {}; for (int i = 0; i < 50; i++) { pTgg10[i] = 0.1 * (i - 0) + 0.0; // from 0 to 5 GeV/c, every 0.1 GeV/c } diff --git a/PWGEM/PhotonMeson/Core/HistogramsLibrary.h b/PWGEM/PhotonMeson/Core/HistogramsLibrary.h index fc8b64fce6a..fd277d6c0ca 100644 --- a/PWGEM/PhotonMeson/Core/HistogramsLibrary.h +++ b/PWGEM/PhotonMeson/Core/HistogramsLibrary.h @@ -73,6 +73,9 @@ void FillHistClass(THashList* list, const char* subGroup, T const& obj, const fl if (obj.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { reinterpret_cast(list->FindObject("hCollisionCounter"))->Fill("Is Good Zvtx FT0vsPV", 1.f); } + if (obj.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + reinterpret_cast(list->FindObject("hCollisionCounter"))->Fill("FT0AND", 1.f); + } if (obj.sel8()) { reinterpret_cast(list->FindObject("hCollisionCounter"))->Fill("sel8", 1.f); } diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index 7d8ab027175..070efd551df 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -141,7 +141,7 @@ namespace emmcparticle { DECLARE_SOA_INDEX_COLUMN(EMMCEvent, emmcevent); DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Mothers, mothers); //! Mother tracks (possible empty) array. Iterate over mcParticle.mothers_as()) -DECLARE_SOA_SELF_SLICE_INDEX_COLUMN(Daughters, daughters); //! Daughter tracks (possibly empty) slice. Check for non-zero with mcParticle.has_daughters(). Iterate over mcParticle.daughters_as()) +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Daughters, daughters); //! Daughter tracks (possibly empty) array. Check for non-zero with mcParticle.has_daughters(). Iterate over mcParticle.daughters_as()) DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) -> float { return RecoDecay::eta(std::array{px, py, pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float px, float py) -> float { return RecoDecay::phi(px, py); }); @@ -160,7 +160,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Y, y, //! Particle rapidity DECLARE_SOA_TABLE_FULL(EMMCParticles, "EMMCParticles", "AOD", "EMMCPARTICLE", //! MC track information (on disk) o2::soa::Index<>, emmcparticle::EMMCEventId, mcparticle::PdgCode, mcparticle::Flags, - emmcparticle::MothersIds, emmcparticle::DaughtersIdSlice, + emmcparticle::MothersIds, emmcparticle::DaughtersIds, mcparticle::Px, mcparticle::Py, mcparticle::Pz, mcparticle::E, mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, mcparticle::Vt, diff --git a/PWGEM/PhotonMeson/TableProducer/associateMCinfo.cxx b/PWGEM/PhotonMeson/TableProducer/associateMCinfo.cxx index 82f930fcd38..0387951b2ee 100644 --- a/PWGEM/PhotonMeson/TableProducer/associateMCinfo.cxx +++ b/PWGEM/PhotonMeson/TableProducer/associateMCinfo.cxx @@ -433,13 +433,15 @@ struct AssociateMCInfo { } } - // TODO: Check that the daughter slice in the skimmed table works as expected - // Note that not all daughters from the original table are preserved in the skimmed MC stack + // Note that not all daughters from the original table are preserved in the skimmed MC stack std::vector daughters; if (mctrack.has_daughters()) { + // LOGF(info, "daughter range in original MC stack pdg = %d | %d - %d , n dau = %d", mctrack.pdgCode(), mctrack.daughtersIds()[0], mctrack.daughtersIds()[1], mctrack.daughtersIds()[1] -mctrack.daughtersIds()[0] +1); for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { // TODO: remove this check as soon as issues with MC production are fixed if (d < mcTracks.size()) { // protect against bad daughter indices + // auto dau_tmp = mcTracks.iteratorAt(d); + // LOGF(info, "daughter pdg = %d", dau_tmp.pdgCode()); if (fNewLabels.find(d) != fNewLabels.end()) { daughters.push_back(fNewLabels.find(d)->second); } @@ -449,14 +451,9 @@ struct AssociateMCInfo { } } } - int daughterRange[2] = {-1, -1}; - if (daughters.size() > 0) { - daughterRange[0] = daughters[0]; - daughterRange[1] = daughters[daughters.size() - 1]; - } emmcparticles(fEventIdx.find(oldLabel)->second, mctrack.pdgCode(), mctrack.flags(), - mothers, daughterRange, + mothers, daughters, mctrack.px(), mctrack.py(), mctrack.pz(), mctrack.e(), mctrack.vx(), mctrack.vy(), mctrack.vz(), mctrack.vt()); } // end loop over labels diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx index d4266554f89..53aebf608e1 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx @@ -233,6 +233,19 @@ struct skimmerDalitzEE { } // end of collision loop } PROCESS_SWITCH(skimmerDalitzEE, processCEFP, "Process dalitz ee for CEFP", false); // for central event filter processing + + void processOnlyNee(soa::Join const& collisions) + { + for (auto& collision : collisions) { + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + event_nee(0, 0, 0); + continue; + } + event_nee(0, 0, 0); + } // end of collision loop + } + PROCESS_SWITCH(skimmerDalitzEE, processOnlyNee, "Process only nee", false); // for central event filter processing }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzMuMu.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzMuMu.cxx index d10e94417c9..25e21deebb0 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzMuMu.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzMuMu.cxx @@ -170,7 +170,7 @@ struct skimmerDalitzMuMu { Partition posTracks = minpt < o2::aod::track::pt && o2::aod::track::pt < maxpt && nabs(o2::aod::track::eta) < maxeta && o2::aod::emprimarymuon::sign > 0 && minTPCNsigmaMu < o2::aod::pidtpc::tpcNSigmaMu&& o2::aod::pidtpc::tpcNSigmaMu < maxTPCNsigmaMu; Partition negTracks = minpt < o2::aod::track::pt && o2::aod::track::pt < maxpt && nabs(o2::aod::track::eta) < maxeta && o2::aod::emprimarymuon::sign < 0 && minTPCNsigmaMu < o2::aod::pidtpc::tpcNSigmaMu && o2::aod::pidtpc::tpcNSigmaMu < maxTPCNsigmaMu; - void process(MyCollisions const& collisions, MyTracks const& tracks) + void processAnalysis(MyCollisions const& collisions, MyTracks const& tracks) { for (auto& collision : collisions) { float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; @@ -191,6 +191,20 @@ struct skimmerDalitzMuMu { event_nmumu(npair_uls, npair_lspp, npair_lsmm); } // end of collision loop } + PROCESS_SWITCH(skimmerDalitzMuMu, processAnalysis, "Process dalitz mumu for analysis", true); + + void processOnlyNmumu(soa::Join const& collisions) + { + for (auto& collision : collisions) { + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + event_nmumu(0, 0, 0); + continue; + } + event_nmumu(0, 0, 0); + } // end of collision loop + } + PROCESS_SWITCH(skimmerDalitzMuMu, processOnlyNmumu, "Process only nmumu", false); // for central event filter processing }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx index 0a8185b9593..837df7baf01 100644 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx @@ -262,10 +262,10 @@ struct MaterialBudgetMC { continue; } auto mcphoton = mcparticles.iteratorAt(photonid); - if (!IsConversionPointInAcceptance(mcphoton, maxRgen, maxY, margin_z_mc, mcparticles)) { + if (!(mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator())) { continue; } - if (!(mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator())) { + if (!IsConversionPointInAcceptance(mcphoton, maxRgen, maxY, margin_z_mc, mcparticles)) { continue; } diff --git a/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx b/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx index cb5bf61ba88..a8387dcd30b 100644 --- a/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx +++ b/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx @@ -43,7 +43,7 @@ using namespace o2::soa; using namespace o2::aod::photonpair; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -569,7 +569,7 @@ struct PhotonHBT { Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_subsys = (o2::aod::emevent::ngpcm >= 1); + Filter collisionFilter_subsys = ((o2::aod::emevent::ngpcm >= 1) && (o2::aod::emevent::neeuls >= 1)) || (o2::aod::emevent::ngpcm >= 2) || (o2::aod::emevent::neeuls >= 2); using MyFilteredCollisions = soa::Filtered; void processPCMPCM(MyCollisions const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs) diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx index 70243cf4b91..70e7ad7de48 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx @@ -47,7 +47,7 @@ using namespace o2::soa; using namespace o2::aod::photonpair; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -645,7 +645,7 @@ struct Pi0EtaToGammaGamma { Partition grouped_collisions = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); // this goes to same event. Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_subsys = (o2::aod::emevent::ngpcm >= 1) || (o2::aod::emevent::ngphos >= 1) || (o2::aod::emevent::ngemc >= 1); + Filter collisionFilter_subsys = (o2::aod::emevent::ngpcm >= 1) || (o2::aod::emevent::ngphos >= 1) || (o2::aod::emevent::ngemc >= 1) || (aod::emevent::neeuls >= 1); using MyFilteredCollisions = soa::Filtered; // this goes to mixed event. void processPCMPCM(MyCollisions const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs) diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx index dad9c961bcf..b10ef63cbc1 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx @@ -69,7 +69,7 @@ struct Pi0EtaToGammaGammaMC { Configurable maxY_track{"maxY_track", 0.9, "maximum rapidity for generated particles"}; // for PCM and dielectron Configurable minPhi_track{"minPhi_track", 0, "minimum azimuthal angle for generated particles"}; // for PCM and dielectron Configurable maxPhi_track{"maxPhi_track", 2 * M_PI, "maximum azimuthal angle for generated particles"}; // for PCM and dielectron - Configurable maxRgen{"maxRgen", 100.f, "maximum radius for generated particles"}; + Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; Configurable maxY_phos{"maxY_phos", 0.9, "maximum rapidity for generated particles"}; // for EMC @@ -466,22 +466,12 @@ struct Pi0EtaToGammaGammaMC { auto g1mc = mcparticles.iteratorAt(photonid1); auto g2mc = mcparticles.iteratorAt(photonid2); - if constexpr (pairtype == PairType::kPCMPCM) { - if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY_track, margin_z_mc, mcparticles)) { - continue; - } - if (!IsConversionPointInAcceptance(g2mc, maxRgen, maxY_track, margin_z_mc, mcparticles)) { - continue; - } - } - pi0id = FindCommonMotherFrom2Prongs(g1mc, g2mc, 22, 22, 111, mcparticles); etaid = FindCommonMotherFrom2Prongs(g1mc, g2mc, 22, 22, 221, mcparticles); if (pi0id < 0 && etaid < 0) { continue; } - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; @@ -492,12 +482,25 @@ struct Pi0EtaToGammaGammaMC { if (pi0id > 0) { auto pi0mc = mcparticles.iteratorAt(pi0id); if (pi0mc.isPhysicalPrimary() || pi0mc.producedByGenerator()) { + if constexpr (pairtype == PairType::kPCMPCM) { + if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY_track, margin_z_mc, mcparticles) || !IsConversionPointInAcceptance(g2mc, maxRgen, maxY_track, margin_z_mc, mcparticles)) { + continue; + } + } reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut.GetName(), cut.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_Primary"))->Fill(v12.M(), v12.Pt()); } else if (IsFromWD(pi0mc.emmcevent(), pi0mc, mcparticles)) { reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut.GetName(), cut.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_FromWD"))->Fill(v12.M(), v12.Pt()); } } else if (etaid > 0) { - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut.GetName(), cut.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Eta_Primary"))->Fill(v12.M(), v12.Pt()); + auto etamc = mcparticles.iteratorAt(etaid); + if (etamc.isPhysicalPrimary() || etamc.producedByGenerator()) { + if constexpr (pairtype == PairType::kPCMPCM) { + if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY_track, margin_z_mc, mcparticles) || !IsConversionPointInAcceptance(g2mc, maxRgen, maxY_track, margin_z_mc, mcparticles)) { + continue; + } + } + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut.GetName(), cut.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Eta_Primary"))->Fill(v12.M(), v12.Pt()); + } } } // end of combination } // end of paircutloop @@ -515,6 +518,9 @@ struct Pi0EtaToGammaGammaMC { continue; } + int photonid1 = -1; + int photonid2 = -1; + if constexpr (pairtype == PairType::kPCMPHOS || pairtype == PairType::kPCMEMC) { auto pos = g1.template posTrack_as(); auto ele = g1.template negTrack_as(); @@ -542,20 +548,14 @@ struct Pi0EtaToGammaGammaMC { auto ele2mc = ele2.template emmcparticle_as(); // LOGF(info,"pos1mc.globalIndex() = %d , ele1mc.globalIndex() = %d , pos2mc.globalIndex() = %d , ele2mc.globalIndex() = %d", pos1mc.globalIndex(), ele1mc.globalIndex(), pos2mc.globalIndex(), ele2mc.globalIndex()); - int photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); // real photon + photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); // real photon if (photonid1 < 0) { continue; } auto g1mc = mcparticles.iteratorAt(photonid1); - if constexpr (pairtype == PairType::kPCMDalitzEE || pairtype == kPCMDalitzMuMu) { - if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY_track, margin_z_mc, mcparticles)) { - continue; - } - } - - if (cut2.IsPhotonConversionSelected()) { // v0photon + photon conversion on ITSib stored in dielectron table. pi0 -> gamma gamma - int photonid2 = FindCommonMotherFrom2Prongs(pos2mc, ele2mc, -11, 11, 22, mcparticles); // photon conversion stored in dielectron table + if (cut2.IsPhotonConversionSelected()) { // v0photon + photon conversion on ITSib stored in dielectron table. pi0 -> gamma gamma + photonid2 = FindCommonMotherFrom2Prongs(pos2mc, ele2mc, -11, 11, 22, mcparticles); // photon conversion stored in dielectron table if (photonid2 < 0) { continue; } @@ -581,7 +581,7 @@ struct Pi0EtaToGammaGammaMC { auto ele2mc = ele2.template emmcparticle_as(); // LOGF(info,"pos1mc.globalIndex() = %d , ele1mc.globalIndex() = %d , pos2mc.globalIndex() = %d , ele2mc.globalIndex() = %d", pos1mc.globalIndex(), ele1mc.globalIndex(), pos2mc.globalIndex(), ele2mc.globalIndex()); - int photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); // real photon + photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); // real photon if (photonid1 < 0) { continue; } @@ -606,12 +606,27 @@ struct Pi0EtaToGammaGammaMC { if (pi0id > 0) { auto pi0mc = mcparticles.iteratorAt(pi0id); if (pi0mc.isPhysicalPrimary() || pi0mc.producedByGenerator()) { + if constexpr (pairtype == PairType::kPCMDalitzEE || pairtype == kPCMDalitzMuMu) { + auto g1mc = mcparticles.iteratorAt(photonid1); + if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY_track, margin_z_mc, mcparticles)) { + continue; + } + } reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_Primary"))->Fill(v12.M(), v12.Pt()); } else if (IsFromWD(pi0mc.emmcevent(), pi0mc, mcparticles)) { reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_FromWD"))->Fill(v12.M(), v12.Pt()); } } else if (etaid > 0) { - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Eta_Primary"))->Fill(v12.M(), v12.Pt()); + auto etamc = mcparticles.iteratorAt(etaid); + if (etamc.isPhysicalPrimary() || etamc.producedByGenerator()) { + if constexpr (pairtype == PairType::kPCMDalitzEE || pairtype == kPCMDalitzMuMu) { + auto g1mc = mcparticles.iteratorAt(photonid1); + if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY_track, margin_z_mc, mcparticles)) { + continue; + } + } + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Eta_Primary"))->Fill(v12.M(), v12.Pt()); + } } } // end of combination @@ -656,25 +671,6 @@ struct Pi0EtaToGammaGammaMC { } auto mccollision = collision.emmcevent(); - reinterpret_cast(list_gen_pair->FindObject("hZvtx_before"))->Fill(mccollision.posZ()); - reinterpret_cast(list_gen_pair->FindObject("hCollisionCounter"))->Fill(1.0); // all - if (!collision.sel8()) { - continue; - } - reinterpret_cast(list_gen_pair->FindObject("hCollisionCounter"))->Fill(2.0); // FT0VX i.e. FT0and - - if (collision.numContrib() < 0.5) { - continue; - } - reinterpret_cast(list_gen_pair->FindObject("hCollisionCounter"))->Fill(3.0); // Ncontrib > 0 - - if (abs(collision.posZ()) > 10.0) { - continue; - } - - reinterpret_cast(list_gen_pair->FindObject("hZvtx_after"))->Fill(mccollision.posZ()); - reinterpret_cast(list_gen_pair->FindObject("hCollisionCounter"))->Fill(4.0); // |Zvtx| < 10 cm - auto mctracks_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); for (auto& mctrack : mctracks_coll) { if (abs(mctrack.y()) > maxY_track) { diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx index eebf9b42a95..3a6e503e411 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx @@ -68,7 +68,7 @@ struct SinglePhotonMC { Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; - Configurable maxRgen{"maxRgen", 100.f, "maximum radius for generated particles"}; + Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis,qc,nocut", "Comma separated list of V0 photon cuts"}; @@ -327,13 +327,13 @@ struct SinglePhotonMC { } auto mcphoton = mcparticles.iteratorAt(photonid); - if constexpr (photontype == EMDetType::kPCM) { - if (!IsConversionPointInAcceptance(mcphoton, maxRgen, maxY, margin_z_mc, mcparticles)) { - continue; - } - } if (mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator()) { + if constexpr (photontype == EMDetType::kPCM) { + if (!IsConversionPointInAcceptance(mcphoton, maxRgen, maxY, margin_z_mc, mcparticles)) { + continue; + } + } reinterpret_cast(list_photon_det_cut->FindObject("hPt_Photon_Primary"))->Fill(v1.Pt()); reinterpret_cast(list_photon_det_cut->FindObject("hY_Photon_Primary"))->Fill(v1.Rapidity()); reinterpret_cast(list_photon_det_cut->FindObject("hPhi_Photon_Primary"))->Fill(v1.Phi() < 0.0 ? v1.Phi() + TMath::TwoPi() : v1.Phi()); diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx index fb6608d7741..760d32da86d 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx @@ -453,7 +453,7 @@ struct TaggingPi0 { Partition grouped_collisions = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); // this goes to same event. Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_subsys = (o2::aod::emevent::ngpcm >= 1) || (o2::aod::emevent::ngphos >= 1) || (o2::aod::emevent::ngemc >= 1); + Filter collisionFilter_subsys = (o2::aod::emevent::ngpcm >= 1) && ((o2::aod::emevent::ngphos >= 1) || (o2::aod::emevent::ngemc >= 1) || (o2::aod::emevent::neeuls >= 1)); using MyFilteredCollisions = soa::Filtered; Filter DalitzEEFilter = o2::aod::dalitzee::sign == 0; // analyze only uls diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx index 38ebda09326..d1c0b01e3d6 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx @@ -64,7 +64,7 @@ struct TaggingPi0MC { Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; - Configurable maxRgen{"maxRgen", 100.f, "maximum radius for generated particles"}; + Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; Configurable fConfigPCMCuts{"cfgPCMCuts", "qc", "Comma separated list of V0 photon cuts"}; @@ -363,9 +363,6 @@ struct TaggingPi0MC { continue; } auto mcphoton1 = mcparticles.iteratorAt(photonid1); - if (!IsConversionPointInAcceptance(mcphoton1, maxRgen, maxY, margin_z_mc, mcparticles)) { - continue; - } int pi0id1 = IsXFromY(mcphoton1, mcparticles, 22, 111); if (pi0id1 < 0) { // photon from pi0 decay @@ -378,6 +375,9 @@ struct TaggingPi0MC { // mcphoton1.isPhysicalPrimary(), mcphoton1.producedByGenerator(), mcpi01.isPhysicalPrimary(), mcpi01.producedByGenerator()); if (mcpi01.isPhysicalPrimary() || mcpi01.producedByGenerator()) { + if (!IsConversionPointInAcceptance(mcphoton1, maxRgen, maxY, margin_z_mc, mcparticles)) { + continue; + } reinterpret_cast(list_pcm->FindObject(cut1.GetName())->FindObject("hPt_v0photon_Pi0_Primary"))->Fill(g1.pt()); } else if (IsFromWD(mcpi01.emmcevent(), mcpi01, mcparticles)) { reinterpret_cast(list_pcm->FindObject(cut1.GetName())->FindObject("hPt_v0photon_Pi0_FromWD"))->Fill(g1.pt()); @@ -422,9 +422,6 @@ struct TaggingPi0MC { } auto g1mc = mcparticles.iteratorAt(photonid1); - if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY, margin_z_mc, mcparticles)) { - continue; - } int pi0id = -1; if constexpr (pairtype == PairType::kPCMDalitzEE) { @@ -454,6 +451,9 @@ struct TaggingPi0MC { if (pi0id > 0) { auto mcpi0 = mcparticles.iteratorAt(pi0id); if (mcpi0.isPhysicalPrimary() || mcpi0.producedByGenerator()) { + if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY, margin_z_mc, mcparticles)) { + continue; + } reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_Primary"))->Fill(v12.M(), v1.Pt()); } else if (IsFromWD(mcpi0.emmcevent(), mcpi0, mcparticles)) { reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_FromWD"))->Fill(v12.M(), v1.Pt()); diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index 70084c278b6..174e4a0216f 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -65,7 +65,7 @@ struct PCMQCMC { Configurable fConfigPCMCuts{"cfgPCMCuts", "qc,qc_ITSTPC,qc_ITSonly,qc_TPConly,wwire_ib,nocut", "Comma separated list of v0 photon cuts"}; Configurable maxY{"maxY", 0.9f, "maximum rapidity for generated particles"}; - Configurable maxRgen{"maxRgen", 100.f, "maximum radius for generated particles"}; + Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; std::vector fPCMCuts; @@ -186,6 +186,8 @@ struct PCMQCMC { auto posmc = pos.template emmcparticle_as(); auto elemc = ele.template emmcparticle_as(); + // LOGF(info, "posmc.isPhysicalPrimary() = %d, posmc.producedByGenerator() = %d, elemc.isPhysicalPrimary() = %d, elemc.producedByGenerator() = %d", posmc.isPhysicalPrimary(), posmc.producedByGenerator(), elemc.isPhysicalPrimary(), elemc.producedByGenerator()); + if (cut.IsSelected(v0)) { reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPt_Photon_Candidate"))->Fill(v0.pt()); reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEtaPhi_Photon_Candidate"))->Fill(v0.phi(), v0.eta()); @@ -195,9 +197,6 @@ struct PCMQCMC { continue; } auto mcphoton = mcparticles.iteratorAt(photonid); - if (!IsConversionPointInAcceptance(mcphoton, maxRgen, maxY, margin_z_mc, mcparticles)) { - continue; - } float rxy_rec = sqrt(v0.vx() * v0.vx() + v0.vy() * v0.vy()); float rxy_mc = sqrt(posmc.vx() * posmc.vx() + posmc.vy() * posmc.vy()); @@ -205,31 +204,33 @@ struct PCMQCMC { o2::aod::pwgem::photon::histogram::FillHistClass(list_v0_cut, "", v0); if (mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator()) { - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPt_Photon_Primary"))->Fill(v0.pt()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEtaPhi_Photon_Primary"))->Fill(v0.phi(), v0.eta()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hXY_Photon_Primary"))->Fill(v0.vx(), v0.vy()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hXY_Photon_Primary_MC"))->Fill(posmc.vx(), posmc.vy()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hRZ_Photon_Primary"))->Fill(v0.vz(), rxy_rec); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hRZ_Photon_Primary_MC"))->Fill(posmc.vz(), rxy_mc); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hCosPA_Rxy_Photon_Primary"))->Fill(v0.v0radius(), v0.cospa()); - - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaPtOverPtGen"))->Fill(mcphoton.pt(), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaEta"))->Fill(mcphoton.pt(), v0.eta() - mcphoton.eta()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaPhi"))->Fill(mcphoton.pt(), v0.phi() - mcphoton.phi()); - - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaPtOverPtGen"))->Fill(eta_cp, (v0.pt() - mcphoton.pt()) / mcphoton.pt()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaEta"))->Fill(eta_cp, v0.eta() - mcphoton.eta()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaPhi"))->Fill(eta_cp, v0.phi() - mcphoton.phi()); - - for (auto& leg : {pos, ele}) { - o2::aod::pwgem::photon::histogram::FillHistClass(list_v0leg_cut, "", leg); - auto mcleg = leg.template emmcparticle_as(); - reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaPtOverPtGen"))->Fill(mcleg.pt(), (leg.pt() - mcleg.pt()) / mcleg.pt()); - reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaEta"))->Fill(mcleg.pt(), leg.eta() - mcleg.eta()); - reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaPhi"))->Fill(mcleg.pt(), leg.phi() - mcleg.phi()); - reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaPtOverPtGen"))->Fill(eta_cp, (leg.pt() - mcleg.pt()) / mcleg.pt()); - reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaEta"))->Fill(eta_cp, leg.eta() - mcleg.eta()); - reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaPhi"))->Fill(eta_cp, leg.phi() - mcleg.phi()); + if (IsConversionPointInAcceptance(mcphoton, maxRgen, maxY, margin_z_mc, mcparticles)) { + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPt_Photon_Primary"))->Fill(v0.pt()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEtaPhi_Photon_Primary"))->Fill(v0.phi(), v0.eta()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hXY_Photon_Primary"))->Fill(v0.vx(), v0.vy()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hXY_Photon_Primary_MC"))->Fill(posmc.vx(), posmc.vy()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hRZ_Photon_Primary"))->Fill(v0.vz(), rxy_rec); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hRZ_Photon_Primary_MC"))->Fill(posmc.vz(), rxy_mc); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hCosPA_Rxy_Photon_Primary"))->Fill(v0.v0radius(), v0.cospa()); + + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaPtOverPtGen"))->Fill(mcphoton.pt(), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaEta"))->Fill(mcphoton.pt(), v0.eta() - mcphoton.eta()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaPhi"))->Fill(mcphoton.pt(), v0.phi() - mcphoton.phi()); + + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaPtOverPtGen"))->Fill(eta_cp, (v0.pt() - mcphoton.pt()) / mcphoton.pt()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaEta"))->Fill(eta_cp, v0.eta() - mcphoton.eta()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaPhi"))->Fill(eta_cp, v0.phi() - mcphoton.phi()); + + for (auto& leg : {pos, ele}) { + o2::aod::pwgem::photon::histogram::FillHistClass(list_v0leg_cut, "", leg); + auto mcleg = leg.template emmcparticle_as(); + reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaPtOverPtGen"))->Fill(mcleg.pt(), (leg.pt() - mcleg.pt()) / mcleg.pt()); + reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaEta"))->Fill(mcleg.pt(), leg.eta() - mcleg.eta()); + reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hPtGen_DeltaPhi"))->Fill(mcleg.pt(), leg.phi() - mcleg.phi()); + reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaPtOverPtGen"))->Fill(eta_cp, (leg.pt() - mcleg.pt()) / mcleg.pt()); + reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaEta"))->Fill(eta_cp, leg.eta() - mcleg.eta()); + reinterpret_cast(fMainList->FindObject("V0Leg")->FindObject(cut.GetName())->FindObject("hEtaRec_DeltaPhi"))->Fill(eta_cp, leg.phi() - mcleg.phi()); + } } } else if (IsFromWD(mcphoton.emmcevent(), mcphoton, mcparticles)) { @@ -276,29 +277,10 @@ struct PCMQCMC { auto mccollision = collision.emmcevent(); // LOGF(info, "mccollision.globalIndex() = %d", mccollision.globalIndex()); - reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(1.0); - reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hZvtx_before"))->Fill(mccollision.posZ()); - if (!collision.sel8()) { - continue; - } - reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(2.0); - - if (collision.numContrib() < 0.5) { - continue; - } - reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(3.0); - - if (abs(collision.posZ()) > 10.0) { - continue; - } - if (!fEMEventCut.IsSelected(collision)) { continue; } - reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(4.0); - reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hZvtx_after"))->Fill(mccollision.posZ()); - auto mctracks_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); for (auto& mctrack : mctracks_coll) { if (abs(mctrack.y()) > maxY) { @@ -312,14 +294,17 @@ struct PCMQCMC { bool is_ele_fromPC = false; bool is_pos_fromPC = false; - auto daughtersIds = mctrack.daughtersIds(); // always size = 2. first and last index. one should run loop from the first index to the last index. + auto daughtersIds = mctrack.daughtersIds(); + if (daughtersIds.size() != 2) { + continue; + } for (auto& daughterId : daughtersIds) { if (daughterId < 0) { continue; } auto daughter = mcparticles.iteratorAt(daughterId); // always electron and positron float rxy_gen_e = sqrt(pow(daughter.vx(), 2) + pow(daughter.vy(), 2)); - if (rxy_gen_e > maxRgen || rxy_gen_e < abs(daughter.vz()) * TMath::Tan(2 * TMath::ATan(TMath::Exp(-maxY))) - margin_z_mc) { + if (rxy_gen_e > maxRgen || rxy_gen_e < abs(daughter.vz()) * std::tan(2 * std::atan(std::exp(-maxY))) - margin_z_mc) { continue; } @@ -328,7 +313,8 @@ struct PCMQCMC { } else if (daughter.pdgCode() == -11) { // positron from photon conversion is_pos_fromPC = true; } - } // end of daughter loop + } // end of daughter loop + if (is_ele_fromPC && is_pos_fromPC) { // ele and pos from photon conversion reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPt_ConvertedPhoton"))->Fill(mctrack.pt()); reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hY_ConvertedPhoton"))->Fill(mctrack.y()); diff --git a/PWGEM/PhotonMeson/Utils/MCUtilities.h b/PWGEM/PhotonMeson/Utils/MCUtilities.h index 57ae2de2a2b..cd6cb0688ec 100644 --- a/PWGEM/PhotonMeson/Utils/MCUtilities.h +++ b/PWGEM/PhotonMeson/Utils/MCUtilities.h @@ -227,23 +227,30 @@ bool IsInAcceptance(TMCParticle const& mcparticle, TMCParticles const& mcparticl return false; // mother rapidity is out of acceptance } auto daughtersIds = mcparticle.daughtersIds(); // always size = 2. first and last index. one should run loop from the first index to the last index. - if (daughtersIds[0] < 0 || daughtersIds[1] < 0) { - return false; - } - if (daughtersIds[1] - daughtersIds[0] + 1 != static_cast(target_pdgs.size())) { + // if (daughtersIds.size() != static_cast(target_pdgs.size())) { + if (daughtersIds.size() != target_pdgs.size()) { return false; } std::vector pdgs; pdgs.reserve(target_pdgs.size()); - for (int idau = daughtersIds[0]; idau <= daughtersIds[1]; idau++) { - auto daughter = mcparticles.iteratorAt(idau); + for (auto& daughterId : daughtersIds) { + if (daughterId < 0) { + pdgs.clear(); + pdgs.shrink_to_fit(); + return false; + } + auto daughter = mcparticles.iteratorAt(daughterId); pdgs.emplace_back(daughter.pdgCode()); if (daughter.eta() < ymin || ymax < daughter.eta()) { + pdgs.clear(); + pdgs.shrink_to_fit(); return false; } if (daughter.phi() < phimin || phimax < daughter.phi()) { + pdgs.clear(); + pdgs.shrink_to_fit(); return false; } } // end of daughter loop @@ -265,18 +272,26 @@ bool IsConversionPointInAcceptance(TMCPhoton const& mcphoton, const float max_r_ return false; } - auto daughtersIds = mcphoton.daughtersIds(); // always size = 2. first and last index. one should run loop from the first index to the last index. - if (daughtersIds[0] < 0 || daughtersIds[1] < 0) { + auto daughtersIds = mcphoton.daughtersIds(); + if (daughtersIds.size() != 2) { return false; } - for (int idau = daughtersIds[0]; idau <= daughtersIds[1]; idau++) { - auto daughter = mcparticles.iteratorAt(idau); + for (auto& daughterId : daughtersIds) { + if (daughterId < 0) { + return false; + } + auto daughter = mcparticles.iteratorAt(daughterId); if (abs(daughter.pdgCode()) != 11) { return false; } + if (daughter.producedByGenerator()) { + return false; + } + float rxy_gen_e = sqrt(pow(daughter.vx(), 2) + pow(daughter.vy(), 2)); + // LOGF(info, "daughterId = %d , pdg = %d , vx = %f , vy = %f , vz = %f, rxy = %f", daughterId, daughter.pdgCode(), daughter.vx(), daughter.vy(), daughter.vz(), rxy_gen_e); if (rxy_gen_e > max_r_gen || rxy_gen_e < abs(daughter.vz()) * std::tan(2 * std::atan(std::exp(-max_eta_gen))) - margin_z_mc) { return false; } diff --git a/PWGHF/D2H/Macros/compute_fraction_cutvar.py b/PWGHF/D2H/Macros/compute_fraction_cutvar.py index be00657a3d1..57182744893 100644 --- a/PWGHF/D2H/Macros/compute_fraction_cutvar.py +++ b/PWGHF/D2H/Macros/compute_fraction_cutvar.py @@ -43,6 +43,20 @@ def main(config): hist_effnp[-1].SetDirectory(0) infile_eff.Close() + 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.SetDirectory(0) + hist_central_effnp.SetDirectory(0) + infile_central_eff.Close() + + # Check if the histograms have the same binning, assuming the two sets of inputs are consistent + for ibin in range(1, hist_rawy[0].GetNbinsX() + 2): # +2 to include the upper edge of last bin + if hist_rawy[0].GetBinLowEdge(ibin) != hist_central_effp.GetBinLowEdge(ibin): + raise ValueError("Histograms have different binning, check the input files") + hist_corry_prompt = hist_rawy[0].Clone("hCorrYieldsPrompt") hist_corry_nonprompt = hist_rawy[0].Clone("hCorrYieldsNonPrompt") hist_covariance = hist_rawy[0].Clone("hCovPromptNonPrompt") @@ -78,6 +92,24 @@ def main(config): fillstyle=0, markerstyle=ROOT.kFullSquare, ) + if cfg["central_efficiency"]["computerawfrac"]: + hist_frac_raw_prompt = hist_rawy[0].Clone("hRawFracPrompt") + hist_frac_raw_nonprompt = hist_rawy[0].Clone("hRawFracNonPrompt") + hist_frac_raw_prompt.GetYaxis().SetTitle("raw fraction prompt") + hist_frac_raw_nonprompt.GetYaxis().SetTitle("raw fraction non-prompt") + set_object_style( + hist_frac_raw_prompt, + color=ROOT.kRed + 1, + fillstyle=0, + markerstyle=ROOT.kFullSquare, + ) + + set_object_style( + hist_frac_raw_nonprompt, + color=ROOT.kAzure + 4, + fillstyle=0, + markerstyle=ROOT.kFullSquare, + ) output = ROOT.TFile(os.path.join(cfg["output"]["directory"], cfg["output"]["file"]), "recreate") n_sets = len(hist_rawy) @@ -109,6 +141,17 @@ def main(config): hist_corrfrac_prompt.SetBinError(ipt + 1, corr_frac_prompt[1]) hist_corrfrac_nonprompt.SetBinContent(ipt + 1, corr_frac_nonprompt[0]) hist_corrfrac_nonprompt.SetBinError(ipt + 1, corr_frac_nonprompt[1]) + if cfg["central_efficiency"]["computerawfrac"]: + raw_frac_prompt = minimiser.get_raw_prompt_fraction( + hist_central_effp.GetBinContent(ipt + 1), hist_central_effnp.GetBinContent(ipt + 1) + ) + raw_frac_nonprompt = minimiser.get_raw_nonprompt_fraction( + hist_central_effp.GetBinContent(ipt + 1), hist_central_effnp.GetBinContent(ipt + 1) + ) + hist_frac_raw_prompt.SetBinContent(ipt + 1, raw_frac_prompt[0]) + hist_frac_raw_prompt.SetBinError(ipt + 1, raw_frac_prompt[1]) + 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}") output.cd() @@ -158,6 +201,9 @@ def main(config): hist_covariance.Write() hist_corrfrac_prompt.Write() hist_corrfrac_nonprompt.Write() + if cfg["central_efficiency"]["computerawfrac"]: + hist_frac_raw_prompt.Write() + hist_frac_raw_nonprompt.Write() output.Close() diff --git a/PWGHF/D2H/Macros/config_cutvar_example.json b/PWGHF/D2H/Macros/config_cutvar_example.json index 420b558fbe4..6ac80c747ad 100644 --- a/PWGHF/D2H/Macros/config_cutvar_example.json +++ b/PWGHF/D2H/Macros/config_cutvar_example.json @@ -1,64 +1,73 @@ { - "rawyields": { - "inputdir": "/Users/fgrosa/cernbox/alice_work/analyses/np_Dplus_vsmult_pp13TeV/outputs/rawyields/MB_INELgtr0", - "inputfiles": [ - "RawYieldsDplus_outFD_pos10.root", - "RawYieldsDplus_outFD_pos11.root", - "RawYieldsDplus_outFD_pos12.root", - "RawYieldsDplus_outFD_pos13.root", - "RawYieldsDplus_outFD_pos14.root", - "RawYieldsDplus_outFD_pos15.root", - "RawYieldsDplus_outFD_pos16.root", - "RawYieldsDplus_outFD_pos17.root", - "RawYieldsDplus_outFD_pos18.root", - "RawYieldsDplus_outFD_pos19.root", - "RawYieldsDplus_outFD_pos20.root", - "RawYieldsDplus_outFD_pos21.root", - "RawYieldsDplus_outFD_pos22.root", - "RawYieldsDplus_outFD_pos23.root", - "RawYieldsDplus_outFD_pos24.root", - "RawYieldsDplus_outFD_pos25.root", - "RawYieldsDplus_outFD_pos26.root", - "RawYieldsDplus_outFD_pos27.root", - "RawYieldsDplus_outFD_pos28.root", - "RawYieldsDplus_outFD_pos29.root" - ], - "histoname": "hRawYields" - }, - "efficiencies": { - "inputdir": "/Users/fgrosa/cernbox/alice_work/analyses/np_Dplus_vsmult_pp13TeV/outputs/efficiencies/MB_INELgtr0", - "inputfiles": [ - "Eff_times_Acc_Dplus_outFD_pos10.root", - "Eff_times_Acc_Dplus_outFD_pos11.root", - "Eff_times_Acc_Dplus_outFD_pos12.root", - "Eff_times_Acc_Dplus_outFD_pos13.root", - "Eff_times_Acc_Dplus_outFD_pos14.root", - "Eff_times_Acc_Dplus_outFD_pos15.root", - "Eff_times_Acc_Dplus_outFD_pos16.root", - "Eff_times_Acc_Dplus_outFD_pos17.root", - "Eff_times_Acc_Dplus_outFD_pos18.root", - "Eff_times_Acc_Dplus_outFD_pos19.root", - "Eff_times_Acc_Dplus_outFD_pos20.root", - "Eff_times_Acc_Dplus_outFD_pos21.root", - "Eff_times_Acc_Dplus_outFD_pos22.root", - "Eff_times_Acc_Dplus_outFD_pos23.root", - "Eff_times_Acc_Dplus_outFD_pos24.root", - "Eff_times_Acc_Dplus_outFD_pos25.root", - "Eff_times_Acc_Dplus_outFD_pos26.root", - "Eff_times_Acc_Dplus_outFD_pos27.root", - "Eff_times_Acc_Dplus_outFD_pos28.root", - "Eff_times_Acc_Dplus_outFD_pos29.root" - ], - "histonames": { - "prompt": "hAccEffPrompt", - "nonprompt": "hAccEffFD" + "rawyields": { + "inputdir": "path/to/RawYields/files", + "inputfiles": [ + "RawYieldsDplus_outFD_pos10.root", + "RawYieldsDplus_outFD_pos11.root", + "RawYieldsDplus_outFD_pos12.root", + "RawYieldsDplus_outFD_pos13.root", + "RawYieldsDplus_outFD_pos14.root", + "RawYieldsDplus_outFD_pos15.root", + "RawYieldsDplus_outFD_pos16.root", + "RawYieldsDplus_outFD_pos17.root", + "RawYieldsDplus_outFD_pos18.root", + "RawYieldsDplus_outFD_pos19.root", + "RawYieldsDplus_outFD_pos20.root", + "RawYieldsDplus_outFD_pos21.root", + "RawYieldsDplus_outFD_pos22.root", + "RawYieldsDplus_outFD_pos23.root", + "RawYieldsDplus_outFD_pos24.root", + "RawYieldsDplus_outFD_pos25.root", + "RawYieldsDplus_outFD_pos26.root", + "RawYieldsDplus_outFD_pos27.root", + "RawYieldsDplus_outFD_pos28.root", + "RawYieldsDplus_outFD_pos29.root" + ], + "histoname": "hRawYields" + }, + "efficiencies": { + "inputdir": "path/to/efficiencies/files", + "inputfiles": [ + "Eff_times_Acc_Dplus_outFD_pos10.root", + "Eff_times_Acc_Dplus_outFD_pos11.root", + "Eff_times_Acc_Dplus_outFD_pos12.root", + "Eff_times_Acc_Dplus_outFD_pos13.root", + "Eff_times_Acc_Dplus_outFD_pos14.root", + "Eff_times_Acc_Dplus_outFD_pos15.root", + "Eff_times_Acc_Dplus_outFD_pos16.root", + "Eff_times_Acc_Dplus_outFD_pos17.root", + "Eff_times_Acc_Dplus_outFD_pos18.root", + "Eff_times_Acc_Dplus_outFD_pos19.root", + "Eff_times_Acc_Dplus_outFD_pos20.root", + "Eff_times_Acc_Dplus_outFD_pos21.root", + "Eff_times_Acc_Dplus_outFD_pos22.root", + "Eff_times_Acc_Dplus_outFD_pos23.root", + "Eff_times_Acc_Dplus_outFD_pos24.root", + "Eff_times_Acc_Dplus_outFD_pos25.root", + "Eff_times_Acc_Dplus_outFD_pos26.root", + "Eff_times_Acc_Dplus_outFD_pos27.root", + "Eff_times_Acc_Dplus_outFD_pos28.root", + "Eff_times_Acc_Dplus_outFD_pos29.root" + ], + "histonames": { + "prompt": "hAccEffPrompt", + "nonprompt": "hAccEffFD" + } + }, + "minimisation": { + "correlated": true + }, + "central_efficiency": { + "computerawfrac": true, + "inputdir": "path/to/central/efficiency", + "inputfile": "efficiency.root", + "histonames": { + "prompt": "hAccEffPrompt", + "nonprompt": "hAccEffFD" + } + }, + "output": { + "directory": ".", + "file": "CutVarDplus_pp13TeV_MB.root" } - }, - "minimisation": { - "correlated": "true" - }, - "output": { - "directory": ".", - "file": "CutVarDplus_pp13TeV_MB.root" - } } \ No newline at end of file diff --git a/PWGHF/D2H/Macros/config_ptspectrum_Dplus_pp5TeV.yml b/PWGHF/D2H/Macros/config_ptspectrum_Dplus_pp5TeV.yml new file mode 100644 index 00000000000..1d0bf6df7a5 --- /dev/null +++ b/PWGHF/D2H/Macros/config_ptspectrum_Dplus_pp5TeV.yml @@ -0,0 +1,25 @@ +# example config for cross section calculation of D+ mesons + +observable: dsigmadpt # options: dsigmadpt, dNdpt +channel: DplustoKpipi # options: D0toKpi, DplustoKpipi, DstoKKpi, DstartoD0pi, LctopKpi, LctopK0S +system: pp # options: pp, pPb, PbPb +energy: 5TeV # options: 5TeV, 13TeV +period: Run2 # options: Run2 + +fraction: Nb # options: Nb, fc + +FONLL: FONLLpred/DmesonLcPredictions_502TeV_y05_FFee_BRpythia8_SepContr_PDG2020.root + +rawyield: + filename: test/RawYields_Dplus_pp5TeV_prompt_central.root + rawyieldhist: hRawYields + normhist: hEvForNorm + +acceff: + filename: test/Eff_times_Acc_Dplus_pp5TeV_central_newAcc.root + prompthist: hAccEffPrompt + nonprompthist: hAccEffFD + +output: + directory: '.' + filename: CrossSectionDplus_pp_5TeV # without extension diff --git a/PWGHF/D2H/Macros/cut_variation.py b/PWGHF/D2H/Macros/cut_variation.py index bf7e51a4532..74292f5acd5 100644 --- a/PWGHF/D2H/Macros/cut_variation.py +++ b/PWGHF/D2H/Macros/cut_variation.py @@ -189,7 +189,7 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) m_corr_yields_old = np.copy(self.m_corr_yields) # chi2 - self.chi_2 = np.float(np.transpose(self.m_res) * self.m_weights * self.m_res) + self.chi_2 = float(np.transpose(self.m_res) * self.m_weights * self.m_res) # fraction for i_set, (effp, effnp) in enumerate(zip(self.eff_prompt, self.eff_nonprompt)): @@ -269,9 +269,9 @@ def get_raw_prompt_fraction(self, effacc_p, effacc_np): Parameters ----------------------------------------------------- - - effacc_p: str + - effacc_p: float eff x acc for prompt signal - - effacc_np: str + - effacc_np: float eff x acc for non-prompt signal Returns @@ -301,9 +301,9 @@ def get_raw_nonprompt_fraction(self, effacc_p, effacc_np): Parameters ----------------------------------------------------- - - effacc_p: str + - effacc_p: float eff x acc for prompt signal - - effacc_np: str + - effacc_np: float eff x acc for non-prompt signal Returns diff --git a/PWGHF/D2H/Tasks/taskXic.cxx b/PWGHF/D2H/Tasks/taskXic.cxx index 8069681dc8b..a2b553fc164 100644 --- a/PWGHF/D2H/Tasks/taskXic.cxx +++ b/PWGHF/D2H/Tasks/taskXic.cxx @@ -45,6 +45,18 @@ struct HfTaskXic { Configurable dcaZTrackMax{"dcaZTrackMax", 0.0025, "max. DCAz for track"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_p_k_pi::vecBinsPt}, "pT bin limits"}; + // THnSparse for ML outputScores and Vars + Configurable enableTHn{"enableTHn", false, "enable THn for Xic"}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {36, 0, 36}, ""}; + ConfigurableAxis thnConfigAxisMass{"thnConfigAxisMass", {300, 1.98, 2.58}, ""}; + ConfigurableAxis thnConfigAxisPtProng{"thnConfigAxisPtProng", {100, 0, 20}, ""}; + ConfigurableAxis thnConfigAxisChi2PCA{"thnConfigAxisChi2PCA", {100, 0, 20}, ""}; + ConfigurableAxis thnConfigAxisDecLength{"thnConfigAxisDecLength", {10, 0, 0.05}, ""}; + ConfigurableAxis thnConfigAxisDecLengthXY{"thnConfigAxisDecLengthXY", {10, 0, 0.05}, ""}; + ConfigurableAxis thnConfigAxisCPA{"thnConfigAxisCPA", {20, 0.8, 1}, ""}; + ConfigurableAxis thnConfigAxisBdtScoreBkg{"thnConfigAxisBdtScoreBkg", {100, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisBdtScoreSignal{"thnConfigAxisBdtScoreSignal", {100, 0., 1.}, ""}; + // Service pdg; HfHelper hfHelper; @@ -79,6 +91,11 @@ struct HfTaskXic { void init(InitContext&) { + std::array doprocess{doprocessDataStd, doprocessDataWithMl, doprocessMcStd, doprocessMcWithMl}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "no or more than one process function enabled! Please check your configuration!"); + } + AxisSpec axisPPid = {100, 0.f, 10.0f, "#it{p} (GeV/#it{c})"}; AxisSpec axisNSigmaPr = {100, -6.f, 6.f, "n#it{#sigma}_{p}"}; AxisSpec axisNSigmaPi = {100, -6.f, 6.f, "n#it{#sigma}_{#pi}"}; @@ -176,7 +193,27 @@ struct HfTaskXic { registry.add("MC/reconstructed/background/hPtProng1RecBg", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("MC/reconstructed/background/hPtProng2RecBg", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});;entries", {HistType::kTH2F, {{100, 0., 10.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("MC/reconstructed/background/hChi2PCARecBg", "3-prong candidates;prong Chi2PCA to sec. vertex (cm);; entries", {HistType::kTH2F, {{100, 0, 120}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - } + + // THn for candidates Xic+ cut variation + if (enableTHn) { + const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (p K #pi) (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T}(#Xi_{c}^{+}) (GeV/#it{c})"}; + const AxisSpec thnAxisChi2PCA{thnConfigAxisChi2PCA, "Chi2PCA to sec. vertex (cm)"}; + const AxisSpec thnAxisDecLength{thnConfigAxisDecLength, "decay length (cm)"}; + const AxisSpec thnAxisDecLengthXY{thnConfigAxisDecLengthXY, "decay length (cm)"}; + const AxisSpec thnAxisCPA{thnConfigAxisCPA, "cosine of pointing angle"}; + const AxisSpec thnAxisBdtScoreXicBkg{thnConfigAxisBdtScoreBkg, "BDT bkg score (Xic)"}; + const AxisSpec thnAxisBdtScoreXicPrompt{thnConfigAxisBdtScoreSignal, "BDT prompt score (Xic)"}; + const AxisSpec thnAxisBdtScoreXicNonPrompt{thnConfigAxisBdtScoreSignal, "BDT non-prompt score (Xic)"}; + const AxisSpec thnAxisMcOrigin{3, -0.5, 2.5, "MC origin"}; + + if (doprocessDataWithMl || doprocessMcWithMl) { // with ML + 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}); + } + } + } // end init /// Selection of Xic daughters in geometrical acceptanc /// \param etaProng is the pseudorapidity of Xic prong @@ -187,10 +224,10 @@ struct HfTaskXic { { return std::abs(etaProng) <= etaMaxAcceptance && ptProng >= ptMinAcceptance; } - - void process(aod::Collision const& collision, - TracksWPid const& tracks, - soa::Filtered> const& candidates) + template + void analysisData(aod::Collision const& collision, + Cands const& candidates, + TracksWPid const& tracks) { int nTracks = 0; @@ -207,15 +244,15 @@ struct HfTaskXic { } registry.fill(HIST("Data/hMultiplicity"), nTracks); // filling the histo for multiplicity + for (const auto& candidate : candidates) { - auto ptCandidate = candidate.pt(); if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::XicToPKPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(hfHelper.yXic(candidate)) > yCandRecoMax) { continue; } + auto ptCandidate = candidate.pt(); if (candidate.isSelXicToPKPi() >= selectionFlagXic) { // pKpi registry.fill(HIST("Data/hMassVsPt"), hfHelper.invMassXicToPKPi(candidate), ptCandidate); @@ -250,9 +287,9 @@ struct HfTaskXic { registry.fill(HIST("Data/hChi2PCA"), candidate.chi2PCA(), ptCandidate); // PID histos - const auto& trackProng0 = candidate.prong0_as(); // bachelor track - const auto& trackProng1 = candidate.prong1_as(); // bachelor track - const auto& trackProng2 = candidate.prong2_as(); // bachelor track + auto trackProng0 = candidate.template prong0_as(); + auto trackProng1 = candidate.template prong1_as(); + auto trackProng2 = candidate.template prong2_as(); auto momentumProng0 = trackProng0.p(); auto momentumProng1 = trackProng1.p(); @@ -283,26 +320,77 @@ struct HfTaskXic { registry.fill(HIST("Data/hPVsTOFNSigmaPr_Prong2"), momentumProng2, trackProng2.tofNSigmaPr()); registry.fill(HIST("Data/hPVsTOFNSigmaPi_Prong2"), momentumProng2, trackProng2.tofNSigmaPi()); registry.fill(HIST("Data/hPVsTOFNSigmaKa_Prong2"), momentumProng2, trackProng2.tofNSigmaKa()); - } + + // THnSparse + if (enableTHn) { + double massXic(-1); + double outputBkg(-1), outputPrompt(-1), outputFD(-1); + if (candidate.isSelXicToPKPi() >= selectionFlagXic) { + massXic = hfHelper.invMassXicToPKPi(candidate); + if constexpr (useMl) { + if (candidate.mlProbXicToPKPi().size() == 3) { + outputBkg = candidate.mlProbXicToPKPi()[0]; /// bkg score + outputPrompt = candidate.mlProbXicToPKPi()[1]; /// prompt score + outputFD = candidate.mlProbXicToPKPi()[2]; /// non-prompt score + } + /// Fill the ML outputScores and variables of candidate Xic + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, 0); + } else { + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), 0); + } + } + if (candidate.isSelXicToPiKP() >= selectionFlagXic) { + massXic = hfHelper.invMassXicToPiKP(candidate); + if constexpr (useMl) { + if (candidate.mlProbXicToPiKP().size() == 3) { + outputBkg = candidate.mlProbXicToPiKP()[0]; /// bkg score + outputPrompt = candidate.mlProbXicToPiKP()[1]; /// prompt score + outputFD = candidate.mlProbXicToPiKP()[2]; /// non-prompt score + } + /// Fill the ML outputScores and variables of candidate + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, 0); + } else { + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), 0); + } + } + } // thn for Xic + } // loop candidates + } // end process data + + void processDataStd(aod::Collision const& collision, + soa::Filtered> const& candidates, + TracksWPid const& tracks) + { + analysisData(collision, candidates, tracks); } - // Fill MC histograms - void processMc(soa::Filtered> const& candidates, - soa::Join const& mcParticles) + PROCESS_SWITCH(HfTaskXic, processDataStd, "Process Data with the standard method", true); + + void processDataWithMl(aod::Collision const& collision, + soa::Filtered> const& candidatesMl, TracksWPid const& tracks) { + analysisData(collision, candidatesMl, tracks); + } + PROCESS_SWITCH(HfTaskXic, processDataWithMl, "Process Data with the ML method", false); + // Fill MC histograms + template + void analysisMc(Cands const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const&) + { // MC rec. for (const auto& candidate : candidates) { + auto ptCandidate = candidate.pt(); // Selected Xic if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::XicToPKPi)) { continue; - } // rapidity selection + } if (yCandRecoMax >= 0. && std::abs(hfHelper.yXic(candidate)) > yCandRecoMax) { continue; } auto massXicToPKPi = 0.; auto massXicToPiKP = 0.; - auto ptCandidate = candidate.pt(); if (candidate.isSelXicToPKPi() >= selectionFlagXic) { massXicToPKPi = hfHelper.invMassXicToPKPi(candidate); @@ -312,8 +400,11 @@ struct HfTaskXic { } if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::XicToPKPi) { + // Get the corresponding MC particle. + auto mcParticleProng0 = candidate.template prong0_as().template mcParticle_as>(); + auto pdgCodeProng0 = std::abs(mcParticleProng0.pdgCode()); // Signal - registry.fill(HIST("MC/reconstructed/signal/hPtRecSig"), ptCandidate); // rec. level pT + registry.fill(HIST("MC/reconstructed/signal/hPtRecSig"), ptCandidate); // rec. level pT if (massXicToPKPi != 0.) { registry.fill(HIST("MC/reconstructed/signal/hMassSig"), massXicToPKPi, ptCandidate); @@ -339,6 +430,39 @@ struct HfTaskXic { registry.fill(HIST("MC/reconstructed/signal/hImpParErrSig"), candidate.errorImpactParameter0(), ptCandidate); registry.fill(HIST("MC/reconstructed/signal/hDecLenErrSig"), candidate.errorDecayLength(), ptCandidate); registry.fill(HIST("MC/reconstructed/signal/hChi2PCARecSig"), candidate.chi2PCA(), ptCandidate); + + if (enableTHn) { + double massXic(-1); + double outputBkg(-1), outputPrompt(-1), outputFD(-1); + if ((candidate.isSelXicToPKPi() >= selectionFlagXic) && pdgCodeProng0 == kProton) { + massXic = hfHelper.invMassXicToPKPi(candidate); + if constexpr (useMl) { + if (candidate.mlProbXicToPKPi().size() == 3) { + outputBkg = candidate.mlProbXicToPKPi()[0]; /// bkg score + outputPrompt = candidate.mlProbXicToPKPi()[1]; /// prompt score + 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()); + } else { + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec()); + } + } + if ((candidate.isSelXicToPiKP() >= selectionFlagXic) && pdgCodeProng0 == kPiPlus) { + massXic = hfHelper.invMassXicToPiKP(candidate); + if constexpr (useMl) { + if (candidate.mlProbXicToPiKP().size() == 3) { + outputBkg = candidate.mlProbXicToPiKP()[0]; /// bkg score + outputPrompt = candidate.mlProbXicToPiKP()[1]; /// prompt score + outputFD = candidate.mlProbXicToPiKP()[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()); + } else { + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec()); + } + } + } // enable THn } else { // Background registry.fill(HIST("MC/reconstructed/background/hPtRecBg"), ptCandidate); @@ -367,8 +491,9 @@ struct HfTaskXic { registry.fill(HIST("MC/reconstructed/background/hImpParErrBg"), candidate.errorImpactParameter0(), ptCandidate); registry.fill(HIST("MC/reconstructed/background/hDecLenErrBg"), candidate.errorDecayLength(), ptCandidate); registry.fill(HIST("MC/reconstructed/background/hChi2PCARecBg"), candidate.chi2PCA(), ptCandidate); - } - } + } // Xic background + } // candidate loop + // MC gen. for (const auto& particle : mcParticles) { if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::XicToPKPi) { @@ -381,7 +506,7 @@ struct HfTaskXic { std::array yProngs; std::array etaProngs; int counter = 0; - for (const auto& daught : particle.daughters_as()) { + for (const auto& daught : particle.daughters_as>()) { ptProngs[counter] = daught.pt(); etaProngs[counter] = daught.eta(); yProngs[counter] = RecoDecay::y(std::array{daught.px(), daught.py(), daught.pz()}, pdg->Mass(daught.pdgCode())); @@ -401,7 +526,22 @@ struct HfTaskXic { } } } - PROCESS_SWITCH(HfTaskXic, processMc, "Process MC", false); + + void processMcStd(soa::Filtered> const& selectedCandidatesMc, + soa::Join const& mcParticles, + aod::TracksWMc const& tracksWithMc) + { + analysisMc(selectedCandidatesMc, mcParticles, tracksWithMc); + } + PROCESS_SWITCH(HfTaskXic, processMcStd, "Process MC with the standard method", false); + + void processMcWithMl(soa::Filtered> const& selectedCandidatesMlMc, + soa::Join const& mcParticles, + aod::TracksWMc const& tracksWithMc) + { + analysisMc(selectedCandidatesMlMc, mcParticles, tracksWithMc); + } + PROCESS_SWITCH(HfTaskXic, processMcWithMl, "Process Mc with the ML method", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/HFC/DataModel/CorrelationTables.h b/PWGHF/HFC/DataModel/CorrelationTables.h index 876c70ac5ac..b6b9ccfa25e 100644 --- a/PWGHF/HFC/DataModel/CorrelationTables.h +++ b/PWGHF/HFC/DataModel/CorrelationTables.h @@ -123,27 +123,39 @@ DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! DeltaEta bet DECLARE_SOA_COLUMN(PtD, ptD, float); //! Transverse momentum of Ds DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); //! Transverse momentum of Hadron DECLARE_SOA_COLUMN(MD, mD, float); //! Invariant mass of Ds +DECLARE_SOA_COLUMN(MlScoreBkg, mlScoreBkg, float); //! ML background score for Ds selection +DECLARE_SOA_COLUMN(MlScorePrompt, mlScorePrompt, float); //! ML prompt score for Ds selection DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin for the MixedEvent DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); //! Used in MC-Rec, Ds Signal DECLARE_SOA_COLUMN(IsPrompt, isPrompt, bool); //! Used in MC-Rec, Ds Prompt or Non-Prompt DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); //! Used in MC-Rec, primary associated particles } // namespace hf_correlation_ds_hadron -DECLARE_SOA_TABLE(DsHadronPair, "AOD", "DSHPAIR", //! Ds-Hadrons pairs Informations +DECLARE_SOA_TABLE(DsHadronPair, "AOD", "DSHPAIR", //! Ds-Hadrons pairs Information aod::hf_correlation_ds_hadron::DeltaPhi, aod::hf_correlation_ds_hadron::DeltaEta, aod::hf_correlation_ds_hadron::PtD, aod::hf_correlation_ds_hadron::PtHadron, aod::hf_correlation_ds_hadron::PoolBin); -DECLARE_SOA_TABLE(DsHadronRecoInfo, "AOD", "DSHRECOINFO", //! Ds-Hadrons pairs Reconstructed Informations +DECLARE_SOA_TABLE(DsHadronRecoInfo, "AOD", "DSHRECOINFO", //! Ds-Hadrons pairs Reconstructed Information aod::hf_correlation_ds_hadron::MD, aod::hf_correlation_ds_hadron::IsSignal); -DECLARE_SOA_TABLE(DsHadronGenInfo, "AOD", "DSHGENINFO", //! Ds-Hadrons pairs Generated Informations +DECLARE_SOA_TABLE(DsHadronGenInfo, "AOD", "DSHGENINFO", //! Ds-Hadrons pairs Generated Information aod::hf_correlation_ds_hadron::IsPrompt, aod::hf_correlation_ds_hadron::IsPhysicalPrimary); +DECLARE_SOA_TABLE(DsHadronMlInfo, "AOD", "DSHMLINFO", //! Ds-Hadrons pairs Machine Learning Information + aod::hf_correlation_ds_hadron::MlScorePrompt, + aod::hf_correlation_ds_hadron::MlScoreBkg); + +DECLARE_SOA_TABLE(DsCandRecoInfo, "AOD", "DSCANDRECOINFO", //! Ds candidates Reconstructed Information + aod::hf_correlation_ds_hadron::MD, + aod::hf_correlation_ds_hadron::PtD, + aod::hf_correlation_ds_hadron::MlScorePrompt, + aod::hf_correlation_ds_hadron::MlScoreBkg); + // definition of columns and tables for Dplus properties namespace hf_dplus_meson { diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index 25756da2a00..5add39eb3c9 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -50,7 +50,8 @@ using BinningType = ColumnBinningPolicy collisionsWithSelDs; - Configurable doSelCollision{"doSelCollision", true, "Select collisions with at least one Ds"}; + Configurable useSel8{"useSel8", true, "Flag for applying sel8 for collision selection"}; + Configurable doSelDsCollision{"doSelDsCollision", true, "Select collisions with at least one Ds"}; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; @@ -58,6 +59,7 @@ struct HfCorrelatorDsHadronsSelCollision { SliceCache cache; HfHelper hfHelper; + using SelCollisions = soa::Join; using CandDsData = soa::Filtered>; using CandDsMcReco = soa::Filtered>; using CandDsMcGen = soa::Join; @@ -65,45 +67,51 @@ struct HfCorrelatorDsHadronsSelCollision { Filter dsFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::DsToKKPi)) != static_cast(0)) && (aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs); /// Code to select collisions with at least one Ds meson - for real data and data-like analysis - void processDsSelCollisionsData(aod::Collision const& collision, + void processDsSelCollisionsData(SelCollisions::iterator const& collision, CandDsData const& candidates) { bool isDsFound = false; - if (doSelCollision) { - if (candidates.size() > 0) { - for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yDs(candidate)) > yCandMax || candidate.pt() < ptCandMin) { - continue; - } - isDsFound = true; - break; + bool isSel8 = false; + if (doSelDsCollision) { + for (const auto& candidate : candidates) { + if (std::abs(hfHelper.yDs(candidate)) > yCandMax || candidate.pt() < ptCandMin) { + continue; } + isDsFound = true; + break; } } else { isDsFound = true; } + if (useSel8) { + isSel8 = collision.sel8(); + isDsFound = isDsFound && isSel8; + } collisionsWithSelDs(isDsFound); } PROCESS_SWITCH(HfCorrelatorDsHadronsSelCollision, processDsSelCollisionsData, "Process Ds Collision Selection Data", true); /// Code to select collisions with at least one Ds meson - for MC reco-level analysis - void processDsSelCollisionsMcRec(aod::Collision const& collision, + void processDsSelCollisionsMcRec(SelCollisions::iterator const& collision, CandDsMcReco const& candidates) { bool isDsFound = false; - if (doSelCollision) { - if (candidates.size() > 0) { - for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yDs(candidate)) > yCandMax || candidate.pt() < ptCandMin) { - continue; - } - isDsFound = true; - break; + bool isSel8 = false; + if (doSelDsCollision) { + for (const auto& candidate : candidates) { + if (std::abs(hfHelper.yDs(candidate)) > yCandMax || candidate.pt() < ptCandMin) { + continue; } + isDsFound = true; + break; } } else { isDsFound = true; } + if (useSel8) { + isSel8 = collision.sel8(); + isDsFound = isDsFound && isSel8; + } collisionsWithSelDs(isDsFound); } PROCESS_SWITCH(HfCorrelatorDsHadronsSelCollision, processDsSelCollisionsMcRec, "Process Ds Collision Selection MCRec", false); @@ -113,7 +121,7 @@ struct HfCorrelatorDsHadronsSelCollision { CandDsMcGen const& mcParticles) { bool isDsFound = false; - if (doSelCollision) { + if (doSelDsCollision) { for (const auto& particle : mcParticles) { if (std::abs(particle.pdgCode()) != Pdg::kDS) { continue; @@ -138,11 +146,13 @@ struct HfCorrelatorDsHadrons { Produces entryDsHadronPair; Produces entryDsHadronRecoInfo; Produces entryDsHadronGenInfo; + Produces entryDsHadronMlInfo; + Produces entryDsCandRecoInfo; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; + Configurable useSel8ForTrackEff{"useSel8ForTrackEff", true, "Flag for applying sel8 for collision selection"}; Configurable applyEfficiency{"applyEfficiency", true, "Flag for applying D-meson efficiency weights"}; - Configurable fillSystematics{"fillSystematics", false, "Flag for filling THnSparse for systematics"}; Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen. cand. rapidity"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "max. eta of tracks"}; @@ -188,15 +198,15 @@ struct HfCorrelatorDsHadrons { kAssocTrackStepFake, kAssocTrackNSteps }; - using SelCollisionsWithDs = soa::Filtered>; // collisionFilter applied - using SelCollisionsWithDsMc = soa::Filtered>; // collisionFilter applied - using CandDsData = soa::Filtered>; // flagDsFilter applied - using CandDsMcReco = soa::Filtered>; // flagDsFilter applied - using CandDsMcGen = soa::Join; // flagDsFilter applied - using MyTracksData = soa::Filtered>; // trackFilter applied - using TracksWithMc = soa::Filtered>; // trackFilter applied + using SelCollisionsWithDs = soa::Filtered>; // collisionFilter applied + using SelCollisionsWithDsMc = soa::Filtered>; // collisionFilter applied + using CandDsData = soa::Filtered>; // flagDsFilter applied + using CandDsMcReco = soa::Filtered>; // flagDsFilter applied + using CandDsMcGen = soa::Join; // flagDsFilter applied + using MyTracksData = soa::Filtered>; // trackFilter applied + using TracksWithMc = soa::Filtered>; // trackFilter applied - Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true && o2::aod::evsel::sel8 == true; + Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; Filter flagDsFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::DsToKKPi)) != static_cast(0)) && (aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs); Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (aod::track::pt > ptTrackMin) && (aod::track::pt < ptTrackMax) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); @@ -377,17 +387,24 @@ struct HfCorrelatorDsHadrons { if (applyEfficiency) { efficiencyWeightD = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())); } + std::vector outputMl = {-1., -1., -1.}; fillHisto(candidate); if (candidate.isSelDsToKKPi() >= selectionFlagDs) { fillHistoKKPi(candidate, efficiencyWeightD); - } - if (candidate.isSelDsToPiKK() >= selectionFlagDs) { + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDsToKKPi()[classMl->at(iclass)]; + } + entryDsCandRecoInfo(hfHelper.invMassDsToKKPi(candidate), candidate.pt(), outputMl[0], outputMl[2]); + } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { fillHistoPiKK(candidate, efficiencyWeightD); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDsToPiKK()[classMl->at(iclass)]; + } + entryDsCandRecoInfo(hfHelper.invMassDsToPiKK(candidate), candidate.pt(), outputMl[0], outputMl[2]); } if (candidate.isSelDsToKKPi() >= selectionFlagDs && candidate.isSelDsToPiKK() >= selectionFlagDs) { registry.fill(HIST("hCountSelectionStatusDsToKKPiAndToPiKK"), 0.); } - std::vector outputMl = {-1., -1., -1.}; // Ds-Hadron correlation dedicated section for (const auto& track : tracks) { @@ -409,12 +426,7 @@ struct HfCorrelatorDsHadrons { poolBin); entryDsHadronRecoInfo(hfHelper.invMassDsToKKPi(candidate), false); entryDsHadronGenInfo(false, false); - if (fillSystematics) { - for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { - outputMl[iclass] = candidate.mlProbDsToKKPi()[classMl->at(iclass)]; - } - registry.fill(HIST("hCorrelSystematics"), getDeltaPhi(track.phi(), candidate.phi()), track.eta() - candidate.eta(), candidate.pt(), track.pt(), hfHelper.invMassDsToKKPi(candidate), outputMl[0], outputMl[2]); - } + entryDsHadronMlInfo(outputMl[0], outputMl[2]); } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { entryDsHadronPair(getDeltaPhi(track.phi(), candidate.phi()), track.eta() - candidate.eta(), @@ -423,12 +435,7 @@ struct HfCorrelatorDsHadrons { poolBin); entryDsHadronRecoInfo(hfHelper.invMassDsToPiKK(candidate), false); entryDsHadronGenInfo(false, false); - if (fillSystematics) { - for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { - outputMl[iclass] = candidate.mlProbDsToPiKK()[classMl->at(iclass)]; - } - registry.fill(HIST("hCorrelSystematics"), getDeltaPhi(track.phi(), candidate.phi()), track.eta() - candidate.eta(), candidate.pt(), track.pt(), hfHelper.invMassDsToPiKK(candidate), outputMl[0], outputMl[2]); - } + entryDsHadronMlInfo(outputMl[0], outputMl[2]); } } // end track loop } // end candidate loop @@ -499,6 +506,7 @@ struct HfCorrelatorDsHadrons { registry.fill(HIST("hSelectionStatusDsToPiKKMcRec"), candidate.isSelDsToPiKK()); } } + std::vector outputMl = {-1., -1., -1.}; // Ds-Hadron correlation dedicated section // if the candidate is selected as Ds, search for Hadron and evaluate correlations @@ -519,6 +527,10 @@ struct HfCorrelatorDsHadrons { track.pt(), poolBin); entryDsHadronRecoInfo(hfHelper.invMassDsToKKPi(candidate), isDsSignal); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDsToKKPi()[classMl->at(iclass)]; + } + entryDsHadronMlInfo(outputMl[0], outputMl[2]); if (track.has_mcParticle()) { auto mcParticle = track.template mcParticle_as(); isPhysicalPrimary = mcParticle.isPhysicalPrimary(); @@ -541,6 +553,10 @@ struct HfCorrelatorDsHadrons { track.pt(), poolBin); entryDsHadronRecoInfo(hfHelper.invMassDsToPiKK(candidate), isDsSignal); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDsToPiKK()[classMl->at(iclass)]; + } + entryDsHadronMlInfo(outputMl[0], outputMl[2]); if (track.has_mcParticle()) { auto mcParticle = track.template mcParticle_as(); isPhysicalPrimary = mcParticle.isPhysicalPrimary(); @@ -622,7 +638,7 @@ struct HfCorrelatorDsHadrons { PROCESS_SWITCH(HfCorrelatorDsHadrons, processMcCandEfficiency, "Process MC for calculating candidate reconstruction efficiency", false); /// Ds-Hadron correlation - for calculating associated particle tracking efficiency using MC reco-level analysis - void processMcTrackEfficiency(soa::Join const&, + void processMcTrackEfficiency(soa::Join const&, soa::Join const&, CandDsMcGen const& mcParticles, TracksWithMc const& tracksData) @@ -652,7 +668,10 @@ struct HfCorrelatorDsHadrons { if (!track.isGlobalTrackWoDCA()) { continue; } - auto collision = track.template collision_as>(); + auto collision = track.template collision_as>(); + if (useSel8ForTrackEff && !collision.sel8()) { + continue; + } multiplicity = collision.multFT0M(); posZ = collision.posZ(); registry.fill(HIST("hZVtx"), posZ); @@ -746,12 +765,7 @@ struct HfCorrelatorDsHadrons { registry.fill(HIST("hMultFT0M"), collision.multFT0M()); registry.fill(HIST("hZVtx"), collision.posZ()); } - for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yDs(candidate)) > yCandMax || candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { - continue; - } - fillHisto(candidate); - } + auto tracksTuple = std::make_tuple(candidates, tracks); Pair pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; @@ -759,6 +773,7 @@ struct HfCorrelatorDsHadrons { if (tracks1.size() == 0) { continue; } + // LOGF(info, "Mixed event collisions: Index = (%d, %d), tracks Size: (%d, %d), Z Vertex: (%f, %f), Pool Bin: (%d, %d)", c1.globalIndex(), c2.globalIndex(), tracks1.size(), tracks2.size(), c1.posZ(), c2.posZ(), corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFT0M())), corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFT0M()))); int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFT0M())); int poolBinDs = corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFT0M())); @@ -785,12 +800,10 @@ struct HfCorrelatorDsHadrons { poolBin); entryDsHadronRecoInfo(hfHelper.invMassDsToKKPi(cand), false); entryDsHadronGenInfo(false, false); - if (fillSystematics) { - for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { - outputMl[iclass] = cand.mlProbDsToKKPi()[classMl->at(iclass)]; - } - registry.fill(HIST("hCorrelSystematics"), getDeltaPhi(pAssoc.phi(), cand.phi()), pAssoc.eta() - cand.eta(), cand.pt(), pAssoc.pt(), hfHelper.invMassDsToKKPi(cand), outputMl[0], outputMl[2]); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = cand.mlProbDsToKKPi()[classMl->at(iclass)]; } + entryDsHadronMlInfo(outputMl[0], outputMl[2]); } else if (cand.isSelDsToPiKK() >= selectionFlagDs) { // LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d), track event: (%d, %d), PiKK", cand.index(), pAssoc.index(), c1.index(), c2.index(), cand.collision().index(), pAssoc.collision().index()); entryDsHadronPair(getDeltaPhi(pAssoc.phi(), cand.phi()), @@ -800,12 +813,10 @@ struct HfCorrelatorDsHadrons { poolBin); entryDsHadronRecoInfo(hfHelper.invMassDsToPiKK(cand), false); entryDsHadronGenInfo(false, false); - if (fillSystematics) { - for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { - outputMl[iclass] = cand.mlProbDsToPiKK()[classMl->at(iclass)]; - } - registry.fill(HIST("hCorrelSystematics"), getDeltaPhi(pAssoc.phi(), cand.phi()), pAssoc.eta() - cand.eta(), cand.pt(), pAssoc.pt(), hfHelper.invMassDsToPiKK(cand), outputMl[0], outputMl[2]); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = cand.mlProbDsToPiKK()[classMl->at(iclass)]; } + entryDsHadronMlInfo(outputMl[0], outputMl[2]); } } } @@ -853,6 +864,7 @@ struct HfCorrelatorDsHadrons { if (!pAssoc.isGlobalTrackWoDCA()) { continue; } + std::vector outputMl = {-1., -1., -1.}; // prompt and non-prompt division isDsPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; // Ds Signal @@ -866,6 +878,10 @@ struct HfCorrelatorDsHadrons { poolBin); entryDsHadronRecoInfo(hfHelper.invMassDsToKKPi(candidate), isDsSignal); entryDsHadronGenInfo(isDsPrompt, false); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDsToKKPi()[classMl->at(iclass)]; + } + entryDsHadronMlInfo(outputMl[0], outputMl[2]); } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { entryDsHadronPair(getDeltaPhi(pAssoc.phi(), candidate.phi()), pAssoc.eta() - candidate.eta(), @@ -874,6 +890,10 @@ struct HfCorrelatorDsHadrons { poolBin); entryDsHadronRecoInfo(hfHelper.invMassDsToPiKK(candidate), isDsSignal); entryDsHadronGenInfo(isDsPrompt, false); + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDsToPiKK()[classMl->at(iclass)]; + } + entryDsHadronMlInfo(outputMl[0], outputMl[2]); } } } diff --git a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx index 57a1171a2fa..0a19f6d8825 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx @@ -33,6 +33,8 @@ struct HfTaskCorrelationDsHadrons { Configurable applyEfficiency{"applyEfficiency", false, "Flag for applying efficiency weights"}; Configurable> binsPtD{"binsPtD", std::vector{o2::analysis::hf_cuts_ds_to_k_k_pi::vecBinsPt}, "pT bin limits for candidate mass plots and efficiency"}; Configurable> binsPtHadron{"binsPtHadron", std::vector{0.3, 2., 4., 8., 12., 50.}, "pT bin limits for assoc particle efficiency"}; + Configurable> mlOutputPrompt{"mlScorePrompt", {0.5, 0.5, 0.5, 0.5}, "Machine learning scores for prompt"}; + Configurable> mlOutputBkg{"mlScoreBkg", {0.5, 0.5, 0.5, 0.5}, "Machine learning scores for bkg"}; Configurable> binsPtEfficiencyD{"binsPtEfficiencyD", std::vector{o2::analysis::hf_cuts_ds_to_k_k_pi::vecBinsPt}, "pT bin limits for D-meson efficiency"}; Configurable> binsPtEfficiencyHad{"binsPtEfficiencyHad", std::vector{0.3, 2., 4., 8., 12., 50.}, "pT bin limits for associated particle efficiency"}; Configurable> efficiencyD{"efficiencyD", {1., 1., 1., 1., 1., 1.}, "efficiency values for Ds meson"}; @@ -43,24 +45,32 @@ struct HfTaskCorrelationDsHadrons { Configurable> sidebandLeftOuter{"sidebandLeftOuter", {1.9040, 1.9040, 1.9040, 1.9040, 1.9040, 1.9040, 1.9040, 1.9040}, "Outer values of left sideband vs pT"}; Configurable> sidebandRightInner{"sidebandRightInner", {2.0000, 2.0000, 2.0000, 2.0000, 2.0000, 2.0000, 2.0000, 2.0000}, "Inner values of right sideband vs pT"}; Configurable> sidebandRightOuter{"sidebandRightOuter", {2.0320, 2.0320, 2.0320, 2.0320, 2.0320, 2.0320, 2.0320, 2.0320}, "Outer values of right sideband vs pT"}; + ConfigurableAxis binsMassD{"binsMassD", {200, 1.7, 2.25}, "inv. mass (K^{#pm}K^{-}#pi^{+}) (GeV/#it{c}^{2})"}; + ConfigurableAxis binsBdtScore{"binsBdtScore", {100, 0., 1.}, "Bdt output scores"}; ConfigurableAxis binsEta{"binsEta", {100, -2., 2.}, "#it{#eta}"}; ConfigurableAxis binsPhi{"binsPhi", {64, -PIHalf, 3. * PIHalf}, "#it{#varphi}"}; ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; using DsHadronPairFull = soa::Join; + using DsHadronPairFullWithMl = soa::Join; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { + AxisSpec axisMassD = {binsMassD, "inv. mass (K^{#pm}K^{-}#pi^{+}) (GeV/#it{c}^{2})"}; AxisSpec axisDetlaEta = {binsEta, "#it{#eta}^{Hadron}-#it{#eta}^{D}"}; AxisSpec axisDetlaPhi = {binsPhi, "#it{#varphi}^{Hadron}-#it{#varphi}^{D} (rad)"}; AxisSpec axisPtD = {(std::vector)binsPtD, "#it{p}_{T}^{D} (GeV/#it{c})"}; AxisSpec axisPtHadron = {(std::vector)binsPtHadron, "#it{p}_{T}^{Hadron} (GeV/#it{c})"}; AxisSpec axisPoolBin = {binsPoolBin, "poolBin"}; + AxisSpec axisBdtScore = {binsBdtScore, "Bdt score"}; AxisSpec axisDsPrompt = {2, -0.5, 1.5, "Prompt Ds"}; // Histograms for data analysis + registry.add("hMassDsVsPt", "Ds candidates massVsPt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hBdtScorePrompt", "Ds BDT prompt score", {HistType::kTH1F, {axisBdtScore}}); + registry.add("hBdtScoreBkg", "Ds BDT bkg score", {HistType::kTH1F, {axisBdtScore}}); registry.add("hDeltaEtaPtIntSignalRegion", "Ds-h deltaEta signal region", {HistType::kTH1F, {axisDetlaEta}}); registry.add("hDeltaPhiPtIntSignalRegion", "Ds-h deltaPhi signal region", {HistType::kTH1F, {axisDetlaPhi}}); registry.add("hCorrel2DVsPtSignalRegion", "Ds-h correlations signal region", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); @@ -91,22 +101,48 @@ struct HfTaskCorrelationDsHadrons { registry.get(HIST("hCorrel2DVsPtMcGenPromptDivision"))->Sumw2(); } - void processData(DsHadronPairFull const& pairEntries) + void processData(DsHadronPairFullWithMl const& pairEntries, + aod::DsCandRecoInfo const& candidates) { + for (const auto& candidate : candidates) { + float massD = candidate.mD(); + float ptD = candidate.ptD(); + float bdtScorePrompt = candidate.mlScorePrompt(); + float bdtScoreBkg = candidate.mlScoreBkg(); + int ptBinD = o2::analysis::findBin(binsPtD, ptD); + + if (bdtScorePrompt < mlOutputPrompt->at(ptBinD) || bdtScoreBkg > mlOutputBkg->at(ptBinD)) { + continue; + } + double efficiencyWeightD = 1.; + if (applyEfficiency) { + efficiencyWeightD = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); + } + registry.fill(HIST("hMassDsVsPt"), massD, ptD, efficiencyWeightD); + registry.fill(HIST("hBdtScorePrompt"), bdtScorePrompt); + registry.fill(HIST("hBdtScoreBkg"), bdtScoreBkg); + } + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities - double deltaPhi = pairEntry.deltaPhi(); - double deltaEta = pairEntry.deltaEta(); - double ptD = pairEntry.ptD(); - double ptHadron = pairEntry.ptHadron(); + float deltaPhi = pairEntry.deltaPhi(); + float deltaEta = pairEntry.deltaEta(); + float ptD = pairEntry.ptD(); + float ptHadron = pairEntry.ptHadron(); + float massD = pairEntry.mD(); + float bdtScorePrompt = pairEntry.mlScorePrompt(); + float bdtScoreBkg = pairEntry.mlScoreBkg(); int poolBin = pairEntry.poolBin(); - double massD = pairEntry.mD(); int ptBinD = o2::analysis::findBin(binsPtD, ptD); + if (bdtScorePrompt < mlOutputPrompt->at(ptBinD) || bdtScoreBkg > mlOutputBkg->at(ptBinD)) { + continue; + } double efficiencyWeight = 1.; if (applyEfficiency) { efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); } + // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); @@ -129,15 +165,15 @@ struct HfTaskCorrelationDsHadrons { { for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities - double deltaPhi = pairEntry.deltaPhi(); - double deltaEta = pairEntry.deltaEta(); - double ptD = pairEntry.ptD(); - double ptHadron = pairEntry.ptHadron(); + float deltaPhi = pairEntry.deltaPhi(); + float deltaEta = pairEntry.deltaEta(); + float ptD = pairEntry.ptD(); + float ptHadron = pairEntry.ptHadron(); + float massD = pairEntry.mD(); int poolBin = pairEntry.poolBin(); - double massD = pairEntry.mD(); int statusDsPrompt = static_cast(pairEntry.isPrompt()); - bool isPhysicalPrimary = pairEntry.isPhysicalPrimary(); int ptBinD = o2::analysis::findBin(binsPtD, ptD); + bool isPhysicalPrimary = pairEntry.isPhysicalPrimary(); double efficiencyWeight = 1.; if (applyEfficiency) { @@ -148,12 +184,12 @@ struct HfTaskCorrelationDsHadrons { registry.fill(HIST("hCorrel2DVsPtSignalRegionMcRec"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegionMcRec"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegionMcRec"), deltaPhi, efficiencyWeight); - if (isPhysicalPrimary) { - registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); - } // prompt and non-prompt division if (pairEntry.isSignal()) { registry.fill(HIST("hCorrel2DVsPtSignalRegionMcRecPromptDivision"), deltaPhi, deltaEta, ptD, ptHadron, statusDsPrompt, poolBin, efficiencyWeight); + if (isPhysicalPrimary) { + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + } } } // in sideband region @@ -172,10 +208,10 @@ struct HfTaskCorrelationDsHadrons { { for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities - double deltaPhi = pairEntry.deltaPhi(); - double deltaEta = pairEntry.deltaEta(); - double ptD = pairEntry.ptD(); - double ptHadron = pairEntry.ptHadron(); + float deltaPhi = pairEntry.deltaPhi(); + float deltaEta = pairEntry.deltaEta(); + float ptD = pairEntry.ptD(); + float ptHadron = pairEntry.ptHadron(); int poolBin = pairEntry.poolBin(); int statusDsPrompt = static_cast(pairEntry.isPrompt()); @@ -186,6 +222,45 @@ struct HfTaskCorrelationDsHadrons { } } PROCESS_SWITCH(HfTaskCorrelationDsHadrons, processMcGen, "Process MC Gen mode", false); + + void processDataME(DsHadronPairFullWithMl const& pairEntries) + { + for (const auto& pairEntry : pairEntries) { + // define variables for widely used quantities + float deltaPhi = pairEntry.deltaPhi(); + float deltaEta = pairEntry.deltaEta(); + float ptD = pairEntry.ptD(); + float ptHadron = pairEntry.ptHadron(); + float massD = pairEntry.mD(); + float bdtScorePrompt = pairEntry.mlScorePrompt(); + float bdtScoreBkg = pairEntry.mlScoreBkg(); + int poolBin = pairEntry.poolBin(); + int ptBinD = o2::analysis::findBin(binsPtD, ptD); + + if (bdtScorePrompt < mlOutputPrompt->at(ptBinD) || bdtScoreBkg > mlOutputBkg->at(ptBinD)) { + continue; + } + double efficiencyWeight = 1.; + if (applyEfficiency) { + efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); + } + + // in signal region + if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { + registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSignalRegion"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSignalRegion"), deltaPhi, efficiencyWeight); + } + // in sideband region + if ((massD > sidebandLeftOuter->at(ptBinD) && massD < sidebandLeftInner->at(ptBinD)) || + (massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD))) { + registry.fill(HIST("hCorrel2DVsPtSidebands"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebands"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebands"), deltaPhi, efficiencyWeight); + } + } + } + PROCESS_SWITCH(HfTaskCorrelationDsHadrons, processDataME, "Process data ME", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/HFL/Tasks/CMakeLists.txt b/PWGHF/HFL/Tasks/CMakeLists.txt index 1e1596f32f9..08579ab236e 100644 --- a/PWGHF/HFL/Tasks/CMakeLists.txt +++ b/PWGHF/HFL/Tasks/CMakeLists.txt @@ -23,3 +23,8 @@ o2physics_add_dpl_workflow(task-single-muon-source SOURCES taskSingleMuonSource.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(task-single-muon-reader + SOURCES taskSingleMuonReader.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) diff --git a/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx b/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx new file mode 100644 index 00000000000..19596aec9a8 --- /dev/null +++ b/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx @@ -0,0 +1,108 @@ +// 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 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" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using MyCollisions = soa::Join; +using MyMuons = soa::Join; + +struct HfTaskSingleMuonReader { + Configurable trkType{"trkType", 0, "Muon track type, valid values are 0, 1, 2, 3 and 4"}; + Configurable etaMin{"etaMin", -3.6, "eta minimum value"}; + Configurable etaMax{"etaMax", -2.5, "eta maximum value"}; + Configurable pDcaMax{"pDcaMax", 594., "p*DCA maximum value"}; + Configurable rAbsMax{"rAbsMax", 89.5, "R at absorber end maximum value"}; + Configurable rAbsMin{"rAbsMin", 26.5, "R at absorber end minimum value"}; + Configurable zVtx{"zVtx", 10., "Z edge of primary vertex [cm]"}; + + o2::framework::HistogramRegistry registry{ + "registry", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + void init(InitContext&) + { + AxisSpec axisPt{200, 0., 100., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisEta{100, -4., -2., "#it{#eta}"}; + AxisSpec axisDCA{400, 0., 4., "#it{DCA}_{xy} (cm)"}; + AxisSpec axisChi2MatchMCHMFT{100, 0., 100., "MCH-MFT matching #chi^{2}"}; + AxisSpec axisSign{5, -2.5, 2.5, "Charge"}; + AxisSpec axisDeltaPt{10000, -50, 50, "#Delta #it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisVtxZ{80, -20., 20., "#it{z}_{vtx} (cm)"}; + + HistogramConfigSpec hTHnMu{HistType::kTHnSparseF, {axisPt, axisEta, axisDCA, axisSign, axisChi2MatchMCHMFT, axisDeltaPt}, 6}; + HistogramConfigSpec hVtxZ{HistType::kTH1F, {axisVtxZ}}; + + registry.add("hMuAfterCuts", "", hTHnMu); + registry.add("hVtxZ", "", hVtxZ); + } + + void process(MyCollisions::iterator const& collision, MyMuons const& muons) + { + registry.fill(HIST("hVtxZ"), collision.posZ()); + for (const auto& muon : muons) { + if (muon.trackType() != trkType) { + continue; + } + + const auto eta(muon.eta()), pDca(muon.pDca()); + const auto rAbs(muon.rAtAbsorberEnd()); + const auto dcaXY(RecoDecay::sqrtSumOfSquares(muon.fwdDcaX(), muon.fwdDcaY())); + const auto pt(muon.pt()); + const auto charge(muon.sign()); + const auto chi2(muon.chi2MatchMCHMFT()); + + if ((eta >= etaMax) || (eta < etaMin)) { + continue; + } + if ((rAbs >= rAbsMax) || (rAbs < rAbsMin)) { + continue; + } + if (pDca >= pDcaMax) { + continue; + } + + // histograms after acceptance cuts + if (muon.has_matchMCHTrack()) { + auto muonType3 = muon.matchMCHTrack_as(); + auto Dpt = muonType3.pt() - pt; + registry.fill(HIST("hMuAfterCuts"), pt, eta, dcaXY, charge, chi2, Dpt); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx index 7fcc5668520..8fe5020cb9e 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx @@ -303,9 +303,6 @@ struct HfTaskSingleMuonSource { aod::McParticles const&) { // event selections - if (!collision.sel8()) { - return; - } if (std::abs(collision.posZ()) > edgeZ) { return; } diff --git a/PWGHF/Tasks/taskMcValidation.cxx b/PWGHF/Tasks/taskMcValidation.cxx index 9fb6e0e6026..7dee6fe4443 100644 --- a/PWGHF/Tasks/taskMcValidation.cxx +++ b/PWGHF/Tasks/taskMcValidation.cxx @@ -36,25 +36,34 @@ using namespace o2::framework::expressions; namespace { -static const int nCharmHadrons = 7; -static const std::array PDGArrayParticle = {o2::constants::physics::Pdg::kDPlus, o2::constants::physics::Pdg::kDStar, o2::constants::physics::Pdg::kD0, o2::constants::physics::Pdg::kDS, o2::constants::physics::Pdg::kLambdaCPlus, o2::constants::physics::Pdg::kXiCPlus, o2::constants::physics::Pdg::kJPsi}; -static const std::array nDaughters = {3, 3, 2, 3, 3, 3, 2}; -static const std::array, nCharmHadrons> arrPDGFinal = {{{kPiPlus, kPiPlus, -kKPlus}, {kPiPlus, kPiPlus, -kKPlus}, {-kKPlus, kPiPlus, 0}, {kPiPlus, kKPlus, -kKPlus}, {kProton, -kKPlus, kPiPlus}, {kProton, -kKPlus, kPiPlus}, {kElectron, -kElectron, 0}}}; -static const std::array labels = {"D^{+}", "D*^{+}", "D^{0}", "D_{s}^{+}", "#Lambda_{c}^{+}", "#Xi_{c}^{+}", "J/#psi"}; -static const std::array particleNames = {"Dplus", "Dstar", "D0", "Ds", "Lc2pKpi", "Xic2pKpi", "Jpsi2ee"}; +enum DecayChannels { DzeroToKPi = 0, + DstarToDzeroPi, + DplusToPiKPi, + DplusToPhiPiToKKPi, // resonant channel with Phi, Dplus -> PhiPi -> KKPi + DsToPhiPiToKKPi, // resonant channel with Phi, Ds -> PhiPi -> KKPi + LcToPKPi, + LcToPiK0s, + XicToPKPi, + nChannels }; // always keep nChannels at the end + +static const std::array PDGArrayParticle = {o2::constants::physics::Pdg::kD0, o2::constants::physics::Pdg::kDStar, o2::constants::physics::Pdg::kDPlus, o2::constants::physics::Pdg::kDPlus, + o2::constants::physics::Pdg::kDS, o2::constants::physics::Pdg::kLambdaCPlus, o2::constants::physics::Pdg::kLambdaCPlus, o2::constants::physics::Pdg::kXiCPlus}; +static const std::array nDaughters = {2, 3, 3, 3, 3, 3, 3, 3}; +static const std::array maxDepthForSearch = {1, 2, 2, 2, 2, 2, 3, 2}; +// keep coherent indexing with PDGArrayParticle +// FIXME: look for a better solution +static const std::array, nChannels> arrPDGFinal2Prong = {{{+kPiPlus, -kKPlus}, {}, {}, {}, {}, {}, {}, {}}}; +static const std::array, nChannels> arrPDGFinal3Prong = {{{}, {+kPiPlus, -kKPlus, +kPiPlus}, {+kPiPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {+kProton, -kKPlus, +kPiPlus}, {+kProton, -kPiPlus, +kPiPlus}, {+kProton, -kKPlus, +kPiPlus}}}; +static const std::array labels = {"D^{0} #rightarrow K#pi", "D*^{+} #rightarrow D^{0}#pi", "D^{+} #rightarrow K#pi#pi", "D^{+} #rightarrow KK#pi", + "D_{s}^{+} #rightarrow KK#pi", "#Lambda_{c}^{+} #rightarrow pK#pi", "#Lambda_{c}^{+} #rightarrow pK^{0}_{s}", "#Xi_{c}^{+} #rightarrow pK#pi"}; +static const std::array particleNames = {"DzeroToKPi", "DstarToDzeroPi", "DplusToPiKPi", "DplusToKKpi", "DsToKKpi", "LcToPKPi", "LcToPiK0s", "XiCplusToPKPi"}; static const std::array originNames = {"Prompt", "NonPrompt"}; } // namespace /// Generated Level Validation /// /// - Number of HF quarks produced per collision -/// - Number of D± → π± K∓ π± per collision -/// D*± → π± K∓ π±, -/// D0(bar) → π± K∓, -/// Ds± → K± K∓ π±, -/// Λc± → p(bar) K∓ π± -/// Ξc± → p(bar) K∓ π± -/// J/psi → e∓ e± +/// - Number of candidates per collision /// - Momentum Conservation for these particles struct HfTaskMcValidationGen { @@ -71,7 +80,7 @@ struct HfTaskMcValidationGen { AxisSpec axisResiduals{100, -0.01, 0.01}; AxisSpec axisPt{100, 0., 50.}; AxisSpec axisY{100, -5., 5.}; - AxisSpec axisSpecies{7, -0.5, 6.5}; + AxisSpec axisSpecies{nChannels, -0.5, static_cast(nChannels) - 0.5}; AxisSpec axisDecLen{100, 0., 10000.}; HistogramRegistry registry{ @@ -82,42 +91,44 @@ struct HfTaskMcValidationGen { {"hPyDiffMotherDaughterGen", "Py Difference Mother-Daughters; #Delta#it{p}_{y}^{gen} (GeV/#it{c}); entries", {HistType::kTH1F, {axisResiduals}}}, {"hPzDiffMotherDaughterGen", "Pz Difference Mother-Daughters; #Delta#it{p}_{z}^{gen} (GeV/#it{c}); entries", {HistType::kTH1F, {axisResiduals}}}, {"hPDiffMotherDaughterGen", "P Difference Mother-Daughters; #Delta#it{p}^{gen} (GeV/#it{c}); entries", {HistType::kTH1F, {axisResiduals}}}, - {"hCountAverageC", "Event counter - Average Number Charm quark; Events Per Collision; entries", {HistType::kTH1F, {axisNquarks}}}, - {"hCountAverageB", "Event counter - Average Number Beauty quark; Events Per Collision; entries", {HistType::kTH1F, {axisNquarks}}}, - {"hCountAverageCbar", "Event counter - Average Number Anti-Charm quark; Events Per Collision; entries", {HistType::kTH1F, {axisNquarks}}}, - {"hCountAverageBbar", "Event counter - Average Number Anti-Beauty quark; Events Per Collision; entries", {HistType::kTH1F, {axisNquarks}}}, - {"hCounterPerCollisionPromptDzero", "Event counter - prompt D0; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionPromptDplus", "Event counter - prompt DPlus; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionPromptDs", "Event counter - prompt Ds; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionPromptDstar", "Event counter - prompt Dstar; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionPromptLambdaC", "Event counter - prompt LambdaC; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionPromptXiC", "Event counter - prompt XiC; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionPromptJPsi", "Event counter - prompt JPsi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionNonPromptDzero", "Event counter - non-prompt D0; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionNonPromptDplus", "Event counter - non-prompt DPlus; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionNonPromptDs", "Event counter - non-prompt Ds; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionNonPromptDstar", "Event counter - non-prompt Dstar; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionNonPromptLambdaC", "Event counter - non-prompt LambdaC; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionNonPromptXiC", "Event counter - non-prompt XiC; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hCounterPerCollisionNonPromptJPsi", "Event counter - non-prompt JPsi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, - {"hPtVsYCharmQuark", "Y vs. Pt - charm quarks ; #it{p}_{T}^{gen} (GeV/#it{c}); #it{y}^{gen}", {HistType::kTH2F, {axisPt, axisY}}}, - {"hPtVsYBeautyQuark", "Y vs. Pt - beauty quarks ; #it{p}_{T}^{gen} (GeV/#it{c}); #it{y}^{gen}", {HistType::kTH2F, {axisPt, axisY}}}, - {"hPromptCharmHadronsPtDistr", "Pt distribution vs prompt charm hadron in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c})", {HistType::kTH2F, {axisSpecies, axisPt}}}, - {"hPromptCharmHadronsYDistr", "Y distribution vs prompt charm hadron; ; #it{y}^{gen}", {HistType::kTH2F, {axisSpecies, axisY}}}, - {"hPromptCharmHadronsDecLenDistr", "Decay length distribution vs prompt charm hadron; ; decay length (#mum)", {HistType::kTH2F, {axisSpecies, axisDecLen}}}, - {"hNonPromptCharmHadronsPtDistr", "Pt distribution vs non-prompt charm hadron in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c})", {HistType::kTH2F, {axisSpecies, axisPt}}}, - {"hNonPromptCharmHadronsYDistr", "Y distribution vs non-prompt charm hadron; ; #it{y}^{gen}", {HistType::kTH2F, {axisSpecies, axisY}}}, - {"hNonPromptCharmHadronsDecLenDistr", "Decay length distribution vs non-prompt charm hadron; ; decay length (#mum)", {HistType::kTH2F, {axisSpecies, axisDecLen}}}}}; + {"quarks/hCountC", "Event counter - Number of charm quarks; Events Per Collision; entries", {HistType::kTH1F, {axisNquarks}}}, + {"quarks/hCountB", "Event counter - Number of beauty quarks; Events Per Collision; entries", {HistType::kTH1F, {axisNquarks}}}, + {"quarks/hCountCbar", "Event counter - Number of anti-charm quarks; Events Per Collision; entries", {HistType::kTH1F, {axisNquarks}}}, + {"quarks/hCountBbar", "Event counter - Number of anti-beauty quarks; Events Per Collision; entries", {HistType::kTH1F, {axisNquarks}}}, + {"quarks/hPtVsYCharmQuark", "Y vs. Pt - charm quarks ; #it{p}_{T}^{gen} (GeV/#it{c}); #it{y}^{gen}", {HistType::kTH2F, {axisPt, axisY}}}, + {"quarks/hPtVsYBeautyQuark", "Y vs. Pt - beauty quarks ; #it{p}_{T}^{gen} (GeV/#it{c}); #it{y}^{gen}", {HistType::kTH2F, {axisPt, axisY}}}, + {"promptCharmHadrons/hCountPromptDzeroToKPi", "Event counter - Prompt D0 to KPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"promptCharmHadrons/hCountPromptDstarToD0Pi", "Event counter - Prompt Dstar to D0Pi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"promptCharmHadrons/hCountPromptDplusToKPiPi", "Event counter - Prompt DPlus to KPiPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"promptCharmHadrons/hCountPromptDplusToKKPi", "Event counter - Prompt DPlus to KKPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"promptCharmHadrons/hCountPromptDsToKKpi", "Event counter - Prompt Ds to KKPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"promptCharmHadrons/hCountPromptLambdaCToPKPi", "Event counter - Prompt LambdaC to PKPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"promptCharmHadrons/hCountPromptLambdaCToPK0s", "Event counter - Prompt LambdaC to PK0s; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"promptCharmHadrons/hCountPromptXiCToPKPi", "Event counter - Prompt XiC to PKPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"nonPromptCharmHadrons/hCountNonPromptDzeroToKPi", "Event counter - Non-prompt D0 to KPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"nonPromptCharmHadrons/hCountNonPromptDstarToD0Pi", "Event counter - Non-prompt Dstar to D0Pi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"nonPromptCharmHadrons/hCountNonPromptDplusToKPiPi", "Event counter - Non-prompt DPlus to KPiPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"nonPromptCharmHadrons/hCountNonPromptDplusToKKPi", "Event counter - Non-prompt DPlus to KKPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"nonPromptCharmHadrons/hCountNonPromptDsToKKpi", "Event counter - Non-prompt Ds to KKP; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"nonPromptCharmHadrons/hCountNonPromptLambdaCToPKPi", "Event counter - Non-prompt LambdaC to PKPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"nonPromptCharmHadrons/hCountNonPromptLambdaCToPK0s", "Event counter - Non-prompt LambdaC to PK0s; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"nonPromptCharmHadrons/hCountNonPromptXiCToPKPi", "Event counter - Non-prompt XiC to PKPi; Events Per Collision; entries", {HistType::kTH1F, {axisNhadrons}}}, + {"promptCharmHadrons/hPromptPtDistr", "Pt distribution vs prompt charm hadron in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c})", {HistType::kTH2F, {axisSpecies, axisPt}}}, + {"promptCharmHadrons/hPromptYDistr", "Y distribution vs prompt charm hadron; ; #it{y}^{gen}", {HistType::kTH2F, {axisSpecies, axisY}}}, + {"promptCharmHadrons/hPromptDecLenDistr", "Decay length distribution vs prompt charm hadron; ; decay length (#mum)", {HistType::kTH2F, {axisSpecies, axisDecLen}}}, + {"nonPromptCharmHadrons/hNonPromptPtDistr", "Pt distribution vs non-prompt charm hadron in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c})", {HistType::kTH2F, {axisSpecies, axisPt}}}, + {"nonPromptCharmHadrons/hNonPromptYDistr", "Y distribution vs non-prompt charm hadron; ; #it{y}^{gen}", {HistType::kTH2F, {axisSpecies, axisY}}}, + {"nonPromptCharmHadrons/hNonPromptDecLenDistr", "Decay length distribution vs non-prompt charm hadron; ; decay length (#mum)", {HistType::kTH2F, {axisSpecies, axisDecLen}}}}}; void init(InitContext&) { - for (auto iBin = 1; iBin <= nCharmHadrons; ++iBin) { - registry.get(HIST("hPromptCharmHadronsPtDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); - registry.get(HIST("hPromptCharmHadronsYDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); - registry.get(HIST("hPromptCharmHadronsDecLenDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); - registry.get(HIST("hNonPromptCharmHadronsPtDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); - registry.get(HIST("hNonPromptCharmHadronsYDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); - registry.get(HIST("hNonPromptCharmHadronsDecLenDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); + for (auto iBin = 1; iBin <= nChannels; ++iBin) { + registry.get(HIST("promptCharmHadrons/hPromptPtDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); + registry.get(HIST("promptCharmHadrons/hPromptYDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); + registry.get(HIST("promptCharmHadrons/hPromptDecLenDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); + registry.get(HIST("nonPromptCharmHadrons/hNonPromptPtDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); + registry.get(HIST("nonPromptCharmHadrons/hNonPromptYDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); + registry.get(HIST("nonPromptCharmHadrons/hNonPromptDecLenDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); } } @@ -155,7 +166,7 @@ struct HfTaskMcValidationGen { int cBarPerCollision = 0; int bPerCollision = 0; int bBarPerCollision = 0; - std::array counterPrompt{0}, counterNonPrompt{0}; + std::array counterPrompt{0}, counterNonPrompt{0}; for (const auto& particle : mcParticles) { if (!particle.has_mothers()) { @@ -163,24 +174,30 @@ struct HfTaskMcValidationGen { } int particlePdgCode = particle.pdgCode(); - auto mother = particle.mothers_as().front(); - if (particlePdgCode != mother.pdgCode()) { + bool isDiffFromMothers = true; + for (const auto& mother : particle.mothers_as()) { + if (particlePdgCode == mother.pdgCode()) { + isDiffFromMothers = false; + break; + } + } + if (isDiffFromMothers) { switch (particlePdgCode) { case kCharm: cPerCollision++; - registry.fill(HIST("hPtVsYCharmQuark"), particle.pt(), particle.y()); + registry.fill(HIST("quarks/hPtVsYCharmQuark"), particle.pt(), particle.y()); break; case kCharmBar: cBarPerCollision++; - registry.fill(HIST("hPtVsYCharmQuark"), particle.pt(), particle.y()); + registry.fill(HIST("quarks/hPtVsYCharmQuark"), particle.pt(), particle.y()); break; case kBottom: bPerCollision++; - registry.fill(HIST("hPtVsYBeautyQuark"), particle.pt(), particle.y()); + registry.fill(HIST("quarks/hPtVsYBeautyQuark"), particle.pt(), particle.y()); break; case kBottomBar: bBarPerCollision++; - registry.fill(HIST("hPtVsYBeautyQuark"), particle.pt(), particle.y()); + registry.fill(HIST("quarks/hPtVsYBeautyQuark"), particle.pt(), particle.y()); break; } } @@ -191,11 +208,32 @@ struct HfTaskMcValidationGen { continue; } - // Check that the number of daughters match what we expect std::vector listDaughters{}; - RecoDecay::getDaughters(particle, &listDaughters, arrPDGFinal[iD], -1); - if (listDaughters.size() != nDaughters[iD]) { - continue; + + // Check that the decay channel is correct and retrieve the daughters + if (nDaughters[iD] == 2) { + if (!RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], arrPDGFinal2Prong[iD], true, nullptr, maxDepthForSearch[iD], &listDaughters)) { + continue; + } + } else if (nDaughters[iD] == 3) { + if (!RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], arrPDGFinal3Prong[iD], true, nullptr, maxDepthForSearch[iD], &listDaughters)) { + continue; + } + if (iD == DstarToDzeroPi && + !RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], std::array{+o2::constants::physics::Pdg::kD0, +kPiPlus}, true)) { + continue; + } + if ((iD == DplusToPhiPiToKKPi || iD == DsToPhiPiToKKPi) && + !RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], std::array{+o2::constants::physics::Pdg::kPhi, +kPiPlus}) && + !RecoDecay::isMatchedMCGen(mcParticles, particle, -PDGArrayParticle[iD], std::array{+o2::constants::physics::Pdg::kPhi, -kPiPlus})) { + continue; + } + // TODO: check if particles are recovered after isMatchedMCGen update to skip daughters from material + if (iD == LcToPiK0s && + !RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], std::array{+kK0Short, +kProton}, false, nullptr, 2) && + !RecoDecay::isMatchedMCGen(mcParticles, particle, -PDGArrayParticle[iD], std::array{+kK0Short, -kProton}, false, nullptr, 2)) { + continue; + } } // Check momentum conservation @@ -224,10 +262,6 @@ struct HfTaskMcValidationGen { registry.fill(HIST("hPDiffMotherDaughterGen"), pDiff); registry.fill(HIST("hPtDiffMotherDaughterGen"), ptDiff); - if (!momentumCheck) { - continue; - } - int origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); if (origin == RecoDecay::OriginType::Prompt) { counterPrompt[iD]++; @@ -241,60 +275,56 @@ struct HfTaskMcValidationGen { auto decayLength = RecoDecay::distance(vertexPrimary, vertexDau); if (origin == RecoDecay::OriginType::Prompt) { if (std::abs(particle.y()) < 0.5) { - registry.fill(HIST("hPromptCharmHadronsPtDistr"), iD, particle.pt()); + registry.fill(HIST("promptCharmHadrons/hPromptPtDistr"), iD, particle.pt()); } - registry.fill(HIST("hPromptCharmHadronsYDistr"), iD, particle.y()); - registry.fill(HIST("hPromptCharmHadronsDecLenDistr"), iD, decayLength * 10000); + registry.fill(HIST("promptCharmHadrons/hPromptYDistr"), iD, particle.y()); + registry.fill(HIST("promptCharmHadrons/hPromptDecLenDistr"), iD, decayLength * 10000); } else if (origin == RecoDecay::OriginType::NonPrompt) { if (std::abs(particle.y()) < 0.5) { - registry.fill(HIST("hNonPromptCharmHadronsPtDistr"), iD, particle.pt()); + registry.fill(HIST("nonPromptCharmHadrons/hNonPromptPtDistr"), iD, particle.pt()); } - registry.fill(HIST("hNonPromptCharmHadronsYDistr"), iD, particle.y()); - registry.fill(HIST("hNonPromptCharmHadronsDecLenDistr"), iD, decayLength * 10000); + registry.fill(HIST("nonPromptCharmHadrons/hNonPromptYDistr"), iD, particle.y()); + registry.fill(HIST("nonPromptCharmHadrons/hNonPromptDecLenDistr"), iD, decayLength * 10000); } } } // end particles - registry.fill(HIST("hCountAverageC"), cPerCollision); - registry.fill(HIST("hCountAverageB"), bPerCollision); - registry.fill(HIST("hCountAverageCbar"), cBarPerCollision); - registry.fill(HIST("hCountAverageBbar"), bBarPerCollision); - registry.fill(HIST("hCounterPerCollisionPromptDplus"), counterPrompt[0]); - registry.fill(HIST("hCounterPerCollisionPromptDstar"), counterPrompt[1]); - registry.fill(HIST("hCounterPerCollisionPromptDzero"), counterPrompt[2]); - registry.fill(HIST("hCounterPerCollisionPromptDs"), counterPrompt[3]); - registry.fill(HIST("hCounterPerCollisionPromptLambdaC"), counterPrompt[4]); - registry.fill(HIST("hCounterPerCollisionPromptXiC"), counterPrompt[5]); - registry.fill(HIST("hCounterPerCollisionPromptJPsi"), counterPrompt[6]); - registry.fill(HIST("hCounterPerCollisionNonPromptDplus"), counterNonPrompt[0]); - registry.fill(HIST("hCounterPerCollisionNonPromptDstar"), counterNonPrompt[1]); - registry.fill(HIST("hCounterPerCollisionNonPromptDzero"), counterNonPrompt[2]); - registry.fill(HIST("hCounterPerCollisionNonPromptDs"), counterNonPrompt[3]); - registry.fill(HIST("hCounterPerCollisionNonPromptLambdaC"), counterNonPrompt[4]); - registry.fill(HIST("hCounterPerCollisionNonPromptXiC"), counterNonPrompt[5]); - registry.fill(HIST("hCounterPerCollisionNonPromptJPsi"), counterNonPrompt[6]); - } + registry.fill(HIST("quarks/hCountC"), cPerCollision); + registry.fill(HIST("quarks/hCountB"), bPerCollision); + registry.fill(HIST("quarks/hCountCbar"), cBarPerCollision); + registry.fill(HIST("quarks/hCountBbar"), bBarPerCollision); + registry.fill(HIST("promptCharmHadrons/hCountPromptDzeroToKPi"), counterPrompt[DzeroToKPi]); + registry.fill(HIST("promptCharmHadrons/hCountPromptDstarToD0Pi"), counterPrompt[DstarToDzeroPi]); + registry.fill(HIST("promptCharmHadrons/hCountPromptDplusToKPiPi"), counterPrompt[DplusToPiKPi]); + registry.fill(HIST("promptCharmHadrons/hCountPromptDplusToKKPi"), counterPrompt[DplusToPhiPiToKKPi]); + registry.fill(HIST("promptCharmHadrons/hCountPromptDsToKKpi"), counterPrompt[DsToPhiPiToKKPi]); + registry.fill(HIST("promptCharmHadrons/hCountPromptLambdaCToPKPi"), counterPrompt[LcToPKPi]); + registry.fill(HIST("promptCharmHadrons/hCountPromptLambdaCToPK0s"), counterPrompt[LcToPiK0s]); + registry.fill(HIST("promptCharmHadrons/hCountPromptXiCToPKPi"), counterPrompt[XicToPKPi]); + registry.fill(HIST("nonPromptCharmHadrons/hCountNonPromptDzeroToKPi"), counterNonPrompt[DzeroToKPi]); + registry.fill(HIST("nonPromptCharmHadrons/hCountNonPromptDstarToD0Pi"), counterNonPrompt[DstarToDzeroPi]); + registry.fill(HIST("nonPromptCharmHadrons/hCountNonPromptDplusToKPiPi"), counterNonPrompt[DplusToPiKPi]); + registry.fill(HIST("nonPromptCharmHadrons/hCountNonPromptDplusToKKPi"), counterNonPrompt[DplusToPhiPiToKKPi]); + registry.fill(HIST("nonPromptCharmHadrons/hCountNonPromptDsToKKpi"), counterNonPrompt[DsToPhiPiToKKPi]); + registry.fill(HIST("nonPromptCharmHadrons/hCountNonPromptLambdaCToPKPi"), counterNonPrompt[LcToPKPi]); + registry.fill(HIST("nonPromptCharmHadrons/hCountNonPromptLambdaCToPK0s"), counterNonPrompt[LcToPiK0s]); + registry.fill(HIST("nonPromptCharmHadrons/hCountNonPromptXiCToPKPi"), counterNonPrompt[XicToPKPi]); + }; }; /// Reconstruction Level Validation /// -/// D± → π± K∓ π± -/// Ds± → K± K∓ π±, -/// D0(bar) → π± K∓, -/// Λc± → p(bar) K∓ π± -/// Ξc± → p(bar) K∓ π± -/// J/psi → e∓ e± /// - Gen-Rec Level Momentum Difference per component; -/// - Gen-Rec Level Difference for secondary Vertex coordinates and decay length; +/// - Gen-Rec Level Difference for secondary-vertex coordinates and decay length; struct HfTaskMcValidationRec { SliceCache cache; Preslice perCol = aod::track::collisionId; Configurable eventGeneratorType{"eventGeneratorType", -1, "If positive, enable event selection using subGeneratorId information. The value indicates which events to keep (0 = MB, 4 = charm triggered, 5 = beauty triggered)"}; - std::array, nCharmHadrons> histDeltaPt, histDeltaPx, histDeltaPy, histDeltaPz, histDeltaSecondaryVertexX, histDeltaSecondaryVertexY, histDeltaSecondaryVertexZ, histDeltaDecayLength; - std::array, 3>, 2>, nCharmHadrons> histPtDau, histEtaDau, histImpactParameterDau; - std::array, 2>, nCharmHadrons> histPtReco; + std::array, nChannels> histDeltaPt, histDeltaPx, histDeltaPy, histDeltaPz, histDeltaSecondaryVertexX, histDeltaSecondaryVertexY, histDeltaSecondaryVertexZ, histDeltaDecayLength; + std::array, 3>, 2>, nChannels> histPtDau, histEtaDau, histImpactParameterDau; + std::array, 2>, nChannels> histPtReco; std::array, 4> histOriginTracks; std::shared_ptr histAmbiguousTracks, histTracks; std::shared_ptr histContributors; @@ -326,10 +356,10 @@ struct HfTaskMcValidationRec { {"histYvtxReco", "Position of reco PV in #it{Y};#it{Y}^{reco} (cm);entries", {HistType::kTH1F, {axisDeltaVtx}}}, {"histZvtxReco", "Position of reco PV in #it{Z};#it{Z}^{reco} (cm);entries", {HistType::kTH1F, {{200, -20, 20.}}}}, {"histDeltaZvtx", "Residual distribution of PV in #it{Z} as a function of number of contributors;number of contributors;#it{Z}^{reco} - #it{Z}^{gen} (cm);entries", {HistType::kTH2F, {{100, -0.5, 99.5}, {1000, -0.5, 0.5}}}}, - {"histAmbiguousTrackNumCollisions", "Number of collisions associated to an ambiguous track;number of collisions;entries", {HistType::kTH1F, {{30, -0.5, 29.5}}}}, - {"histAmbiguousTrackZvtxRMS", "RMS of #it{Z}^{reco} of collisions associated to a track;RMS(#it{Z}^{reco}) (cm);entries", {HistType::kTH1F, {{100, 0., 0.5}}}}, - {"histFracGoodContributors", "Fraction of PV contributors originating from the correct collision;fraction;entries", {HistType::kTH1F, {{101, 0., 1.01}}}}, - {"histCollisionsSameBC", "Collisions in same BC;number of contributors collision 1;number of contributors collision 2;#it{R}_{xy} collision 1 (cm);#it{R}_{xy} collision 2 (cm);number of contributors from beauty collision 1;number of contributors from beauty collision 2;", {HistType::kTHnSparseF, {axisMult, axisMult, axisR, axisR, axisSmallNum, axisSmallNum}}}}}; + {"trackToCollChecks/histAmbiguousTrackNumCollisions", "Number of collisions associated to an ambiguous track;number of collisions;entries", {HistType::kTH1F, {{30, -0.5, 29.5}}}}, + {"trackToCollChecks/histAmbiguousTrackZvtxRMS", "RMS of #it{Z}^{reco} of collisions associated to a track;RMS(#it{Z}^{reco}) (cm);entries", {HistType::kTH1F, {{100, 0., 0.5}}}}, + {"trackToCollChecks/histFracGoodContributors", "Fraction of PV contributors originating from the correct collision;fraction;entries", {HistType::kTH1F, {{101, 0., 1.01}}}}, + {"trackToCollChecks/histCollisionsSameBC", "Collisions in same BC;number of contributors collision 1;number of contributors collision 2;#it{R}_{xy} collision 1 (cm);#it{R}_{xy} collision 2 (cm);number of contributors from beauty collision 1;number of contributors from beauty collision 2;", {HistType::kTHnSparseF, {axisMult, axisMult, axisR, axisR, axisSmallNum, axisSmallNum}}}}}; /// RMS calculation /// \param vec vector of values to compute RMS @@ -347,19 +377,56 @@ struct HfTaskMcValidationRec { return stdev; } + /// Fill MC histograms with decay properties at reconstruction level + /// \param candidate is candidate + /// \param mother is mother particle + /// \param whichHad int indicating charm-hadron and decay channel, see enum DecayChannels + /// \param whichOrigin int indicating origin: prompt or non-prompt + template + void fillHisto(const T& candidate, const U& mother, int whichHad, int whichOrigin) + { + histDeltaPt[whichHad]->Fill(candidate.pt() - mother.pt()); + histDeltaPx[whichHad]->Fill(candidate.px() - mother.px()); + histDeltaPy[whichHad]->Fill(candidate.py() - mother.py()); + histDeltaPz[whichHad]->Fill(candidate.pz() - mother.pz()); + // Compare Secondary vertex and decay length with MC + 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); + + histDeltaSecondaryVertexX[whichHad]->Fill(candidate.xSecondaryVertex() - vertexDau[0]); + histDeltaSecondaryVertexY[whichHad]->Fill(candidate.ySecondaryVertex() - vertexDau[1]); + histDeltaSecondaryVertexZ[whichHad]->Fill(candidate.zSecondaryVertex() - vertexDau[2]); + histDeltaDecayLength[whichHad]->Fill(candidate.decayLength() - decayLength); + std::array momDau0 = {candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0()}; + std::array momDau1 = {candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1()}; + histPtReco[whichHad][whichOrigin]->Fill(candidate.pt()); + histPtDau[whichHad][whichOrigin][0]->Fill(RecoDecay::pt(momDau0)); + histEtaDau[whichHad][whichOrigin][0]->Fill(RecoDecay::eta(momDau0)); + histImpactParameterDau[whichHad][whichOrigin][0]->Fill(candidate.impactParameter0()); + histPtDau[whichHad][whichOrigin][1]->Fill(RecoDecay::pt(momDau1)); + histEtaDau[whichHad][whichOrigin][1]->Fill(RecoDecay::eta(momDau1)); + histImpactParameterDau[whichHad][whichOrigin][1]->Fill(candidate.impactParameter1()); + } + void init(InitContext&) { - histOriginTracks[0] = registry.add("histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks not associated to any collision - histOriginTracks[1] = registry.add("histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks associasted to a collision - histOriginTracks[2] = registry.add("histOriginGoodAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks associated to the correct collision considering only first reco collision (based on the MC collision index) - histOriginTracks[3] = registry.add("histOriginGoodAssociatedTracksAmbiguous", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks associated to the correct collision considering all ambiguous reco collisions (based on the MC collision index) + histOriginTracks[0] = registry.add("trackToCollChecks/histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks not associated to any collision + histOriginTracks[1] = registry.add("trackToCollChecks/histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks associasted to a collision + histOriginTracks[2] = registry.add("trackToCollChecks/histOriginGoodAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks associated to the correct collision considering only first reco collision (based on the MC collision index) + histOriginTracks[3] = registry.add("trackToCollChecks/histOriginGoodAssociatedTracksAmbiguous", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks associated to the correct collision considering all ambiguous reco collisions (based on the MC collision index) for (std::size_t iHist{0}; iHist < histOriginTracks.size(); ++iHist) { histOriginTracks[iHist]->GetAxis(0)->SetBinLabel(1, "no MC particle"); histOriginTracks[iHist]->GetAxis(0)->SetBinLabel(2, "no quark"); histOriginTracks[iHist]->GetAxis(0)->SetBinLabel(3, "charm"); histOriginTracks[iHist]->GetAxis(0)->SetBinLabel(4, "beauty"); } - histAmbiguousTracks = registry.add("histAmbiguousTracks", "Tracks that are ambiguous vs. origin;#it{p}_{T}^{reco} (GeV/#it{c});entries", HistType::kTH2F, {axisOrigin, axisPt}); + histAmbiguousTracks = registry.add("trackToCollChecks/histAmbiguousTracks", "Tracks that are ambiguous vs. origin;#it{p}_{T}^{reco} (GeV/#it{c});entries", HistType::kTH2F, {axisOrigin, axisPt}); histTracks = registry.add("histTracks", "Tracks vs. origin;#it{p}_{T}^{reco} (GeV/#it{c});entries", HistType::kTH2F, {axisOrigin, axisPt}); histTracks->GetXaxis()->SetBinLabel(1, "no MC particle"); histTracks->GetXaxis()->SetBinLabel(2, "no quark"); @@ -369,25 +436,25 @@ struct HfTaskMcValidationRec { histAmbiguousTracks->GetXaxis()->SetBinLabel(2, "no quark"); histAmbiguousTracks->GetXaxis()->SetBinLabel(3, "charm"); histAmbiguousTracks->GetXaxis()->SetBinLabel(4, "beauty"); - for (auto iHad = 0; iHad < nCharmHadrons; ++iHad) { - histDeltaPt[iHad] = registry.add(Form("histDeltaPt%s", particleNames[iHad].data()), Form("Pt difference reco - MC %s; #it{p}_{T}^{reco} - #it{p}_{T}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); - histDeltaPx[iHad] = registry.add(Form("histDeltaPx%s", particleNames[iHad].data()), Form("Px difference reco - MC %s; #it{p}_{x}^{reco} - #it{p}_{x}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); - histDeltaPy[iHad] = registry.add(Form("histDeltaPy%s", particleNames[iHad].data()), Form("Py difference reco - MC %s; #it{p}_{y}^{reco} - #it{p}_{y}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); - histDeltaPz[iHad] = registry.add(Form("histDeltaPz%s", particleNames[iHad].data()), Form("Pz difference reco - MC %s; #it{p}_{z}^{reco} - #it{p}_{z}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); - histDeltaSecondaryVertexX[iHad] = registry.add(Form("histDeltaSecondaryVertexX%s", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta x (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); - histDeltaSecondaryVertexY[iHad] = registry.add(Form("histDeltaSecondaryVertexY%s", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta y (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); - histDeltaSecondaryVertexZ[iHad] = registry.add(Form("histDeltaSecondaryVertexZ%s", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta z (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); - histDeltaDecayLength[iHad] = registry.add(Form("histDeltaDecayLength%s", particleNames[iHad].data()), Form("Decay length difference reco - MC (%s); #Delta L (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + for (auto iHad = 0; iHad < nChannels; ++iHad) { + histDeltaPt[iHad] = registry.add(Form("%s/histDeltaPt", particleNames[iHad].data()), Form("Pt difference reco - MC %s; #it{p}_{T}^{reco} - #it{p}_{T}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaPx[iHad] = registry.add(Form("%s/histDeltaPx", particleNames[iHad].data()), Form("Px difference reco - MC %s; #it{p}_{x}^{reco} - #it{p}_{x}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaPy[iHad] = registry.add(Form("%s/histDeltaPy", particleNames[iHad].data()), Form("Py difference reco - MC %s; #it{p}_{y}^{reco} - #it{p}_{y}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaPz[iHad] = registry.add(Form("%s/histDeltaPz", particleNames[iHad].data()), Form("Pz difference reco - MC %s; #it{p}_{z}^{reco} - #it{p}_{z}^{gen} (GeV/#it{c}); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaMom}); + histDeltaSecondaryVertexX[iHad] = registry.add(Form("%s/histDeltaSecondaryVertexX", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta x (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histDeltaSecondaryVertexY[iHad] = registry.add(Form("%s/histDeltaSecondaryVertexY", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta y (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histDeltaSecondaryVertexZ[iHad] = registry.add(Form("%s/histDeltaSecondaryVertexZ", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta z (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histDeltaDecayLength[iHad] = registry.add(Form("%s/histDeltaDecayLength", particleNames[iHad].data()), Form("Decay length difference reco - MC (%s); #Delta L (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); for (auto iOrigin = 0; iOrigin < 2; ++iOrigin) { - histPtReco[iHad][iOrigin] = registry.add(Form("histPtReco%s%s", originNames[iOrigin].data(), particleNames[iHad].data()), Form("Pt reco %s %s; #it{p}_{T}^{reco} (GeV/#it{c}); entries", originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPtD}); + histPtReco[iHad][iOrigin] = registry.add(Form("%s/histPtReco%s", particleNames[iHad].data(), originNames[iOrigin].data()), Form("Pt reco %s %s; #it{p}_{T}^{reco} (GeV/#it{c}); entries", originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPtD}); for (unsigned int iDau = 0; iDau < nDaughters[iHad]; ++iDau) { - histPtDau[iHad][iOrigin][iDau] = registry.add(Form("histPtDau%d%s%s", iDau, originNames[iOrigin].data(), particleNames[iHad].data()), Form("Daughter %d Pt reco - %s %s; #it{p}_{T}^{dau, reco} (GeV/#it{c}); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPt}); - histEtaDau[iHad][iOrigin][iDau] = registry.add(Form("histEtaDau%d%s%s", iDau, originNames[iOrigin].data(), particleNames[iHad].data()), Form("Daughter %d Eta reco - %s %s; #it{#eta}^{dau, reco}; entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {{100, -1., 1.}}); - histImpactParameterDau[iHad][iOrigin][iDau] = registry.add(Form("histImpactParameterDau%d%s%s", iDau, originNames[iOrigin].data(), particleNames[iHad].data()), Form("Daughter %d DCAxy reco - %s %s; DCAxy (cm); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); + histPtDau[iHad][iOrigin][iDau] = registry.add(Form("%s/histPtDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Pt reco - %s %s; #it{p}_{T}^{dau, reco} (GeV/#it{c}); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPt}); + histEtaDau[iHad][iOrigin][iDau] = registry.add(Form("%s/histEtaDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Eta reco - %s %s; #it{#eta}^{dau, reco}; entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {{100, -1., 1.}}); + histImpactParameterDau[iHad][iOrigin][iDau] = registry.add(Form("%s/histImpactParameterDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d DCAxy reco - %s %s; DCAxy (cm); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); } } } - histContributors = registry.add("histContributors", "PV contributors from correct/wrong MC collision;;entries", HistType::kTH1F, {axisDecision}); + histContributors = registry.add("trackToCollChecks/histContributors", "PV contributors from correct/wrong MC collision;;entries", HistType::kTH1F, {axisDecision}); histContributors->GetXaxis()->SetBinLabel(1, "correct MC collision"); histContributors->GetXaxis()->SetBinLabel(2, "wrong MC collision"); } @@ -435,7 +502,7 @@ struct HfTaskMcValidationRec { } } float frac = (nContributors > 0) ? static_cast(nGoodContributors) / nContributors : 1.; - registry.fill(HIST("histFracGoodContributors"), frac); + registry.fill(HIST("trackToCollChecks/histFracGoodContributors"), frac); uint64_t mostProbableBC = collision.bc().globalBC(); for (auto collision2 = collision + 1; collision2 != collisions.end(); ++collision2) { uint64_t mostProbableBC2 = collision2.bc().globalBC(); @@ -462,7 +529,7 @@ struct HfTaskMcValidationRec { } } } - registry.fill(HIST("histCollisionsSameBC"), collision.numContrib(), collision2.numContrib(), radColl1, radColl2, nFromBeautyColl1, nFromBeautyColl2); + registry.fill(HIST("trackToCollChecks/histCollisionsSameBC"), collision.numContrib(), collision2.numContrib(), radColl1, radColl2, nFromBeautyColl1, nFromBeautyColl2); break; } } @@ -489,7 +556,7 @@ struct HfTaskMcValidationRec { histTracks->Fill(origin, track.pt()); bool isAmbiguous = (track.compatibleCollIds().size() != 1); if (isAmbiguous) { - registry.fill(HIST("histAmbiguousTrackNumCollisions"), track.compatibleCollIds().size()); + registry.fill(HIST("trackToCollChecks/histAmbiguousTrackNumCollisions"), track.compatibleCollIds().size()); histAmbiguousTracks->Fill(origin, track.pt()); std::vector ambCollPosZ{}; for (const auto& collIdx : track.compatibleCollIds()) { @@ -498,7 +565,7 @@ struct HfTaskMcValidationRec { } // here we are only interested to tracks associated to multiple vertices if (ambCollPosZ.size() > 0) { - registry.fill(HIST("histAmbiguousTrackZvtxRMS"), computeRMS(ambCollPosZ)); + registry.fill(HIST("trackToCollChecks/histAmbiguousTrackZvtxRMS"), computeRMS(ambCollPosZ)); } } float deltaZ = -999.f; @@ -546,56 +613,30 @@ struct HfTaskMcValidationRec { // determine which kind of candidate it is bool isD0Sel = TESTBIT(cand2Prong.hfflag(), o2::aod::hf_cand_2prong::DecayType::D0ToPiK); - bool isJPsiSel = TESTBIT(cand2Prong.hfflag(), o2::aod::hf_cand_2prong::DecayType::JpsiToEE); - if (!isD0Sel && !isJPsiSel) { + if (!isD0Sel) { continue; } int whichHad = -1; if (isD0Sel && TESTBIT(std::abs(cand2Prong.flagMcMatchRec()), hf_cand_2prong::DecayType::D0ToPiK)) { - whichHad = 2; - } else if (isJPsiSel && TESTBIT(std::abs(cand2Prong.flagMcMatchRec()), hf_cand_2prong::DecayType::JpsiToEE)) { - whichHad = 6; + whichHad = DzeroToKPi; } - int whichOrigin = -1; + int whichOrigin; if (cand2Prong.originMcRec() == RecoDecay::OriginType::Prompt) { whichOrigin = 0; } else { whichOrigin = 1; } - if (whichHad >= 0 && whichOrigin >= 0) { - int indexParticle = 0; + if (whichHad >= 0) { + int indexParticle = -1; if (cand2Prong.prong0_as().has_mcParticle()) { indexParticle = RecoDecay::getMother(mcParticles, cand2Prong.prong0_as().mcParticle(), PDGArrayParticle[whichHad], true); } + if (indexParticle < 0) { + continue; + } auto mother = mcParticles.rawIteratorAt(indexParticle); - histDeltaPt[whichHad]->Fill(cand2Prong.pt() - mother.pt()); - histDeltaPx[whichHad]->Fill(cand2Prong.px() - mother.px()); - histDeltaPy[whichHad]->Fill(cand2Prong.py() - mother.py()); - histDeltaPz[whichHad]->Fill(cand2Prong.pz() - mother.pz()); - // Compare Secondary vertex and decay length with MC - auto daughter0 = mother.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); - - histDeltaSecondaryVertexX[whichHad]->Fill(cand2Prong.xSecondaryVertex() - vertexDau[0]); - histDeltaSecondaryVertexY[whichHad]->Fill(cand2Prong.ySecondaryVertex() - vertexDau[1]); - histDeltaSecondaryVertexZ[whichHad]->Fill(cand2Prong.zSecondaryVertex() - vertexDau[2]); - histDeltaDecayLength[whichHad]->Fill(cand2Prong.decayLength() - decayLength); - std::array momDau0 = {cand2Prong.pxProng0(), - cand2Prong.pyProng0(), - cand2Prong.pzProng0()}; - std::array momDau1 = {cand2Prong.pxProng1(), - cand2Prong.pyProng1(), - cand2Prong.pzProng1()}; - histPtReco[whichHad][whichOrigin]->Fill(cand2Prong.pt()); - histPtDau[whichHad][whichOrigin][0]->Fill(RecoDecay::pt(momDau0)); - histEtaDau[whichHad][whichOrigin][0]->Fill(RecoDecay::eta(momDau0)); - histImpactParameterDau[whichHad][whichOrigin][0]->Fill(cand2Prong.impactParameter0()); - histPtDau[whichHad][whichOrigin][1]->Fill(RecoDecay::pt(momDau1)); - histEtaDau[whichHad][whichOrigin][1]->Fill(RecoDecay::eta(momDau1)); - histImpactParameterDau[whichHad][whichOrigin][1]->Fill(cand2Prong.impactParameter1()); + fillHisto(cand2Prong, mother, whichHad, whichOrigin); } } // end loop on 2-prong candidates @@ -610,25 +651,31 @@ struct HfTaskMcValidationRec { } // determine which kind of candidate it is - bool isDPlusSel = TESTBIT(cand3Prong.hfflag(), o2::aod::hf_cand_3prong::DecayType::DplusToPiKPi); + bool isDPlusSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::DplusToPiKPi); bool isDStarSel = false; // FIXME: add proper check when D* will be added in HF vertexing - bool isDsSel = TESTBIT(cand3Prong.hfflag(), o2::aod::hf_cand_3prong::DecayType::DsToKKPi); - bool isLcSel = TESTBIT(cand3Prong.hfflag(), o2::aod::hf_cand_3prong::DecayType::LcToPKPi); - bool isXicSel = TESTBIT(cand3Prong.hfflag(), o2::aod::hf_cand_3prong::DecayType::XicToPKPi); - if (!isDPlusSel && !isDStarSel && !isDsSel && !isLcSel && !isXicSel) { + bool isDsSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::DsToKKPi); + bool isLcSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::LcToPKPi); + bool isLcToPK0sSel = false; // FIXME: add in case of integration with cascades + bool isXicSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::XicToPKPi); + if (!isDPlusSel && !isDStarSel && !isDsSel && !isLcSel && !isLcToPK0sSel && !isXicSel) { continue; } int whichHad = -1; if (isDPlusSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::DplusToPiKPi)) { - whichHad = 0; + whichHad = DplusToPiKPi; } else if (isDsSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::DsToKKPi)) { - whichHad = 3; + if (TESTBIT(std::abs(cand3Prong.flagMcDecayChanRec()), hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi)) { + whichHad = DsToPhiPiToKKPi; + } + if (TESTBIT(std::abs(cand3Prong.flagMcDecayChanRec()), hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi)) { + whichHad = DplusToPhiPiToKKPi; + } } else if (isLcSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::LcToPKPi)) { - whichHad = 4; + whichHad = LcToPKPi; } else if (isXicSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::XicToPKPi)) { - whichHad = 5; + whichHad = XicToPKPi; } - int whichOrigin = -1; + int whichOrigin; if (cand3Prong.originMcRec() == RecoDecay::OriginType::Prompt) { whichOrigin = 0; } else { @@ -636,41 +683,18 @@ struct HfTaskMcValidationRec { } if (whichHad >= 0) { - int indexParticle = 0; + int indexParticle = -1; if (cand3Prong.prong0_as().has_mcParticle()) { indexParticle = RecoDecay::getMother(mcParticles, cand3Prong.prong0_as().mcParticle(), PDGArrayParticle[whichHad], true); } + if (indexParticle < 0) { + continue; + } auto mother = mcParticles.rawIteratorAt(indexParticle); - histDeltaPt[whichHad]->Fill(cand3Prong.pt() - mother.pt()); - histDeltaPx[whichHad]->Fill(cand3Prong.px() - mother.px()); - histDeltaPy[whichHad]->Fill(cand3Prong.py() - mother.py()); - histDeltaPz[whichHad]->Fill(cand3Prong.pz() - mother.pz()); - // Compare Secondary vertex and decay length with MC - auto daughter0 = mother.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); - - histDeltaSecondaryVertexX[whichHad]->Fill(cand3Prong.xSecondaryVertex() - vertexDau[0]); - histDeltaSecondaryVertexY[whichHad]->Fill(cand3Prong.ySecondaryVertex() - vertexDau[1]); - histDeltaSecondaryVertexZ[whichHad]->Fill(cand3Prong.zSecondaryVertex() - vertexDau[2]); - histDeltaDecayLength[whichHad]->Fill(cand3Prong.decayLength() - decayLength); - std::array momDau0 = {cand3Prong.pxProng0(), - cand3Prong.pyProng0(), - cand3Prong.pzProng0()}; - std::array momDau1 = {cand3Prong.pxProng1(), - cand3Prong.pyProng1(), - cand3Prong.pzProng1()}; + fillHisto(cand3Prong, mother, whichHad, whichOrigin); std::array momDau2 = {cand3Prong.pxProng2(), cand3Prong.pyProng2(), cand3Prong.pzProng2()}; - histPtReco[whichHad][whichOrigin]->Fill(cand3Prong.pt()); - histPtDau[whichHad][whichOrigin][0]->Fill(RecoDecay::pt(momDau0)); - histEtaDau[whichHad][whichOrigin][0]->Fill(RecoDecay::eta(momDau0)); - histImpactParameterDau[whichHad][whichOrigin][0]->Fill(cand3Prong.impactParameter0()); - histPtDau[whichHad][whichOrigin][1]->Fill(RecoDecay::pt(momDau1)); - histEtaDau[whichHad][whichOrigin][1]->Fill(RecoDecay::eta(momDau1)); - histImpactParameterDau[whichHad][whichOrigin][1]->Fill(cand3Prong.impactParameter1()); histPtDau[whichHad][whichOrigin][2]->Fill(RecoDecay::pt(momDau2)); histEtaDau[whichHad][whichOrigin][2]->Fill(RecoDecay::eta(momDau2)); histImpactParameterDau[whichHad][whichOrigin][2]->Fill(cand3Prong.impactParameter2()); diff --git a/PWGJE/Core/JetDerivedDataUtilities.h b/PWGJE/Core/JetDerivedDataUtilities.h index 97df387811e..0e6e1e9e5ec 100644 --- a/PWGJE/Core/JetDerivedDataUtilities.h +++ b/PWGJE/Core/JetDerivedDataUtilities.h @@ -90,7 +90,8 @@ enum JTrigSelCh { noChargedTigger = 0, chargedLow = 1, chargedHigh = 2, - trackPt = 3 + trackLowPt = 3, + trackHighPt = 4 }; template @@ -110,9 +111,13 @@ int initialiseChargedTriggerSelection(std::string triggerSelection) if (triggerSelection == "chargedHigh") { return JTrigSelCh::chargedHigh; } - if (triggerSelection == "trackPt") { - return JTrigSelCh::trackPt; + if (triggerSelection == "trackLowPt") { + return JTrigSelCh::trackLowPt; } + if (triggerSelection == "trackHighPt") { + return JTrigSelCh::trackHighPt; + } + return -1; } @@ -127,9 +132,13 @@ uint8_t setChargedTriggerSelectionBit(T const& collision) if (collision.hasJetChHighPt()) { SETBIT(bit, JTrigSelCh::chargedHigh); } + if (collision.hasTrackLowPt()) { + SETBIT(bit, JTrigSelCh::trackLowPt); + } if (collision.hasTrackHighPt()) { - SETBIT(bit, JTrigSelCh::trackPt); + SETBIT(bit, JTrigSelCh::trackHighPt); } + return bit; } diff --git a/PWGJE/Tasks/ChJetTriggerQATask.cxx b/PWGJE/Tasks/ChJetTriggerQATask.cxx index 30df24cd118..c575736a8dd 100644 --- a/PWGJE/Tasks/ChJetTriggerQATask.cxx +++ b/PWGJE/Tasks/ChJetTriggerQATask.cxx @@ -73,7 +73,8 @@ struct ChJetTriggerQATask { Configurable bLowPtTrigger{"bLowPtTrigger", false, "charged jet low pT trigger selection"}; Configurable bHighPtTrigger{"bHighPtTrigger", false, "charged jet high pT trigger selection"}; - Configurable bTrackPtTrigger{"bTrackPtTrigger", false, "track pT trigger selection"}; + Configurable bTrackLowPtTrigger{"bTrackLowPtTrigger", false, "track low pT trigger selection"}; + Configurable bTrackHighPtTrigger{"bTrackHighPtTrigger", false, "track high pT trigger selection"}; Configurable bAddSupplementHistosToOutput{"bAddAdditionalHistosToOutput", false, "add supplementary histos to the output"}; @@ -144,12 +145,19 @@ struct ChJetTriggerQATask { return; } - if ((bLowPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)) || (bHighPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)) || (bTrackPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::trackPt)) || ((!bLowPtTrigger) && (!bHighPtTrigger) && (!bTrackPtTrigger))) { + bool bLowPtJet = (bLowPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedLow)); + bool bHighPtJet = (bHighPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::chargedHigh)); + bool bLowPtTrack = (bTrackLowPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::trackLowPt)); + bool bHighPtTrack = (bTrackHighPtTrigger && jetderiveddatautilities::selectChargedTrigger(collision, jetderiveddatautilities::JTrigSelCh::trackHighPt)); + bool bMinimumBias = ((!bLowPtTrigger) && (!bHighPtTrigger) && (!bTrackLowPtTrigger) && (!bTrackHighPtTrigger)); + + if (bLowPtJet || bHighPtJet || bLowPtTrack || bHighPtTrack || bMinimumBias) { // bLowPtTrigger=1 and bHighPtTrigger=0 --> fill histos with low trigger only // bLowPtTrigger=0 and bHighPtTrigger=1 --> fill histos with high trigger only // bLowPtTrigger=1 and bHighPtTrigger=1 --> fill histos with mixture of low and high trigger - // bTrackPtTrigger=1 --> fill histos for high pt track trigger - // bLowPtTrigger=0 and bHighPtTrigger=0 and bTrackPtTrigger=0 --> fill histos with minimum bias ie. ignore trigger decision + // bTrackLowPtTrigger=1 --> fill histos for low pt track trigger + // bTrackHighPtTrigger=1 --> fill histos for high pt track trigger + // bLowPtTrigger=0 and bHighPtTrigger=0 and bTrackLowPtTrigger=0 and bTrackHighPtTrigger=0 --> fill histos with minimum bias ie. ignore trigger decision float leadingJetPt = -1.0; float leadingJetEta = -2.0; diff --git a/PWGJE/Tasks/jetChCorr.cxx b/PWGJE/Tasks/jetChCorr.cxx index 2ba5905ed78..bc94aec61bc 100644 --- a/PWGJE/Tasks/jetChCorr.cxx +++ b/PWGJE/Tasks/jetChCorr.cxx @@ -350,7 +350,7 @@ struct JetChCorr { nn = 0; ch_mult = jet.tracksIds().size(); for (auto& jetConstituent : jet.template tracks_as()) { - if (iord[nn] != 0 || iord[nn] != 1) + if (iord[nn] > 1) continue; if (iord[nn] == 0) { diff --git a/PWGJE/Tasks/triggerCorrelations.cxx b/PWGJE/Tasks/triggerCorrelations.cxx index aea97bc151e..e215bae706e 100644 --- a/PWGJE/Tasks/triggerCorrelations.cxx +++ b/PWGJE/Tasks/triggerCorrelations.cxx @@ -55,7 +55,7 @@ struct TriggerCorrelationsTask { void init(o2::framework::InitContext&) { - std::vector trigSelChLabels = {"chargedLow", "chargedHigh", "trackPt"}; + std::vector trigSelChLabels = {"chargedLow", "chargedHigh", "trackLowPt", "trackHighPt"}; std::vector trigSelFullLabels = {"fullHigh", "fullLow", "neutralHigh", "neutralLow", "gammaVeryHighEMCAL", "gammaHighEMCAL", "gammaLowEMCAL", "gammaVeryLowEMCAL", "gammaVeryHighDCAL", "gammaHighDCAL", "gammaLowDCAL", "gammaVeryLowDCAL"}; std::vector trigSelChHFLabels = {"chargedD0Low", "chargedD0High", "chargedLcLow", "chargedLcHigh"}; nChTrigs = trigSelChLabels.size(); diff --git a/PWGLF/DataModel/LFLithium4Tables.h b/PWGLF/DataModel/LFLithium4Tables.h index 699e6f7f2c0..50c5acb5cca 100644 --- a/PWGLF/DataModel/LFLithium4Tables.h +++ b/PWGLF/DataModel/LFLithium4Tables.h @@ -25,8 +25,6 @@ namespace o2::aod namespace Lithium4TablesNS { -DECLARE_SOA_COLUMN(IsMatter, isMatter, bool); - DECLARE_SOA_COLUMN(PtHe3, ptHe3, float); DECLARE_SOA_COLUMN(EtaHe3, etaHe3, float); DECLARE_SOA_COLUMN(PhiHe3, phiHe3, float); @@ -34,75 +32,97 @@ DECLARE_SOA_COLUMN(PtPr, ptPr, float); DECLARE_SOA_COLUMN(EtaPr, etaPr, float); DECLARE_SOA_COLUMN(PhiPr, phiPr, float); -DECLARE_SOA_COLUMN(He3DCAxy, he3DcaXY, float); -DECLARE_SOA_COLUMN(He3DCAz, he3DcaZ, float); -DECLARE_SOA_COLUMN(ProtonDCAxy, protonDcaXY, float); -DECLARE_SOA_COLUMN(ProtonDCAz, protonDcaZ, float); +DECLARE_SOA_COLUMN(DCAxyHe3, dcaxyHe3, float); +DECLARE_SOA_COLUMN(DCAzHe3, dcazHe3, float); +DECLARE_SOA_COLUMN(DCAxyPr, dcaxyPr, float); +DECLARE_SOA_COLUMN(DCAzPr, dcazPr, float); + +DECLARE_SOA_COLUMN(SignalTPCHe3, signalTPCHe3, float); +DECLARE_SOA_COLUMN(InnerParamTPCHe3, innerParamTPCHe3, float); +DECLARE_SOA_COLUMN(SignalTPCPr, signalTPCPr, float); +DECLARE_SOA_COLUMN(InnerParamTPCPr, innerParamTPCPr, float); +DECLARE_SOA_COLUMN(NClsTPCHe3, nClsTPCHe3, uint8_t); +DECLARE_SOA_COLUMN(NSigmaTPCHe3, nSigmaTPCHe3, float); +DECLARE_SOA_COLUMN(NSigmaTPCPr, nSigmaTOFPr, float); +DECLARE_SOA_COLUMN(MassTOFHe3, massTOFHe3, float); +DECLARE_SOA_COLUMN(MassTOFPr, massTOFPr, float); +DECLARE_SOA_COLUMN(PIDtrkHe3, pidTrkHe3, uint32_t); +DECLARE_SOA_COLUMN(PIDtrkPr, pidTrkPr, uint32_t); + +DECLARE_SOA_COLUMN(ItsClusterSizeHe3, itsClusterSizeHe3, uint32_t); +DECLARE_SOA_COLUMN(ItsClusterSizePr, itsClusterSizePr, uint32_t); -DECLARE_SOA_COLUMN(He3SignalTPC, he3SignalTPC, float); -DECLARE_SOA_COLUMN(He3InnerParamTPC, he3InnerParamTPC, float); -DECLARE_SOA_COLUMN(He3NClsTPC, he3NClsTPC, uint8_t); -DECLARE_SOA_COLUMN(He3NSigmaTPC, he3NSigmaTPC, float); -DECLARE_SOA_COLUMN(PrNSigmaTPC, prNSigmaTOF, float); -DECLARE_SOA_COLUMN(He3MassTOF, he3MassTOF, float); -DECLARE_SOA_COLUMN(PrMassTOF, prMassTOF, float); DECLARE_SOA_COLUMN(SharedClustersHe3, sharedClustersHe3, uint8_t); DECLARE_SOA_COLUMN(SharedClustersPr, sharedClustersPr, uint8_t); DECLARE_SOA_COLUMN(IsBkgLS, isBkgLS, bool); DECLARE_SOA_COLUMN(IsBkgEM, isBkgEM, bool); +DECLARE_SOA_COLUMN(PtMCHe3, ptMCHe3, float); +DECLARE_SOA_COLUMN(PtMCPr, ptMCPr, float); DECLARE_SOA_COLUMN(SignedPtMC, signedPtMC, float); DECLARE_SOA_COLUMN(MassMC, massMC, float); } // namespace Lithium4TablesNS DECLARE_SOA_TABLE(Lithium4Table, "AOD", "LITHIUM4TABLE", - Lithium4TablesNS::IsMatter, Lithium4TablesNS::PtHe3, Lithium4TablesNS::EtaHe3, Lithium4TablesNS::PhiHe3, Lithium4TablesNS::PtPr, Lithium4TablesNS::EtaPr, Lithium4TablesNS::PhiPr, - Lithium4TablesNS::He3DCAxy, - Lithium4TablesNS::He3DCAz, - Lithium4TablesNS::ProtonDCAxy, - Lithium4TablesNS::ProtonDCAz, - Lithium4TablesNS::He3SignalTPC, - Lithium4TablesNS::He3InnerParamTPC, - Lithium4TablesNS::He3NClsTPC, - Lithium4TablesNS::He3NSigmaTPC, - Lithium4TablesNS::PrNSigmaTPC, - Lithium4TablesNS::He3MassTOF, - Lithium4TablesNS::PrMassTOF, + Lithium4TablesNS::DCAxyHe3, + Lithium4TablesNS::DCAzHe3, + Lithium4TablesNS::DCAxyPr, + Lithium4TablesNS::DCAzPr, + Lithium4TablesNS::SignalTPCHe3, + Lithium4TablesNS::InnerParamTPCHe3, + Lithium4TablesNS::SignalTPCPr, + Lithium4TablesNS::InnerParamTPCPr, + Lithium4TablesNS::NClsTPCHe3, + Lithium4TablesNS::NSigmaTPCHe3, + Lithium4TablesNS::NSigmaTPCPr, + Lithium4TablesNS::MassTOFHe3, + Lithium4TablesNS::MassTOFPr, + Lithium4TablesNS::PIDtrkHe3, + Lithium4TablesNS::PIDtrkPr, + Lithium4TablesNS::ItsClusterSizeHe3, + Lithium4TablesNS::ItsClusterSizePr, Lithium4TablesNS::SharedClustersHe3, Lithium4TablesNS::SharedClustersPr, Lithium4TablesNS::IsBkgLS, Lithium4TablesNS::IsBkgEM) DECLARE_SOA_TABLE(Lithium4TableMC, "AOD", "LITHIUM4TABLEMC", - Lithium4TablesNS::IsMatter, Lithium4TablesNS::PtHe3, Lithium4TablesNS::EtaHe3, Lithium4TablesNS::PhiHe3, Lithium4TablesNS::PtPr, Lithium4TablesNS::EtaPr, Lithium4TablesNS::PhiPr, - Lithium4TablesNS::He3DCAxy, - Lithium4TablesNS::He3DCAz, - Lithium4TablesNS::ProtonDCAxy, - Lithium4TablesNS::ProtonDCAz, - Lithium4TablesNS::He3SignalTPC, - Lithium4TablesNS::He3InnerParamTPC, - Lithium4TablesNS::He3NClsTPC, - Lithium4TablesNS::He3NSigmaTPC, - Lithium4TablesNS::PrNSigmaTPC, - Lithium4TablesNS::He3MassTOF, - Lithium4TablesNS::PrMassTOF, + Lithium4TablesNS::DCAxyHe3, + Lithium4TablesNS::DCAzHe3, + Lithium4TablesNS::DCAxyPr, + Lithium4TablesNS::DCAzPr, + Lithium4TablesNS::SignalTPCHe3, + Lithium4TablesNS::InnerParamTPCHe3, + Lithium4TablesNS::SignalTPCPr, + Lithium4TablesNS::InnerParamTPCPr, + Lithium4TablesNS::NClsTPCHe3, + Lithium4TablesNS::NSigmaTPCHe3, + Lithium4TablesNS::NSigmaTPCPr, + Lithium4TablesNS::MassTOFHe3, + Lithium4TablesNS::MassTOFPr, + Lithium4TablesNS::PIDtrkHe3, + Lithium4TablesNS::PIDtrkPr, + Lithium4TablesNS::ItsClusterSizeHe3, + Lithium4TablesNS::ItsClusterSizePr, Lithium4TablesNS::SharedClustersHe3, Lithium4TablesNS::SharedClustersPr, Lithium4TablesNS::IsBkgLS, Lithium4TablesNS::IsBkgEM, + Lithium4TablesNS::PtMCHe3, + Lithium4TablesNS::PtMCPr, Lithium4TablesNS::SignedPtMC, Lithium4TablesNS::MassMC) diff --git a/PWGLF/DataModel/LFSigmaTables.h b/PWGLF/DataModel/LFSigmaTables.h new file mode 100644 index 00000000000..e2df7da8bbe --- /dev/null +++ b/PWGLF/DataModel/LFSigmaTables.h @@ -0,0 +1,99 @@ +// 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 +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" +#include "CommonConstants/PhysicsConstants.h" + +#ifndef PWGLF_DATAMODEL_LFSIGMATABLES_H_ +#define PWGLF_DATAMODEL_LFSIGMATABLES_H_ + +using namespace o2; +using namespace o2::framework; + +// Creating output TTree for sigma analysis +namespace o2::aod +{ + +// for real data +namespace v0SigmaCandidate +{ +DECLARE_SOA_COLUMN(SigmapT, sigmapT, float); +DECLARE_SOA_COLUMN(SigmaMass, sigmaMass, float); +// DECLARE_SOA_COLUMN(SigmaDCAz, sigmaDCAz, float); +// DECLARE_SOA_COLUMN(SigmaDCAxy, sigmaDCAxy, float); +// DECLARE_SOA_COLUMN(SigmaDCADau, sigmaDCADau, float); +DECLARE_SOA_COLUMN(PhotonPt, photonPt, float); +DECLARE_SOA_COLUMN(PhotonMass, photonMass, float); +DECLARE_SOA_COLUMN(PhotonQt, photonQt, float); +DECLARE_SOA_COLUMN(PhotonAlpha, photonAlpha, float); +DECLARE_SOA_COLUMN(PhotonRadius, photonRadius, float); +DECLARE_SOA_COLUMN(PhotonCosPA, photonCosPA, float); +DECLARE_SOA_COLUMN(PhotonDCADau, photonDCADau, float); +DECLARE_SOA_COLUMN(PhotonDCANegPV, photonDCANegPV, float); +DECLARE_SOA_COLUMN(PhotonDCAPosPV, photonDCAPosPV, float); +DECLARE_SOA_COLUMN(PhotonZconv, photonZconv, float); +DECLARE_SOA_COLUMN(LambdaPt, lambdaPt, float); +DECLARE_SOA_COLUMN(LambdaMass, lambdaMass, float); +DECLARE_SOA_COLUMN(LambdaQt, lambdaQt, float); +DECLARE_SOA_COLUMN(LambdaAlpha, lambdaAlpha, float); +DECLARE_SOA_COLUMN(LambdaRadius, lambdaRadius, float); +DECLARE_SOA_COLUMN(LambdaCosPA, lambdaCosPA, float); +DECLARE_SOA_COLUMN(LambdaDCADau, lambdaDCADau, float); +DECLARE_SOA_COLUMN(LambdaDCANegPV, lambdaDCANegPV, float); +DECLARE_SOA_COLUMN(LambdaDCAPosPV, lambdaDCAPosPV, float); +DECLARE_SOA_COLUMN(GammaProbability, gammaProbability, float); +DECLARE_SOA_COLUMN(LambdaProbability, lambdaProbability, float); + +} // namespace v0SigmaCandidate + +DECLARE_SOA_TABLE(V0SigmaCandidates, "AOD", "V0SIGMAS", + v0SigmaCandidate::SigmapT, + v0SigmaCandidate::SigmaMass, + // v0SigmaCandidate::SigmaDCAz, + // v0SigmaCandidate::SigmaDCAxy, + // v0SigmaCandidate::SigmaDCADau, + v0SigmaCandidate::PhotonPt, + v0SigmaCandidate::PhotonMass, + v0SigmaCandidate::PhotonQt, + v0SigmaCandidate::PhotonAlpha, + v0SigmaCandidate::PhotonRadius, + v0SigmaCandidate::PhotonCosPA, + v0SigmaCandidate::PhotonDCADau, + v0SigmaCandidate::PhotonDCANegPV, + v0SigmaCandidate::PhotonDCAPosPV, + v0SigmaCandidate::PhotonZconv, + v0SigmaCandidate::LambdaPt, + v0SigmaCandidate::LambdaMass, + v0SigmaCandidate::LambdaQt, + v0SigmaCandidate::LambdaAlpha, + v0SigmaCandidate::LambdaRadius, + v0SigmaCandidate::LambdaCosPA, + v0SigmaCandidate::LambdaDCADau, + v0SigmaCandidate::LambdaDCANegPV, + v0SigmaCandidate::LambdaDCAPosPV, + v0SigmaCandidate::GammaProbability, + v0SigmaCandidate::LambdaProbability); + +// for MC data +namespace v0SigmaMCCandidate +{ +DECLARE_SOA_COLUMN(IsSigma, isSigma, bool); + +} // namespace v0SigmaMCCandidate + +DECLARE_SOA_TABLE(V0SigmaMCCandidates, "AOD", "V0MCSIGMAS", + v0SigmaMCCandidate::IsSigma); +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LFSIGMATABLES_H_ diff --git a/PWGLF/DataModel/LFStrangenessMLTables.h b/PWGLF/DataModel/LFStrangenessMLTables.h new file mode 100644 index 00000000000..c052ab70fdf --- /dev/null +++ b/PWGLF/DataModel/LFStrangenessMLTables.h @@ -0,0 +1,241 @@ +// 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 +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" +#include "CommonConstants/PhysicsConstants.h" + +#ifndef PWGLF_DATAMODEL_LFSTRANGENESSMLTABLES_H_ +#define PWGLF_DATAMODEL_LFSTRANGENESSMLTABLES_H_ + +using namespace o2; +using namespace o2::framework; + +// Creating output TTree for ML analysis +namespace o2::aod +{ +namespace v0mlcandidates +{ +DECLARE_SOA_COLUMN(PosITSCls, posITSCls, int); +DECLARE_SOA_COLUMN(NegITSCls, negITSCls, int); +DECLARE_SOA_COLUMN(PosITSClSize, posITSClSize, uint32_t); +DECLARE_SOA_COLUMN(NegITSClSize, negITSClSize, uint32_t); +DECLARE_SOA_COLUMN(PosTPCRows, posTPCRows, float); +DECLARE_SOA_COLUMN(NegTPCRows, negTPCRows, float); +DECLARE_SOA_COLUMN(PosTPCSigmaPi, posTPCSigmaPi, float); +DECLARE_SOA_COLUMN(NegTPCSigmaPi, negTPCSigmaPi, float); +DECLARE_SOA_COLUMN(PosTPCSigmaPr, posTPCSigmaPr, float); +DECLARE_SOA_COLUMN(NegTPCSigmaPr, negTPCSigmaPr, float); +DECLARE_SOA_COLUMN(PosTPCSigmaEl, posTPCSigmaEl, float); +DECLARE_SOA_COLUMN(NegTPCSigmaEl, negTPCSigmaEl, float); +DECLARE_SOA_COLUMN(TOFSigmaLaPr, tofSigmaLaPr, float); +DECLARE_SOA_COLUMN(TOFSigmaLaPi, tofSigmaLaPi, float); +DECLARE_SOA_COLUMN(TOFSigmaALaPi, tofSigmaALaPi, float); +DECLARE_SOA_COLUMN(TOFSigmaALaPr, tofSigmaALaPr, float); +DECLARE_SOA_COLUMN(TOFSigmaK0PiPlus, tofSigmaK0PiPlus, float); +DECLARE_SOA_COLUMN(TOFSigmaK0PiMinus, tofSigmaK0PiMinus, float); +DECLARE_SOA_COLUMN(LambdaMass, lambdaMass, float); +DECLARE_SOA_COLUMN(AntiLambdaMass, antiLambdaMass, float); +DECLARE_SOA_COLUMN(GammaMass, gammaMass, float); +DECLARE_SOA_COLUMN(KZeroShortMass, kZeroShortMass, float); +DECLARE_SOA_COLUMN(PT, pT, float); +DECLARE_SOA_COLUMN(Qt, qt, float); +DECLARE_SOA_COLUMN(Alpha, alpha, float); +DECLARE_SOA_COLUMN(PosEta, posEta, float); +DECLARE_SOA_COLUMN(NegEta, negEta, float); +DECLARE_SOA_COLUMN(V0Eta, v0Eta, float); +DECLARE_SOA_COLUMN(Z, z, float); +DECLARE_SOA_COLUMN(V0radius, v0radius, float); +DECLARE_SOA_COLUMN(PA, pa, float); +DECLARE_SOA_COLUMN(DCApostopv, dcapostopv, float); +DECLARE_SOA_COLUMN(DCAnegtopv, dcanegtopv, float); +DECLARE_SOA_COLUMN(DCAV0daughters, dcaV0daughters, float); +DECLARE_SOA_COLUMN(DCAv0topv, dcav0topv, float); +DECLARE_SOA_COLUMN(PsiPair, psiPair, float); +DECLARE_SOA_COLUMN(V0type, v0type, uint8_t); +DECLARE_SOA_COLUMN(Centrality, centrality, float); +DECLARE_SOA_COLUMN(SelHypothesis, selHypothesis, uint8_t); +DECLARE_SOA_COLUMN(IsLambda, isLambda, bool); +DECLARE_SOA_COLUMN(IsAntiLambda, isAntiLambda, bool); +DECLARE_SOA_COLUMN(IsGamma, isGamma, bool); +DECLARE_SOA_COLUMN(IsKZeroShort, isKZeroShort, bool); +} // namespace v0mlcandidates + +DECLARE_SOA_TABLE(V0MLCandidates, "AOD", "V0MLCANDIDATES", + v0mlcandidates::PosITSCls, + v0mlcandidates::NegITSCls, + v0mlcandidates::PosITSClSize, + v0mlcandidates::NegITSClSize, + v0mlcandidates::PosTPCRows, + v0mlcandidates::NegTPCRows, + v0mlcandidates::PosTPCSigmaPi, + v0mlcandidates::NegTPCSigmaPi, + v0mlcandidates::PosTPCSigmaPr, + v0mlcandidates::NegTPCSigmaPr, + v0mlcandidates::PosTPCSigmaEl, + v0mlcandidates::NegTPCSigmaEl, + v0mlcandidates::TOFSigmaLaPr, + v0mlcandidates::TOFSigmaLaPi, + v0mlcandidates::TOFSigmaALaPi, + v0mlcandidates::TOFSigmaALaPr, + v0mlcandidates::TOFSigmaK0PiPlus, + v0mlcandidates::TOFSigmaK0PiMinus, + v0mlcandidates::LambdaMass, + v0mlcandidates::AntiLambdaMass, + v0mlcandidates::GammaMass, + v0mlcandidates::KZeroShortMass, + v0mlcandidates::PT, + v0mlcandidates::Qt, + v0mlcandidates::Alpha, + v0mlcandidates::PosEta, + v0mlcandidates::NegEta, + v0mlcandidates::V0Eta, + v0mlcandidates::Z, + v0mlcandidates::V0radius, + v0mlcandidates::PA, + v0mlcandidates::DCApostopv, + v0mlcandidates::DCAnegtopv, + v0mlcandidates::DCAV0daughters, + v0mlcandidates::DCAv0topv, + v0mlcandidates::PsiPair, + v0mlcandidates::V0type, + v0mlcandidates::Centrality, + v0mlcandidates::SelHypothesis, + v0mlcandidates::IsLambda, + v0mlcandidates::IsAntiLambda, + v0mlcandidates::IsGamma, + v0mlcandidates::IsKZeroShort); + +namespace V0MLSelection +{ +DECLARE_SOA_COLUMN(GammaBDTScore, gammaBDTScore, float); +DECLARE_SOA_COLUMN(LambdaBDTScore, lambdaBDTScore, float); +DECLARE_SOA_COLUMN(AntiLambdaBDTScore, antiLambdaBDTScore, float); +DECLARE_SOA_COLUMN(K0ShortBDTScore, k0ShortBDTScore, float); +} // namespace V0MLSelection + +DECLARE_SOA_TABLE(V0GammaMLScores, "AOD", "V0GaMLScores", + V0MLSelection::GammaBDTScore); +DECLARE_SOA_TABLE(V0LambdaMLScores, "AOD", "V0LaMLScores", + V0MLSelection::LambdaBDTScore); +DECLARE_SOA_TABLE(V0AntiLambdaMLScores, "AOD", "V0ALaMLScores", + V0MLSelection::AntiLambdaBDTScore); +DECLARE_SOA_TABLE(V0K0ShortMLScores, "AOD", "V0K0MLScores", + V0MLSelection::K0ShortBDTScore); + +// Cascade candidates +namespace cascmlcandidates +{ +DECLARE_SOA_COLUMN(MassWindows, massWindows, uint8_t); +DECLARE_SOA_COLUMN(Charge, charge, int); +DECLARE_SOA_COLUMN(Centrality, centrality, float); +DECLARE_SOA_COLUMN(PosITSCls, posITSCls, int); +DECLARE_SOA_COLUMN(NegITSCls, negITSCls, int); +DECLARE_SOA_COLUMN(BachITSCls, bachITSCls, int); +DECLARE_SOA_COLUMN(PosITSClSize, posITSClSize, int); +DECLARE_SOA_COLUMN(NegITSClSize, negITSClSize, int); +DECLARE_SOA_COLUMN(BachITSClSize, bachITSClSize, int); +DECLARE_SOA_COLUMN(PosTPCRows, posTPCRows, float); +DECLARE_SOA_COLUMN(NegTPCRows, negTPCRows, float); +DECLARE_SOA_COLUMN(BachTPCRows, bachTPCRows, float); +DECLARE_SOA_COLUMN(PosTPCSigmaPi, posTPCSigmaPi, float); +DECLARE_SOA_COLUMN(NegTPCSigmaPi, negTPCSigmaPi, float); +DECLARE_SOA_COLUMN(PosTPCSigmaPr, posTPCSigmaPr, float); +DECLARE_SOA_COLUMN(NegTPCSigmaPr, negTPCSigmaPr, float); +DECLARE_SOA_COLUMN(BachTPCSigmaPi, bachTPCSigmaPi, float); +DECLARE_SOA_COLUMN(BachTPCSigmaKa, bachTPCSigmaKa, float); +DECLARE_SOA_COLUMN(TOFNSigmaXiLaPi, tofNSigmaXiLaPi, float); +DECLARE_SOA_COLUMN(TOFNSigmaXiLaPr, tofNSigmaXiLaPr, float); +DECLARE_SOA_COLUMN(TOFNSigmaXiPi, tofNSigmaXiPi, float); +DECLARE_SOA_COLUMN(TOFNSigmaOmLaPi, tofNSigmaOmLaPi, float); +DECLARE_SOA_COLUMN(TOFNSigmaOmLaPr, tofNSigmaOmLaPr, float); +DECLARE_SOA_COLUMN(TOFNSigmaOmKa, tofNSigmaOmKa, float); + +DECLARE_SOA_COLUMN(MXi, mXi, float); +DECLARE_SOA_COLUMN(MOmega, mOmega, float); +DECLARE_SOA_COLUMN(YXi, yXi, float); +DECLARE_SOA_COLUMN(YOmega, yOmega, float); +DECLARE_SOA_COLUMN(MLambda, mLambda, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(PosEta, posEta, float); +DECLARE_SOA_COLUMN(NegEta, negEta, float); +DECLARE_SOA_COLUMN(BachEta, bachEta, float); + +DECLARE_SOA_COLUMN(V0radius, v0radius, float); +DECLARE_SOA_COLUMN(CascRadius, cascradius, float); +DECLARE_SOA_COLUMN(DCApostopv, dcapostopv, float); +DECLARE_SOA_COLUMN(DCAnegtopv, dcanegtopv, float); +DECLARE_SOA_COLUMN(DCAbachtopv, dcabachtopv, float); +DECLARE_SOA_COLUMN(DCAV0daughters, dcaV0daughters, float); +DECLARE_SOA_COLUMN(DCACascDaughters, dcaCascDaughters, float); +DECLARE_SOA_COLUMN(DCAv0topv, dcav0topv, float); +DECLARE_SOA_COLUMN(V0PA, v0PA, float); +DECLARE_SOA_COLUMN(CascPA, cascPA, float); + +DECLARE_SOA_COLUMN(IsXiMinus, isXiMinus, bool); +DECLARE_SOA_COLUMN(IsXiPlus, isXiPlus, bool); +DECLARE_SOA_COLUMN(IsOmegaMinus, isOmegaMinus, bool); +DECLARE_SOA_COLUMN(IsOmegaPlus, isOmegaPlus, bool); +} // namespace cascmlcandidates + +DECLARE_SOA_TABLE(CascMLCandidates, "AOD", "CAMLCANDIDATES", + cascmlcandidates::MassWindows, + cascmlcandidates::Charge, + cascmlcandidates::Centrality, + cascmlcandidates::PosITSCls, + cascmlcandidates::NegITSCls, + cascmlcandidates::BachITSCls, + cascmlcandidates::PosITSClSize, + cascmlcandidates::NegITSClSize, + cascmlcandidates::BachITSClSize, + cascmlcandidates::PosTPCRows, + cascmlcandidates::NegTPCRows, + cascmlcandidates::BachTPCRows, + cascmlcandidates::PosTPCSigmaPi, + cascmlcandidates::NegTPCSigmaPi, + cascmlcandidates::PosTPCSigmaPr, + cascmlcandidates::NegTPCSigmaPr, + cascmlcandidates::BachTPCSigmaPi, + cascmlcandidates::BachTPCSigmaKa, + cascmlcandidates::TOFNSigmaXiLaPi, + cascmlcandidates::TOFNSigmaXiLaPr, + cascmlcandidates::TOFNSigmaXiPi, + cascmlcandidates::TOFNSigmaOmLaPi, + cascmlcandidates::TOFNSigmaOmLaPr, + cascmlcandidates::TOFNSigmaOmKa, + cascmlcandidates::MXi, + cascmlcandidates::MOmega, + cascmlcandidates::YXi, + cascmlcandidates::YOmega, + cascmlcandidates::MLambda, + cascmlcandidates::Pt, + cascmlcandidates::PosEta, + cascmlcandidates::NegEta, + cascmlcandidates::BachEta, + cascmlcandidates::V0radius, + cascmlcandidates::CascRadius, + cascmlcandidates::DCApostopv, + cascmlcandidates::DCAnegtopv, + cascmlcandidates::DCAbachtopv, + cascmlcandidates::DCAV0daughters, + cascmlcandidates::DCACascDaughters, + cascmlcandidates::DCAv0topv, + cascmlcandidates::V0PA, + cascmlcandidates::CascPA, + cascmlcandidates::IsXiMinus, + cascmlcandidates::IsXiPlus, + cascmlcandidates::IsOmegaMinus, + cascmlcandidates::IsOmegaPlus); +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LFSTRANGENESSMLTABLES_H_ diff --git a/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx b/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx index 19ae25e93c4..96931db8767 100644 --- a/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx +++ b/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx @@ -84,32 +84,43 @@ struct lithium4Candidate { float recoPhiPr() const { return std::atan2(momPr[1], momPr[0]); } float recoEtaPr() const { return std::asinh(momPr[2] / recoPtPr()); } - std::array momHe3; - std::array momPr; + std::array momHe3 = {99.f, 99.f, 99.f}; + std::array momPr = {99.f, 99.f, 99.f}; + + bool isMatter = false; + + uint32_t PIDtrkHe3 = 0xFFFFF; // PID in tracking + uint32_t PIDtrkPr = 0xFFFFF; float nSigmaHe3 = -10; float nSigmaPr = -10; float massTOFHe3 = -10; float massTOFPr = -10; - float he3DCAXY = -10; - float he3DCAZ = -10; - float protonDCAXY = -10; - float protonDCAZ = -10; + float DCAxyHe3 = -10; + float DCAzHe3 = -10; + float DCAxyPr = -10; + float DCAzPr = -10; uint16_t tpcSignalHe3 = 0u; - float momHe3TPC = -10.f; - float momPrTPC = -10.f; + float momHe3TPC = -99.f; + uint16_t tpcSignalPr = 0u; + float momPrTPC = -99.f; float invMass = -10.f; + + uint32_t itsClSizeHe3 = 0u; + uint32_t itsClSizePr = 0u; uint8_t nTPCClustersHe3 = 0u; + float momHe3MC = -99.f; + float momPrMC = -99.f; + uint8_t sharedClustersHe3 = 0u; uint8_t sharedClustersPr = 0u; bool isBkgUS = false; bool isBkgEM = false; - bool isMatter = false; - float l4PtMC = -10.f; + float l4PtMC = -99.f; float l4MassMC = -10.f; }; @@ -146,15 +157,15 @@ struct lithium4analysis { histos.add("hCentrality", "Centrality distribution", kTH1F, {{2001, -0.5, 2000.5}}); histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); histos.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 2000.0f}}); - histos.add("hHe3Dcaxy", ";DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hHe3Dcaz", ";DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDCAxyHe3", ";DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDCAzHe3", ";DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); histos.add("hLitInvMass", "; M(^{3}He + p) (GeV/#it{c}^{2})", kTH1F, {{50, 3.74f, 3.85f}}); histos.add("hHe3Pt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", kTH1F, {{200, 0.0f, 6.0f}}); histos.add("hProtonPt", "Pt distribution; #it{p}_{T} (GeV/#it{c})", kTH1F, {{200, 0.0f, 3.0f}}); histos.add("h2NsigmaHe3TPC", "NsigmaHe3 TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}({}^{3}He)", kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}); histos.add("h2NsigmaProtonTPC", "NsigmaProton TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}(p)", kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}); histos.add("h2NsigmaProtonTOF", "NsigmaProton TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}); - histos.add("hTrackSel", "Accepted tracks", kTH1F, {{Selections::kAll, -0.5, +Selections::kAll - 0.5}}); + histos.add("hTrackSel", "Accepted tracks", kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}); for (int i = 0; i < 5; i++) { mBBparamsHe[i] = cfgBetheBlochParams->get("He3", Form("p%i", i)); @@ -172,7 +183,7 @@ struct lithium4analysis { { if (candidate.itsNCls() < 5 || - candidate.tpcNClsFound() < 70 || + candidate.tpcNClsFound() < 100 || // candidate.tpcNClsFound() < 70 || candidate.tpcNClsCrossedRows() < 70 || candidate.tpcNClsCrossedRows() < 0.8 * candidate.tpcNClsFindable() || candidate.tpcChi2NCl() > 4.f || @@ -231,22 +242,28 @@ struct lithium4analysis { return false; } - int he3Sign = candidateHe3.sign(); - int protonSign = candidatePr.sign(); + l4Cand.PIDtrkHe3 = candidateHe3.pidForTracking(); + l4Cand.PIDtrkPr = candidatePr.pidForTracking(); - l4Cand.isBkgUS = he3Sign * protonSign < 0; + l4Cand.isBkgUS = candidateHe3.sign() * candidatePr.sign() < 0; l4Cand.isBkgEM = mix; - l4Cand.isMatter = he3Sign > 0; - l4Cand.he3DCAXY = candidateHe3.dcaXY(); - l4Cand.he3DCAZ = candidateHe3.dcaZ(); - l4Cand.protonDCAXY = candidatePr.dcaXY(); - l4Cand.protonDCAZ = candidatePr.dcaZ(); + l4Cand.isMatter = candidateHe3.sign() > 0; + l4Cand.DCAxyHe3 = candidateHe3.dcaXY(); + l4Cand.DCAzHe3 = candidateHe3.dcaZ(); + l4Cand.DCAxyPr = candidatePr.dcaXY(); + l4Cand.DCAzPr = candidatePr.dcaZ(); + l4Cand.tpcSignalHe3 = candidateHe3.tpcSignal(); l4Cand.momHe3TPC = candidateHe3.tpcInnerParam(); + l4Cand.tpcSignalPr = candidatePr.tpcSignal(); l4Cand.momPrTPC = candidatePr.tpcInnerParam(); l4Cand.invMass = invMass; + l4Cand.itsClSizeHe3 = candidateHe3.itsClusterSizes(); + l4Cand.itsClSizePr = candidatePr.itsClusterSizes(); + l4Cand.nTPCClustersHe3 = candidateHe3.tpcNClsFound(); + l4Cand.nSigmaHe3 = computeNSigmaHe3(candidateHe3); l4Cand.nSigmaPr = candidatePr.tpcNSigmaPr(); @@ -264,8 +281,8 @@ struct lithium4analysis { histos.fill(HIST("hHe3Pt"), l4cand.recoPtHe3()); histos.fill(HIST("hProtonPt"), l4cand.recoPtPr()); histos.fill(HIST("hLitInvMass"), l4cand.invMass); - histos.fill(HIST("hHe3Dcaxy"), l4cand.he3DCAXY); - histos.fill(HIST("hHe3Dcaz"), l4cand.he3DCAZ); + histos.fill(HIST("hDCAxyHe3"), l4cand.DCAxyHe3); + histos.fill(HIST("hDCAzHe3"), l4cand.DCAzHe3); histos.fill(HIST("h2NsigmaHe3TPC"), candSign * l4cand.momHe3TPC, l4cand.nSigmaHe3); histos.fill(HIST("h2NsigmaProtonTPC"), candSign * l4cand.momPrTPC, l4cand.nSigmaPr); histos.fill(HIST("h2NsigmaProtonTOF"), l4cand.recoPtPr(), l4cand.nSigmaPr); @@ -369,12 +386,15 @@ struct lithium4analysis { } for (auto& l4Cand : l4Candidates) { - outputDataTable(l4Cand.isMatter, l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), + outputDataTable(l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), l4Cand.recoPtPr(), l4Cand.recoEtaPr(), l4Cand.recoPhiPr(), - l4Cand.he3DCAXY, l4Cand.he3DCAZ, l4Cand.protonDCAXY, l4Cand.protonDCAZ, - l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.nTPCClustersHe3, l4Cand.nSigmaHe3, - l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, l4Cand.sharedClustersHe3, - l4Cand.sharedClustersPr, l4Cand.isBkgUS, l4Cand.isBkgEM); + l4Cand.DCAxyHe3, l4Cand.DCAzHe3, l4Cand.DCAxyPr, l4Cand.DCAzPr, + l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.tpcSignalPr, l4Cand.momPrTPC, + l4Cand.nTPCClustersHe3, + l4Cand.nSigmaHe3, l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, + l4Cand.PIDtrkHe3, l4Cand.PIDtrkPr, l4Cand.itsClSizeHe3, l4Cand.itsClSizePr, + l4Cand.sharedClustersHe3, l4Cand.sharedClustersPr, + l4Cand.isBkgUS, l4Cand.isBkgEM); } } PROCESS_SWITCH(lithium4analysis, processSameEvent, "Process Same event", false); @@ -444,12 +464,15 @@ struct lithium4analysis { } for (auto& l4Cand : l4Candidates) { - outputDataTable(l4Cand.isMatter, l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), + outputDataTable(l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), l4Cand.recoPtPr(), l4Cand.recoEtaPr(), l4Cand.recoPhiPr(), - l4Cand.he3DCAXY, l4Cand.he3DCAZ, l4Cand.protonDCAXY, l4Cand.protonDCAZ, - l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.nTPCClustersHe3, l4Cand.nSigmaHe3, - l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, l4Cand.sharedClustersHe3, - l4Cand.sharedClustersPr, l4Cand.isBkgUS, l4Cand.isBkgEM); + l4Cand.DCAxyHe3, l4Cand.DCAzHe3, l4Cand.DCAxyPr, l4Cand.DCAzPr, + l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.tpcSignalPr, l4Cand.momPrTPC, + l4Cand.nTPCClustersHe3, + l4Cand.nSigmaHe3, l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, + l4Cand.PIDtrkHe3, l4Cand.PIDtrkPr, l4Cand.itsClSizeHe3, l4Cand.itsClSizePr, + l4Cand.sharedClustersHe3, l4Cand.sharedClustersPr, + l4Cand.isBkgUS, l4Cand.isBkgEM); } } PROCESS_SWITCH(lithium4analysis, processMixedEvent, "Process Mixed event", false); @@ -550,7 +573,10 @@ struct lithium4analysis { beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked cand.massTOFPr = track2.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); } - cand.l4PtMC = mothertrack.pt(); + + cand.momHe3MC = mctrackHe3.pt() * (mctrackHe3.pdgCode() > 0 ? 1 : -1); + cand.momPrMC = mctrackPr.pt() * (mctrackPr.pdgCode() > 0 ? 1 : -1); + cand.l4PtMC = mothertrack.pt() * (mothertrack.pdgCode() > 0 ? 1 : -1); double eLit = mctrackHe3.e() + mctrackPr.e(); cand.l4MassMC = std::sqrt(eLit * eLit - mothertrack.p() * mothertrack.p()); filledMothers.push_back(mothertrack.globalIndex()); @@ -579,31 +605,43 @@ struct lithium4analysis { auto daughtHe3 = false; auto daughtPr = false; double eLit = 0; + int signHe3 = 0, signPr = 0; + double ptHe3 = 0, ptPr = 0; for (auto kCurrentDaughter : kDaughters) { if (std::abs(kCurrentDaughter.pdgCode()) == he3PDG) { daughtHe3 = true; + signHe3 = kCurrentDaughter.pdgCode() > 0 ? 1 : -1; + ptHe3 = kCurrentDaughter.pt(); eLit += kCurrentDaughter.e(); } else if (std::abs(kCurrentDaughter.pdgCode()) == protonPDG) { daughtPr = true; + signPr = kCurrentDaughter.pdgCode() > 0 ? 1 : -1; + ptPr = kCurrentDaughter.pt(); eLit += kCurrentDaughter.e(); } } if (daughtHe3 && daughtPr) { lithium4Candidate l4Candidate; - int sign = mcParticle.pdgCode() > 0 ? 1 : -1; - l4Candidate.l4PtMC = mcParticle.pt() * sign; + int signLi = mcParticle.pdgCode() > 0 ? 1 : -1; + l4Candidate.l4PtMC = mcParticle.pt() * signLi; + l4Candidate.momHe3MC = ptHe3 * signHe3; + l4Candidate.momPrMC = ptPr * signPr; l4Candidate.l4MassMC = std::sqrt(eLit * eLit - mcParticle.p() * mcParticle.p()); l4Candidates.push_back(l4Candidate); } } for (auto& l4Cand : l4Candidates) { - outputMCTable(l4Cand.isMatter, l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), + outputMCTable(l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), l4Cand.recoPtPr(), l4Cand.recoEtaPr(), l4Cand.recoPhiPr(), - l4Cand.he3DCAXY, l4Cand.he3DCAZ, l4Cand.protonDCAXY, l4Cand.protonDCAZ, - l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.nTPCClustersHe3, l4Cand.nSigmaHe3, - l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, l4Cand.sharedClustersHe3, - l4Cand.sharedClustersPr, l4Cand.isBkgUS, l4Cand.isBkgEM, + l4Cand.DCAxyHe3, l4Cand.DCAzHe3, l4Cand.DCAxyPr, l4Cand.DCAzPr, + l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.tpcSignalPr, l4Cand.momPrTPC, + l4Cand.nTPCClustersHe3, + l4Cand.nSigmaHe3, l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, + l4Cand.PIDtrkHe3, l4Cand.PIDtrkPr, l4Cand.itsClSizeHe3, l4Cand.itsClSizePr, + l4Cand.sharedClustersHe3, l4Cand.sharedClustersPr, + l4Cand.isBkgUS, l4Cand.isBkgEM, + l4Cand.momHe3MC, l4Cand.momPrMC, l4Cand.l4PtMC, l4Cand.l4MassMC); } } diff --git a/PWGLF/TableProducer/Strangeness/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/CMakeLists.txt index cd7896e6b07..3f3ddddaa31 100644 --- a/PWGLF/TableProducer/Strangeness/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(cascadebuilder SOURCES cascadebuilder.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore KFParticle::KFParticle + PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore KFParticle::KFParticle O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(cascadefinder @@ -56,7 +56,7 @@ o2physics_add_dpl_workflow(hstrangecorrelationfilter o2physics_add_dpl_workflow(lambdakzerobuilder SOURCES lambdakzerobuilder.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lambdakzerofinder @@ -103,3 +103,24 @@ o2physics_add_dpl_workflow(v0qaanalysis SOURCES v0qaanalysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +# ML selection +o2physics_add_dpl_workflow(lambdakzeromlselectiontreecreator + SOURCES lambdakzeroMLSelectionTreeCreator.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(cascademlselectiontreecreator + SOURCES cascadeMLSelectionTreeCreator.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lambdakzeromlselection + SOURCES lambdakzeromlselection.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(sigma0builder + SOURCES sigma0builder.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGLF/TableProducer/Strangeness/cascadeMLSelectionTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/cascadeMLSelectionTreeCreator.cxx new file mode 100644 index 00000000000..f3bfc813c89 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/cascadeMLSelectionTreeCreator.cxx @@ -0,0 +1,359 @@ +// 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. +// +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// Cascade ML Tree Creator task +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// +// This task loops over a set of V0 indices and +// creates a TTree for ML training and testing. +// +// Comments, questions, complaints, suggestions? +// Please write to: +// gianni.shigeru.setoue.liveraro@cern.ch +// romain.schotter@cern.ch +// david.dobrigkeit.chinellato@cern.ch +// + +#include // C system +#include // C++ system +#include // C++ system +#include // C++ system + +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/ASoA.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.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 "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/TableProducer/PID/pidTOFBase.h" +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using std::cout; +using std::endl; + +using dauTracks = soa::Join; + +struct cascadeMLSelectionTreeCreator { + Produces cascadeMLCandidates; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // selection switches: please, use just one at a time! + Configurable getXiMinus{"getXiMinus", false, "If True, apply cuts to select XiMinus signal and bkg candidates"}; + Configurable getXiPlus{"getXiPlus", false, "If True, apply cuts to select XiPlus signal and bkg candidates"}; + Configurable getOmegaMinus{"getOmegaMinus", false, "If True, apply cuts to select OmegaMinus signal and bkg candidates"}; + Configurable getOmegaPlus{"getOmegaPlus", false, "If True, apply cuts to select OmegaPlus signal and bkg candidates"}; + + Configurable xiMassWindow{"xiMassWindow", 0.060, "Xi Mass Window around mass peak to consider (+/-, in GeV/c^2)"}; + Configurable omegaMassWindow{"omegaMassWindow", 0.060, "Omega Mass Window around mass peak to consider (+/-, in GeV/c^2)"}; + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + // Selection criteria - compatible with core wagon autodetect + Configurable v0setting_cospa{"v0setting_cospa", 0.9, "v0setting_cospa"}; + Configurable v0setting_dcav0dau{"v0setting_dcav0dau", 2.0, "v0setting_dcav0dau"}; + Configurable v0setting_dcapostopv{"v0setting_dcapostopv", 0.05, "v0setting_dcapostopv"}; + Configurable v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.05, "v0setting_dcanegtopv"}; + Configurable v0setting_radius{"v0setting_radius", 0.9, "v0setting_radius"}; + Configurable cascadesetting_cospa{"cascadesetting_cospa", 0.9, "cascadesetting_cospa"}; + Configurable cascadesetting_dcacascdau{"cascadesetting_dcacascdau", 2.0, "cascadesetting_dcacascdau"}; + Configurable cascadesetting_dcabachtopv{"cascadesetting_dcabachtopv", 0.05, "cascadesetting_dcabachtopv"}; + Configurable cascadesetting_cascradius{"cascadesetting_cascradius", 0.5, "cascadesetting_cascradius"}; + Configurable cascadesetting_v0masswindow{"cascadesetting_v0masswindow", 0.02, "cascadesetting_v0masswindow"}; + Configurable cascadesetting_mindcav0topv{"cascadesetting_mindcav0topv", 0.0, "cascadesetting_mindcav0topv"}; + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + // Axis: + ConfigurableAxis centralityAxis{"centralityAxis", {100, 0.0f, 100.0f}, ""}; + + void init(InitContext const&) + { + histos.add("hEventCentrality", "hEventCentrality", kTH1F, {centralityAxis}); + } + + // Helper struct to pass v0 information + struct { + uint8_t massWindows; + int charge; + float centrality; + + // tracking properties + int posITSCls; + int negITSCls; + int bachITSCls; + uint32_t posITSClsSizes; + uint32_t negITSClsSizes; + uint32_t bachITSClsSizes; + float posTPCRows; + float negTPCRows; + float bachTPCRows; + + // PID properties + float posTPCSigmaPi; + float negTPCSigmaPi; + float posTPCSigmaPr; + float negTPCSigmaPr; + float bachTPCSigmaPi; + float bachTPCSigmaKa; + float TOFNSigmaXiLaPi; + float TOFNSigmaXiLaPr; + float TOFNSigmaXiPi; + float TOFNSigmaOmLaPi; + float TOFNSigmaOmLaPr; + float TOFNSigmaOmKa; + + // Basic kine + float mXi; + float mOmega; + float yXi; + float yOmega; + float mLambdaDaughter; + float pt; + float posEta; + float negEta; + float bachEta; + + // Topological + float v0radius; + float cascradius; + float dcapostopv; + float dcanegtopv; + float dcabachtopv; + float dcaV0Daughters; + float dcaCascDaughters; + float dcav0topv; + float v0CosPA; + float cascCosPA; + + // reserved for MC operation + bool isXiMinus; + bool isXiPlus; + bool isOmegaMinus; + bool isOmegaPlus; + } cascadeCandidate; + + // Process candidate and store properties in object + template + void processCandidate(TCollision const& coll, TCascObject const& cand) + { + auto posTrackExtra = cand.template posTrackExtra_as(); + auto negTrackExtra = cand.template negTrackExtra_as(); + auto bachTrackExtra = cand.template bachTrackExtra_as(); + + cascadeCandidate.charge = cand.sign(); + cascadeCandidate.centrality = coll.centFT0C(); + + // Track quality + cascadeCandidate.posITSCls = posTrackExtra.itsNCls(); + cascadeCandidate.negITSCls = negTrackExtra.itsNCls(); + cascadeCandidate.bachITSCls = negTrackExtra.itsNCls(); + cascadeCandidate.posITSClsSizes = posTrackExtra.itsClusterSizes(); + cascadeCandidate.negITSClsSizes = negTrackExtra.itsClusterSizes(); + cascadeCandidate.bachITSClsSizes = negTrackExtra.itsClusterSizes(); + cascadeCandidate.posTPCRows = posTrackExtra.tpcCrossedRows(); + cascadeCandidate.negTPCRows = negTrackExtra.tpcCrossedRows(); + cascadeCandidate.bachTPCRows = bachTrackExtra.tpcCrossedRows(); + + // TPC PID + cascadeCandidate.posTPCSigmaPi = posTrackExtra.tpcNSigmaPi(); + cascadeCandidate.negTPCSigmaPi = negTrackExtra.tpcNSigmaPi(); + cascadeCandidate.posTPCSigmaPr = posTrackExtra.tpcNSigmaPr(); + cascadeCandidate.negTPCSigmaPr = negTrackExtra.tpcNSigmaPr(); + cascadeCandidate.bachTPCSigmaPi = bachTrackExtra.tpcNSigmaPi(); + cascadeCandidate.bachTPCSigmaKa = bachTrackExtra.tpcNSigmaKa(); + + // TOF PID + cascadeCandidate.TOFNSigmaXiLaPi = cand.tofNSigmaXiLaPi(); + cascadeCandidate.TOFNSigmaXiLaPr = cand.tofNSigmaXiLaPr(); + cascadeCandidate.TOFNSigmaXiPi = cand.tofNSigmaXiPi(); + cascadeCandidate.TOFNSigmaOmLaPi = cand.tofNSigmaOmLaPi(); + cascadeCandidate.TOFNSigmaOmLaPr = cand.tofNSigmaOmLaPr(); + cascadeCandidate.TOFNSigmaOmKa = cand.tofNSigmaOmKa(); + + // Basic Kine + cascadeCandidate.mXi = cand.mXi(); + cascadeCandidate.mOmega = cand.mOmega(); + cascadeCandidate.yXi = cand.yXi(); + cascadeCandidate.yOmega = cand.yOmega(); + cascadeCandidate.mLambdaDaughter = cand.mLambda(); + cascadeCandidate.pt = cand.pt(); + cascadeCandidate.posEta = cand.positiveeta(); + cascadeCandidate.negEta = cand.negativeeta(); + cascadeCandidate.bachEta = cand.bacheloreta(); + + // Topological + cascadeCandidate.v0radius = cand.v0radius(); + cascadeCandidate.cascradius = cand.cascradius(); + cascadeCandidate.dcapostopv = cand.dcapostopv(); + cascadeCandidate.dcanegtopv = cand.dcanegtopv(); + cascadeCandidate.dcabachtopv = cand.dcabachtopv(); + cascadeCandidate.dcaV0Daughters = cand.dcaV0daughters(); + cascadeCandidate.dcaCascDaughters = cand.dcacascdaughters(); + cascadeCandidate.dcav0topv = cand.dcav0topv(coll.posX(), coll.posY(), coll.posZ()); + cascadeCandidate.v0CosPA = cand.v0cosPA(coll.posX(), coll.posY(), coll.posZ()); + cascadeCandidate.cascCosPA = cand.casccosPA(coll.posX(), coll.posY(), coll.posZ()); + + // MC flags + cascadeCandidate.isXiMinus = false; + cascadeCandidate.isXiPlus = false; + cascadeCandidate.isOmegaMinus = false; + cascadeCandidate.isOmegaPlus = false; + + if constexpr (requires { cand.pdgCode(); }) { + cascadeCandidate.isXiMinus = (cand.pdgCode() == 3312); + cascadeCandidate.isXiPlus = (cand.pdgCode() == -3312); + cascadeCandidate.isOmegaMinus = (cand.pdgCode() == 3334); + cascadeCandidate.isOmegaPlus = (cand.pdgCode() == -3334); + } + + // base topological selections + if (cascadeCandidate.v0CosPA < v0setting_cospa) + return; + if (cascadeCandidate.dcaV0Daughters > v0setting_dcav0dau) + return; + if (cascadeCandidate.dcapostopv < v0setting_dcapostopv) + return; + if (cascadeCandidate.dcapostopv < v0setting_dcanegtopv) + return; + if (cascadeCandidate.dcabachtopv < cascadesetting_dcabachtopv) + return; + if (cascadeCandidate.v0radius < v0setting_radius) + return; + if (cascadeCandidate.cascCosPA < cascadesetting_cospa) + return; + if (cascadeCandidate.dcaCascDaughters > cascadesetting_dcacascdau) + return; + if (cascadeCandidate.cascradius < cascadesetting_cascradius) + return; + if (std::abs(cascadeCandidate.mLambdaDaughter - 1.116) > cascadesetting_v0masswindow) + return; + if (cascadeCandidate.dcav0topv < cascadesetting_mindcav0topv) + return; + + // Mass window selections + cascadeCandidate.massWindows = 0; + if (std::abs(cascadeCandidate.mXi - 1.322) < xiMassWindow) { + cascadeCandidate.massWindows = cascadeCandidate.massWindows | 1 << 0; + } + if (std::abs(cascadeCandidate.mOmega - 1.6725) < omegaMassWindow) { + cascadeCandidate.massWindows = cascadeCandidate.massWindows | 1 << 1; + } + if (cascadeCandidate.massWindows == 0) { + return; // skip + } + + // populate + cascadeMLCandidates( + cascadeCandidate.massWindows, + cascadeCandidate.charge, + cascadeCandidate.centrality, + + // Track quality + cascadeCandidate.posITSCls, + cascadeCandidate.negITSCls, + cascadeCandidate.bachITSCls, + cascadeCandidate.posITSClsSizes, + cascadeCandidate.negITSClsSizes, + cascadeCandidate.bachITSClsSizes, + cascadeCandidate.posTPCRows, + cascadeCandidate.negTPCRows, + cascadeCandidate.bachTPCRows, + + // TPC PID + cascadeCandidate.posTPCSigmaPi, + cascadeCandidate.negTPCSigmaPi, + cascadeCandidate.posTPCSigmaPr, + cascadeCandidate.negTPCSigmaPr, + cascadeCandidate.bachTPCSigmaPi, + cascadeCandidate.bachTPCSigmaKa, + + // TOF PID + cascadeCandidate.TOFNSigmaXiLaPi, + cascadeCandidate.TOFNSigmaXiLaPr, + cascadeCandidate.TOFNSigmaXiPi, + cascadeCandidate.TOFNSigmaOmLaPi, + cascadeCandidate.TOFNSigmaOmLaPr, + cascadeCandidate.TOFNSigmaOmKa, + + // Basic Kine + cascadeCandidate.mXi, + cascadeCandidate.mOmega, + cascadeCandidate.yXi, + cascadeCandidate.yOmega, + cascadeCandidate.mLambdaDaughter, + cascadeCandidate.pt, + cascadeCandidate.posEta, + cascadeCandidate.negEta, + cascadeCandidate.bachEta, + + // Topological + cascadeCandidate.v0radius, + cascadeCandidate.cascradius, + cascadeCandidate.dcapostopv, + cascadeCandidate.dcanegtopv, + cascadeCandidate.dcabachtopv, + cascadeCandidate.dcaV0Daughters, + cascadeCandidate.dcaCascDaughters, + cascadeCandidate.dcav0topv, + TMath::ACos(cascadeCandidate.v0CosPA), + TMath::ACos(cascadeCandidate.cascCosPA), + + // MC identity + cascadeCandidate.isXiMinus, + cascadeCandidate.isXiPlus, + cascadeCandidate.isOmegaMinus, + cascadeCandidate.isOmegaPlus); + } + + void processRealData(soa::Join::iterator const& coll, soa::Join const& cascades, dauTracks const&) + { + histos.fill(HIST("hEventCentrality"), coll.centFT0C()); + for (auto& casc : cascades) { // looping over lambdas + processCandidate(coll, casc); + } + } + void processSimData(soa::Join::iterator const& coll, soa::Join const& cascades, dauTracks const&) + { + histos.fill(HIST("hEventCentrality"), coll.centFT0C()); + for (auto& casc : cascades) { // looping over lambdas + processCandidate(coll, casc); + } + } + + PROCESS_SWITCH(cascadeMLSelectionTreeCreator, processRealData, "Produce Run 3 cascade tables (real data)", false); + PROCESS_SWITCH(cascadeMLSelectionTreeCreator, processSimData, "Produce Run 3 cascade tables (simulation)", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx b/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx index 0d94bc67356..ce6ab3aaaac 100644 --- a/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx @@ -61,6 +61,8 @@ #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" #ifndef HomogeneousField #define HomogeneousField @@ -104,6 +106,13 @@ using LabeledTracksExtra = soa::Join; //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* // Builder task: rebuilds multi-strange candidates struct cascadeBuilder { + o2::ml::OnnxModel mlModelXiMinus; + o2::ml::OnnxModel mlModelXiPlus; + o2::ml::OnnxModel mlModelOmegaMinus; + o2::ml::OnnxModel mlModelOmegaPlus; + + std::map metadata; + Produces cascidx; Produces kfcascidx; Produces trackedcascidx; @@ -114,6 +123,8 @@ struct cascadeBuilder { Produces cascbb; // if enabled Produces casccovs; // if requested by someone Produces kfcasccovs; // if requested by someone + + o2::ccdb::CcdbApi ccdbApi; Service ccdb; Configurable d_UseAutodetectMode{"d_UseAutodetectMode", false, "Autodetect requested topo sels"}; @@ -149,26 +160,30 @@ struct cascadeBuilder { Configurable calculateBachBaryonVars{"calculateBachBaryonVars", false, "calculate variables for removing cascade inv mass bump"}; // 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"}; + struct : ConfigurableGroup { + 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; // generate and fill extra QA histograms if requested - Configurable d_doQA{"d_doQA", false, "Do basic QA"}; - Configurable dQANBinsRadius{"dQANBinsRadius", 500, "Number of radius bins in QA histo"}; - Configurable dQANBinsPtCoarse{"dQANBinsPtCoarse", 10, "Number of pT bins in QA histo"}; - Configurable dQANBinsMass{"dQANBinsMass", 400, "Number of mass bins for QA histograms"}; - Configurable dQANBinsDCAxy{"dQANBinsDCAxy", 200, "DCAxy of cascade to PV Nbins"}; - Configurable dQANBinsChi2{"dQANBinsChi2", 200, "Chi2 Nbins"}; - Configurable dQANBinsCluSize{"dQANBinsCluSize", 200, "Cluster size Nbins"}; - Configurable dQAMaxPt{"dQAMaxPt", 5, "max pT in QA histo"}; - Configurable dQAMaxDCA{"dQAMaxDCA", 1, "max DCAxy QA histo"}; - Configurable dQAMaxChi2{"dQAMaxChi2", 20, "max chi2"}; - Configurable dQAMaxCluSize{"dQAMaxCluSize", 10, "max ITS clu size"}; - Configurable dQAXiMassWindow{"dQAXiMassWindow", 0.005, "Xi mass window for ITS cluster map QA"}; - Configurable dQAOmegaMassWindow{"dQAOmegaMassWindow", 0.005, "Omega mass window for ITS cluster map QA"}; + struct : ConfigurableGroup { + Configurable d_doQA{"qaConfigurations.d_doQA", false, "Do basic QA"}; + Configurable dQANBinsRadius{"qaConfigurations.dQANBinsRadius", 500, "Number of radius bins in QA histo"}; + Configurable dQANBinsPtCoarse{"qaConfigurations.dQANBinsPtCoarse", 10, "Number of pT bins in QA histo"}; + Configurable dQANBinsMass{"qaConfigurations.dQANBinsMass", 400, "Number of mass bins for QA histograms"}; + Configurable dQANBinsDCAxy{"qaConfigurations.dQANBinsDCAxy", 200, "DCAxy of cascade to PV Nbins"}; + Configurable dQANBinsChi2{"qaConfigurations.dQANBinsChi2", 200, "Chi2 Nbins"}; + Configurable dQANBinsCluSize{"qaConfigurations.dQANBinsCluSize", 200, "Cluster size Nbins"}; + Configurable dQAMaxPt{"qaConfigurations.dQAMaxPt", 5, "max pT in QA histo"}; + Configurable dQAMaxDCA{"qaConfigurations.dQAMaxDCA", 1, "max DCAxy QA histo"}; + Configurable dQAMaxChi2{"qaConfigurations.dQAMaxChi2", 20, "max chi2"}; + Configurable dQAMaxCluSize{"qaConfigurations.dQAMaxCluSize", 10, "max ITS clu size"}; + Configurable dQAXiMassWindow{"qaConfigurations.dQAXiMassWindow", 0.005, "Xi mass window for ITS cluster map QA"}; + Configurable dQAOmegaMassWindow{"qaConfigurations.dQAOmegaMassWindow", 0.005, "Omega mass window for ITS cluster map QA"}; + } qaConfigurations; // for KF particle operation Configurable kfTuneForOmega{"kfTuneForOmega", false, "if enabled, take main cascade properties from Omega fit instead of Xi fit (= default)"}; @@ -178,15 +193,43 @@ struct cascadeBuilder { Configurable kfDoDCAFitterPreMinimV0{"kfDoDCAFitterPreMinimV0", true, "KF: do DCAFitter pre-optimization before KF fit to include material corrections for V0"}; Configurable kfDoDCAFitterPreMinimCasc{"kfDoDCAFitterPreMinimCasc", true, "KF: do DCAFitter pre-optimization before KF fit to include material corrections for Xi"}; - ConfigurableAxis axisPtQA{"axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; - // for topo var QA - ConfigurableAxis axisTopoVarPointingAngle{"axisTopoVarPointingAngle", {50, 0.0, 1.0}, "pointing angle"}; - ConfigurableAxis axisTopoVarRAP{"axisTopoVarRAP", {50, 0.0, 1.0}, "radius x pointing angle axis"}; - ConfigurableAxis axisTopoVarV0Radius{"axisTopoVarV0Radius", {500, 0.0, 100.0}, "V0 decay radius (cm)"}; - ConfigurableAxis axisTopoVarDCAV0Dau{"axisTopoVarDCAV0Dau", {200, 0.0, 2.0}, "DCA between V0 daughters (cm)"}; - ConfigurableAxis axisTopoVarDCAToPV{"axisTopoVarDCAToPV", {200, -1, 1.0}, "single track DCA to PV (cm)"}; - ConfigurableAxis axisTopoVarDCAV0ToPV{"axisTopoVarDCAV0ToPV", {200, 0, 5.0}, "V0 DCA to PV (cm)"}; + struct : ConfigurableGroup { + ConfigurableAxis axisTopoVarPointingAngle{"axisConfigurations.axisTopoVarPointingAngle", {50, 0.0, 1.0}, "pointing angle"}; + ConfigurableAxis axisTopoVarRAP{"axisConfigurations.axisTopoVarRAP", {50, 0.0, 1.0}, "radius x pointing angle axis"}; + ConfigurableAxis axisTopoVarV0Radius{"axisConfigurations.axisTopoVarV0Radius", {500, 0.0, 100.0}, "V0 decay radius (cm)"}; + ConfigurableAxis axisTopoVarDCAV0Dau{"axisConfigurations.axisTopoVarDCAV0Dau", {200, 0.0, 2.0}, "DCA between V0 daughters (cm)"}; + ConfigurableAxis axisTopoVarDCAToPV{"axisConfigurations.axisTopoVarDCAToPV", {200, -1, 1.0}, "single track DCA to PV (cm)"}; + ConfigurableAxis axisTopoVarDCAV0ToPV{"axisConfigurations.axisTopoVarDCAV0ToPV", {200, 0, 5.0}, "V0 DCA to PV (cm)"}; + ConfigurableAxis axisPtQA{"axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + } axisConfigurations; + + // Machine learning evaluation for pre-selection and corresponding information generation + struct : ConfigurableGroup { + // ML classifiers: master flags to populate ML Selection tables + Configurable calculateXiMinusScores{"mlConfigurations.calculateXiMinusScores", false, "calculate XiMinus ML scores"}; + Configurable calculateXiPlusScores{"mlConfigurations.calculateXiPlusScores", false, "calculate XiPlus ML scores"}; + Configurable calculateOmegaMinusScores{"mlConfigurations.calculateOmegaMinusScores", false, "calculate OmegaMinus ML scores"}; + Configurable calculateOmegaPlusScores{"mlConfigurations.calculateOmegaPlusScores", false, "calculate OmegaPlus ML scores"}; + + // ML input for ML calculation + Configurable modelPathCCDB{"mlConfigurations.modelPathCCDB", "", "ML Model path in CCDB"}; + Configurable timestampCCDB{"mlConfigurations.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{"mlConfigurations.loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"mlConfigurations.enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + + // Local paths for test purposes + Configurable localModelPathXiMinus{"mlConfigurations.localModelPathXiMinus", "XiMinus_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable localModelPathXiPlus{"mlConfigurations.localModelPathXiPlus", "XiPlus_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable localModelPathOmegaMinus{"mlConfigurations.localModelPathOmegaMinus", "OmegaMinus_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable localModelPathOmegaPlus{"mlConfigurations.localModelPathOmegaPlus", "OmegaPlus_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + + // Thresholds for choosing to populate V0Cores tables with pre-selections + Configurable thresholdXiMinus{"mlConfigurations.thresholdXiMinus", -1.0f, "Threshold to keep XiMinus candidates"}; + Configurable thresholdXiPlus{"mlConfigurations.thresholdXiPlus", -1.0f, "Threshold to keep XiPlus candidates"}; + Configurable thresholdOmegaMinus{"mlConfigurations.thresholdOmegaMinus", -1.0f, "Threshold to keep OmegaMinus candidates"}; + Configurable thresholdOmegaPlus{"mlConfigurations.thresholdOmegaPlus", -1.0f, "Threshold to keep OmegaPlus candidates"}; + } mlConfigurations; // round some V0 core variables up to a certain level of precision if requested // useful to keep derived data sizes under control @@ -265,6 +308,10 @@ struct cascadeBuilder { std::array kfV0Cov; std::array kfV0DauPosCov; std::array kfV0DauNegCov; + float mlXiMinusScore; + float mlXiPlusScore; + float mlOmegaMinusScore; + float mlOmegaPlusScore; } cascadecandidate; o2::track::TrackParCov lBachelorTrack; @@ -354,27 +401,27 @@ struct cascadeBuilder { h->GetXaxis()->SetBinLabel(10, "Tracked"); // Optionally, add extra QA histograms to processing chain - if (d_doQA) { + if (qaConfigurations.d_doQA) { // Basic histograms containing invariant masses of all built candidates - const AxisSpec axisVsPtCoarse{static_cast(dQANBinsPtCoarse), 0, dQAMaxPt, "#it{p}_{T} (GeV/c)"}; - const AxisSpec axisLamMass{static_cast(dQANBinsMass), 1.075f, 1.275f, "Inv. Mass (GeV/c^{2})"}; - const AxisSpec axisXiMass{static_cast(dQANBinsMass), 1.222f, 1.422f, "Inv. Mass (GeV/c^{2})"}; - const AxisSpec axisOmegaMass{static_cast(dQANBinsMass), 1.572f, 1.772f, "Inv. Mass (GeV/c^{2})"}; - const AxisSpec axisCascadeDCAtoPV{static_cast(dQANBinsDCAxy), -dQAMaxDCA, dQAMaxDCA, "DCA_{xy} (cm)"}; - - registry.add("h2dLambdaMass", "h2dLambdaMass", kTH2F, {axisPtQA, axisLamMass}); - registry.add("h2dAntiLambdaMass", "h2dAntiLambdaMass", kTH2F, {axisPtQA, axisLamMass}); - registry.add("MassHistograms/h2dXiMinusMass", "h2dXiMinusMass", kTH2F, {axisPtQA, axisXiMass}); - registry.add("MassHistograms/h2dXiPlusMass", "h2dXiPlusMass", kTH2F, {axisPtQA, axisXiMass}); - registry.add("MassHistograms/h2dOmegaMinusMass", "h2dOmegaMinusMass", kTH2F, {axisPtQA, axisOmegaMass}); - registry.add("MassHistograms/h2dOmegaPlusMass", "h2dOmegaPlusMass", kTH2F, {axisPtQA, axisOmegaMass}); + const AxisSpec axisVsPtCoarse{static_cast(qaConfigurations.dQANBinsPtCoarse), 0, qaConfigurations.dQAMaxPt, "#it{p}_{T} (GeV/c)"}; + const AxisSpec axisLamMass{static_cast(qaConfigurations.dQANBinsMass), 1.075f, 1.275f, "Inv. Mass (GeV/c^{2})"}; + const AxisSpec axisXiMass{static_cast(qaConfigurations.dQANBinsMass), 1.222f, 1.422f, "Inv. Mass (GeV/c^{2})"}; + const AxisSpec axisOmegaMass{static_cast(qaConfigurations.dQANBinsMass), 1.572f, 1.772f, "Inv. Mass (GeV/c^{2})"}; + const AxisSpec axisCascadeDCAtoPV{static_cast(qaConfigurations.dQANBinsDCAxy), -qaConfigurations.dQAMaxDCA, qaConfigurations.dQAMaxDCA, "DCA_{xy} (cm)"}; + + registry.add("h2dLambdaMass", "h2dLambdaMass", kTH2F, {axisConfigurations.axisPtQA, axisLamMass}); + registry.add("h2dAntiLambdaMass", "h2dAntiLambdaMass", kTH2F, {axisConfigurations.axisPtQA, axisLamMass}); + registry.add("MassHistograms/h2dXiMinusMass", "h2dXiMinusMass", kTH2F, {axisConfigurations.axisPtQA, axisXiMass}); + registry.add("MassHistograms/h2dXiPlusMass", "h2dXiPlusMass", kTH2F, {axisConfigurations.axisPtQA, axisXiMass}); + registry.add("MassHistograms/h2dOmegaMinusMass", "h2dOmegaMinusMass", kTH2F, {axisConfigurations.axisPtQA, axisOmegaMass}); + registry.add("MassHistograms/h2dOmegaPlusMass", "h2dOmegaPlusMass", kTH2F, {axisConfigurations.axisPtQA, axisOmegaMass}); if (d_doPtDep_CosPaCut) registry.addClone("MassHistograms/", "MassHistograms_BefPAcut/"); // bit packed ITS cluster map const AxisSpec axisITSCluMap{static_cast(128), -0.5f, +127.5f, "Packed ITS map"}; - const AxisSpec axisRadius{static_cast(dQANBinsRadius), 0.0f, +50.0f, "Radius (cm)"}; + const AxisSpec axisRadius{static_cast(qaConfigurations.dQANBinsRadius), 0.0f, +50.0f, "Radius (cm)"}; // Histogram to bookkeep cluster maps registry.add("h2dITSCluMap_XiMinusPositive", "h2dITSCluMap_XiMinusPositive", kTH2D, {axisITSCluMap, axisRadius}); @@ -391,9 +438,9 @@ struct cascadeBuilder { registry.add("h2dITSCluMap_OmegaPlusBachelor", "h2dITSCluMap_OmegaPlusBachelor", kTH2D, {axisITSCluMap, axisRadius}); // QA plots of topological variables using axisPtQA - registry.add("h2dTopoVarCascPointingAngle", "h2dTopoVarCascPointingAngle", kTH2D, {axisPtQA, axisTopoVarPointingAngle}); - registry.add("h2dTopoVarCascRAP", "h2dTopoVarCascRAP", kTH2D, {axisPtQA, axisTopoVarRAP}); - registry.add("h2dTopoVarCascRadius", "h2dTopoVarCascRadius", kTH2D, {axisPtQA, axisTopoVarV0Radius}); + registry.add("h2dTopoVarCascPointingAngle", "h2dTopoVarCascPointingAngle", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarPointingAngle}); + registry.add("h2dTopoVarCascRAP", "h2dTopoVarCascRAP", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarRAP}); + registry.add("h2dTopoVarCascRadius", "h2dTopoVarCascRadius", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarV0Radius}); // if basic strangeness tracking QA is desired, do it here // convenience: equivalence between regular cascade and tracked cascade is easy to check here @@ -448,8 +495,8 @@ struct cascadeBuilder { registry.add("hDCAzTrackedCascadeToPVOmegaPlus", "hDCAzTrackedCascadeToPVOmegaPlus", kTH2F, {axisVsPtCoarse, axisCascadeDCAtoPV}); // specific variables associated to strangeness tracking - const AxisSpec axisChi2{static_cast(dQANBinsChi2), 0.0f, dQAMaxChi2, "#chi^{2}"}; - const AxisSpec axisCluSize{static_cast(dQANBinsCluSize), 0.0f, dQAMaxCluSize, "Mean ITS cluster size"}; + const AxisSpec axisChi2{static_cast(qaConfigurations.dQANBinsChi2), 0.0f, qaConfigurations.dQAMaxChi2, "#chi^{2}"}; + const AxisSpec axisCluSize{static_cast(qaConfigurations.dQANBinsCluSize), 0.0f, qaConfigurations.dQAMaxCluSize, "Mean ITS cluster size"}; registry.add("hMatchingChi2_XiMinus", "hMatchingChi2_XiMinus", kTH1D, {axisChi2}); registry.add("hMatchingChi2_XiPlus", "hMatchingChi2_XiPlus", kTH1D, {axisChi2}); registry.add("hMatchingChi2_OmegaMinus", "hMatchingChi2_OmegaMinus", kTH1D, {axisChi2}); @@ -470,7 +517,7 @@ struct cascadeBuilder { maxSnp = 0.85f; // could be changed later maxStep = 2.00f; // could be changed later - ccdb->setURL(ccdburl); + ccdb->setURL(ccdbConfigurations.ccdburl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); @@ -478,12 +525,12 @@ struct cascadeBuilder { if (useMatCorrType == 1) { LOGF(info, "TGeo correction requested, loading geometry"); if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(geoPath); + ccdb->get(ccdbConfigurations.geoPath); } } if (useMatCorrType == 2) { LOGF(info, "LUT correction requested, loading LUT"); - lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbConfigurations.lutPath)); } if (doprocessRun2 == false && doprocessRun3 == false && doprocessRun3withStrangenessTracking == false && doprocessRun3withKFParticle == false) { @@ -646,6 +693,17 @@ struct cascadeBuilder { return; } + // machine learning initialization if requested + if (mlConfigurations.calculateXiMinusScores || + mlConfigurations.calculateXiPlusScores || + mlConfigurations.calculateOmegaMinusScores || + mlConfigurations.calculateOmegaPlusScores) { + int64_t timeStampML = bc.timestamp(); + if (mlConfigurations.timestampCCDB.value != -1) + timeStampML = mlConfigurations.timestampCCDB.value; + LoadMachines(timeStampML); + } + // In case override, don't proceed, please - no CCDB access required if (d_bz_input > -990) { d_bz = d_bz_input; @@ -663,15 +721,15 @@ struct cascadeBuilder { o2::parameters::GRPObject* grpo = 0x0; o2::parameters::GRPMagField* grpmag = 0x0; if (doprocessRun2) { - grpo = ccdb->getForTimeStamp(grpPath, timestamp); + grpo = ccdb->getForTimeStamp(ccdbConfigurations.grpPath, timestamp); if (!grpo) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpPath << " of object GRPObject for timestamp " << timestamp; + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfigurations.grpPath << " of object GRPObject for timestamp " << timestamp; } o2::base::Propagator::initFieldFromGRP(grpo); } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, timestamp); + grpmag = ccdb->getForTimeStamp(ccdbConfigurations.grpmagPath, timestamp); if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField for timestamp " << timestamp; + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfigurations.grpmagPath << " of object GRPMagField for timestamp " << timestamp; } o2::base::Propagator::initFieldFromGRP(grpmag); } @@ -690,6 +748,62 @@ struct cascadeBuilder { o2::base::Propagator::Instance()->setMatLUT(lut); } } + + // function to load models for ML-based classifiers + void LoadMachines(int64_t timeStampML) + { + if (mlConfigurations.loadModelsFromCCDB) { + ccdbApi.init(ccdbConfigurations.ccdburl); + LOG(info) << "Fetching cascade models for timestamp: " << timeStampML; + + if (mlConfigurations.calculateXiMinusScores) { + bool retrieveSuccess = ccdbApi.retrieveBlob(mlConfigurations.modelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathXiMinus.value); + if (retrieveSuccess) { + mlModelXiMinus.initModel(mlConfigurations.localModelPathXiMinus.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the XiMinus model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (mlConfigurations.calculateXiPlusScores) { + bool retrieveSuccess = ccdbApi.retrieveBlob(mlConfigurations.modelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathXiPlus.value); + if (retrieveSuccess) { + mlModelXiPlus.initModel(mlConfigurations.localModelPathXiPlus.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the XiPlus model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (mlConfigurations.calculateOmegaMinusScores) { + bool retrieveSuccess = ccdbApi.retrieveBlob(mlConfigurations.modelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathOmegaMinus.value); + if (retrieveSuccess) { + mlModelOmegaMinus.initModel(mlConfigurations.localModelPathOmegaMinus.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the OmegaMinus model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (mlConfigurations.calculateOmegaPlusScores) { + bool retrieveSuccess = ccdbApi.retrieveBlob(mlConfigurations.modelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathOmegaPlus.value); + if (retrieveSuccess) { + mlModelOmegaPlus.initModel(mlConfigurations.localModelPathOmegaPlus.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the OmegaPlus model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + } else { + if (mlConfigurations.calculateXiMinusScores) + mlModelXiMinus.initModel(mlConfigurations.localModelPathXiMinus.value, mlConfigurations.enableOptimizations.value); + if (mlConfigurations.calculateXiPlusScores) + mlModelXiPlus.initModel(mlConfigurations.localModelPathXiPlus.value, mlConfigurations.enableOptimizations.value); + if (mlConfigurations.calculateOmegaMinusScores) + mlModelOmegaMinus.initModel(mlConfigurations.localModelPathOmegaMinus.value, mlConfigurations.enableOptimizations.value); + if (mlConfigurations.calculateOmegaPlusScores) + mlModelOmegaPlus.initModel(mlConfigurations.localModelPathOmegaPlus.value, mlConfigurations.enableOptimizations.value); + } + LOG(info) << "Cascade ML Models loaded."; + } + // TrackParCov to KF converter // FIXME: could be an utility somewhere else // from Carolina Reetz (thank you!) @@ -836,7 +950,7 @@ struct cascadeBuilder { // Overall cascade charge cascadecandidate.charge = bachTrack.signed1Pt() > 0 ? +1 : -1; - if (d_doQA) { + if (qaConfigurations.d_doQA) { // produce a plot that showcases the mass of the received lambdas if (cascadecandidate.charge < 0) registry.fill(HIST("h2dLambdaMass"), v0.pt(), v0.mLambda()); @@ -916,7 +1030,7 @@ struct cascadeBuilder { cascadecandidate.pos[i] = vtx[i]; } - if (d_doQA && d_doPtDep_CosPaCut) { + if (qaConfigurations.d_doQA && d_doPtDep_CosPaCut) { bool mcUnchecked = !d_QA_checkMC; bool dEdxUnchecked = !d_QA_checkdEdx; @@ -1011,7 +1125,7 @@ struct cascadeBuilder { statisticsRegistry.bachITSclu[bachTrack.itsNCls()]++; } - if (d_doQA) { + if (qaConfigurations.d_doQA) { bool mcUnchecked = !d_QA_checkMC; bool dEdxUnchecked = !d_QA_checkdEdx; @@ -1030,22 +1144,22 @@ struct cascadeBuilder { registry.fill(HIST("MassHistograms/h2dOmegaPlusMass"), lPt, cascadecandidate.mOmega); // Fill ITS cluster maps with specific mass cuts - if (TMath::Abs(cascadecandidate.mXi - 1.322) < dQAXiMassWindow && ((cascade.isdEdxXiMinus() || dEdxUnchecked) && (cascade.isTrueXiMinus() || mcUnchecked)) && cascadecandidate.charge < 0) { + if (TMath::Abs(cascadecandidate.mXi - 1.322) < qaConfigurations.dQAXiMassWindow && ((cascade.isdEdxXiMinus() || dEdxUnchecked) && (cascade.isTrueXiMinus() || mcUnchecked)) && cascadecandidate.charge < 0) { registry.fill(HIST("h2dITSCluMap_XiMinusPositive"), static_cast(posTrack.itsClusterMap()), v0.v0radius()); registry.fill(HIST("h2dITSCluMap_XiMinusNegative"), static_cast(negTrack.itsClusterMap()), v0.v0radius()); registry.fill(HIST("h2dITSCluMap_XiMinusBachelor"), static_cast(bachTrack.itsClusterMap()), cascadecandidate.cascradius); } - if (TMath::Abs(cascadecandidate.mXi - 1.322) < dQAXiMassWindow && ((cascade.isdEdxXiPlus() || dEdxUnchecked) && (cascade.isTrueXiPlus() || mcUnchecked)) && cascadecandidate.charge > 0) { + if (TMath::Abs(cascadecandidate.mXi - 1.322) < qaConfigurations.dQAXiMassWindow && ((cascade.isdEdxXiPlus() || dEdxUnchecked) && (cascade.isTrueXiPlus() || mcUnchecked)) && cascadecandidate.charge > 0) { registry.fill(HIST("h2dITSCluMap_XiPlusPositive"), static_cast(posTrack.itsClusterMap()), v0.v0radius()); registry.fill(HIST("h2dITSCluMap_XiPlusNegative"), static_cast(negTrack.itsClusterMap()), v0.v0radius()); registry.fill(HIST("h2dITSCluMap_XiPlusBachelor"), static_cast(bachTrack.itsClusterMap()), cascadecandidate.cascradius); } - if (TMath::Abs(cascadecandidate.mOmega - 1.672) < dQAOmegaMassWindow && ((cascade.isdEdxOmegaMinus() || dEdxUnchecked) && (cascade.isTrueOmegaMinus() || mcUnchecked)) && cascadecandidate.charge < 0) { + if (TMath::Abs(cascadecandidate.mOmega - 1.672) < qaConfigurations.dQAOmegaMassWindow && ((cascade.isdEdxOmegaMinus() || dEdxUnchecked) && (cascade.isTrueOmegaMinus() || mcUnchecked)) && cascadecandidate.charge < 0) { registry.fill(HIST("h2dITSCluMap_OmegaMinusPositive"), static_cast(posTrack.itsClusterMap()), v0.v0radius()); registry.fill(HIST("h2dITSCluMap_OmegaMinusNegative"), static_cast(negTrack.itsClusterMap()), v0.v0radius()); registry.fill(HIST("h2dITSCluMap_OmegaMinusBachelor"), static_cast(bachTrack.itsClusterMap()), cascadecandidate.cascradius); } - if (TMath::Abs(cascadecandidate.mOmega - 1.672) < dQAOmegaMassWindow && ((cascade.isdEdxOmegaPlus() || dEdxUnchecked) && (cascade.isTrueOmegaPlus() || mcUnchecked)) && cascadecandidate.charge > 0) { + if (TMath::Abs(cascadecandidate.mOmega - 1.672) < qaConfigurations.dQAOmegaMassWindow && ((cascade.isdEdxOmegaPlus() || dEdxUnchecked) && (cascade.isTrueOmegaPlus() || mcUnchecked)) && cascadecandidate.charge > 0) { registry.fill(HIST("h2dITSCluMap_OmegaPlusPositive"), static_cast(posTrack.itsClusterMap()), v0.v0radius()); registry.fill(HIST("h2dITSCluMap_OmegaPlusNegative"), static_cast(negTrack.itsClusterMap()), v0.v0radius()); registry.fill(HIST("h2dITSCluMap_OmegaPlusBachelor"), static_cast(bachTrack.itsClusterMap()), cascadecandidate.cascradius); @@ -1056,6 +1170,50 @@ struct cascadeBuilder { registry.fill(HIST("h2dTopoVarCascRAP"), lPt, TMath::ACos(cascadecandidate.cosPA) * cascadecandidate.cascradius); registry.fill(HIST("h2dTopoVarCascRadius"), lPt, cascadecandidate.cascradius); } + + // calculate machine learning scores, compare against thresholds + cascadecandidate.mlXiMinusScore = -1.0f; + cascadecandidate.mlXiPlusScore = -1.0f; + cascadecandidate.mlOmegaMinusScore = -1.0f; + cascadecandidate.mlOmegaPlusScore = -1.0f; + + if (mlConfigurations.calculateXiMinusScores || + mlConfigurations.calculateXiPlusScores || + mlConfigurations.calculateOmegaMinusScores || + mlConfigurations.calculateOmegaPlusScores) { + // machine learning is on, go for calculation of thresholds + // FIXME THIS NEEDS ADJUSTING + std::vector inputFeatures{0.0f, 0.0f, + 0.0f, 0.0f}; + + // calculate scores + if (mlConfigurations.calculateXiMinusScores) { + float* xiMinusProbability = mlModelXiMinus.evalModel(inputFeatures); + cascadecandidate.mlXiMinusScore = xiMinusProbability[1]; + } + if (mlConfigurations.calculateXiPlusScores) { + float* xiPlusProbability = mlModelXiPlus.evalModel(inputFeatures); + cascadecandidate.mlXiPlusScore = xiPlusProbability[1]; + } + if (mlConfigurations.calculateOmegaMinusScores) { + float* omegaMinusProbability = mlModelOmegaMinus.evalModel(inputFeatures); + cascadecandidate.mlOmegaMinusScore = omegaMinusProbability[1]; + } + if (mlConfigurations.calculateOmegaPlusScores) { + float* omegaPlusProbability = mlModelOmegaPlus.evalModel(inputFeatures); + cascadecandidate.mlOmegaPlusScore = omegaPlusProbability[1]; + } + + // Skip anything that doesn't fulfull any of the desired conditions + if (cascadecandidate.mlXiMinusScore < mlConfigurations.thresholdXiMinus.value && + cascadecandidate.mlXiPlusScore < mlConfigurations.thresholdXiPlus.value && + cascadecandidate.mlOmegaMinusScore < mlConfigurations.thresholdOmegaMinus.value && + cascadecandidate.mlOmegaPlusScore < mlConfigurations.thresholdOmegaPlus.value) { + return false; // skipped as uninteresting in any hypothesis considered + } + } + + // Final outcome is YES if I got here! return true; } diff --git a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx index a9a9c7b66af..c639f176cab 100644 --- a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx +++ b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx @@ -48,8 +48,6 @@ struct cascqaanalysis { // Event selection criteria Configurable cutzvertex{"cutzvertex", 20.0f, "Accepted z-vertex range (cm)"}; Configurable sel8{"sel8", 1, "Apply sel8 event selection"}; - Configurable isTimeFrameBorderCut{"isTimeFrameBorderCut", 1, "Apply timeframe border cut"}; - Configurable isITSROFrameBorderCut{"isITSROFrameBorderCut", 1, "Apply ITS frame border cut"}; Configurable isVertexITSTPCCut{"isVertexITSTPCCut", 1, "Select collisions with at least one ITS-TPC track"}; Configurable isNoSameBunchPileupCut{"isNoSameBunchPileupCut", 1, "Same found-by-T0 bunch crossing rejection"}; Configurable isGoodZvtxFT0vsPVCut{"isGoodZvtxFT0vsPVCut", 1, "z of PV by tracks and z of PV from FT0 A-C time difference cut"}; @@ -113,9 +111,9 @@ struct cascqaanalysis { TString hCandidateCounterLabels[5] = {"All candidates", "v0data exists", "passed topo cuts", "has associated MC particle", "associated with Xi(Omega)"}; TString hNEventsMCLabels[6] = {"All", "z vrtx", "INEL", "INEL>0", "INEL>1", "Associated with rec. collision"}; - TString hNEventsLabels[11] = {"All", "sel8", "TimeFrame cut", "ITS ROF cut", "kIsVertexITSTPC", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "z vrtx", "INEL", "INEL>0", "INEL>1"}; + TString hNEventsLabels[9] = {"All", "sel8", "kIsVertexITSTPC", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "z vrtx", "INEL", "INEL>0", "INEL>1"}; - registry.add("hNEvents", "hNEvents", {HistType::kTH1F, {{11, 0.f, 11.f}}}); + registry.add("hNEvents", "hNEvents", {HistType::kTH1F, {{9, 0.f, 9.f}}}); for (Int_t n = 1; n <= registry.get(HIST("hNEvents"))->GetNbinsX(); n++) { registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(n, hNEventsLabels[n - 1]); } @@ -242,14 +240,14 @@ struct cascqaanalysis { { // 0 - INEL, 1 - INEL > 0, 2 - INEL>1 int evFlag = 0; - registry.fill(HIST("hNEvents"), 8.5); // INEL + registry.fill(HIST("hNEvents"), 6.5); // INEL if (collision.multNTracksPVeta1() > 0) { evFlag += 1; - registry.fill(HIST("hNEvents"), 9.5); // INEL>0 + registry.fill(HIST("hNEvents"), 7.5); // INEL>0 } if (collision.multNTracksPVeta1() > 1) { evFlag += 1; - registry.fill(HIST("hNEvents"), 10.5); // INEL>1 + registry.fill(HIST("hNEvents"), 8.5); // INEL>1 } return evFlag; } @@ -268,42 +266,26 @@ struct cascqaanalysis { registry.fill(HIST("hNEvents"), 1.5); } - // kNoTimeFrameBorder selection - if (isTimeFrameBorderCut && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - return false; - } - if (isFillEventSelectionQA) { - registry.fill(HIST("hNEvents"), 2.5); - } - - // kNoITSROFrameBorder selection - if (isITSROFrameBorderCut && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { - return false; - } - if (isFillEventSelectionQA) { - registry.fill(HIST("hNEvents"), 3.5); - } - // kIsVertexITSTPC selection if (isVertexITSTPCCut && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) { return false; } if (isFillEventSelectionQA) { - registry.fill(HIST("hNEvents"), 4.5); + registry.fill(HIST("hNEvents"), 2.5); } // kNoSameBunchPileup selection if (isNoSameBunchPileupCut && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return false; } if (isFillEventSelectionQA) { - registry.fill(HIST("hNEvents"), 5.5); + registry.fill(HIST("hNEvents"), 3.5); } // kIsGoodZvtxFT0vsPV selection if (isGoodZvtxFT0vsPVCut && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } if (isFillEventSelectionQA) { - registry.fill(HIST("hNEvents"), 6.5); + registry.fill(HIST("hNEvents"), 4.5); } // Z vertex selection @@ -311,7 +293,7 @@ struct cascqaanalysis { return false; } if (isFillEventSelectionQA) { - registry.fill(HIST("hNEvents"), 7.5); + registry.fill(HIST("hNEvents"), 5.5); registry.fill(HIST("hZCollision"), collision.posZ()); } diff --git a/PWGLF/TableProducer/Strangeness/lambdakzeroMLSelectionTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/lambdakzeroMLSelectionTreeCreator.cxx new file mode 100644 index 00000000000..ae7c9deaf42 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/lambdakzeroMLSelectionTreeCreator.cxx @@ -0,0 +1,298 @@ +// 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. +// +// *+-+*+-+*+-+*+-+*+-+*+-+* +// V0 ML Tree Creator task +// *+-+*+-+*+-+*+-+*+-+*+-+* +// +// This task loops over a set of V0 indices and +// creates a TTree for ML training and testing. +// +// +// Comments, questions, complaints, suggestions? +// Please write to: +// gianni.shigeru.setoue.liveraro@cern.ch +// romain.schotter@cern.ch +// david.dobrigkeit.chinellato@cern.ch +// + +#include // C system +#include // C++ system +#include // C++ system +#include // C++ system + +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/ASoA.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.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 "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/TableProducer/PID/pidTOFBase.h" +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using std::cout; +using std::endl; + +using dauTracks = soa::Join; + +struct lambdakzeroMLSelectionTreeCreator { + Produces v0MLCandidates; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Base selection criteria + + // Lambda standard criteria:: + Configurable Lambdav0cospa{"Lambdav0cospa", 0.90, "min V0 CosPA"}; + Configurable Lambdadcav0dau{"Lambdadcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; + Configurable Lambdadcanegtopv{"Lambdadcanegtopv", .05, "min DCA Neg To PV (cm)"}; + Configurable Lambdadcapostopv{"Lambdadcapostopv", .05, "min DCA Pos To PV (cm)"}; + Configurable Lambdav0radius{"Lambdav0radius", 1.5, "minimum V0 radius (cm)"}; + Configurable LambdaWindow{"LambdaWindow", 0.01, "Mass window around expected (in GeV/c2)"}; + + // Anti-Lambda standard criteria:: + Configurable AntiLambdav0cospa{"AntiLambdav0cospa", 0.90, "min V0 CosPA"}; + Configurable AntiLambdadcav0dau{"AntiLambdadcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; + Configurable AntiLambdadcanegtopv{"AntiLambdadcanegtopv", .05, "min DCA Neg To PV (cm)"}; + Configurable AntiLambdadcapostopv{"AntiLambdadcapostopv", .05, "min DCA Pos To PV (cm)"}; + Configurable AntiLambdav0radius{"AntiLambdav0radius", 1.5, "minimum V0 radius (cm)"}; + Configurable AntiLambdaWindow{"AntiLambdaWindow", 0.01, "Mass window around expected (in GeV/c2)"}; + + // Photon standard criteria: + Configurable PhotonMinRadius{"PhotonMinRadius", 1.0, "minimum photon conversion radius (cm)"}; + Configurable PhotonMaxRadius{"PhotonMaxRadius", 200, "maximum photon conversion radius (cm)"}; + Configurable PhotonMinPt{"PhotonMinPt", 0.001, "minimum photon pT (GeV/c)"}; + Configurable PhotonMaxMass{"PhotonMaxMass", 0.2, "Maximum photon mass (GeV/c^{2})"}; + Configurable PhotonMaxqt{"PhotonMaxqt", 0.1, "Maximum photon qt value (AP plot) (GeV/c)"}; + Configurable PhotonMaxalpha{"PhotonMaxalpha", 1.0, "Max photon alpha absolute value (AP plot)"}; + Configurable PhotonWindow{"PhotonWindow", 0.01, "Mass window around expected (in GeV/c2)"}; + + // KZeroShort standard criteria: + // TODO: update criteria + Configurable K0Shortv0cospa{"K0Shortv0cospa", 0.90, "min V0 CosPA"}; + Configurable K0Shortdcav0dau{"K0Shortdcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; + Configurable K0Shortdcanegtopv{"K0Shortdcanegtopv", .05, "min DCA Neg To PV (cm)"}; + Configurable K0Shortdcapostopv{"K0Shortdcapostopv", .05, "min DCA Pos To PV (cm)"}; + Configurable K0Shortv0radius{"K0Shortv0radius", 1.5, "minimum V0 radius (cm)"}; + Configurable K0ShortWindow{"K0ShortWindow", 0.01, "Mass window around expected (in GeV/c2)"}; + + // Axis: + ConfigurableAxis centralityAxis{"centralityAxis", {100, 0.0f, 100.0f}, ""}; + + // Save certain candidates only + Configurable saveCandidateMask{"saveCandidateMask", 15, "Mask to decide saving candidates"}; + + void init(InitContext const&) + { + histos.add("hEventCentrality", "hEventCentrality", kTH1F, {centralityAxis}); + } + + // Helper struct to pass v0 information + struct { + int posITSCls; + int negITSCls; + uint32_t posITSClSize; + uint32_t negITSClSize; + float posTPCRows; + float negTPCRows; + float posTPCSigmaPi; + float negTPCSigmaPi; + float posTPCSigmaPr; + float negTPCSigmaPr; + float posTPCSigmaEl; + float negTPCSigmaEl; + float TOFSigmaLaPr; + float TOFSigmaLaPi; + float TOFSigmaALaPi; + float TOFSigmaALaPr; + float TOFSigmaK0PiPlus; + float TOFSigmaK0PiMinus; + float LambdaMass; + float AntiLambdaMass; + float GammaMass; + float KZeroShortMass; + float pT; + float qt; + float alpha; + float posEta; + float negEta; + float v0Eta; + float Z; + float v0radius; + float PA; + float dcapostopv; + float dcanegtopv; + float dcaV0daughters; + float dcav0topv; + float PsiPair; + uint8_t v0type; + float centrality; + uint8_t SelHypothesis; + bool isLambda; + bool isAntiLambda; + bool isGamma; + bool isKZeroShort; + } Candidate; + + // Process candidate and store properties in object + template + void processCandidate(TCollision const& coll, TV0Object const& cand) + { + bool lConsistentWithLambda = true; + bool lConsistentWithAntiLambda = true; + bool lConsistentWithGamma = true; + bool lConsistentWithK0Short = true; + + auto posTrackExtra = cand.template posTrackExtra_as(); + auto negTrackExtra = cand.template negTrackExtra_as(); + + // Track quality + Candidate.posITSCls = posTrackExtra.itsNCls(); + Candidate.negITSCls = negTrackExtra.itsNCls(); + Candidate.posITSClSize = posTrackExtra.itsClusterSizes(); + Candidate.negITSClSize = negTrackExtra.itsClusterSizes(); + Candidate.posTPCRows = posTrackExtra.tpcCrossedRows(); + Candidate.negTPCRows = negTrackExtra.tpcCrossedRows(); + + // TPC PID + Candidate.posTPCSigmaPi = posTrackExtra.tpcNSigmaPi(); + Candidate.negTPCSigmaPi = negTrackExtra.tpcNSigmaPi(); + Candidate.posTPCSigmaPr = posTrackExtra.tpcNSigmaPr(); + Candidate.negTPCSigmaPr = negTrackExtra.tpcNSigmaPr(); + Candidate.posTPCSigmaEl = posTrackExtra.tpcNSigmaEl(); + Candidate.negTPCSigmaEl = negTrackExtra.tpcNSigmaEl(); + + // TOF PID: + Candidate.TOFSigmaLaPr = cand.tofNSigmaLaPr(); + Candidate.TOFSigmaLaPi = cand.tofNSigmaLaPi(); + Candidate.TOFSigmaALaPi = cand.tofNSigmaALaPi(); + Candidate.TOFSigmaALaPr = cand.tofNSigmaALaPr(); + Candidate.TOFSigmaK0PiPlus = cand.tofNSigmaK0PiPlus(); + Candidate.TOFSigmaK0PiMinus = cand.tofNSigmaK0PiMinus(); + + // General + Candidate.LambdaMass = cand.mLambda(); + Candidate.AntiLambdaMass = cand.mAntiLambda(); + Candidate.GammaMass = cand.mGamma(); + Candidate.KZeroShortMass = cand.mK0Short(); + Candidate.pT = cand.pt(); + Candidate.qt = cand.qtarm(); + Candidate.alpha = cand.alpha(); + Candidate.posEta = cand.positiveeta(); + Candidate.negEta = cand.negativeeta(); + Candidate.v0Eta = cand.eta(); + Candidate.Z = cand.z(); + + // Topological + Candidate.v0radius = cand.v0radius(); + Candidate.PA = TMath::ACos(cand.v0cosPA()); + Candidate.dcapostopv = cand.dcapostopv(); + Candidate.dcanegtopv = cand.dcanegtopv(); + Candidate.dcaV0daughters = cand.dcaV0daughters(); + Candidate.dcav0topv = cand.dcav0topv(); + Candidate.PsiPair = cand.psipair(); + + // Debug/Aditional + Candidate.v0type = cand.v0Type(); + Candidate.centrality = coll.centFT0C(); + + // Applying selections and saving hypothesis + if ((std::abs(cand.mLambda() - 1.115683) > LambdaWindow) || (cand.v0radius() < Lambdav0radius) || (cand.v0cosPA() < Lambdav0cospa) || (TMath::Abs(cand.dcapostopv()) < Lambdadcapostopv) || (TMath::Abs(cand.dcanegtopv()) < Lambdadcanegtopv) || (cand.dcaV0daughters() > Lambdadcav0dau)) + lConsistentWithLambda = false; + if ((std::abs(cand.mAntiLambda() - 1.115683) > AntiLambdaWindow) || (cand.v0radius() < AntiLambdav0radius) || (cand.v0cosPA() < AntiLambdav0cospa) || (TMath::Abs(cand.dcapostopv()) < AntiLambdadcapostopv) || (TMath::Abs(cand.dcanegtopv()) < AntiLambdadcanegtopv) || (cand.dcaV0daughters() > AntiLambdadcav0dau)) + lConsistentWithAntiLambda = false; + if ((std::abs(cand.mGamma()) > PhotonWindow) || (cand.mGamma() > PhotonMaxMass) || (cand.v0radius() < PhotonMinRadius) || (cand.v0radius() > PhotonMaxRadius) || (cand.pt() < PhotonMinPt) || (cand.qtarm() > PhotonMaxqt) || (TMath::Abs(cand.alpha()) > PhotonMaxalpha)) + lConsistentWithGamma = false; + if ((std::abs(cand.mK0Short() - 0.497) > K0ShortWindow) || (cand.v0radius() < K0Shortv0radius) || (cand.v0cosPA() < K0Shortv0cospa) || (TMath::Abs(cand.dcapostopv()) < K0Shortdcapostopv) || (TMath::Abs(cand.dcanegtopv()) < K0Shortdcanegtopv) || (cand.dcaV0daughters() > K0Shortdcav0dau)) + lConsistentWithK0Short = false; + + Candidate.SelHypothesis = lConsistentWithLambda << 0 | lConsistentWithAntiLambda << 1 | lConsistentWithGamma << 2 | lConsistentWithK0Short << 3; + // 1: Consistent with Lambda only, 2: Consistent with Anti-Lambda only + // 3: Consistent with Lambda and Anti-Lambda, 4: Consistent with Gamma only + // 5: Consistent with Lambda and Gamma, 6: Consistent with Anti-Lambda and Gamma + // 7: Consistent with Lambda, Anti-Lambda, and Gamma, 8: Consistent with K0Short only + // 9: Consistent with Lambda and K0Short, 10: Consistent with Anti-Lambda and K0Short + // 11: Consistent with Lambda, Anti-Lambda, and K0Short, 12: Consistent with Gamma and K0Short + // 13: Consistent with Lambda, Gamma, and K0Short, 14: Consistent with Anti-Lambda, Gamma, and K0Short + // 15: Consistent with Lambda, Anti-Lambda, Gamma, and K0Short + + if ((Candidate.SelHypothesis & saveCandidateMask) != saveCandidateMask) + return; + + // MC flags + Candidate.isLambda = false; + Candidate.isAntiLambda = false; + Candidate.isGamma = false; + Candidate.isKZeroShort = false; + + if constexpr (requires { cand.pdgCode(); }) { + Candidate.isLambda = (cand.pdgCode() == 3122); + Candidate.isAntiLambda = (cand.pdgCode() == -3122); + Candidate.isGamma = (cand.pdgCode() == 22); + Candidate.isKZeroShort = (cand.pdgCode() == 310); + } + + // Filling TTree for ML analysis + v0MLCandidates(Candidate.posITSCls, Candidate.negITSCls, Candidate.posITSClSize, Candidate.negITSClSize, Candidate.posTPCRows, Candidate.negTPCRows, + Candidate.posTPCSigmaPi, Candidate.negTPCSigmaPi, Candidate.posTPCSigmaPr, Candidate.negTPCSigmaPr, + Candidate.posTPCSigmaEl, Candidate.negTPCSigmaEl, Candidate.TOFSigmaLaPr, Candidate.TOFSigmaLaPi, + Candidate.TOFSigmaALaPi, Candidate.TOFSigmaALaPr, Candidate.TOFSigmaK0PiPlus, Candidate.TOFSigmaK0PiMinus, + Candidate.LambdaMass, Candidate.AntiLambdaMass, Candidate.GammaMass, Candidate.KZeroShortMass, Candidate.pT, + Candidate.qt, Candidate.alpha, Candidate.posEta, Candidate.negEta, Candidate.v0Eta, Candidate.Z, + Candidate.v0radius, Candidate.PA, Candidate.dcapostopv, Candidate.dcanegtopv, Candidate.dcaV0daughters, Candidate.dcav0topv, Candidate.PsiPair, + Candidate.v0type, Candidate.centrality, Candidate.SelHypothesis, Candidate.isLambda, Candidate.isAntiLambda, Candidate.isGamma, Candidate.isKZeroShort); + } + + void processRealData(soa::Join::iterator const& coll, soa::Join const& v0s, dauTracks const&) + { + histos.fill(HIST("hEventCentrality"), coll.centFT0C()); + for (auto& cand : v0s) { // looping over lambdas + processCandidate(coll, cand); + } + } + + void processSimData(soa::Join::iterator const& coll, soa::Join const& v0s, dauTracks const&) + { + histos.fill(HIST("hEventCentrality"), coll.centFT0C()); + for (auto& cand : v0s) { // looping over lambdas + processCandidate(coll, cand); + } + } + + PROCESS_SWITCH(lambdakzeroMLSelectionTreeCreator, processRealData, "Produce Run 3 v0 tables (real data)", false); + PROCESS_SWITCH(lambdakzeroMLSelectionTreeCreator, processSimData, "Produce Run 3 v0 tables (simulation)", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx b/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx index 77bc8f4220f..8574c5cce0e 100644 --- a/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx @@ -54,6 +54,7 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.h" #include "PWGLF/DataModel/LFParticleIdentification.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -64,6 +65,8 @@ #include "CCDB/BasicCCDBManager.h" #include "DataFormatsCalibration/MeanVertexObject.h" #include "TableHelper.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" using namespace o2; using namespace o2::framework; @@ -92,6 +95,13 @@ using TaggedV0s = soa::Join; using LabeledTracksExtra = soa::Join; struct lambdakzeroBuilder { + o2::ml::OnnxModel mlModelK0Short; + o2::ml::OnnxModel mlModelLambda; + o2::ml::OnnxModel mlModelAntiLambda; + o2::ml::OnnxModel mlModelGamma; + + std::map metadata; + Produces v0indices; Produces v0cores; Produces v0trackXs; @@ -107,6 +117,13 @@ struct lambdakzeroBuilder { Produces v0fctrackXs; Produces v0fccovs; + // produces calls for machine-learning selections + Produces gammaMLSelections; // gamma scores + Produces lambdaMLSelections; // lambda scores + Produces antiLambdaMLSelections; // AntiLambda scores + Produces k0ShortMLSelections; // K0Short scores + + o2::ccdb::CcdbApi ccdbApi; Service ccdb; // Configurables related to table creation @@ -121,19 +138,19 @@ struct lambdakzeroBuilder { Configurable d_UseAutodetectMode{"d_UseAutodetectMode", false, "Autodetect requested topo sels"}; // downscaling for testing - Configurable downscaleFactor{"downscaleFactor", 2, "Downscale factor (0: build nothing, 1: build all)"}; unsigned int randomSeed = 0; TRandom3 prng; // downscaling for Marian Ivanov -> different strategies struct : ConfigurableGroup { - Configurable downscale_adaptive{"downscale_adaptive", false, "Downscale: use pT-dependent techniques"}; - Configurable downscale_mass{"downscale_mass", .139, "Downscale: Tsallis Mass"}; - Configurable downscale_sqrts{"downscale_sqrts", 13.6, "Downscale: Tsallis sqrts"}; - Configurable downscale_factorPt{"downscale_factorPt", 1.0, "Downscale: factor Pt"}; - Configurable downscale_factor1Pt{"downscale_factor1Pt", 1.0, "Downscale: factor 1/Pt"}; - Configurable downscale_factorUniform{"downscale_factorUniform", 1e-3, "Downscale: factor Pt"}; - Configurable downscale_triggerMaskSelection{"downscale_triggerMaskSelection", 0, "Downscale: trigger mask selection"}; + Configurable downscaleFactor{"downscalingOptions.downscaleFactor", 2, "Downscale factor (0: build nothing, 1: build all)"}; + Configurable downscale_adaptive{"downscalingOptions.downscale_adaptive", false, "Downscale: use pT-dependent techniques"}; + Configurable downscale_mass{"downscalingOptions.downscale_mass", .139, "Downscale: Tsallis Mass"}; + Configurable downscale_sqrts{"downscalingOptions.downscale_sqrts", 13.6, "Downscale: Tsallis sqrts"}; + Configurable downscale_factorPt{"downscalingOptions.downscale_factorPt", 1.0, "Downscale: factor Pt"}; + Configurable downscale_factor1Pt{"downscalingOptions.downscale_factor1Pt", 1.0, "Downscale: factor 1/Pt"}; + Configurable downscale_factorUniform{"downscalingOptions.downscale_factorUniform", 1e-3, "Downscale: factor Pt"}; + Configurable downscale_triggerMaskSelection{"downscalingOptions.downscale_triggerMaskSelection", 0, "Downscale: trigger mask selection"}; } downscalingOptions; Configurable dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; @@ -149,27 +166,53 @@ struct lambdakzeroBuilder { Configurable maximumPt{"maximumPt", 1000.0f, "Maximum pT to store candidate"}; Configurable maxDaughterEta{"maxDaughterEta", 5.0, "Maximum daughter eta"}; + // Machine learning evaluation for pre-selection and corresponding information generation + struct : ConfigurableGroup { + // ML classifiers: master flags to populate ML Selection tables + Configurable calculateK0ShortScores{"mlConfigurations.calculateK0ShortScores", false, "calculate K0Short ML scores"}; + Configurable calculateLambdaScores{"mlConfigurations.calculateLambdaScores", false, "calculate Lambda ML scores"}; + Configurable calculateAntiLambdaScores{"mlConfigurations.calculateAntiLambdaScores", false, "calculate AntiLambda ML scores"}; + Configurable calculateGammaScores{"mlConfigurations.calculateGammaScores", false, "calculate Gamma ML scores"}; + + // ML input for ML calculation + Configurable modelPathCCDB{"mlConfigurations.modelPathCCDB", "", "ML Model path in CCDB"}; + Configurable timestampCCDB{"mlConfigurations.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{"mlConfigurations.loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"mlConfigurations.enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + + // Local paths for test purposes + Configurable localModelPathLambda{"mlConfigurations.localModelPathLambda", "Lambda_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable localModelPathAntiLambda{"mlConfigurations.localModelPathAntiLambda", "AntiLambda_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable localModelPathGamma{"mlConfigurations.localModelPathGamma", "Gamma_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable localModelPathK0Short{"mlConfigurations.localModelPathK0Short", "KZeroShort_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + + // Thresholds for choosing to populate V0Cores tables with pre-selections + Configurable thresholdGamma{"mlConfigurations.thresholdGamma", -1.0f, "Threshold to keep gamma candidates"}; + Configurable thresholdLambda{"mlConfigurations.thresholdLambda", -1.0f, "Threshold to keep Lambda candidates"}; + Configurable thresholdAntiLambda{"mlConfigurations.thresholdAntiLambda", -1.0f, "Threshold to keep AntiLambda candidates"}; + Configurable thresholdK0Short{"mlConfigurations.thresholdK0Short", -1.0f, "Threshold to keep K0Short candidates"}; + } mlConfigurations; + // Operation and minimisation criteria - Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; - Configurable d_UseAbsDCA{"d_UseAbsDCA", true, "Use Abs DCAs"}; - Configurable d_UseWeightedPCA{"d_UseWeightedPCA", false, "Vertices use cov matrices"}; - Configurable d_UseCollinearFit{"d_UseCollinearFit", false, "Fit V0s via the collinear Method in DCAFitter"}; - Configurable d_maxDZIni{"d_maxDZIni", 1e9, "Dont consider a seed (circles intersection) if Z distance exceeds this"}; - Configurable d_maxDXYIni{"d_maxDXYIni", 4, "Dont consider a seed (circles intersection) if XY distance exceeds this"}; - Configurable useMatCorrType{"useMatCorrType", 2, "0: none, 1: TGeo, 2: LUT"}; - Configurable rejDiffCollTracks{"rejDiffCollTracks", 0, "rejDiffCollTracks"}; - Configurable d_doTrackQA{"d_doTrackQA", false, "do track QA"}; - Configurable d_QA_checkMC{"d_QA_checkMC", true, "check MC truth in QA"}; - Configurable d_QA_checkdEdx{"d_QA_checkdEdx", false, "check dEdx in QA"}; + struct : ConfigurableGroup { + Configurable d_bz_input{"dcaFitterConfigurations.d_bz", -999, "bz field, -999 is automatic"}; + Configurable d_UseAbsDCA{"dcaFitterConfigurations.d_UseAbsDCA", true, "Use Abs DCAs"}; + Configurable d_UseWeightedPCA{"dcaFitterConfigurations.d_UseWeightedPCA", false, "Vertices use cov matrices"}; + Configurable d_UseCollinearFit{"dcaFitterConfigurations.d_UseCollinearFit", false, "Fit V0s via the collinear Method in DCAFitter"}; + Configurable d_maxDZIni{"dcaFitterConfigurations.d_maxDZIni", 1e9, "Dont consider a seed (circles intersection) if Z distance exceeds this"}; + Configurable d_maxDXYIni{"dcaFitterConfigurations.d_maxDXYIni", 4, "Dont consider a seed (circles intersection) if XY distance exceeds this"}; + Configurable useMatCorrType{"dcaFitterConfigurations.useMatCorrType", 2, "0: none, 1: TGeo, 2: LUT"}; + Configurable rejDiffCollTracks{"dcaFitterConfigurations.rejDiffCollTracks", 0, "rejDiffCollTracks"}; + } dcaFitterConfigurations; // CCDB options struct : ConfigurableGroup { - 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"}; - Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + Configurable ccdburl{"ccdbConfigurations.ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"ccdbConfigurations.grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"ccdbConfigurations.grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable lutPath{"ccdbConfigurations.lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"ccdbConfigurations.geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable mVtxPath{"ccdbConfigurations.mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; } ccdbConfigurations; // round some V0 core variables up to a certain level of precision if requested @@ -179,16 +222,19 @@ struct lambdakzeroBuilder { Configurable precisionDCAs{"precisionDCAs", 0.01f, "precision to keep the DCAs with"}; // generate and fill extra QA histograms if requested - Configurable d_doQA{"d_doQA", false, "Do basic QA"}; - Configurable dQANBinsRadius{"dQANBinsRadius", 500, "Number of radius bins in QA histo"}; - Configurable dQANBinsPtCoarse{"dQANBinsPtCoarse", 10, "Number of pT bins in QA histo"}; - Configurable dQANBinsMass{"dQANBinsMass", 400, "Number of mass bins for QA histograms"}; - Configurable dQAMaxPt{"dQAMaxPt", 5, "max pT in QA histo"}; - Configurable dQAGammaMassWindow{"dQAGammaMassWindow", 0.05, "gamma mass window for ITS cluster map QA"}; - Configurable dQAK0ShortMassWindow{"dQAK0ShortMassWindow", 0.005, "K0 mass window for ITS cluster map QA"}; - Configurable dQALambdaMassWindow{"dQALambdaMassWindow", 0.005, "Lambda/AntiLambda mass window for ITS cluster map QA"}; - - ConfigurableAxis axisPtQA{"axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + struct : ConfigurableGroup { + Configurable d_doQA{"qaConfigurations.d_doQA", false, "Do basic QA"}; + Configurable dQANBinsRadius{"qaConfigurations.dQANBinsRadius", 500, "Number of radius bins in QA histo"}; + Configurable dQANBinsPtCoarse{"qaConfigurations.dQANBinsPtCoarse", 10, "Number of pT bins in QA histo"}; + Configurable dQANBinsMass{"qaConfigurations.dQANBinsMass", 400, "Number of mass bins for QA histograms"}; + Configurable dQAMaxPt{"qaConfigurations.dQAMaxPt", 5, "max pT in QA histo"}; + Configurable dQAGammaMassWindow{"qaConfigurations.dQAGammaMassWindow", 0.05, "gamma mass window for ITS cluster map QA"}; + Configurable dQAK0ShortMassWindow{"qaConfigurations.dQAK0ShortMassWindow", 0.005, "K0 mass window for ITS cluster map QA"}; + Configurable dQALambdaMassWindow{"qaConfigurations.dQALambdaMassWindow", 0.005, "Lambda/AntiLambda mass window for ITS cluster map QA"}; + Configurable d_doTrackQA{"qaConfigurations.d_doTrackQA", false, "do track QA"}; + Configurable d_QA_checkMC{"qaConfigurations.d_QA_checkMC", true, "check MC truth in QA"}; + Configurable d_QA_checkdEdx{"qaConfigurations.d_QA_checkdEdx", false, "check dEdx in QA"}; + } qaConfigurations; // for topo var QA struct : ConfigurableGroup { @@ -205,6 +251,8 @@ struct lambdakzeroBuilder { ConfigurableAxis axisDCAXY{"axisConfigurations.axisDCAXY", {500, -50, 50}, "(cm)"}; ConfigurableAxis axisDCACHI2{"axisConfigurations.axisDCACHI2", {500, 0, 50}, "#chi^{2}"}; ConfigurableAxis axisPositionGuess{"axisConfigurations.axisPositionGuess", {240, 0, 120}, "(cm)"}; + + ConfigurableAxis axisPtQA{"axisConfigurations.axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; } axisConfigurations; // default parameters from central Pb-Pb (worst case scenario), PbPb 2023 pass1 @@ -373,7 +421,7 @@ struct lambdakzeroBuilder { registry.fill(HIST("hCaughtExceptions"), 0.0, statisticsRegistry.exceptions); for (Int_t ii = 0; ii < kNV0Steps; ii++) registry.fill(HIST("hV0Criteria"), ii, statisticsRegistry.v0stats[ii]); - if (d_doTrackQA) { + if (qaConfigurations.d_doTrackQA) { for (Int_t ii = 0; ii < 10; ii++) { registry.fill(HIST("hPositiveITSClusters"), ii, statisticsRegistry.posITSclu[ii]); registry.fill(HIST("hNegativeITSClusters"), ii, statisticsRegistry.negITSclu[ii]); @@ -404,13 +452,13 @@ struct lambdakzeroBuilder { randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); // Optionally, add extra QA histograms to processing chain - if (d_doQA) { + if (qaConfigurations.d_doQA) { // Basic histograms containing invariant masses of all built candidates - const AxisSpec axisVsPtCoarse{static_cast(dQANBinsPtCoarse), 0, dQAMaxPt, "#it{p}_{T} (GeV/c)"}; - const AxisSpec axisGammaMass{static_cast(dQANBinsMass), 0.000f, 0.400f, "Inv. Mass (GeV/c^{2})"}; - const AxisSpec axisK0ShortMass{static_cast(dQANBinsMass), 0.400f, 0.600f, "Inv. Mass (GeV/c^{2})"}; - const AxisSpec axisLambdaMass{static_cast(5 * dQANBinsMass), 1.01f, 2.01f, "Inv. Mass (GeV/c^{2})"}; - const AxisSpec axisHypertritonMass{static_cast(dQANBinsMass), 2.900f, 3.300f, "Inv. Mass (GeV/c^{2})"}; + const AxisSpec axisVsPtCoarse{static_cast(qaConfigurations.dQANBinsPtCoarse), 0, qaConfigurations.dQAMaxPt, "#it{p}_{T} (GeV/c)"}; + const AxisSpec axisGammaMass{static_cast(qaConfigurations.dQANBinsMass), 0.000f, 0.400f, "Inv. Mass (GeV/c^{2})"}; + const AxisSpec axisK0ShortMass{static_cast(qaConfigurations.dQANBinsMass), 0.400f, 0.600f, "Inv. Mass (GeV/c^{2})"}; + const AxisSpec axisLambdaMass{static_cast(5 * qaConfigurations.dQANBinsMass), 1.01f, 2.01f, "Inv. Mass (GeV/c^{2})"}; + const AxisSpec axisHypertritonMass{static_cast(qaConfigurations.dQANBinsMass), 2.900f, 3.300f, "Inv. Mass (GeV/c^{2})"}; registry.add("h2dGammaMass", "h2dGammaMass", kTH2F, {axisVsPtCoarse, axisGammaMass}); registry.add("h2dK0ShortMass", "h2dK0ShortMass", kTH2F, {axisVsPtCoarse, axisK0ShortMass}); @@ -435,27 +483,27 @@ struct lambdakzeroBuilder { registry.add("h2dXIU_AntiLambda", "h2dXIU_AntiLambda", kTH3D, {axisConfigurations.axisX, axisConfigurations.axisX, axisConfigurations.axisRadius}); // QA plots of topological variables using axisPtQA - registry.add("h2dTopoVarPointingAngle", "h2dTopoVarPointingAngle", kTH2D, {axisPtQA, axisConfigurations.axisTopoVarPointingAngle}); - registry.add("h2dTopoVarRAP", "h2dTopoVarRAP", kTH2D, {axisPtQA, axisConfigurations.axisTopoVarRAP}); - registry.add("h2dTopoVarV0Radius", "h2dTopoVarV0Radius", kTH2D, {axisPtQA, axisConfigurations.axisTopoVarV0Radius}); - registry.add("h2dTopoVarDCAV0Dau", "h2dTopoVarDCAV0Dau", kTH2D, {axisPtQA, axisConfigurations.axisTopoVarDCAV0Dau}); - registry.add("h2dTopoVarPosDCAToPV", "h2dTopoVarPosDCAToPV", kTH2D, {axisPtQA, axisConfigurations.axisTopoVarDCAToPV}); - registry.add("h2dTopoVarNegDCAToPV", "h2dTopoVarNegDCAToPV", kTH2D, {axisPtQA, axisConfigurations.axisTopoVarDCAToPV}); - registry.add("h2dTopoVarDCAV0ToPV", "h2dTopoVarDCAV0ToPV", kTH2D, {axisPtQA, axisConfigurations.axisTopoVarDCAV0ToPV}); + registry.add("h2dTopoVarPointingAngle", "h2dTopoVarPointingAngle", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarPointingAngle}); + registry.add("h2dTopoVarRAP", "h2dTopoVarRAP", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarRAP}); + registry.add("h2dTopoVarV0Radius", "h2dTopoVarV0Radius", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarV0Radius}); + registry.add("h2dTopoVarDCAV0Dau", "h2dTopoVarDCAV0Dau", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarDCAV0Dau}); + registry.add("h2dTopoVarPosDCAToPV", "h2dTopoVarPosDCAToPV", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarDCAToPV}); + registry.add("h2dTopoVarNegDCAToPV", "h2dTopoVarNegDCAToPV", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarDCAToPV}); + registry.add("h2dTopoVarDCAV0ToPV", "h2dTopoVarDCAV0ToPV", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisTopoVarDCAV0ToPV}); // QA for PCM - registry.add("h2d_pcm_DCAXY_True", "h2d_pcm_DCAXY_True", kTH2D, {axisPtQA, axisConfigurations.axisDCAXY}); - registry.add("h2d_pcm_DCAXY_Bg", "h2d_pcm_DCAXY_Bg", kTH2D, {axisPtQA, axisConfigurations.axisDCAXY}); - registry.add("h2d_pcm_DCACHI2_True", "h2d_pcm_DCACHI2_True", kTH2D, {axisPtQA, axisConfigurations.axisDCACHI2}); - registry.add("h2d_pcm_DCACHI2_Bg", "h2d_pcm_DCACHI2_Bg", kTH2D, {axisPtQA, axisConfigurations.axisDCACHI2}); - registry.add("h2d_pcm_DeltaDistanceRadii_True", "h2d_pcm_DeltaDistanceRadii_True", kTH2D, {axisPtQA, axisConfigurations.axisDeltaDistanceRadii}); - registry.add("h2d_pcm_DeltaDistanceRadii_Bg", "h2d_pcm_DeltaDistanceRadii_Bg", kTH2D, {axisPtQA, axisConfigurations.axisDeltaDistanceRadii}); - registry.add("h2d_pcm_PositionGuess_True", "h2d_pcm_PositionGuess_True", kTH2D, {axisPtQA, axisConfigurations.axisPositionGuess}); - registry.add("h2d_pcm_PositionGuess_Bg", "h2d_pcm_PositionGuess_Bg", kTH2D, {axisPtQA, axisConfigurations.axisPositionGuess}); - registry.add("h2d_pcm_RadiallyOutgoingAtThisRadius1_True", "h2d_pcm_RadiallyOutgoingAtThisRadius1_True", kTH2D, {axisPtQA, axisConfigurations.axisPositionGuess}); - registry.add("h2d_pcm_RadiallyOutgoingAtThisRadius2_True", "h2d_pcm_RadiallyOutgoingAtThisRadius2_True", kTH2D, {axisPtQA, axisConfigurations.axisPositionGuess}); - registry.add("h2d_pcm_RadiallyOutgoingAtThisRadius1_Bg", "h2d_pcm_RadiallyOutgoingAtThisRadius1_Bg", kTH2D, {axisPtQA, axisConfigurations.axisPositionGuess}); - registry.add("h2d_pcm_RadiallyOutgoingAtThisRadius2_Bg", "h2d_pcm_RadiallyOutgoingAtThisRadius2_Bg", kTH2D, {axisPtQA, axisConfigurations.axisPositionGuess}); + registry.add("h2d_pcm_DCAXY_True", "h2d_pcm_DCAXY_True", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisDCAXY}); + registry.add("h2d_pcm_DCAXY_Bg", "h2d_pcm_DCAXY_Bg", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisDCAXY}); + registry.add("h2d_pcm_DCACHI2_True", "h2d_pcm_DCACHI2_True", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisDCACHI2}); + registry.add("h2d_pcm_DCACHI2_Bg", "h2d_pcm_DCACHI2_Bg", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisDCACHI2}); + registry.add("h2d_pcm_DeltaDistanceRadii_True", "h2d_pcm_DeltaDistanceRadii_True", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisDeltaDistanceRadii}); + registry.add("h2d_pcm_DeltaDistanceRadii_Bg", "h2d_pcm_DeltaDistanceRadii_Bg", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisDeltaDistanceRadii}); + registry.add("h2d_pcm_PositionGuess_True", "h2d_pcm_PositionGuess_True", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisPositionGuess}); + registry.add("h2d_pcm_PositionGuess_Bg", "h2d_pcm_PositionGuess_Bg", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisPositionGuess}); + registry.add("h2d_pcm_RadiallyOutgoingAtThisRadius1_True", "h2d_pcm_RadiallyOutgoingAtThisRadius1_True", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisPositionGuess}); + registry.add("h2d_pcm_RadiallyOutgoingAtThisRadius2_True", "h2d_pcm_RadiallyOutgoingAtThisRadius2_True", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisPositionGuess}); + registry.add("h2d_pcm_RadiallyOutgoingAtThisRadius1_Bg", "h2d_pcm_RadiallyOutgoingAtThisRadius1_Bg", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisPositionGuess}); + registry.add("h2d_pcm_RadiallyOutgoingAtThisRadius2_Bg", "h2d_pcm_RadiallyOutgoingAtThisRadius2_Bg", kTH2D, {axisConfigurations.axisPtQA, axisConfigurations.axisPositionGuess}); } mRunNumber = 0; @@ -468,13 +516,13 @@ struct lambdakzeroBuilder { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - if (useMatCorrType == 1) { + if (dcaFitterConfigurations.useMatCorrType == 1) { LOGF(info, "TGeo correction requested, loading geometry"); if (!o2::base::GeometryManager::isGeometryLoaded()) { ccdb->get(ccdbConfigurations.geoPath); } } - if (useMatCorrType == 2) { + if (dcaFitterConfigurations.useMatCorrType == 2) { LOGF(info, "LUT correction requested, loading LUT"); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbConfigurations.lutPath)); LOGF(info, "LUT load done!"); @@ -595,17 +643,17 @@ struct lambdakzeroBuilder { fitter.setMaxR(200.); fitter.setMinParamChange(1e-3); fitter.setMinRelChi2Change(0.9); - fitter.setMaxDZIni(d_maxDZIni); - fitter.setMaxDXYIni(d_maxDXYIni); + fitter.setMaxDZIni(dcaFitterConfigurations.d_maxDZIni); + fitter.setMaxDXYIni(dcaFitterConfigurations.d_maxDXYIni); fitter.setMaxChi2(1e9); - fitter.setUseAbsDCA(d_UseAbsDCA); - fitter.setWeightedFinalPCA(d_UseWeightedPCA); + fitter.setUseAbsDCA(dcaFitterConfigurations.d_UseAbsDCA); + fitter.setWeightedFinalPCA(dcaFitterConfigurations.d_UseWeightedPCA); // Material correction in the DCA fitter o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - if (useMatCorrType == 1) + if (dcaFitterConfigurations.useMatCorrType == 1) matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; - if (useMatCorrType == 2) + if (dcaFitterConfigurations.useMatCorrType == 2) matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; fitter.setMatCorrType(matCorr); } @@ -616,9 +664,20 @@ struct lambdakzeroBuilder { return; } + // machine learning initialization if requested + if (mlConfigurations.calculateK0ShortScores || + mlConfigurations.calculateLambdaScores || + mlConfigurations.calculateAntiLambdaScores || + mlConfigurations.calculateGammaScores) { + int64_t timeStampML = bc.timestamp(); + if (mlConfigurations.timestampCCDB.value != -1) + timeStampML = mlConfigurations.timestampCCDB.value; + LoadMachines(timeStampML); + } + // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; + if (dcaFitterConfigurations.d_bz_input > -990) { + d_bz = dcaFitterConfigurations.d_bz_input; fitter.setBz(d_bz); o2::parameters::GRPMagField grpmag; if (fabs(d_bz) > 1e-5) { @@ -654,13 +713,68 @@ struct lambdakzeroBuilder { // Set magnetic field value once known fitter.setBz(d_bz); - if (useMatCorrType == 2) { + if (dcaFitterConfigurations.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); } } + // function to load models for ML-based classifiers + void LoadMachines(int64_t timeStampML) + { + if (mlConfigurations.loadModelsFromCCDB) { + ccdbApi.init(ccdbConfigurations.ccdburl); + LOG(info) << "Fetching models for timestamp: " << timeStampML; + + if (mlConfigurations.calculateLambdaScores) { + bool retrieveSuccessLambda = ccdbApi.retrieveBlob(mlConfigurations.modelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathLambda.value); + if (retrieveSuccessLambda) { + mlModelLambda.initModel(mlConfigurations.localModelPathLambda.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Lambda model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (mlConfigurations.calculateAntiLambdaScores) { + bool retrieveSuccessAntiLambda = ccdbApi.retrieveBlob(mlConfigurations.modelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathAntiLambda.value); + if (retrieveSuccessAntiLambda) { + mlModelAntiLambda.initModel(mlConfigurations.localModelPathAntiLambda.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the AntiLambda model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (mlConfigurations.calculateGammaScores) { + bool retrieveSuccessGamma = ccdbApi.retrieveBlob(mlConfigurations.modelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathGamma.value); + if (retrieveSuccessGamma) { + mlModelGamma.initModel(mlConfigurations.localModelPathGamma.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (mlConfigurations.calculateK0ShortScores) { + bool retrieveSuccessKZeroShort = ccdbApi.retrieveBlob(mlConfigurations.modelPathCCDB, ".", metadata, timeStampML, false, mlConfigurations.localModelPathK0Short.value); + if (retrieveSuccessKZeroShort) { + mlModelK0Short.initModel(mlConfigurations.localModelPathK0Short.value, mlConfigurations.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the K0Short model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + } else { + if (mlConfigurations.calculateLambdaScores) + mlModelLambda.initModel(mlConfigurations.localModelPathLambda.value, mlConfigurations.enableOptimizations.value); + if (mlConfigurations.calculateAntiLambdaScores) + mlModelAntiLambda.initModel(mlConfigurations.localModelPathAntiLambda.value, mlConfigurations.enableOptimizations.value); + if (mlConfigurations.calculateGammaScores) + mlModelGamma.initModel(mlConfigurations.localModelPathGamma.value, mlConfigurations.enableOptimizations.value); + if (mlConfigurations.calculateK0ShortScores) + mlModelK0Short.initModel(mlConfigurations.localModelPathK0Short.value, mlConfigurations.enableOptimizations.value); + } + LOG(info) << "ML Models loaded."; + } + template bool buildV0Candidate(TV0Object const& V0) { @@ -723,7 +837,7 @@ struct lambdakzeroBuilder { //---/---/---/ // Move close to minima int nCand = 0; - fitter.setCollinear(d_UseCollinearFit || V0.isCollinearV0()); + fitter.setCollinear(dcaFitterConfigurations.d_UseCollinearFit || V0.isCollinearV0()); try { nCand = fitter.process(lPositiveTrack, lNegativeTrack); } catch (...) { @@ -856,16 +970,16 @@ struct lambdakzeroBuilder { if (!keepCandidate) return false; - if (d_doTrackQA) { + if (qaConfigurations.d_doTrackQA) { if (posTrack.itsNCls() < 10) statisticsRegistry.posITSclu[posTrack.itsNCls()]++; if (negTrack.itsNCls() < 10) statisticsRegistry.negITSclu[negTrack.itsNCls()]++; } - if (d_doQA) { - bool mcUnchecked = !d_QA_checkMC; - bool dEdxUnchecked = !d_QA_checkdEdx; + if (qaConfigurations.d_doQA) { + bool mcUnchecked = !qaConfigurations.d_QA_checkMC; + bool dEdxUnchecked = !qaConfigurations.d_QA_checkdEdx; auto lPtHy = RecoDecay::sqrtSumOfSquares(2.0f * v0candidate.posP[0] + v0candidate.negP[0], 2.0f * v0candidate.posP[1] + v0candidate.negP[1]); auto lPtAnHy = RecoDecay::sqrtSumOfSquares(v0candidate.posP[0] + 2.0f * v0candidate.negP[0], v0candidate.posP[1] + 2.0f * v0candidate.negP[1]); @@ -887,19 +1001,19 @@ struct lambdakzeroBuilder { } // Fill ITS cluster maps with specific mass cuts - if (TMath::Abs(lGammaMass - 0.0) < dQAGammaMassWindow && ((V0.isdEdxGamma() || dEdxUnchecked) && (V0.isTrueGamma() || mcUnchecked))) { + if (TMath::Abs(lGammaMass - 0.0) < qaConfigurations.dQAGammaMassWindow && ((V0.isdEdxGamma() || dEdxUnchecked) && (V0.isTrueGamma() || mcUnchecked))) { registry.fill(HIST("h2dITSCluMap_Gamma"), static_cast(posTrack.itsClusterMap()), static_cast(negTrack.itsClusterMap()), v0candidate.V0radius); registry.fill(HIST("h2dXIU_Gamma"), static_cast(posTrack.x()), static_cast(negTrack.x()), v0candidate.V0radius); } - if (TMath::Abs(v0candidate.k0ShortMass - 0.497) < dQAK0ShortMassWindow && ((V0.isdEdxK0Short() || dEdxUnchecked) && (V0.isTrueK0Short() || mcUnchecked))) { + if (TMath::Abs(v0candidate.k0ShortMass - 0.497) < qaConfigurations.dQAK0ShortMassWindow && ((V0.isdEdxK0Short() || dEdxUnchecked) && (V0.isTrueK0Short() || mcUnchecked))) { registry.fill(HIST("h2dITSCluMap_K0Short"), static_cast(posTrack.itsClusterMap()), static_cast(negTrack.itsClusterMap()), v0candidate.V0radius); registry.fill(HIST("h2dXIU_K0Short"), static_cast(posTrack.x()), static_cast(negTrack.x()), v0candidate.V0radius); } - if (TMath::Abs(v0candidate.lambdaMass - 1.116) < dQALambdaMassWindow && ((V0.isdEdxLambda() || dEdxUnchecked) && (V0.isTrueLambda() || mcUnchecked))) { + if (TMath::Abs(v0candidate.lambdaMass - 1.116) < qaConfigurations.dQALambdaMassWindow && ((V0.isdEdxLambda() || dEdxUnchecked) && (V0.isTrueLambda() || mcUnchecked))) { registry.fill(HIST("h2dITSCluMap_Lambda"), static_cast(posTrack.itsClusterMap()), static_cast(negTrack.itsClusterMap()), v0candidate.V0radius); registry.fill(HIST("h2dXIU_Lambda"), static_cast(posTrack.x()), static_cast(negTrack.x()), v0candidate.V0radius); } - if (TMath::Abs(v0candidate.antiLambdaMass - 1.116) < dQALambdaMassWindow && ((V0.isdEdxAntiLambda() || dEdxUnchecked) && (V0.isTrueAntiLambda() || mcUnchecked))) { + if (TMath::Abs(v0candidate.antiLambdaMass - 1.116) < qaConfigurations.dQALambdaMassWindow && ((V0.isdEdxAntiLambda() || dEdxUnchecked) && (V0.isTrueAntiLambda() || mcUnchecked))) { registry.fill(HIST("h2dITSCluMap_AntiLambda"), static_cast(posTrack.itsClusterMap()), static_cast(negTrack.itsClusterMap()), v0candidate.V0radius); registry.fill(HIST("h2dXIU_AntiLambda"), static_cast(posTrack.x()), static_cast(negTrack.x()), v0candidate.V0radius); } @@ -968,7 +1082,7 @@ struct lambdakzeroBuilder { // Loops over all V0s in the time frame for (auto& V0 : V0s) { // downscale some V0s if requested to do so - if (downscaleFactor < 1.f && (static_cast(rand_r(&randomSeed)) / static_cast(RAND_MAX)) > downscaleFactor) { + if (downscalingOptions.downscaleFactor < 1.f && (static_cast(rand_r(&randomSeed)) / static_cast(RAND_MAX)) > downscalingOptions.downscaleFactor) { return; } @@ -980,8 +1094,8 @@ struct lambdakzeroBuilder { } int ivanovMap = 0; + float pt = RecoDecay::sqrtSumOfSquares(v0candidate.posP[0] + v0candidate.negP[0], v0candidate.posP[1] + v0candidate.negP[1]); if (downscalingOptions.downscale_adaptive) { - float pt = RecoDecay::sqrtSumOfSquares(v0candidate.posP[0] + v0candidate.negP[0], v0candidate.posP[1] + v0candidate.negP[1]); ivanovMap = DownsampleMap(pt); if (ivanovMap == 0) continue; // skip this V0, passes nothing @@ -991,11 +1105,56 @@ struct lambdakzeroBuilder { if (roundDCAVariables) roundV0CandidateVariables(); + // evaluate machine-learning scores + float gammaScore = -1.0f, lambdaScore = -1.0f, antiLambdaScore = -1.0f, k0ShortScore = -1.0f; + + if (mlConfigurations.calculateK0ShortScores || + mlConfigurations.calculateLambdaScores || + mlConfigurations.calculateAntiLambdaScores || + mlConfigurations.calculateGammaScores) { + // machine learning is on, go for calculation of thresholds + // FIXME THIS NEEDS ADJUSTING + std::vector inputFeatures{pt, 0.0f, + 0.0f, v0candidate.V0radius, + v0candidate.cosPA, v0candidate.dcaV0dau, + v0candidate.posDCAxy, v0candidate.negDCAxy}; + + // calculate scores + if (mlConfigurations.calculateLambdaScores) { + float* lambdaProbability = mlModelLambda.evalModel(inputFeatures); + lambdaScore = lambdaProbability[1]; + } + if (mlConfigurations.calculateGammaScores) { + float* gammaProbability = mlModelGamma.evalModel(inputFeatures); + gammaScore = gammaProbability[1]; + } + + // Skip anything that doesn't fulfull any of the desired conditions + if (gammaScore < mlConfigurations.thresholdGamma.value && + lambdaScore < mlConfigurations.thresholdLambda.value && + antiLambdaScore < mlConfigurations.thresholdAntiLambda.value && + k0ShortScore < mlConfigurations.thresholdK0Short.value) { + continue; // skipped as uninteresting in any hypothesis considered + } + } + // V0 logic reminder // 0: v0 saved for the only due to the cascade, 1: standalone v0, 3: standard v0 with photon-only test if (V0.v0Type() > 0) { if (V0.v0Type() > 1 && !storePhotonCandidates) continue; + + if (mlConfigurations.calculateK0ShortScores || + mlConfigurations.calculateLambdaScores || + mlConfigurations.calculateAntiLambdaScores || + mlConfigurations.calculateGammaScores) { + // at this stage, the candidate is interesting -> populate table + gammaMLSelections(gammaScore); + lambdaMLSelections(lambdaScore); + antiLambdaMLSelections(antiLambdaScore); + k0ShortMLSelections(k0ShortScore); + } + // populates the various tables for analysis statisticsRegistry.v0stats[kCountStandardV0]++; v0indices(V0.posTrackId(), V0.negTrackId(), diff --git a/PWGLF/TableProducer/Strangeness/lambdakzeromlselection.cxx b/PWGLF/TableProducer/Strangeness/lambdakzeromlselection.cxx new file mode 100644 index 00000000000..53c353193a6 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/lambdakzeromlselection.cxx @@ -0,0 +1,210 @@ +// 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. +// +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// Lambdakzero ML selection task +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// +// Comments, questions, complaints, suggestions? +// Please write to: +// gianni.shigeru.setoue.liveraro@cern.ch +// romain.schotter@cern.ch +// david.dobrigkeit.chinellato@cern.ch +// + +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/ASoA.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.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 "CCDB/BasicCCDBManager.h" +#include +#include +#include +#include +#include +#include +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" + +using namespace o2; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::ml; +using std::array; +using std::cout; +using std::endl; + +// For original data loops +using V0OriginalDatas = soa::Join; + +// For derived data analysis +using V0DerivedDatas = soa::Join; + +struct lambdakzeromlselection { + o2::ml::OnnxModel lambda_bdt; + ; + o2::ml::OnnxModel antilambda_bdt; + o2::ml::OnnxModel gamma_bdt; + o2::ml::OnnxModel kzeroshort_bdt; + + std::map metadata; + + Produces gammaMLSelections; // optionally aggregate information from ML output for posterior analysis (derived data) + Produces lambdaMLSelections; // optionally aggregate information from ML output for posterior analysis (derived data) + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // ML inference + Configurable PredictLambda{"PredictLambda", true, "Flag to enable or disable the loading of model"}; + Configurable PredictAntiLambda{"PredictAntiLambda", false, "Flag to enable or disable the loading of model"}; + Configurable PredictGamma{"PredictGamma", true, "Flag to enable or disable the loading of model"}; + Configurable PredictKZeroShort{"PredictKZeroShort", false, "Flag to enable or disable the loading of model"}; + Configurable fIsMC{"fIsMC", false, "If true, save additional MC info for analysis"}; + + // CCDB configuration + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + Configurable ccdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable BDTLocalPathLambda{"BDTLocalPathLambda", "Lambda_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable BDTLocalPathAntiLambda{"BDTLocalPathAntiLambda", "AntiLambda_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable BDTLocalPathGamma{"BDTLocalPathGamma", "Gamma_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable BDTLocalPathKZeroShort{"BDTLocalPathKZeroShort", "KZeroShort_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/g/gsetouel/MLModels2", "Path on CCDB"}; + 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)"}; + + // Axis + // base properties + ConfigurableAxis vertexZ{"vertexZ", {30, -15.0f, 15.0f}, ""}; + + int nCandidates = 0; + void init(InitContext const&) + { + // Histograms + histos.add("hEventVertexZ", "hEventVertexZ", kTH1F, {vertexZ}); + + ccdb->setURL(ccdbUrl.value); + // Retrieve the model from CCDB + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + + /// Fetching model for specific timestamp + LOG(info) << "Fetching model for timestamp: " << timestampCCDB.value; + + if (PredictLambda) { + bool retrieveSuccessLambda = ccdbApi.retrieveBlob(BDTPathCCDB.value, ".", metadata, timestampCCDB.value, false, BDTLocalPathLambda.value); + if (retrieveSuccessLambda) { + lambda_bdt.initModel(BDTLocalPathLambda.value, enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Lambda model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (PredictAntiLambda) { + bool retrieveSuccessAntiLambda = ccdbApi.retrieveBlob(BDTPathCCDB.value, ".", metadata, timestampCCDB.value, false, BDTLocalPathAntiLambda.value); + if (retrieveSuccessAntiLambda) { + antilambda_bdt.initModel(BDTLocalPathAntiLambda.value, enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the AntiLambda model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (PredictGamma) { + bool retrieveSuccessGamma = ccdbApi.retrieveBlob(BDTPathCCDB.value, ".", metadata, timestampCCDB.value, false, BDTLocalPathGamma.value); + if (retrieveSuccessGamma) { + gamma_bdt.initModel(BDTLocalPathGamma.value, enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + + if (PredictKZeroShort) { + bool retrieveSuccessKZeroShort = ccdbApi.retrieveBlob(BDTPathCCDB.value, ".", metadata, timestampCCDB.value, false, BDTLocalPathKZeroShort.value); + if (retrieveSuccessKZeroShort) { + kzeroshort_bdt.initModel(BDTLocalPathKZeroShort.value, enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the KZeroShort model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } + } else { + if (PredictLambda) + lambda_bdt.initModel(BDTLocalPathLambda.value, enableOptimizations.value); + if (PredictAntiLambda) + antilambda_bdt.initModel(BDTLocalPathAntiLambda.value, enableOptimizations.value); + if (PredictGamma) + gamma_bdt.initModel(BDTLocalPathGamma.value, enableOptimizations.value); + if (PredictKZeroShort) + kzeroshort_bdt.initModel(BDTLocalPathKZeroShort.value, enableOptimizations.value); + } + } + + // Process candidate and store properties in object + template + void processCandidate(TV0Object const& cand) + { + std::vector inputFeatures{cand.pt(), static_cast(cand.qtarm()), + cand.alpha(), cand.v0radius(), + cand.v0cosPA(), cand.dcaV0daughters(), + cand.dcapostopv(), cand.dcanegtopv()}; + + // calculate classifier + float* LambdaProbability = lambda_bdt.evalModel(inputFeatures); + float* GammaProbability = gamma_bdt.evalModel(inputFeatures); + // float* AntiLambdaProbability = antilambda_bdt.evalModel(inputFeatures); // WIP + // float* KZeroShortProbability = kzeroshort_bdt.evalModel(inputFeatures); // WIP + + gammaMLSelections(GammaProbability[1]); + lambdaMLSelections(LambdaProbability[1]); + } + + void processDerivedData(aod::StraCollision const& coll, V0DerivedDatas const& v0s) + { + histos.fill(HIST("hEventVertexZ"), coll.posZ()); + for (auto& v0 : v0s) { // looping over lambdas + processCandidate(v0); + } + } + void processStandardData(aod::Collision const& coll, V0OriginalDatas const& v0s) + { + histos.fill(HIST("hEventVertexZ"), coll.posZ()); + for (auto& v0 : v0s) { // looping over lambdas + processCandidate(v0); + } + } + + PROCESS_SWITCH(lambdakzeromlselection, processStandardData, "Process standard data", true); + PROCESS_SWITCH(lambdakzeromlselection, processDerivedData, "Process derived data", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx new file mode 100644 index 00000000000..2a3974588ef --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx @@ -0,0 +1,175 @@ +// 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 is a task that employs the standard V0 tables and attempts to combine +// two V0s into a Sigma0 -> Lambda + gamma candidate. + +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/ASoA.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.h" +#include "PWGLF/DataModel/LFSigmaTables.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 "CCDB/BasicCCDBManager.h" +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using std::cout; +using std::endl; + +struct sigma0builder { + Produces v0Sigmas; // save sigma0 candidates for analysis + Produces v0MCSigmas; // save sigma0 candidates for analysis + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Configurable Gamma_MLThreshold{"Gamma_MLThreshold", 0.1, "Decision Threshold value to select gammas of sigma0 candidates"}; + Configurable Lambda_MLThreshold{"Lambda_MLThreshold", 0.1, "Decision Threshold value to select lambdas of sigma0 candidates"}; + // Axis + // base properties + ConfigurableAxis vertexZ{"vertexZ", {30, -15.0f, 15.0f}, ""}; + // Invariant Mass + ConfigurableAxis axisSigmaMass{"axisSigmaMass", {200, 1.16f, 1.23f}, "M_{#Sigma^{0}} (GeV/c^{2})"}; + + void init(InitContext const&) + { + // Event counter + histos.add("hEventVertexZ", "hEventVertexZ", kTH1F, {vertexZ}); + histos.add("hEventVertexZMC", "hEventVertexZMC", kTH1F, {vertexZ}); + } + + // Helper struct to pass v0 information + struct { + float mass; + float pT; + } sigmaCandidate; + + // Process sigma candidate and store properties in object + template + bool processSigmaCandidate(TCollision const& collision, TV0Object const& lambda, TV0Object const& gamma) + { + // Gamma selection: + if (gamma.gammaBDTScore() <= Gamma_MLThreshold) + return false; + + // Lambda selection: + if (lambda.lambdaBDTScore() <= Lambda_MLThreshold) + return false; + + std::array pVecPhotons{gamma.px(), gamma.py(), gamma.pz()}; + std::array pVecLambda{lambda.px(), lambda.py(), lambda.pz()}; + auto arrMom = std::array{pVecPhotons, pVecLambda}; + sigmaCandidate.mass = RecoDecay::m(arrMom, std::array{o2::constants::physics::MassPhoton, o2::constants::physics::MassLambda0}); + sigmaCandidate.pT = RecoDecay::pt(array{gamma.px() + lambda.px(), gamma.py() + lambda.py()}); + return true; + } + + void processMonteCarlo(aod::StraCollision const& coll, soa::Join const& v0s) + { + histos.fill(HIST("hEventVertexZMC"), coll.posZ()); + + for (auto& gamma : v0s) { // selecting photons from Sigma0 + + if ((gamma.pdgCode() != 22) || (gamma.pdgCodeMother() != 3212)) + continue; + for (auto& lambda : v0s) { // selecting lambdas from Sigma0 + if ((lambda.pdgCode() != 3122) || (lambda.pdgCodeMother() != 3212)) + continue; + + // if (gamma.motherMCPartId()!=lambda.motherMCPartId()) continue; + if (!processSigmaCandidate(coll, lambda, gamma)) + continue; + bool fIsSigma = (gamma.motherMCPartId() == lambda.motherMCPartId()); + + // Filling TTree for ML analysis + v0MCSigmas(fIsSigma); + } + } + } + + void processRealData(aod::StraCollision const& coll, soa::Join const& v0s) + { + histos.fill(HIST("hEventVertexZ"), coll.posZ()); + + for (auto& gamma : v0s) { // selecting photons from Sigma0 + for (auto& lambda : v0s) { // selecting lambdas from Sigma0 + if (!processSigmaCandidate(coll, lambda, gamma)) + continue; + + // Sigma related + float fSigmapT = sigmaCandidate.pT; + float fSigmaMass = sigmaCandidate.mass; + + // Daughters related + /// Photon + float fPhotonPt = gamma.pt(); + float fPhotonMass = gamma.mGamma(); + float fPhotonQt = gamma.qtarm(); + float fPhotonAlpha = gamma.alpha(); + float fPhotonRadius = gamma.v0radius(); + float fPhotonCosPA = gamma.v0cosPA(); + float fPhotonDCADau = gamma.dcaV0daughters(); + float fPhotonDCANegPV = gamma.dcanegtopv(); + float fPhotonDCAPosPV = gamma.dcapostopv(); + float fPhotonZconv = gamma.z(); + + // Lambda + float fLambdaPt = lambda.pt(); + float fLambdaMass = lambda.mLambda(); + float fLambdaQt = lambda.qtarm(); + float fLambdaAlpha = lambda.alpha(); + float fLambdaRadius = lambda.v0radius(); + float fLambdaCosPA = lambda.v0cosPA(); + float fLambdaDCADau = lambda.dcaV0daughters(); + float fLambdaDCANegPV = lambda.dcanegtopv(); + float fLambdaDCAPosPV = lambda.dcapostopv(); + + // Filling TTree for ML analysis + v0Sigmas(fSigmapT, fSigmaMass, fPhotonPt, fPhotonMass, fPhotonQt, fPhotonAlpha, + fPhotonRadius, fPhotonCosPA, fPhotonDCADau, fPhotonDCANegPV, fPhotonDCAPosPV, + fPhotonZconv, fLambdaPt, fLambdaMass, fLambdaQt, fLambdaAlpha, fLambdaRadius, + fLambdaCosPA, fLambdaDCADau, fLambdaDCANegPV, fLambdaDCAPosPV, + gamma.gammaBDTScore(), lambda.lambdaBDTScore()); + } + } + } + PROCESS_SWITCH(sigma0builder, processMonteCarlo, "Do Monte-Carlo-based analysis", false); + PROCESS_SWITCH(sigma0builder, processRealData, "Do real data analysis", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Nuspex/antidLambdaEbye.cxx b/PWGLF/Tasks/Nuspex/antidLambdaEbye.cxx index 0451e2a8052..8398308d2c1 100644 --- a/PWGLF/Tasks/Nuspex/antidLambdaEbye.cxx +++ b/PWGLF/Tasks/Nuspex/antidLambdaEbye.cxx @@ -36,6 +36,7 @@ #include "Common/Core/PID/TPCPIDResponse.h" #include "Common/DataModel/PIDResponse.h" +#include "DCAFitter/DCAFitterN.h" #include "TDatabasePDG.h" @@ -43,8 +44,8 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using TracksFull = soa::Join; -using BCsWithRun2Info = soa::Join; +using TracksFull = soa::Join; +using BCsWithRun2Info = soa::Join; namespace { @@ -61,7 +62,6 @@ static const std::vector estimatorsCorrelationCoefParNames{"p0", "p static const std::vector estimatorsSigmaParNames{"p0", "p1", "p2", "p3"}; static const std::vector deltaEstimatorNsigmaParNames{"low", "high"}; static const std::vector datasetNames{"LHC18qr"}; -static const std::vector pidHypotheses{"Electron", "Muon", "Pion", "Kaon", "Proton", "Deuteron", "Triton", "He3", "Alpha", "Pion0", "Photon", "K0", "Lambda", "HyperTriton", "Hyperhydrog4", "XiMinus", "OmegaMinus"}; std::array, kNpart> tempTracks; std::shared_ptr tempAntiLambda; std::shared_ptr tempLambda; @@ -96,10 +96,51 @@ std::array, kNpart> genAntiTracks; std::array, kNpart> tpcNsigma; std::array, kNpart> tpcNsigmaGlo; std::array, kNpart> tofMass; -std::array, kNpart> momCorr; -std::array, kNpart> tpcSignalBkg; std::array, kNpart> tofSignal; std::array, kNpart> tofSignal_glo; +void momTotXYZ(std::array& momA, std::array const& momB, std::array const& momC) +{ + for (int i = 0; i < 3; ++i) { + momA[i] = momB[i] + momC[i]; + } +} +float invMass2Body(std::array const& momA, std::array const& momB, std::array const& momC, float const& massB, float const& massC) +{ + float p2B = momB[0] * momB[0] + momB[1] * momB[1] + momB[2] * momB[2]; + float p2C = momC[0] * momC[0] + momC[1] * momC[1] + momC[2] * momC[2]; + float eB = std::sqrt(p2B + massB * massB); + float eC = std::sqrt(p2C + massC * massC); + float eA = eB + eC; + float massA = std::sqrt(eA * eA - momA[0] * momA[0] - momA[1] * momA[1] - momA[2] * momA[2]); + return massA; +} +float alphaAP(std::array const& momA, std::array const& momB, std::array const& momC) +{ + float momTot = std::sqrt(std::pow(momA[0], 2.) + std::pow(momA[1], 2.) + std::pow(momA[2], 2.)); + float lQlPos = (momB[0] * momA[0] + momB[1] * momA[1] + momB[2] * momA[2]) / momTot; + float lQlNeg = (momC[0] * momA[0] + momC[1] * momA[1] + momC[2] * momA[2]) / momTot; + return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); +} +float etaFromMom(std::array const& momA, std::array const& momB) +{ + if (std::sqrt((1.f * momA[0] + 1.f * momB[0]) * (1.f * momA[0] + 1.f * momB[0]) + + (1.f * momA[1] + 1.f * momB[1]) * (1.f * momA[1] + 1.f * momB[1]) + + (1.f * momA[2] + 1.f * momB[2]) * (1.f * momA[2] + 1.f * momB[2])) - + (1.f * momA[2] + 1.f * momB[2]) < + static_cast(1e-7)) { + if ((1.f * momA[2] + 1.f * momB[2]) < 0.f) + return -100.f; + return 100.f; + } + return 0.5f * std::log((std::sqrt((1.f * momA[0] + 1.f * momB[0]) * (1.f * momA[0] + 1.f * momB[0]) + + (1.f * momA[1] + 1.f * momB[1]) * (1.f * momA[1] + 1.f * momB[1]) + + (1.f * momA[2] + 1.f * momB[2]) * (1.f * momA[2] + 1.f * momB[2])) + + (1.f * momA[2] + 1.f * momB[2])) / + (std::sqrt((1.f * momA[0] + 1.f * momB[0]) * (1.f * momA[0] + 1.f * momB[0]) + + (1.f * momA[1] + 1.f * momB[1]) * (1.f * momA[1] + 1.f * momB[1]) + + (1.f * momA[2] + 1.f * momB[2]) * (1.f * momA[2] + 1.f * momB[2])) - + (1.f * momA[2] + 1.f * momB[2]))); +} } // namespace struct CandidateV0 { @@ -120,10 +161,14 @@ struct antidLambdaEbye { std::mt19937 gen32; std::vector candidateV0s; std::array, 2> candidateTracks; - int globalTrackCounter; + Service ccdb; + o2::vertexing::DCAFitterN<2> fitter; int nSubsamples; + float d_bz; + o2::base::MatLayerCylSet* lut = nullptr; + Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 2, 6, particleNamesBB, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for deuteron"}; Configurable> cfgEstimatorsCorrelationCoef{"cfgEstimatorsCorrelationCoef", {estimatorsCorrelationCoef[0], 1, 2, datasetNames, estimatorsCorrelationCoefParNames}, "estimators correlation parameters"}; @@ -138,8 +183,8 @@ struct antidLambdaEbye { ConfigurableAxis ptLambdaAxis{"ptLambdaAxis", {VARIABLE_WIDTH, 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}, "binning of the (anti)lambda pT axis (GeV/c)"}; ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; - ConfigurableAxis multAxis{"multAxis", {1000, 0, 10000}, "Binning for the multiplicity axis"}; - ConfigurableAxis multFt0Axis{"multFt0Axis", {1000, 0, 100000}, "Binning for the ft0 multiplicity axis"}; + ConfigurableAxis multAxis{"multAxis", {100, 0, 10000}, "Binning for the multiplicity axis"}; + ConfigurableAxis multFt0Axis{"multFt0Axis", {100, 0, 100000}, "Binning for the ft0 multiplicity axis"}; ConfigurableAxis nGenRecAxis{"nGenRecAxis", {20, 0, 20}, "binning for the number of reconstructed or generated candidates per event"}; // binning of (anti)lambda QA histograms @@ -157,7 +202,6 @@ struct antidLambdaEbye { ConfigurableAxis momResAxis{"momResAxis", {1.e2, -1.f, 1.f}, "momentum resolution binning"}; ConfigurableAxis tpcAxis{"tpcAxis", {4.e2, 0.f, 4.e3f}, "tpc signal axis binning"}; ConfigurableAxis tofAxis{"tofAxis", {1.e3, 0.f, 1.f}, "tof signal axis binning"}; - ConfigurableAxis trackingPidAxis{"trackingPidAxis", {static_cast(pidHypotheses.size()), 0, static_cast(pidHypotheses.size())}, "tracking pid hypothesis binning"}; Configurable zVtxMax{"zVtxMax", 10.0f, "maximum z position of the primary vertex"}; Configurable etaMax{"etaMax", 0.8f, "maximum eta"}; @@ -209,6 +253,7 @@ struct antidLambdaEbye { Configurable v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.1f, "DCA Neg To PV"}; Configurable v0setting_cospa{"v0setting_cospa", 0.98, "V0 CosPA"}; Configurable v0setting_radius{"v0setting_radius", 0.5f, "v0radius"}; + Configurable v0setting_nsigmatpc{"v0setting_nsigmatpc", 4.f, "nsigmatpc"}; Configurable lambdaMassCut{"lambdaMassCut", 0.005f, "maximum deviation from PDG mass"}; Configurable lambdaMassCutQA{"lambdaMassCutQA", 0.02f, "maximum deviation from PDG mass (for QA histograms)"}; @@ -227,11 +272,7 @@ struct antidLambdaEbye { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry tempHistos{"tempHistos", {}, OutputObjHandlingPolicy::TransientObject}; - Filter preFilterV0 = (nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && - nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv && - aod::v0data::dcaV0daughters < v0setting_dcav0dau); - - Preslice perCollisionV0 = o2::aod::v0data::collisionId; + Preslice perCollisionV0 = o2::aod::v0::collisionId; Preslice perCollisionTracksFull = o2::aod::track::collisionId; Preslice perCollisionMcParts = o2::aod::mcparticle::mcCollisionId; @@ -338,9 +379,55 @@ struct antidLambdaEbye { } } + template + void initCCDB(Bc const& bc) + { + auto timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (doprocessRun2 || doprocessMcRun2) { + auto grpPath{"GLO/GRP/GRP"}; + grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); + if (!grpo) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpPath << " of object GRPObject for timestamp " << timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpo); + } else { + auto grpmagPath{"GLO/Config/GRPMagField"}; + grpmag = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField for timestamp " << timestamp; + } + 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"; + + o2::base::Propagator::Instance()->setMatLUT(lut); + } + void init(o2::framework::InitContext&) { + d_bz = 0; + + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(true); + int mat{static_cast(cfgMaterialCorrection)}; + fitter.setMatCorrType(static_cast(mat)); + uint32_t randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); gen32.seed(randomSeed); @@ -387,9 +474,7 @@ struct antidLambdaEbye { // event QA if (doprocessRun3) { - histos.add("QA/GlobalMultVsCent", ";Centrality T0C (%);#it{N}_{global};", HistType::kTH2F, {centAxis, multAxis}); histos.add("QA/PvMultVsCent", ";Centrality T0C (%);#it{N}_{PV contributors};", HistType::kTH2F, {centAxis, multAxis}); - histos.add("QA/GlobalMultVsPvMult", ";#it{N}_{PV contrib};#it{N}_{global}", HistType::kTH2F, {multAxis, multAxis}); histos.add("QA/MultVsCent", ";Centrality T0C (%);Multiplicity T0C;", HistType::kTH2F, {centAxis, multFt0Axis}); } else if (doprocessRun2) { histos.add("QA/V0MvsCL0", ";Centrality CL0 (%);Centrality V0M (%)", HistType::kTH2F, {centAxis, centAxis}); @@ -411,16 +496,12 @@ struct antidLambdaEbye { tpcNsigma[0] = histos.add("QA/tpcNsigma_p", ";#it{p}_{TPC} (GeV/#it{c});n#sigma_{TPC} (a.u.)", HistType::kTH2F, {momAxis, tpcNsigmaAxis}); tpcNsigmaGlo[0] = histos.add("QA/tpcNsigmaGlo_p", ";Centrality (%);#it{p}_{T} (GeV/#it{c});n#sigma_{TPC} (a.u.)", HistType::kTH3F, {centAxis, momAxis, tpcNsigmaAxis}); tofMass[0] = histos.add("QA/tofMass_p", ";Centrality (%);#it{p}_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});Entries", HistType::kTH3F, {centAxis, momAxis, tofMassAxis}); - momCorr[0] = histos.add("QA/momCorr_p", ";#it{p}_{glo} (GeV/#it{c});#it{p}_{TPC} - #it{p}_{glo} (GeV/#it{c});", HistType::kTH3F, {momAxisFine, momResAxis, trackingPidAxis}); - tpcSignalBkg[0] = histos.add("QA/tpcSignalBkg_p", ";#it{p}_{TPC} (GeV/#it{c});d#it{E}/d#it{x}_{TPC} (a.u.)", HistType::kTH2F, {momAxisFine, tpcAxis}); tofSignal[0] = histos.add("QA/tofSignal_p", ";#it{p}_{TPC} (GeV/#it{c});#beta_{TOF}", HistType::kTH2F, {momAxisFine, tofAxis}); tofSignal_glo[0] = histos.add("QA/tofSignal_glo_p", ";#it{p}_{T} (GeV/#it{c});#beta_{TOF}", HistType::kTH2F, {momAxisFine, tofAxis}); tpcNsigma[1] = histos.add("QA/tpcNsigma_d", ";#it{p}_{TPC} (GeV/#it{c});n#sigma_{TPC} (a.u.)", HistType::kTH2F, {momAxis, tpcNsigmaAxis}); tpcNsigmaGlo[1] = histos.add("QA/tpcNsigmaGlo_d", ";Centrality (%);#it{p}_{T} (GeV/#it{c});n#sigma_{TPC} (a.u.)", HistType::kTH3F, {centAxis, momAxis, tpcNsigmaAxis}); tofMass[1] = histos.add("QA/tofMass_d", ";Centrality (%);#it{p}_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});Entries", HistType::kTH3F, {centAxis, momAxis, tofMassAxis}); - momCorr[1] = histos.add("QA/momCorr_d", ";#it{p}_{glo} (GeV/#it{c});#it{p}_{TPC} - #it{p}_{glo} (GeV/#it{c});", HistType::kTH3F, {momAxisFine, momResAxis, trackingPidAxis}); - tpcSignalBkg[1] = histos.add("QA/tpcSignalBkg_d", ";#it{p}_{TPC} (GeV/#it{c});d#it{E}/d#it{x}_{TPC} (a.u.)", HistType::kTH2F, {momAxisFine, tpcAxis}); tofSignal[1] = histos.add("QA/tofSignal_d", ";#it{p}_{TPC} (GeV/#it{c});#beta_{TOF}", HistType::kTH2F, {momAxisFine, tofAxis}); tofSignal_glo[1] = histos.add("QA/tofSignal_glo_d", ";#it{p}_{T} (GeV/#it{c});#beta_{TOF}", HistType::kTH2F, {momAxisFine, tofAxis}); @@ -440,12 +521,6 @@ struct antidLambdaEbye { genAntiTracks[1] = histos.add("genAntid", ";Centrality (%); #it{p}_{T} (GeV/#it{c});#Delta#eta", HistType::kTH3D, {centAxis, ptAntidAxis, deltaEtaAxis}); } - for (int i{1}; i < momCorr[0]->GetNbinsZ() + 1; ++i) { - for (int iP{0}; iP < kNpart; ++iP) { - momCorr[iP]->GetZaxis()->SetBinLabel(i, pidHypotheses[i - 1].data()); - } - } - // temporary histograms tempTracks[0] = tempHistos.add("tempAntip", ";#Delta#eta;#it{p}_{T} (GeV/#it{c})", HistType::kTH2D, {deltaEtaAxis, ptAntipAxis}); tempTracks[1] = tempHistos.add("tempAntid", ";#Delta#eta;#it{p}_{T} (GeV/#it{c})", HistType::kTH2D, {deltaEtaAxis, ptAntidAxis}); @@ -463,8 +538,10 @@ struct antidLambdaEbye { tofMassMax = std::array{antipTofMassMax, antidTofMassMax}; } - int fillRecoEvent(TracksFull const& tracks, aod::V0Datas const& V0s, float const& centrality) + template + int fillRecoEvent(C const& collision, TracksFull const& tracksAll, aod::V0s const& V0s, float const& centrality) { + auto tracks = tracksAll.sliceBy(perCollisionTracksFull, collision.globalIndex()); candidateTracks[0].clear(); candidateTracks[1].clear(); candidateV0s.clear(); @@ -476,13 +553,10 @@ struct antidLambdaEbye { auto rnd = static_cast(gen32()) / static_cast(gen32.max()); auto subsample = static_cast(rnd * nSubsamples); - globalTrackCounter = 0; - for (const auto& track : tracks) { if (!selectTrack(track)) { continue; } - globalTrackCounter += 1; if (track.sign() > 0.) { continue; @@ -527,20 +601,13 @@ struct antidLambdaEbye { continue; } - // qa tpcNsigma[iP]->Fill(track.tpcInnerParam(), nSigmaTPC); - momCorr[iP]->Fill(track.p(), track.tpcInnerParam() - track.p(), track.pidForTracking()); - // check contamination - if (track.tpcInnerParam() < tpcInnerParamMax[iP]) { - tpcSignalBkg[iP]->Fill(track.tpcInnerParam(), track.tpcSignal()); - } - if (track.pt() > ptTof[iP] && hasTof) { tofSignal_glo[iP]->Fill(track.p(), beta); tofSignal[iP]->Fill(track.tpcInnerParam(), beta); } - // temporary cut to reject fake matches + // temporary cut to reject fake matches (run 3) if (track.tpcInnerParam() < tpcInnerParamMax[iP]) { continue; } @@ -561,64 +628,136 @@ struct antidLambdaEbye { std::vector trkId; for (const auto& v0 : V0s) { - if (v0.pt() < lambdaPtMin || v0.pt() > lambdaPtMax) { + auto posTrack = v0.posTrack_as(); + auto negTrack = v0.negTrack_as(); + + bool posSelect = selectV0Daughter(posTrack); + bool negSelect = selectV0Daughter(negTrack); + if (!posSelect || !negSelect) continue; + + if (doprocessRun2 || doprocessMcRun2) { + bool checkPosPileUp = posTrack.hasTOF() || (posTrack.flags() & o2::aod::track::TrackFlagsRun2Enum::ITSrefit); + bool checkNegPileUp = negTrack.hasTOF() || (negTrack.flags() & o2::aod::track::TrackFlagsRun2Enum::ITSrefit); + if (!checkPosPileUp && !checkNegPileUp) { + continue; + } } - if (!selectLambda(v0)) { + auto posTrackCov = getTrackParCov(posTrack); + auto negTrackCov = getTrackParCov(negTrack); + + int nCand = 0; + try { + nCand = fitter.process(posTrackCov, negTrackCov); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call!"; + continue; + } + if (nCand == 0) { continue; } - auto pos = v0.template posTrack_as(); - auto neg = v0.template negTrack_as(); - if (std::abs(pos.eta()) > etaMax || std::abs(neg.eta()) > etaMax) { + auto& posPropTrack = fitter.getTrack(0); + auto& negPropTrack = fitter.getTrack(1); + + std::array momPos; + std::array momNeg; + std::array momV0; + posPropTrack.getPxPyPzGlo(momPos); + negPropTrack.getPxPyPzGlo(momNeg); + momTotXYZ(momV0, momPos, momNeg); + + auto ptV0 = std::hypot(momV0[0], momV0[1]); + if (ptV0 < lambdaPtMin || ptV0 > lambdaPtMax) { continue; } - bool selectPos = selectV0Daughter(pos); - bool selectNeg = selectV0Daughter(neg); - if (!selectPos || !selectNeg) + auto etaV0 = etaFromMom(momPos, momNeg); + if (std::abs(etaV0) > etaMax) { continue; + } - if (doprocessRun2 || doprocessMcRun2) { - bool checkPosPileUp = pos.hasTOF() || (pos.flags() & o2::aod::track::TrackFlagsRun2Enum::ITSrefit); - bool checkNegPileUp = neg.hasTOF() || (neg.flags() & o2::aod::track::TrackFlagsRun2Enum::ITSrefit); - if (!checkPosPileUp && !checkNegPileUp) { - continue; - } + auto alpha = alphaAP(momV0, momPos, momNeg); + 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); + + // veto on K0s mass + if (std::abs(mK0Short - o2::constants::physics::MassK0Short) < vetoMassK0Short) { + continue; + } + + // pid selections + double expBethePos{tpc::BetheBlochAleph(static_cast(posTrack.tpcInnerParam() / massPos), cfgBetheBlochParams->get("p0"), cfgBetheBlochParams->get("p1"), cfgBetheBlochParams->get("p2"), cfgBetheBlochParams->get("p3"), cfgBetheBlochParams->get("p4"))}; + double expSigmaPos{expBethePos * cfgBetheBlochParams->get("resolution")}; + auto nSigmaTPCPos = static_cast((posTrack.tpcSignal() - expBethePos) / expSigmaPos); + double expBetheNeg{tpc::BetheBlochAleph(static_cast(negTrack.tpcInnerParam() / massNeg), cfgBetheBlochParams->get("p0"), cfgBetheBlochParams->get("p1"), cfgBetheBlochParams->get("p2"), cfgBetheBlochParams->get("p3"), cfgBetheBlochParams->get("p4"))}; + double expSigmaNeg{expBetheNeg * cfgBetheBlochParams->get("resolution")}; + auto nSigmaTPCNeg = static_cast((negTrack.tpcSignal() - expBetheNeg) / expSigmaNeg); + + if (std::abs(nSigmaTPCPos) > v0setting_nsigmatpc || std::abs(nSigmaTPCNeg) > v0setting_nsigmatpc) + ; + + float dcaV0dau = std::sqrt(fitter.getChi2AtPCACandidate()); + if (dcaV0dau > v0setting_dcav0dau) { + continue; + } + + std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; + const auto& vtx = fitter.getPCACandidate(); + double cosPA = RecoDecay::cpa(primVtx, vtx, momV0); + if (cosPA < v0setting_cospa) { + continue; + } + + float radiusV0 = std::hypot(vtx[0], vtx[1]); + if (radiusV0 < v0setting_radius) { + continue; } - bool matter = v0.alpha() > 0; + gpu::gpustd::array dcaInfo; + + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, posTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); + auto posDcaToPv = dcaInfo[0]; + + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, negTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); + auto negDcaToPv = dcaInfo[0]; + + if (std::abs(posDcaToPv) < v0setting_dcapostopv || std::abs(negDcaToPv) < v0setting_dcanegtopv) { + continue; + } - auto mLambda = v0.alpha() > 0 ? v0.mLambda() : v0.mAntiLambda(); if (std::abs(mLambda - o2::constants::physics::MassLambda0) > lambdaMassCutQA) { // for QA histograms continue; } - histos.fill(HIST("QA/massLambda"), centrality, v0.pt(), matter ? v0.mLambda() : v0.mAntiLambda()); - histos.fill(HIST("QA/cosPa"), v0.v0cosPA()); - histos.fill(HIST("QA/radius"), v0.v0radius()); - histos.fill(HIST("QA/dcaV0daugh"), v0.dcaV0daughters()); - histos.fill(HIST("QA/dcaPosPv"), v0.dcapostopv()); - histos.fill(HIST("QA/dcaNegPv"), v0.dcanegtopv()); + histos.fill(HIST("QA/massLambda"), centrality, ptV0, mLambda); if (std::abs(mLambda - o2::constants::physics::MassLambda0) > lambdaMassCut) { continue; } + histos.fill(HIST("QA/cosPa"), cosPA); + histos.fill(HIST("QA/radius"), radiusV0); + histos.fill(HIST("QA/dcaV0daugh"), dcaV0dau); + histos.fill(HIST("QA/dcaPosPv"), posDcaToPv); + histos.fill(HIST("QA/dcaNegPv"), negDcaToPv); if (matter) { - tempHistos.fill(HIST("tempLambda"), std::abs(v0.eta()), v0.pt()); + tempHistos.fill(HIST("tempLambda"), std::abs(etaV0), ptV0); } else { - tempHistos.fill(HIST("tempAntiLambda"), std::abs(v0.eta()), v0.pt()); + tempHistos.fill(HIST("tempAntiLambda"), std::abs(etaV0), ptV0); } - trkId.emplace_back(pos.globalIndex()); - trkId.emplace_back(neg.globalIndex()); + trkId.emplace_back(posTrack.globalIndex()); + trkId.emplace_back(negTrack.globalIndex()); CandidateV0 candV0; - candV0.pt = v0.pt(); - candV0.eta = v0.eta(); - candV0.globalIndexPos = pos.globalIndex(); - candV0.globalIndexNeg = neg.globalIndex(); + candV0.pt = ptV0; + candV0.eta = etaV0; + candV0.globalIndexPos = posTrack.globalIndex(); + candV0.globalIndexNeg = negTrack.globalIndex(); candidateV0s.push_back(candV0); } @@ -664,9 +803,10 @@ struct antidLambdaEbye { return 0; } - void fillMcEvent(TracksFull const& tracks, aod::V0Datas const& V0s, float const& centrality, aod::McParticles const&, aod::McTrackLabels const& mcLabels) + template + void fillMcEvent(C const& collision, TracksFull const& tracks, aod::V0s const& V0s, float const& centrality, aod::McParticles const&, aod::McTrackLabels const& mcLabels) { - int subsample = fillRecoEvent(tracks, V0s, centrality); + int subsample = fillRecoEvent(collision, tracks, V0s, centrality); if (candidateV0s.size() == 1 && candidateV0s[0].pt < -998.f && candidateV0s[0].eta < -998.f && candidateV0s[0].globalIndexPos == -999 && candidateV0s[0].globalIndexPos == -999) { return; } @@ -715,7 +855,7 @@ struct antidLambdaEbye { continue; if (std::abs(posMother.pdgCode()) != 3122) continue; - if (!posMother.isPhysicalPrimary()) + if (!posMother.isPhysicalPrimary() && !posMother.has_mothers()) continue; if ((posMother.flags() & 0x8) || (posMother.flags() & 0x2) || (posMother.flags() & 0x1)) continue; @@ -782,7 +922,7 @@ struct antidLambdaEbye { continue; auto pdgCode = mcPart.pdgCode(); if (std::abs(pdgCode) == 3122) { - if (!mcPart.isPhysicalPrimary()) + if (!mcPart.isPhysicalPrimary() && !mcPart.has_mothers()) continue; bool foundPr = false; for (auto& mcDaught : mcPart.daughters_as()) { @@ -808,7 +948,7 @@ struct antidLambdaEbye { if (std::abs(pdgCode) == partPdg[0]) { iP = 0; } - if (!mcPart.isPhysicalPrimary()) + if (!mcPart.isPhysicalPrimary() && !mcPart.has_mothers()) continue; auto genPt = std::hypot(mcPart.px(), mcPart.py()); if (pdgCode > 0) { @@ -837,9 +977,12 @@ struct antidLambdaEbye { } } - void processRun3(soa::Join const& collisions, TracksFull const& tracks, soa::Filtered const& V0s) + void processRun3(soa::Join const& collisions, TracksFull const& tracks, aod::V0s const& V0s, aod::BCsWithTimestamps const&) { for (const auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + if (!collision.sel8()) continue; @@ -855,29 +998,28 @@ struct antidLambdaEbye { histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); - auto TrackTable_thisCollision = tracks.sliceBy(perCollisionTracksFull, collIdx); auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); V0Table_thisCollision.bindExternalIndices(&tracks); auto multiplicity = collision.multFT0C(); auto centrality = collision.centFT0C(); - fillRecoEvent(TrackTable_thisCollision, V0Table_thisCollision, centrality); + fillRecoEvent(collision, tracks, V0Table_thisCollision, centrality); - histos.fill(HIST("QA/GlobalMultVsCent"), centrality, globalTrackCounter); histos.fill(HIST("QA/PvMultVsCent"), centrality, collision.numContrib()); - histos.fill(HIST("QA/GlobalMultVsPvMult"), collision.numContrib(), globalTrackCounter); histos.fill(HIST("QA/MultVsCent"), centrality, multiplicity); } } PROCESS_SWITCH(antidLambdaEbye, processRun3, "process (Run 3)", false); - void processRun2(soa::Join const& collisions, TracksFull const& tracks, soa::Filtered const& V0s, BCsWithRun2Info const&) + void processRun2(soa::Join const& collisions, TracksFull const& tracks, aod::V0s const& V0s, BCsWithRun2Info const&) { for (const auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + if (std::abs(collision.posZ()) > zVtxMax) continue; - auto bc = collision.bc_as(); if (!(bc.eventCuts() & BIT(aod::Run2EventCuts::kAliEventCutsAccepted))) continue; @@ -901,12 +1043,11 @@ struct antidLambdaEbye { histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); - auto TrackTable_thisCollision = tracks.sliceBy(perCollisionTracksFull, collIdx); auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); V0Table_thisCollision.bindExternalIndices(&tracks); auto multTracklets = collision.multTracklets(); - fillRecoEvent(TrackTable_thisCollision, V0Table_thisCollision, centrality); + fillRecoEvent(collision, tracks, V0Table_thisCollision, centrality); histos.fill(HIST("QA/V0MvsCL0"), centralityCl0, centrality); histos.fill(HIST("QA/trackletsVsV0M"), centrality, multTracklets); @@ -914,10 +1055,13 @@ struct antidLambdaEbye { } PROCESS_SWITCH(antidLambdaEbye, processRun2, "process (Run 2)", false); - void processMcRun3(soa::Join const& collisions, aod::McCollisions const& mcCollisions, TracksFull const& tracks, soa::Filtered const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab) + void processMcRun3(soa::Join const& collisions, aod::McCollisions const& mcCollisions, TracksFull const& tracks, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, aod::BCsWithTimestamps const&) { std::vector> goodCollisions(mcCollisions.size(), std::make_pair(false, -999.)); for (auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + if (!collision.sel8()) continue; @@ -931,11 +1075,10 @@ struct antidLambdaEbye { histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); - auto TrackTable_thisCollision = tracks.sliceBy(perCollisionTracksFull, collIdx); auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); V0Table_thisCollision.bindExternalIndices(&tracks); - fillMcEvent(TrackTable_thisCollision, V0Table_thisCollision, centrality, mcParticles, mcLab); + fillMcEvent(collision, tracks, V0Table_thisCollision, centrality, mcParticles, mcLab); if (candidateV0s.size() == 1 && candidateV0s[0].pt < -998.f && candidateV0s[0].eta < -998.f && candidateV0s[0].globalIndexPos == -999 && candidateV0s[0].globalIndexPos == -999) { goodCollisions[collision.mcCollisionId()].first = false; } @@ -945,14 +1088,16 @@ struct antidLambdaEbye { } PROCESS_SWITCH(antidLambdaEbye, processMcRun3, "process MC (Run 3)", false); - void processMcRun2(soa::Join const& collisions, aod::McCollisions const& mcCollisions, TracksFull const& tracks, soa::Filtered const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, BCsWithRun2Info const&) + void processMcRun2(soa::Join const& collisions, aod::McCollisions const& mcCollisions, TracksFull const& tracks, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, BCsWithRun2Info const&) { std::vector> goodCollisions(mcCollisions.size(), std::make_pair(false, -999.)); for (auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + if (std::abs(collision.posZ()) > zVtxMax) continue; - auto bc = collision.bc_as(); if (!(bc.eventCuts() & BIT(aod::Run2EventCuts::kAliEventCutsAccepted))) continue; @@ -963,11 +1108,10 @@ struct antidLambdaEbye { histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); - auto TrackTable_thisCollision = tracks.sliceBy(perCollisionTracksFull, collIdx); auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); V0Table_thisCollision.bindExternalIndices(&tracks); - fillMcEvent(TrackTable_thisCollision, V0Table_thisCollision, centrality, mcParticles, mcLab); + fillMcEvent(collision, tracks, V0Table_thisCollision, centrality, mcParticles, mcLab); if (candidateV0s.size() == 1 && candidateV0s[0].pt < -998.f && candidateV0s[0].eta < -998.f && candidateV0s[0].globalIndexPos == -999 && candidateV0s[0].globalIndexPos == -999) { goodCollisions[collision.mcCollisionId()].first = false; } diff --git a/PWGLF/Tasks/Nuspex/spectraTOF.cxx b/PWGLF/Tasks/Nuspex/spectraTOF.cxx index 3ed131b0a41..ac0b1c51a60 100644 --- a/PWGLF/Tasks/Nuspex/spectraTOF.cxx +++ b/PWGLF/Tasks/Nuspex/spectraTOF.cxx @@ -33,6 +33,7 @@ #include "Common/Core/TrackSelectionDefaults.h" #include "PWGLF/DataModel/LFParticleIdentification.h" #include "PWGLF/DataModel/spectraTOF.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "TPDGCode.h" @@ -796,8 +797,8 @@ struct tofSpectra { } } - template - bool isEventSelected(CollisionType const& collision, TrackType const& tracks) + template + bool isEventSelected(CollisionType const& collision) { if constexpr (fillHistograms) { histos.fill(HIST("evsel"), 1.f); @@ -1131,7 +1132,7 @@ struct tofSpectra { void processStandard(CollisionCandidate::iterator const& collision, TrackCandidates const& tracks) { - if (!isEventSelected(collision, tracks)) { + if (!isEventSelected(collision)) { return; } for (const auto& track : tracks) { @@ -1148,7 +1149,7 @@ struct tofSpectra { aod::SpTracks const& tracks) { for (const auto& collision : collisions) { - if (!isEventSelected(collision, tracks)) { + if (!isEventSelected(collision)) { return; } const auto& tracksInCollision = tracks.sliceByCached(aod::spectra::collisionId, collision.globalIndex(), cacheTrk); @@ -1170,7 +1171,7 @@ struct tofSpectra { aod::pid##tofTable##inputPid, \ aod::pid##tpcTable##inputPid> const& tracks) \ { \ - if (!isEventSelected(collision, tracks)) { \ + if (!isEventSelected(collision)) { \ return; \ } \ for (const auto& track : tracks) { \ @@ -1591,27 +1592,25 @@ struct tofSpectra { const float multiplicity = getMultiplicity(collision); if (mcParticle.isPhysicalPrimary()) { - if (collision.sel8()) { - if (abs(collision.posZ()) < cfgCutVertex) { - if (includeCentralityMC) { - histos.fill(HIST(hpt_den_prm_goodev[i]), mcParticle.pt(), multiplicity, mcParticle.eta()); - } else { - histos.fill(HIST(hpt_den_prm_goodev[i]), mcParticle.pt()); - } + if (isEventSelected(collision)) { + if (includeCentralityMC) { + histos.fill(HIST(hpt_den_prm_goodev[i]), mcParticle.pt(), multiplicity, mcParticle.eta()); } else { - if (includeCentralityMC) { - histos.fill(HIST(hpt_den_prm_evsel[i]), mcParticle.pt(), multiplicity, mcParticle.eta()); - } else { - histos.fill(HIST(hpt_den_prm_evsel[i]), mcParticle.pt()); - } + histos.fill(HIST(hpt_den_prm_goodev[i]), mcParticle.pt()); } - } else { + } else if (collision.sel8()) { if (includeCentralityMC) { - histos.fill(HIST(hpt_den_prm_recoev[i]), mcParticle.pt(), multiplicity, mcParticle.eta()); + histos.fill(HIST(hpt_den_prm_evsel[i]), mcParticle.pt(), multiplicity, mcParticle.eta()); } else { - histos.fill(HIST(hpt_den_prm_recoev[i]), mcParticle.pt()); + histos.fill(HIST(hpt_den_prm_evsel[i]), mcParticle.pt()); } } + } else { + if (includeCentralityMC) { + histos.fill(HIST(hpt_den_prm_recoev[i]), mcParticle.pt(), multiplicity, mcParticle.eta()); + } else { + histos.fill(HIST(hpt_den_prm_recoev[i]), mcParticle.pt()); + } } } @@ -1689,6 +1688,36 @@ struct tofSpectra { } } + Service pdgDB; + + // Event selection + template + bool isTrueINELgt0(TMcParticles particles) + { + int nPart = 0; + for (const auto& particle : particles) { + if (particle.isPhysicalPrimary() == 0) + continue; // consider only primaries + + const auto& pdgInfo = pdgDB->GetParticle(particle.pdgCode()); + if (!pdgInfo) { + continue; + } + if (TMath::Abs(pdgInfo->Charge()) < 0.001) { + continue; // consider only charged particles + } + + if (particle.eta() < -1.0 || particle.eta() > 1.0) + continue; // consider only particles in |eta| < 1 + + nPart++; + } + if (nPart > 0) + return true; + else + return false; + } + Preslice perMCCol = aod::mcparticle::mcCollisionId; SliceCache cache; void processMC(soa::Join 0) { @@ -1712,7 +1741,7 @@ struct tofSpectra { } continue; }; - if (!isEventSelected(track.collision_as(), tracks)) { + if (!isEventSelected(track.collision_as())) { continue; } if (!passesCutWoDCA(track)) { @@ -1784,6 +1813,11 @@ struct tofSpectra { const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); bool hasParticleInFT0C = false; bool hasParticleInFT0A = false; + if (cfgINELCut.value == 1) { + if (!isTrueINELgt0(particlesInCollision)) { + continue; + } + } int nInelPart = 0; for (const auto& mcParticle : particlesInCollision) { diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index 6f146bf79d7..e6cc019ae50 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -129,3 +129,8 @@ o2physics_add_dpl_workflow(kaonkaonanalysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(highmasslambda + SOURCES highmasslambda.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGLF/Tasks/Resonances/KshortKshort.cxx b/PWGLF/Tasks/Resonances/KshortKshort.cxx index 9ff0f0f4918..4bd72525586 100644 --- a/PWGLF/Tasks/Resonances/KshortKshort.cxx +++ b/PWGLF/Tasks/Resonances/KshortKshort.cxx @@ -134,8 +134,8 @@ struct strangeness_tutorial { hglue.add("h1glueInvMassDS", "h1glueInvMassDS", kTH1F, {glueballMassAxis}); hglue.add("h1glueInvMassME", "h1glueInvMassME", kTH1F, {glueballMassAxis}); } - hglue.add("h3glueInvMassDS", "h3glueInvMassDS", kTH3F, {multiplicityAxis, ptAxis, glueballMassAxis}); - hglue.add("h3glueInvMassME", "h3glueInvMassME", kTH3F, {multiplicityAxis, ptAxis, glueballMassAxis}); + hglue.add("h3glueInvMassDS", "h3glueInvMassDS", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis}, true); + hglue.add("h3glueInvMassME", "h3glueInvMassME", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis}, true); // K0s topological/PID cuts if (QAv0) { diff --git a/PWGLF/Tasks/Resonances/highmasslambda.cxx b/PWGLF/Tasks/Resonances/highmasslambda.cxx new file mode 100644 index 00000000000..44c9068aeb4 --- /dev/null +++ b/PWGLF/Tasks/Resonances/highmasslambda.cxx @@ -0,0 +1,522 @@ +// 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. +// Phi meson spin alignment task +// sourav.kundu@cern.ch + +#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 "PWGLF/DataModel/LFStrangenessTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +struct highmasslambda { + + int mRunNumber; + int multEstimator; + float d_bz; + Service ccdb; + Service pdg; + + // 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"}; + + // fill output + Configurable fillPolarization{"fillPolarization", false, "fill polarization"}; + + // events + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutCentralityMax{"cfgCutCentralityMax", 80.0f, "Accepted maximum Centrality"}; + Configurable cfgCutCentralityMin{"cfgCutCentralityMin", 20.0f, "Accepted minimum Centrality"}; + + // proton track cut + Configurable confRapidity{"confRapidity", 0.5, "cut on Rapidity"}; + Configurable cfgCutPT{"cfgCutPT", 0.3, "PT cut on daughter track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + Configurable cfgCutMinDCAxy{"cfgCutMinDCAxy", 0.0f, "Minimum DCAxy range for proton"}; + Configurable cfgCutDCAxy{"cfgCutDCAxy", 0.1f, "DCAxy range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 1.0f, "DCAz range for tracks"}; + Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; + Configurable ispTdepPID{"ispTdepPID", true, "pT dependent PID"}; + Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable nsigmaCutTOF{"nsigmacutTOF", 3.0, "Value of the TOF Nsigma cut"}; + Configurable nsigmaCutTPCPre{"nsigmacutTPCPre", 5.0, "Value of the TPC Nsigma cut Pre filter"}; + // Configs for V0 + Configurable ConfV0PtMin{"ConfV0PtMin", 0.f, "Minimum transverse momentum of V0"}; + Configurable ConfV0DCADaughMax{"ConfV0DCADaughMax", 0.4f, "Maximum DCA between the V0 daughters"}; + Configurable ConfV0CPAMin{"ConfV0CPAMin", 0.996f, "Minimum CPA of V0"}; + Configurable ConfV0TranRadV0Min{"ConfV0TranRadV0Min", 1.5f, "Minimum transverse radius"}; + Configurable ConfV0TranRadV0Max{"ConfV0TranRadV0Max", 100.f, "Maximum transverse radius"}; + Configurable cMaxV0DCA{"cMaxV0DCA", 0.5, "Maximum V0 DCA to PV"}; + Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 20, "Maximum V0 life time"}; + Configurable cSigmaMassKs0{"cSigmaMassKs0", 0.006, "Sigma cut on KS0 mass"}; + + // config for V0 daughters + Configurable ConfDaughEta{"ConfDaughEta", 0.8f, "V0 Daugh sel: max eta"}; + Configurable ConfDaughPt{"ConfDaughPt", 0.1f, "V0 Daugh sel: min pt"}; + Configurable ConfDaughTPCnclsMin{"ConfDaughTPCnclsMin", 70.f, "V0 Daugh sel: Min. nCls TPC"}; + Configurable ConfDaughDCAMin{"ConfDaughDCAMin", 0.08f, "V0 Daugh sel: Max. DCA Daugh to PV (cm)"}; + Configurable ConfDaughPIDCuts{"ConfDaughPIDCuts", 3, "PID selections for KS0 daughters"}; + + // Mixed event + Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 1, "Number of mixed events per event"}; + + // THnsparse bining + ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {60, 2.15, 2.45}, "#it{M} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisPt{"configThnAxisPt", {30, 1.0, 31.}, "#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", {100, -1, 1}, "V2"}; + ConfigurableAxis configThnAxisSA{"configThnAxisSA", {100, -1, 1}, "SA"}; + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter centralityFilter = (nabs(aod::cent::centFT0C) < cfgCutCentralityMax && nabs(aod::cent::centFT0C) > cfgCutCentralityMin); + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); + Filter dcaCutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + Filter pidFilter = nabs(aod::pidtpc::tpcNSigmaPr) < nsigmaCutTPCPre; + + using EventCandidates = soa::Filtered>; + using TrackCandidates = soa::Filtered>; + using AllTrackCandidates = soa::Join; + using ResoV0s = aod::V0Datas; + + SliceCache cache; + // Partition posTracks = aod::track::signed1Pt > cfgCutCharge; + // Partition negTracks = aod::track::signed1Pt < cfgCutCharge; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + 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)"}; + const AxisSpec thnAxisPhiminusPsi{configThnAxisPhiminusPsi, "#phi - #psi"}; + const AxisSpec thnAxisCentrality{configThnAxisCentrality, "Centrality (%)"}; + const AxisSpec thnAxisV2{configThnAxisV2, "V2"}; + const AxisSpec thnAxisSA{configThnAxisSA, "SA"}; + + AxisSpec phiAxis = {500, -6.28, 6.28, "phi"}; + AxisSpec resAxis = {400, -2, 2, "Res"}; + AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; + AxisSpec dcaAxis = {100, 0.0, 0.1, "V0M (%)"}; + AxisSpec dcatoPVAxis = {10, 0.0, 0.5, "V0M (%)"}; + + histos.add("hInvMassKs0", "hInvMassKs0", kTH1F, {{200, 0.4f, 0.6f}}); + histos.add("hV0Dca", "hV0Dca", kTH1F, {{2000, -1.0f, 1.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, {{1000, -0.5f, 0.5f}}); + histos.add("hDcaz", "Dcaz distribution", kTH1F, {{1000, -0.5f, 0.5f}}); + histos.add("hNsigmaProtonTPC", "NsigmaProton TPC distribution", kTH1F, {{200, -10.0f, 10.0f}}); + histos.add("hNsigmaProtonTOF", "NsigmaProton TOF distribution", kTH1F, {{200, -10.0f, 10.0f}}); + histos.add("hPsiFT0C", "PsiFT0C", kTH2F, {centAxis, phiAxis}); + histos.add("hPsiFT0A", "PsiFT0A", kTH2F, {centAxis, phiAxis}); + histos.add("hPsiTPC", "PsiTPC", kTH2F, {centAxis, phiAxis}); + histos.add("hPsiTPCR", "PsiTPCR", kTH2F, {centAxis, phiAxis}); + histos.add("hPsiTPCL", "PsiTPCL", kTH2F, {centAxis, phiAxis}); + + histos.add("hSparseV2SASameEvent_V2", "hSparseV2SASameEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, dcaAxis, dcatoPVAxis, thnAxisCentrality}); + histos.add("hSparseV2SAMixedEvent_V2", "hSparseV2SAMixedEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, dcaAxis, dcatoPVAxis, thnAxisCentrality}); + + if (fillPolarization) { + histos.add("hSparseV2SASameEventplus_SA", "hSparseV2SASameEventplus_SA", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisPhiminusPsi, thnAxisCentrality}); + histos.add("hSparseV2SASameEventplus_SA_A0", "hSparseV2SASameEventplus_SA_A0", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisPhiminusPsi, thnAxisCentrality}); + histos.add("hSparseV2SASameEventplus_SA_azimuth", "hSparseV2SASameEventplus_SA_azimuth", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisCentrality}); + histos.add("hSparseV2SASameEventminus_SA", "hSparseV2SASameEventminus_SA", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisPhiminusPsi, thnAxisCentrality}); + histos.add("hSparseV2SASameEventminus_SA_A0", "hSparseV2SASameEventminus_SA_A0", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisPhiminusPsi, thnAxisCentrality}); + histos.add("hSparseV2SASameEventminus_SA_azimuth", "hSparseV2SASameEventminus_SA_azimuth", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisCentrality}); + + histos.add("hSparseV2SAMixedEventplus_SA", "hSparseV2SAMixedEventplus_SA", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisPhiminusPsi, thnAxisCentrality}); + histos.add("hSparseV2SAMixedEventplus_SA_A0", "hSparseV2SAMixedEventplus_SA_A0", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisPhiminusPsi, thnAxisCentrality}); + histos.add("hSparseV2SAMixedEventplus_SA_azimuth", "hSparseV2SAMixedEventplus_SA_azimuth", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisCentrality}); + histos.add("hSparseV2SAMixedEventminus_SA", "hSparseV2SAMixedEventminus_SA", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisPhiminusPsi, thnAxisCentrality}); + histos.add("hSparseV2SAMixedEventminus_SA_A0", "hSparseV2SAMixedEventminus_SA_A0", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisPhiminusPsi, thnAxisCentrality}); + histos.add("hSparseV2SAMixedEventminus_SA_azimuth", "hSparseV2SAMixedEventminus_SA_azimuth", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisCentrality}); + } + + // histogram for resolution + histos.add("ResFT0CTPC", "ResFT0CTPC", kTH2F, {centAxis, resAxis}); + histos.add("ResFT0CTPCR", "ResFT0CTPCR", kTH2F, {centAxis, resAxis}); + histos.add("ResFT0CTPCL", "ResFT0CTPCL", kTH2F, {centAxis, resAxis}); + histos.add("ResTPCRTPCL", "ResTPCRTPCL", kTH2F, {centAxis, resAxis}); + histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH2F, {centAxis, resAxis}); + histos.add("ResFT0ATPC", "ResFT0ATPC", kTH2F, {centAxis, resAxis}); + } + + template + bool selectionTrack(const T& candidate) + { + if (!(candidate.isGlobalTrack() && candidate.isPVContributor() && candidate.itsNCls() > cfgITScluster && candidate.tpcNClsFound() > cfgTPCcluster && TMath::Abs(candidate.dcaXY()) > cfgCutMinDCAxy)) { + return false; + } + return true; + } + + template + bool selectionPIDpTdependent(const T& candidate) + { + if (candidate.p() <= 0.5 && TMath::Abs(candidate.tpcNSigmaPr()) < 5.0) { + return true; + } + if (candidate.p() > 0.5 && candidate.p() <= 0.8 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.p() > 0.8 && candidate.hasTOF() && TMath::Sqrt(candidate.tofNSigmaPr() * candidate.tofNSigmaPr() + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr()) < 2.0 * nsigmaCutTOF * nsigmaCutTOF) { + return true; + } + return false; + } + + template + bool selectionPID(const T& candidate) + { + if (candidate.p() <= 0.5 && TMath::Abs(candidate.tpcNSigmaPr()) < 5.0) { + return true; + } + if (candidate.p() > 0.5 && candidate.p() <= 0.8 && TMath::Abs(candidate.tpcNSigmaPr()) < 3.0) { + return true; + } + if (candidate.p() > 0.8 && !candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaPr()) < nsigmaCutTPC) { + return true; + } + if (candidate.p() > 0.8 && candidate.hasTOF() && TMath::Sqrt(candidate.tofNSigmaPr() * candidate.tofNSigmaPr() + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr()) < 2.0 * nsigmaCutTOF * nsigmaCutTOF) { + return true; + } + return false; + } + + template + bool SelectionV0(Collision const& collision, V0 const& candidate) + { + if (fabs(candidate.dcav0topv()) > cMaxV0DCA) { + return false; + } + const float pT = candidate.pt(); + const std::vector decVtx = {candidate.x(), candidate.y(), candidate.z()}; + const float tranRad = candidate.v0radius(); + const double dcaDaughv0 = candidate.dcaV0daughters(); + const double cpav0 = candidate.v0cosPA(); + + float CtauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass(); // FIXME: Get from the common header + float lowmasscutks0 = 0.497 - 2.0 * cSigmaMassKs0; + float highmasscutks0 = 0.497 + 2.0 * cSigmaMassKs0; + + if (pT < ConfV0PtMin) { + return false; + } + if (dcaDaughv0 > ConfV0DCADaughMax) { + return false; + } + if (cpav0 < ConfV0CPAMin) { + return false; + } + if (tranRad < ConfV0TranRadV0Min) { + return false; + } + if (tranRad > ConfV0TranRadV0Max) { + return false; + } + if (fabs(CtauK0s) > cMaxV0LifeTime || candidate.mK0Short() < lowmasscutks0 || candidate.mK0Short() > highmasscutks0) { + return false; + } + return true; + } + + template + bool isSelectedV0Daughter(T const& track, float charge) + { + const auto eta = track.eta(); + const auto pt = track.pt(); + const auto tpcNClsF = track.tpcNClsFound(); + const auto dcaXY = track.dcaXY(); + const auto sign = track.sign(); + if (charge < 0 && sign > 0) { + return false; + } + if (charge > 0 && sign < 0) { + return false; + } + if (std::abs(eta) > ConfDaughEta) { + return false; + } + if (std::abs(pt) < ConfDaughPt) { + return false; + } + if (tpcNClsF < ConfDaughTPCnclsMin) { + return false; + } + if (std::abs(dcaXY) < ConfDaughDCAMin) { + return false; + } + if (std::abs(track.tpcNSigmaPi()) > ConfDaughPIDCuts) { + return false; + } + return true; + } + + double GetPhiInRange(double phi) + { + double result = phi; + while (result < 0) { + result = result + 2. * TMath::Pi() / 2; + } + while (result > 2. * TMath::Pi() / 2) { + result = result - 2. * TMath::Pi() / 2; + } + return result; + } + + ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for bin"}; + ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {10, 0, 100}, "multiplicity percentile for bin"}; + ConfigurableAxis axisEPAngle{"axisEPAngle", {1, -TMath::Pi() / 2, TMath::Pi() / 2}, "event plane angle"}; + + using BinningTypeVertexContributor = ColumnBinningPolicy; + ROOT::Math::PxPyPzMVector Lambdac, Proton, Kshort, fourVecDauCM; + ROOT::Math::XYZVector threeVecDauCM, threeVecDauCMXY, eventplaneVec, eventplaneVecNorm, beamvector; + double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); // FIXME: Get from the common header + double massPr = TDatabasePDG::Instance()->GetParticle(kProton)->Mass(); // FIXME: Get from the common header + double massK0s = TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass(); // FIXME: Get from the common header + void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, AllTrackCandidates const& alltracks, ResoV0s const& V0s, aod::BCs const&) + { + if (!collision.sel8()) { + return; + } + auto centrality = collision.centFT0C(); + auto multTPC = collision.multNTracksPV(); + histos.fill(HIST("hFTOCvsTPCNoCut"), centrality, multTPC); + if (!collision.triggereventep()) { + return; + } + auto psiFT0C = collision.psiFT0C(); + auto psiFT0A = collision.psiFT0A(); + auto psiTPC = collision.psiTPC(); + auto psiTPCR = collision.psiTPCR(); + auto psiTPCL = collision.psiTPCL(); + histos.fill(HIST("hFTOCvsTPC"), centrality, multTPC); + histos.fill(HIST("hFTOCvsTPCSelected"), centrality, multTPC); + histos.fill(HIST("hPsiFT0C"), centrality, psiFT0C); + histos.fill(HIST("hPsiFT0A"), centrality, psiFT0A); + histos.fill(HIST("hPsiTPC"), centrality, psiTPC); + histos.fill(HIST("hPsiTPCR"), centrality, psiTPCR); + histos.fill(HIST("hPsiTPCL"), centrality, psiTPCL); + histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPC))); + histos.fill(HIST("ResFT0CTPCR"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCR))); + histos.fill(HIST("ResFT0CTPCL"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCL))); + histos.fill(HIST("ResTPCRTPCL"), centrality, TMath::Cos(2.0 * (psiTPCR - psiTPCL))); + histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(2.0 * (psiFT0C - psiFT0A))); + histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(2.0 * (psiTPC - psiFT0A))); + histos.fill(HIST("hCentrality"), centrality); + histos.fill(HIST("hVtxZ"), collision.posZ()); + auto firstprimarytrack = 0; + for (auto track1 : tracks) { + if (!selectionTrack(track1)) { + continue; + } + // PID check + if (ispTdepPID && !selectionPIDpTdependent(track1)) { + continue; + } + if (!ispTdepPID && !selectionPID(track1)) { + continue; + } + histos.fill(HIST("hEta"), track1.eta()); + histos.fill(HIST("hDcaxy"), track1.dcaXY()); + histos.fill(HIST("hDcaz"), track1.dcaZ()); + histos.fill(HIST("hNsigmaProtonTPC"), track1.tpcNSigmaPr()); + histos.fill(HIST("hNsigmaProtonTOF"), track1.tofNSigmaPr()); + auto track1ID = track1.globalIndex(); + for (auto v0 : V0s) { + if (firstprimarytrack == 0) { + histos.fill(HIST("hV0Dca"), v0.dcav0topv()); + } + if (!SelectionV0(collision, v0)) { + continue; + } + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + if (!isSelectedV0Daughter(postrack, 1)) { + continue; + } + if (!isSelectedV0Daughter(negtrack, -1)) { + continue; + } + if (track1ID == postrack.globalIndex()) { + continue; + } + if (track1ID == negtrack.globalIndex()) { + continue; + } + if (firstprimarytrack == 0) { + histos.fill(HIST("hInvMassKs0"), v0.mK0Short()); + } + firstprimarytrack = firstprimarytrack + 1; + Proton = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPr); + Kshort = ROOT::Math::PxPyPzMVector(v0.pt(), v0.eta(), v0.phi(), massK0s); + Lambdac = Proton + Kshort; + if (TMath::Abs(Lambdac.Rapidity()) > confRapidity) { + continue; + } + auto phiminuspsi = GetPhiInRange(Lambdac.Phi() - psiFT0C); + auto v2 = TMath::Cos(2.0 * phiminuspsi); + histos.fill(HIST("hSparseV2SASameEvent_V2"), Lambdac.M(), Lambdac.Pt(), v2, std::abs(track1.dcaXY()), std::abs(v0.dcav0topv()), centrality); + + ROOT::Math::Boost boost{Lambdac.BoostToCM()}; + fourVecDauCM = boost(Kshort); + threeVecDauCM = fourVecDauCM.Vect(); + threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); + beamvector = ROOT::Math::XYZVector(0, 0, 1); + auto cosThetaStar = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); + auto SA = cosThetaStar * TMath::Sin(2.0 * phiminuspsi); + if (fillPolarization) { + if (track1.sign() > 0) { + histos.fill(HIST("hSparseV2SASameEventplus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SASameEventplus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SASameEventplus_SA_azimuth"), Lambdac.M(), Lambdac.Pt(), SA, centrality); + } + if (track1.sign() < 0) { + histos.fill(HIST("hSparseV2SASameEventminus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SASameEventminus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SASameEventminus_SA_azimuth"), Lambdac.M(), Lambdac.Pt(), SA, centrality); + } + } + } + } + } + PROCESS_SWITCH(highmasslambda, processSameEvent, "Process Same event", true); + void processMixedEventOpti(EventCandidates const& collisions, TrackCandidates const& tracks, AllTrackCandidates const& alltracks, ResoV0s const& V0s) + { + auto tracksV0sTuple = std::make_tuple(tracks, V0s); + BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisEPAngle}, true}; + Pair pairs{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksV0sTuple, &cache}; // -1 is the number of the bin to skip + for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (!collision1.sel8() || !collision2.sel8()) { + continue; + } + if (!collision1.triggereventep() || !collision2.triggereventep()) { + continue; + } + auto centrality = collision1.centFT0C(); + auto psiFT0C = collision1.psiFT0C(); + + for (auto& [track1, v0] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (!selectionTrack(track1)) { + continue; + } + // PID check + if (ispTdepPID && !selectionPIDpTdependent(track1)) { + continue; + } + if (!ispTdepPID && !selectionPID(track1)) { + continue; + } + if (!SelectionV0(collision2, v0)) { + continue; + } + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + if (!isSelectedV0Daughter(postrack, 1)) { + continue; + } + if (!isSelectedV0Daughter(negtrack, -1)) { + continue; + } + + Proton = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPr); + Kshort = ROOT::Math::PxPyPzMVector(v0.pt(), v0.eta(), v0.phi(), massK0s); + Lambdac = Proton + Kshort; + if (TMath::Abs(Lambdac.Rapidity()) > confRapidity) { + continue; + } + auto phiminuspsi = GetPhiInRange(Lambdac.Phi() - psiFT0C); + auto v2 = TMath::Cos(2.0 * phiminuspsi); + histos.fill(HIST("hSparseV2SAMixedEvent_V2"), Lambdac.M(), Lambdac.Pt(), v2, std::abs(track1.dcaXY()), std::abs(v0.dcav0topv()), centrality); + + ROOT::Math::Boost boost{Lambdac.BoostToCM()}; + fourVecDauCM = boost(Kshort); + threeVecDauCM = fourVecDauCM.Vect(); + threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); + beamvector = ROOT::Math::XYZVector(0, 0, 1); + auto cosThetaStar = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); + auto SA = cosThetaStar * TMath::Sin(2.0 * phiminuspsi); + if (fillPolarization) { + if (track1.sign() > 0) { + histos.fill(HIST("hSparseV2SAMixedEventplus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SAMixedEventplus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SAMixedEventplus_SA_azimuth"), Lambdac.M(), Lambdac.Pt(), SA, centrality); + } + if (track1.sign() < 0) { + histos.fill(HIST("hSparseV2SAMixedEventminus_SA"), Lambdac.M(), Lambdac.Pt(), cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SAMixedEventminus_SA_A0"), Lambdac.M(), Lambdac.Pt(), cosThetaStar * cosThetaStar, phiminuspsi, centrality); + histos.fill(HIST("hSparseV2SAMixedEventminus_SA_azimuth"), Lambdac.M(), Lambdac.Pt(), SA, centrality); + } + } + } + } + } + PROCESS_SWITCH(highmasslambda, processMixedEventOpti, "Process Mixed event new", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"highmasslambda"})}; +} diff --git a/PWGLF/Tasks/Resonances/k892analysis.cxx b/PWGLF/Tasks/Resonances/k892analysis.cxx index 4743bc33f7e..d865af01814 100644 --- a/PWGLF/Tasks/Resonances/k892analysis.cxx +++ b/PWGLF/Tasks/Resonances/k892analysis.cxx @@ -79,15 +79,18 @@ struct k892analysis { // 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 cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor + 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 tof_at_high_pt{"tof_at_high_pt", false, "Use TOF at high pT"}; Configurable additionalEvsel{"additionalEvsel", true, "Additional event selcection"}; - Configurable manualtrkselcuts{"manualtrkselcuts", false, "Tracks selection cuts (nClusters)"}; Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; - Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; - Configurable cfgRCRFC{"cfgRCRFC", 0.8f, "Crossed Rows to Findable Clusters"}; - Configurable allmanualcuts{"allmanualcuts", false, "All manual cuts without using track selection table"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 0, "Number of TPC cluster"}; + Configurable cfgRatioTPCRowsOverFindableCls{"cfgRatioTPCRowsOverFindableCls", 0.0f, "TPC Crossed Rows to Findable Clusters"}; + Configurable cfgITSChi2NCl{"cfgITSChi2NCl", 999.0, "ITS Chi2/NCl"}; + Configurable cfgTPCChi2NCl{"cfgTPCChi2NCl", 999.0, "TPC Chi2/NCl"}; + Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; + Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; // Event selection cuts - Alex (Temporary, need to fix!) TF1* fMultPVCutLow = nullptr; @@ -176,10 +179,10 @@ struct k892analysis { histos.add("QAMCTrue/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); histos.add("h3Reck892invmass", "Invariant mass of Reconstructed MC K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); histos.add("h3Reck892invmassAnti", "Invariant mass of Reconstructed MC Anti-K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("k892Gen", "pT distribution of True MC K(892)0", kTH2F, {ptAxis, centAxis}); - histos.add("k892GenAnti", "pT distribution of True MC Anti-K(892)0", kTH2F, {ptAxis, centAxis}); - histos.add("k892Rec", "pT distribution of Reconstructed MC K(892)0", kTH2F, {ptAxis, centAxis}); - histos.add("k892RecAnti", "pT distribution of Reconstructed MC Anti-K(892)0", kTH2F, {ptAxis, centAxis}); + histos.add("k892Gen", "pT distribution of True MC K(892)0", kTH2D, {ptAxis, centAxis}); + histos.add("k892GenAnti", "pT distribution of True MC Anti-K(892)0", kTH2D, {ptAxis, centAxis}); + histos.add("k892Rec", "pT distribution of Reconstructed MC K(892)0", kTH2D, {ptAxis, centAxis}); + histos.add("k892RecAnti", "pT distribution of Reconstructed MC Anti-K(892)0", kTH2D, {ptAxis, centAxis}); histos.add("k892Recinvmass", "Inv mass distribution of Reconstructed MC Phi", kTH1F, {invMassAxis}); } // Print output histograms statistics @@ -234,36 +237,28 @@ struct k892analysis { return false; if (std::abs(track.dcaZ()) > cMaxDCAzToPVcut) return false; + if (track.itsNCls() < cfgITScluster) + return false; + if (track.tpcNClsFound() < cfgTPCcluster) + return false; + if (track.tpcCrossedRowsOverFindableCls() < cfgRatioTPCRowsOverFindableCls) + return false; + if (track.itsChi2NCl() >= cfgITSChi2NCl) + return false; + if (track.tpcChi2NCl() >= cfgTPCChi2NCl) + return false; + if (cfgUseITSRefit && !track.passedITSRefit()) + return false; + if (cfgUseTPCRefit && !track.passedTPCRefit()) + return false; if (cfgPVContributor && !track.isPVContributor()) return false; - if (!allmanualcuts) { - if (!manualtrkselcuts) { - // if (cfgPrimaryTrack && !track.isPrimaryTrack()) - // return false; - if (!track.isGlobalTrack()) - return false; - } else if (manualtrkselcuts) { - if (!(track.isGlobalTrackWoDCA() && - track.itsNCls() > cfgITScluster && track.tpcNClsFound() > cfgTPCcluster && track.tpcCrossedRowsOverFindableCls() > cfgRCRFC)) { - return false; // condition is like \bar{A.B} = \bar{A} + \bar{B} (+ is or, . is and) - } - } - } else { - if (track.itsNCls() < cfgITScluster) - return false; - if (track.tpcNClsFound() < cfgTPCcluster) - return false; - if (track.tpcCrossedRowsOverFindableCls() < cfgRCRFC) - return false; - if (track.itsChi2NCl() >= 36) - return false; - if (track.tpcChi2NCl() >= 4) - return false; - if (!track.passedITSRefit()) - return false; - if (!track.passedTPCRefit()) - return false; - } + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgGlobalTrack && !track.isGlobalTrack()) + return false; return true; } diff --git a/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx b/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx index b1f9d07f9ce..1776b251f31 100644 --- a/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx +++ b/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx @@ -104,24 +104,24 @@ struct phianalysisrun3 { histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH1F, {{200, -10.0f, 10.0f}}); histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH1F, {{200, -10.0f, 10.0f}}); if (!isMC) { - histos.add("h3PhiInvMassUnlikeSign", "Invariant mass of Phi meson Unlike Sign", kTH3F, {axisMult, axisPt, axisMass}); - histos.add("h3PhiInvMassLikeSignPP", "Invariant mass of Phi meson Like Sign positive", kTH3F, {axisMult, axisPt, axisMass}); - histos.add("h3PhiInvMassLikeSignMM", "Invariant mass of Phi meson Like Sign negative", kTH3F, {axisMult, axisPt, axisMass}); - histos.add("h3PhiInvMassMixed", "Invariant mass of Phi meson Mixed", kTH3F, {axisMult, axisPt, axisMass}); - histos.add("h3PhiInvMassRotation", "Invariant mass of Phi meson Rotation", kTH3F, {axisMult, axisPt, axisMass}); + histos.add("h3PhiInvMassUnlikeSign", "Invariant mass of Phi meson Unlike Sign", kTHnSparseF, {axisMult, axisPt, axisMass}, true); + histos.add("h3PhiInvMassLikeSignPP", "Invariant mass of Phi meson Like Sign positive", kTHnSparseF, {axisMult, axisPt, axisMass}, true); + histos.add("h3PhiInvMassLikeSignMM", "Invariant mass of Phi meson Like Sign negative", kTHnSparseF, {axisMult, axisPt, axisMass}, true); + histos.add("h3PhiInvMassMixed", "Invariant mass of Phi meson Mixed", kTHnSparseF, {axisMult, axisPt, axisMass}, true); + histos.add("h3PhiInvMassRotation", "Invariant mass of Phi meson Rotation", kTHnSparseF, {axisMult, axisPt, axisMass}, true); if (isEtaAssym) { - histos.add("h3PhiInvMassUnlikeSignAside", "Invariant mass of Phi meson Unlike Sign A side", kTH3F, {axisMult, axisPt, axisMass}); - histos.add("h3PhiInvMassLikeSignAside", "Invariant mass of Phi meson Like Sign A side", kTH3F, {axisMult, axisPt, axisMass}); - histos.add("h3PhiInvMassMixedAside", "Invariant mass of Phi meson Mixed A side", kTH3F, {axisMult, axisPt, axisMass}); - histos.add("h3PhiInvMassUnlikeSignCside", "Invariant mass of Phi meson Unlike Sign C side", kTH3F, {axisMult, axisPt, axisMass}); - histos.add("h3PhiInvMassLikeSignCside", "Invariant mass of Phi meson Like Sign C side", kTH3F, {axisMult, axisPt, axisMass}); - histos.add("h3PhiInvMassMixedCside", "Invariant mass of Phi meson Mixed C side", kTH3F, {axisMult, axisPt, axisMass}); + histos.add("h3PhiInvMassUnlikeSignAside", "Invariant mass of Phi meson Unlike Sign A side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); + histos.add("h3PhiInvMassLikeSignAside", "Invariant mass of Phi meson Like Sign A side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); + histos.add("h3PhiInvMassMixedAside", "Invariant mass of Phi meson Mixed A side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); + histos.add("h3PhiInvMassUnlikeSignCside", "Invariant mass of Phi meson Unlike Sign C side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); + histos.add("h3PhiInvMassLikeSignCside", "Invariant mass of Phi meson Like Sign C side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); + histos.add("h3PhiInvMassMixedCside", "Invariant mass of Phi meson Mixed C side", kTHnSparseF, {axisMult, axisPt, axisMass}, true); } } else if (isMC) { histos.add("hMC", "MC Event statistics", kTH1F, {{6, 0.0f, 6.0f}}); histos.add("h1PhiGen", "Phi meson Gen", kTH1F, {axisPt}); histos.add("h1PhiRecsplit", "Phi meson Rec split", kTH1F, {axisPt}); - histos.add("h3PhiRec", "Phi meson Rec", kTH3F, {axisPt, axisPt, {200, -0.1, 0.1}}); + histos.add("h3PhiRec", "Phi meson Rec", kTHnSparseF, {axisPt, axisPt, {200, -0.1, 0.1}}, true); } } diff --git a/PWGLF/Tasks/Resonances/phipbpb.cxx b/PWGLF/Tasks/Resonances/phipbpb.cxx index 26f53b43f73..a77b266e737 100644 --- a/PWGLF/Tasks/Resonances/phipbpb.cxx +++ b/PWGLF/Tasks/Resonances/phipbpb.cxx @@ -804,11 +804,11 @@ struct phipbpb { auto cosPhistarminuspsi = GetPhiInRange(fourVecDauCM.Phi() - psiFT0C); auto SA = TMath::Cos(2.0 * cosPhistarminuspsi); // auto cosThetaStarOP = TMath::Abs(eventplaneVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2())); + auto cosThetaStarIP = eventplaneVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVec.Mag2()); auto cosThetaStarOP = eventplaneVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2()); auto cosThetaStarOPbeam = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); auto SA_A0 = 1 - (cosThetaStarOP * cosThetaStarOP); // auto cosThetaStarIP = TMath::Abs(eventplaneVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVec.Mag2())); - auto cosThetaStarIP = eventplaneVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVec.Mag2()); auto phiminuspsi = GetPhiInRange(PhiMesonMother.Phi() - psiFT0C); auto v2 = TMath::Cos(2.0 * phiminuspsi); if (!fillRapidity) { @@ -880,10 +880,10 @@ struct phipbpb { 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 cosThetaStarOP = TMath::Abs(eventplaneVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2())); - auto cosThetaStarOPbeam = TMath::Abs(beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2())); + auto cosThetaStarIP = eventplaneVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVec.Mag2()); + auto cosThetaStarOP = eventplaneVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2()); + auto cosThetaStarOPbeam = beamvector.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(beamvector.Mag2()); auto SA_A0 = 1 - (cosThetaStarOP * cosThetaStarOP); - auto cosThetaStarIP = TMath::Abs(eventplaneVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVec.Mag2())); auto phiminuspsi = GetPhiInRange(PhiMesonMother.Phi() - psiFT0C); auto v2 = TMath::Cos(2.0 * phiminuspsi); if (!fillRapidity) { diff --git a/PWGLF/Tasks/Strangeness/CMakeLists.txt b/PWGLF/Tasks/Strangeness/CMakeLists.txt index 3458c3dfb81..e765fe1e847 100644 --- a/PWGLF/Tasks/Strangeness/CMakeLists.txt +++ b/PWGLF/Tasks/Strangeness/CMakeLists.txt @@ -78,3 +78,8 @@ o2physics_add_dpl_workflow(hstrangecorrelation SOURCES hStrangeCorrelation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(sigmaanalysis + SOURCES sigmaanalysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx index c8d711bcc4d..497718d40a0 100644 --- a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx @@ -63,11 +63,16 @@ struct derivedCascadeAnalysis { Configurable isXi{"isXi", 1, "Apply cuts for Xi identification"}; Configurable isMC{"isMC", false, "MC data are processed"}; Configurable doBefSelCheck{"doBefSelCheck", false, "Fill mass histograms of all candidates before selections"}; - Configurable doBefSelEventMultCorr{"doBefSelEventMultCorr", false, "Fill historam of multiplicity correlations before selections"}; Configurable doPtDepCutStudy{"doPtDepCutStudy", false, "Fill histogram with a cutting paramer"}; - Configurable doITSFrameBorderCut{"doITSFrameBorderCut", true, "Do the event selection based on the ITSROFrameBorder"}; - Configurable doTFeventCut{"doTFeventCut", true, "Remove the collisions at the edges of the time frames"}; - Configurable doPIDwrongIDcandidateCheck{"doPIDwrongIDcandidateCheck", true, "check PDG code of wrongly ID candidates"}; + Configurable doGoodPVFT0EventCut{"doGoodPVFT0EventCut", true, "check for the PV position diffrence when estimated from tracks and FT0"}; + Configurable doITSTPCvertexEventCut{"doITSTPCvertexEventCut", true, "checks the presence of at least one ITS-TPC track"}; + Configurable doSameBunchPileUpEventCut{"doSameBunchPileUpEventCut", true, "removes events associated with the same \"found-by-T0\" bunch crossing"}; + Configurable doVertexTOFmatch{"doVertexTOFmatch", false, "Checks wherher at least one of vertex contributors is matched to TOF"}; + Configurable doVertexTRDmatch{"doVertexTRDmatch", false, "Checks wherher at least one of vertex contributors is matched to TRD"}; + Configurable doBefSelEventMultCorr{"doBefSelEventMultCorr", false, "Enable histogram of multiplicity correlation before cuts"}; + Configurable doTFeventCut{"doTFeventCut", false, "Enable TF event Cut"}; + Configurable doITSFrameBorderCut{"doITSFrameBorderCut", false, "Enable ITSFrame event cut"}; + Configurable doMultiplicityCorrCut{"doMultiplicityCorrCut", false, "Enable multiplicity vs centrality correlation cut"}; Configurable centMin{"centMin", 0, "Minimal accepted centrality"}; Configurable centMax{"centMax", 100, "Maximal accepted centrality"}; @@ -92,6 +97,10 @@ struct derivedCascadeAnalysis { Configurable nsigmatpcPi{"nsigmatpcPi", 5, "N sigma TPC Pion"}; Configurable nsigmatpcPr{"nsigmatpcPr", 5, "N sigma TPC Proton"}; Configurable nsigmatpcKa{"nsigmatpcKa", 5, "N sigma TPC Kaon"}; + Configurable nsigmatofPr{"nsigmatofPr", 3, "N sigma TOF Proton"}; + Configurable nsigmatofPion{"nsigmatofPion", 3, "N sigma TOF for Pion from V0"}; + Configurable nsigmatofBachPion{"nsigmatofBachPion", 3, "N sigma TOF for bachelor Pion"}; + Configurable nsigmatofBachKaon{"nsigmatofBachKaon", 3, "N sigma TOF for bachelor Kaon"}; Configurable bachBaryonCosPA{"bachBaryonCosPA", 0.9999, "Bachelor baryon CosPA"}; Configurable bachBaryonDCAxyToPV{"bachBaryonDCAxyToPV", 0.08, "DCA bachelor baryon to PV"}; Configurable mintpccrrows{"mintpccrrows", 50, "min N TPC crossed rows"}; @@ -116,12 +125,12 @@ struct derivedCascadeAnalysis { Configurable doNTPCSigmaCut{"doNTPCSigmaCut", false, "Enable cut N sigma TPC"}; Configurable doBachelorBaryonCut{"doBachelorBaryonCut", true, "Enable Bachelor-Baryon cut "}; Configurable doProperLifeTimeCut{"doProperLifeTimeCut", true, "Enable proper life-time cut "}; + Configurable doNTOFSigmaProtonCut{"doNTOFSigmaProtonCut", true, "Enable n sigma TOF PID cut for proton from V0"}; + Configurable doNTOFSigmaV0PionCut{"doNTOFSigmaV0PionCut", false, "Enable n sigma TOF PID cut for pion from V0"}; + Configurable doNTOFSigmaBachelorCut{"doNTOFSigmaBachelorCut", false, "Enable n sigma TOF PID cut for bachelor track"}; - Configurable cosPApar0{"cosPApar0", 0.247403, "const par for pt dep cosPA cut"}; - Configurable cosPApar1{"cosPApar1", -0.068957, "linear par for pt dep cosPA cut"}; - Configurable cosPApar2{"cosPApar2", 0.004934, "quadratic par for pt dep cosPA cut"}; - - Configurable cosPAV0par{"cosPAV0par", 0.162740, "par for pt dep V0cosPA cut"}; + Configurable cosPApar0{"cosPApar0", 0.2, "const par for pt dep cosPA cut"}; + Configurable cosPApar1{"cosPApar1", -0.022, "linear par for pt dep cosPA cut"}; Configurable parCascRadius0{"parCascRadius0", 1.216159, "const par for pt dep radius cut"}; Configurable parCascRadius1{"parCascRadius1", 0.064462, "linear par for pt dep radius cut"}; @@ -129,7 +138,9 @@ struct derivedCascadeAnalysis { Configurable parV0Radius0{"parV0Radius0", 2.136381, "const par for pt dep V0 radius cut"}; Configurable parV0Radius1{"parV0Radius1", 0.437074, "linear par for pt dep V0 radius cut"}; - Configurable dcaCacsDauPar{"dcaCacsDauPar", 0.404424, " par for pt dep DCA cascade daughter cut"}; + Configurable dcaCacsDauPar0{"dcaCacsDauPar0", 0.8, " par for pt dep DCA cascade daughter cut, p_T < 1 GeV/c"}; + Configurable dcaCacsDauPar1{"dcaCacsDauPar1", 0.5, " par for pt dep DCA cascade daughter cut, 1< p_T < 4 GeV/c"}; + Configurable dcaCacsDauPar2{"dcaCacsDauPar2", 0.2, " par for pt dep DCA cascade daughter cut, p_T > 4 GeV/c"}; Service pdgDB; @@ -137,13 +148,16 @@ struct derivedCascadeAnalysis { { histos.add("hEventVertexZ", "hEventVertexZ", kTH1F, {vertexZ}); histos.add("hEventCentrality", "hEventCentrality", kTH1F, {{101, 0, 101}}); - histos.add("hEventSelection", "hEventSelection", kTH1F, {{6, 0, 6}}); + histos.add("hEventSelection", "hEventSelection", kTH1F, {{12, 0, 12}}); + histos.add("hEventNchCorrelationAfCuts", "hEventNchCorrelationAfCuts", kTH2F, {{5000, 0, 5000}, {5000, 0, 2500}}); + histos.add("hEventPVcontributorsVsCentrality", "hEventPVcontributorsVsCentrality", kTH2F, {{100, 0, 100}, {5000, 0, 5000}}); + histos.add("hEventGlobalTracksVsCentrality", "hEventGlobalTracksVsCentrality", kTH2F, {{100, 0, 100}, {2500, 0, 2500}}); if (doBefSelEventMultCorr) { - histos.add("hEventNchCorrelationBefCuts", "hEventNchCorrelationBefCuts", kTH2F, {{5000, 0, 5000}, {5000, 0, 5000}}); - histos.add("hEventNchCorrelationAfITSCut", "hEventNchCorrelationAfITSCut", kTH2F, {{5000, 0, 5000}, {5000, 0, 5000}}); + histos.add("hEventNchCorrelationBefCuts", "hEventNchCorrelationBefCuts", kTH2F, {{5000, 0, 5000}, {2500, 0, 2500}}); + histos.add("hEventPVcontributorsVsCentralityBefCuts", "hEventPVcontributorsVsCentralityBefCuts", kTH2F, {{100, 0, 100}, {5000, 0, 5000}}); + histos.add("hEventGlobalTracksVsCentralityBefCuts", "hEventGlobalTracksVsCentralityBefCuts", kTH2F, {{100, 0, 100}, {2500, 0, 2500}}); } - histos.add("hEventNchCorrelationAfCuts", "hEventNchCorrelationAfCuts", kTH2F, {{5000, 0, 5000}, {5000, 0, 5000}}); histos.add("hCandidate", "hCandidate", HistType::kTH1D, {{22, -0.5, 21.5}}); histos.add("hCutValue", "hCutValue", HistType::kTH2D, {{22, -0.5, 21.5}, {300, 0, 3.01}}); @@ -156,6 +170,17 @@ struct derivedCascadeAnalysis { histos.add("hNsigmaPionNegBach", "hNsigmaPionNegBach", HistType::kTH3D, {{175, -7, 7}, {100, 0, 10}, {100, 0, 100}}); histos.add("hNsigmaKaon", "hNsigmaKaon", HistType::kTH3D, {{175, -7, 7}, {100, 0, 10}, {100, 0, 100}}); + if (doNTOFSigmaProtonCut) + histos.add("hNsigmaTOFProton", "", HistType::kTH3D, {{70, -7, 7}, {100, 0, 10}, {100, 0, 100}}); + if (doNTOFSigmaV0PionCut) + histos.add("hNsigmaTOFV0Pion", "", HistType::kTH3D, {{70, -7, 7}, {100, 0, 10}, {100, 0, 100}}); + if (doNTOFSigmaBachelorCut) { + if (isXi) + histos.add("hNsigmaTOFBachelorPion", "", HistType::kTH3D, {{70, -7, 7}, {100, 0, 10}, {100, 0, 100}}); + else + histos.add("hNsigmaTOFBachelorKaon", "", HistType::kTH3D, {{70, -7, 7}, {100, 0, 10}, {100, 0, 100}}); + } + TString CutLabel[22] = {"All", "MassWin", "y", "DCACascDau", "DCAV0Dau", "rCasc", "rCascMax", "rV0", "rV0Max", "LambdaMass", "Bach-baryon", "V0CosPA", "CompDecayMass", "DCADauToPV", "EtaDau", "CascCosPA", "DCAV0ToPV", "nSigmaTPCV0Dau", "NTPCrows", "OOBRej", "nSigmaTPCbachelor", "ctau"}; for (Int_t i = 1; i <= histos.get(HIST("hCandidate"))->GetNbinsX(); i++) { histos.get(HIST("hCandidate"))->GetXaxis()->SetBinLabel(i, CutLabel[i - 1]); @@ -175,10 +200,6 @@ struct derivedCascadeAnalysis { if (isMC) histos.addClone("InvMassAfterSel/", "InvMassAfterSelMCrecTruth/"); - if (doPIDwrongIDcandidateCheck) { - histos.add("hPDGcodeWrongPIDNeg", "hPDGcodeWrongPIDNeg", HistType::kTH3F, {axisPt, {5000, 0, 5000}, {101, 0, 101}}); - histos.add("hPDGcodeWrongPIDPos", "hPDGcodeWrongPIDPos", HistType::kTH3F, {axisPt, {5000, 0, 5000}, {101, 0, 101}}); - } if (doPtDepCutStudy && !doProperLifeTimeCut) { histos.add("PtDepCutStudy/hNegativeCascadeProperLifeTime", "hNegativeCascadeProperLifeTime", HistType::kTH3F, {axisPt, axisXiMass, {100, 0, 10}}); @@ -281,12 +302,6 @@ struct derivedCascadeAnalysis { histos.get(HIST("hNegativeCascadePtForEfficiency"))->GetYaxis()->Set(200, 1.572f, 1.772f); histos.get(HIST("hPositiveCascadePtForEfficiency"))->GetYaxis()->Set(200, 1.572f, 1.772f); } - - histos.add("h2dNVerticesVsCentrality", "h2dNVerticesVsCentrality", HistType::kTH2F, {{101, 0, 101}, {20, -0.5, 19.5}}); - histos.add("hGenNegativeXi", "hGenNegativeXi", HistType::kTH2F, {{101, 0, 101}, axisPt}); - histos.add("hGenPositiveXi", "hGenPositiveXi", HistType::kTH2F, {{101, 0, 101}, axisPt}); - histos.add("hGenNegativeOmega", "hGenNegativeOmega", HistType::kTH2F, {{101, 0, 101}, axisPt}); - histos.add("hGenPositiveOmega", "hGenPositiveOmega", HistType::kTH2F, {{101, 0, 101}, axisPt}); } } template @@ -296,12 +311,12 @@ struct derivedCascadeAnalysis { if (ptdepcut) { double ptdepCut; if (isCascPa) - ptdepCut = cosPApar0 + cosPApar1 * casc.pt() + cosPApar2 * TMath::Power(casc.pt(), 2); + ptdepCut = cosPApar0 + cosPApar1 * casc.pt(); else - ptdepCut = cosPAV0par / casc.pt(); + ptdepCut = cosPApar0 + cosPApar1 * casc.pt(); if (ptdepCut > 0.3 && casc.pt() < 0.5) ptdepCut = 0.3; - if (ptdepCut < 0.012 || casc.pt() > 7) + if (ptdepCut < 0.012) ptdepCut = 0.012; if (isCascPa) histos.fill(HIST("hCutValue"), 16, TMath::Cos(ptdepCut)); @@ -331,6 +346,13 @@ struct derivedCascadeAnalysis { { histos.fill(HIST("hEventSelection"), 0.5 /* all collisions */); + + if (doBefSelEventMultCorr) { + histos.fill(HIST("hEventNchCorrelationBefCuts"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); + histos.fill(HIST("hEventPVcontributorsVsCentralityBefCuts"), coll.centFT0C(), coll.multNTracksPVeta1()); + histos.fill(HIST("hEventGlobalTracksVsCentralityBefCuts"), coll.centFT0C(), coll.multNTracksGlobal()); + } + if (!sel) { return false; } @@ -346,25 +368,55 @@ struct derivedCascadeAnalysis { } histos.fill(HIST("hEventSelection"), 3.5 /* collisions after centrality sel*/); - if (doBefSelEventMultCorr) - histos.fill(HIST("hEventNchCorrelationBefCuts"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); - if (doITSFrameBorderCut && !coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (doSameBunchPileUpEventCut && !coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + histos.fill(HIST("hEventSelection"), 4.5 /* Not same Bunch pile up */); + + if (doGoodPVFT0EventCut && !coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + histos.fill(HIST("hEventSelection"), 5.5 /* No large vertexZ difference from tracks and FT0*/); + + if (doITSTPCvertexEventCut && !coll.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + histos.fill(HIST("hEventSelection"), 6.5 /* At least one ITS-TPC track in the event*/); + + if (doVertexTOFmatch && !coll.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { return false; } - histos.fill(HIST("hEventSelection"), 4.5 /* Not at ITS ROF border */); + histos.fill(HIST("hEventSelection"), 7.5 /* At least one of vertex contributors is matched to TOF*/); - if (doBefSelEventMultCorr) - histos.fill(HIST("hEventNchCorrelationAfITSCut"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); + if (doVertexTRDmatch && !coll.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + return false; + } + histos.fill(HIST("hEventSelection"), 8.5 /* At least one of vertex contributors is matched to TRD*/); + + if (doITSFrameBorderCut && !coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + histos.fill(HIST("hEventSelection"), 9.5 /* Not at ITS ROF border */); if (doTFeventCut && !coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { return false; } - histos.fill(HIST("hEventSelection"), 5.5 /* Not at TF border */); + histos.fill(HIST("hEventSelection"), 10.5 /* Not at TF border */); + + if (doMultiplicityCorrCut) { + if (coll.multNTracksGlobal() < (1343.3 * TMath::Exp(-0.0443259 * coll.centFT0C()) - 50) || coll.multNTracksGlobal() > (2098.9 * TMath::Exp(-0.0332444 * coll.centFT0C()))) + return false; + if (coll.multNTracksPVeta1() < (3703 * TMath::Exp(-0.0455483 * coll.centFT0C()) - 150) || coll.multNTracksPVeta1() > (4937.33 * TMath::Exp(-0.0372668 * coll.centFT0C()) + 20)) + return false; + } + histos.fill(HIST("hEventSelection"), 11.5 /* Remove outlyers */); histos.fill(HIST("hEventCentrality"), coll.centFT0C()); histos.fill(HIST("hEventVertexZ"), coll.posZ()); histos.fill(HIST("hEventNchCorrelationAfCuts"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); + histos.fill(HIST("hEventPVcontributorsVsCentrality"), coll.centFT0C(), coll.multNTracksPVeta1()); + histos.fill(HIST("hEventGlobalTracksVsCentrality"), coll.centFT0C(), coll.multNTracksGlobal()); return true; } @@ -395,7 +447,11 @@ struct derivedCascadeAnalysis { if (doDCACascadeDauCut) { if (doPtDepDCAcascDauCut) { - float ptDepCut = dcaCacsDauPar / casc.pt(); + float ptDepCut = dcaCacsDauPar0; + if (casc.pt() > 1 && casc.pt() < 4) + ptDepCut = dcaCacsDauPar1; + else if (casc.pt() > 4) + ptDepCut = dcaCacsDauPar2; histos.fill(HIST("hCutValue"), 4, ptDepCut); if (casc.dcacascdaughters() > ptDepCut) return false; @@ -512,7 +568,7 @@ struct derivedCascadeAnalysis { return true; } - void processCascades(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) + void processCascades(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) { if (!IsEventAccepted(coll, coll.sel8())) @@ -611,6 +667,32 @@ struct derivedCascadeAnalysis { cut = ctau; histos.fill(HIST("hCutValue"), 22, cut); + if (posExtra.hasTOF()) { + if (doNTOFSigmaProtonCut && casc.sign() < 0) { + histos.fill(HIST("hNsigmaTOFProton"), casc.tofNSigmaXiLaPr(), TMath::Sqrt(TMath::Power(casc.pxpos(), 2) + TMath::Power(casc.pypos(), 2) + TMath::Power(casc.pzpos(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiLaPr()) > nsigmatofPr) + continue; + } + if (doNTOFSigmaV0PionCut && casc.sign() > 0) { + histos.fill(HIST("hNsigmaTOFV0Pion"), casc.tofNSigmaXiLaPi(), TMath::Sqrt(TMath::Power(casc.pxpos(), 2) + TMath::Power(casc.pypos(), 2) + TMath::Power(casc.pzpos(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiLaPi()) > nsigmatofPion) + continue; + } + } + + if (negExtra.hasTOF()) { + if (doNTOFSigmaProtonCut && casc.sign() > 0) { + histos.fill(HIST("hNsigmaTOFProton"), casc.tofNSigmaXiLaPr(), TMath::Sqrt(TMath::Power(casc.pxneg(), 2) + TMath::Power(casc.pyneg(), 2) + TMath::Power(casc.pzneg(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiLaPr()) > nsigmatofPr) + continue; + } + if (doNTOFSigmaV0PionCut && casc.sign() < 0) { + histos.fill(HIST("hNsigmaTOFV0Pion"), casc.tofNSigmaXiLaPi(), TMath::Sqrt(TMath::Power(casc.pxneg(), 2) + TMath::Power(casc.pyneg(), 2) + TMath::Power(casc.pzneg(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiLaPi()) > nsigmatofPion) + continue; + } + } + if (isXi) { if (casc.sign() < 0) histos.fill(HIST("hNsigmaPionNegBach"), bachExtra.tpcNSigmaPi(), TMath::Sqrt(TMath::Power(casc.pxbach(), 2) + TMath::Power(casc.pybach(), 2) + TMath::Power(casc.pzbach(), 2)), coll.centFT0C()); @@ -623,6 +705,12 @@ struct derivedCascadeAnalysis { } else ++counter; + if (bachExtra.hasTOF() && doNTOFSigmaBachelorCut) { + histos.fill(HIST("hNsigmaTOFBachelorPion"), casc.tofNSigmaXiPi(), TMath::Sqrt(TMath::Power(casc.pxbach(), 2) + TMath::Power(casc.pybach(), 2) + TMath::Power(casc.pzbach(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiPi()) > nsigmatofBachPion) + continue; + } + ctau = pdgDB->Mass(3312) * cascpos / ((cascptotmom + 1e-13) * ctauxiPDG); if (doProperLifeTimeCut) { if (ctau > proplifetime) @@ -640,6 +728,12 @@ struct derivedCascadeAnalysis { } else ++counter; + if (bachExtra.hasTOF() && doNTOFSigmaBachelorCut) { + histos.fill(HIST("hNsigmaTOFBachelorKaon"), casc.tofNSigmaOmKa(), TMath::Sqrt(TMath::Power(casc.pxbach(), 2) + TMath::Power(casc.pybach(), 2) + TMath::Power(casc.pzbach(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaOmKa()) > nsigmatofBachKaon) + continue; + } + ctau = pdgDB->Mass(3334) * cascpos / ((cascptotmom + 1e-13) * ctauomegaPDG); if (doProperLifeTimeCut) { if (ctau > proplifetime) @@ -702,7 +796,7 @@ struct derivedCascadeAnalysis { } } } - void processCascadesMCrec(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) + void processCascadesMCrec(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) { if (!IsEventAccepted(coll, coll.sel8())) return; @@ -795,6 +889,32 @@ struct derivedCascadeAnalysis { float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); float ctau = -10; + if (posExtra.hasTOF()) { + if (doNTOFSigmaProtonCut && casc.sign() < 0) { + histos.fill(HIST("hNsigmaTOFProton"), casc.tofNSigmaXiLaPr(), TMath::Sqrt(TMath::Power(casc.pxpos(), 2) + TMath::Power(casc.pypos(), 2) + TMath::Power(casc.pzpos(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiLaPr()) > nsigmatofPr) + continue; + } + if (doNTOFSigmaV0PionCut && casc.sign() > 0) { + histos.fill(HIST("hNsigmaTOFV0Pion"), casc.tofNSigmaXiLaPi(), TMath::Sqrt(TMath::Power(casc.pxpos(), 2) + TMath::Power(casc.pypos(), 2) + TMath::Power(casc.pzpos(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiLaPi()) > nsigmatofPion) + continue; + } + } + + if (negExtra.hasTOF()) { + if (doNTOFSigmaProtonCut && casc.sign() > 0) { + histos.fill(HIST("hNsigmaTOFProton"), casc.tofNSigmaXiLaPr(), TMath::Sqrt(TMath::Power(casc.pxneg(), 2) + TMath::Power(casc.pyneg(), 2) + TMath::Power(casc.pzneg(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiLaPr()) > nsigmatofPr) + continue; + } + if (doNTOFSigmaV0PionCut && casc.sign() < 0) { + histos.fill(HIST("hNsigmaTOFV0Pion"), casc.tofNSigmaXiLaPi(), TMath::Sqrt(TMath::Power(casc.pxneg(), 2) + TMath::Power(casc.pyneg(), 2) + TMath::Power(casc.pzneg(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiLaPi()) > nsigmatofPion) + continue; + } + } + if (isXi) { if (casc.sign() < 0) histos.fill(HIST("hNsigmaPionNegBach"), bachExtra.tpcNSigmaPi(), TMath::Sqrt(TMath::Power(casc.pxbach(), 2) + TMath::Power(casc.pybach(), 2) + TMath::Power(casc.pzbach(), 2)), coll.centFT0C()); @@ -807,6 +927,12 @@ struct derivedCascadeAnalysis { } else ++counter; + if (bachExtra.hasTOF() && doNTOFSigmaBachelorCut) { + histos.fill(HIST("hNsigmaTOFBachelorPion"), casc.tofNSigmaXiPi(), TMath::Sqrt(TMath::Power(casc.pxbach(), 2) + TMath::Power(casc.pybach(), 2) + TMath::Power(casc.pzbach(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaXiPi()) > nsigmatofBachPion) + continue; + } + ctau = pdgDB->Mass(3312) * cascpos / ((cascptotmom + 1e-13) * ctauxiPDG); if (doProperLifeTimeCut) { if (ctau > proplifetime) @@ -825,6 +951,13 @@ struct derivedCascadeAnalysis { histos.fill(HIST("hCandidate"), ++counter); } else ++counter; + + if (bachExtra.hasTOF() && doNTOFSigmaBachelorCut) { + histos.fill(HIST("hNsigmaTOFBachelorKaon"), casc.tofNSigmaOmKa(), TMath::Sqrt(TMath::Power(casc.pxbach(), 2) + TMath::Power(casc.pybach(), 2) + TMath::Power(casc.pzbach(), 2)), coll.centFT0C()); + if (TMath::Abs(casc.tofNSigmaOmKa()) > nsigmatofBachKaon) + continue; + } + ctau = pdgDB->Mass(3334) * cascpos / ((cascptotmom + 1e-13) * ctauomegaPDG); if (doProperLifeTimeCut) { if (ctau > proplifetime) @@ -889,9 +1022,6 @@ struct derivedCascadeAnalysis { if ((isXi && casc.pdgCodeV0() == 3122 && casc.pdgCodePositive() == 2212 && casc.pdgCodeNegative() == -211 && casc.pdgCodeBachelor() == -211) || (!isXi && casc.pdgCodeV0() == 3122 && casc.pdgCodePositive() == 2212 && casc.pdgCodeNegative() == -211 && casc.pdgCodeBachelor() == -321)) histos.fill(HIST("hNegativeCascadePtForEfficiency"), casc.pt(), invmass, coll.centFT0C()); } - } else { - if (doPIDwrongIDcandidateCheck) - histos.fill(HIST("hPDGcodeWrongPIDNeg"), casc.pt(), casc.pdgCode(), coll.centFT0C()); } } else { histos.fill(HIST("InvMassAfterSel/hPositiveCascade"), casc.pt(), invmass, coll.centFT0C()); @@ -946,9 +1076,6 @@ struct derivedCascadeAnalysis { histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveCascadeProperLifeTime"), casc.pt(), invmass, ctau); if ((isXi && casc.pdgCodeV0() == -3122 && casc.pdgCodePositive() == 211 && casc.pdgCodeNegative() == -2212 && casc.pdgCodeBachelor() == 211) || (!isXi && casc.pdgCodeV0() == -3122 && casc.pdgCodePositive() == 211 && casc.pdgCodeNegative() == -2212 && casc.pdgCodeBachelor() == 321)) histos.fill(HIST("hPositiveCascadePtForEfficiency"), casc.pt(), invmass, coll.centFT0C()); - } else { - if (doPIDwrongIDcandidateCheck) - histos.fill(HIST("hPDGcodeWrongPIDPos"), casc.pt(), casc.pdgCode(), coll.centFT0C()); } } } diff --git a/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx b/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx new file mode 100644 index 00000000000..a6eeb697198 --- /dev/null +++ b/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx @@ -0,0 +1,309 @@ +// 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 is a task that employs the standard V0 tables and attempts to combine +// two V0s into a Sigma0 -> Lambda + gamma candidate. + +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/ASoA.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.h" +#include "PWGLF/DataModel/LFSigmaTables.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 "CCDB/BasicCCDBManager.h" +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using std::cout; +using std::endl; +using dauTracks = soa::Join; + +struct sigmaanalysis { + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // master analysis switches + // Configurable fSaveTTree{"fSaveTTree", false, "Save TTree with Sigma0 candidates info for ML-based analysis"}; + // Configurable analyseSigma{"analyseSigma", false, "process Sigma-like candidates"}; + // Configurable analyseAntiSigma{"analyseAntiSigma", false, "process AntiSigma-like candidates"}; + // Base selection criteria + + // Selection criteria: acceptance + Configurable rapidityCut{"rapidityCut", 0.5, "rapidity"}; + Configurable daughterEtaCut{"daughterEtaCut", 0.8, "max eta for daughters"}; + + // Photon standard criteria: + Configurable minPhotonRadius{"minPhotonRadius", 5.0, "minimum photon conversion radius (cm)"}; + Configurable maxPhotonRadius{"maxPhotonRadius", 180, "maximum photon conversion radius (cm)"}; + Configurable minPhotonPt{"minPhotonPt", 0.02, "minimum photon pT (GeV/c)"}; + Configurable minPhotonEta{"minPhotonEta", 0.9, "minimum photon eta"}; + Configurable maxPhotonMass{"maxPhotonMass", 0.1, "Maximum photon mass (GeV/c^{2})"}; + Configurable maxPhotonqt{"maxPhotonqt", 0.06, "Maximum photon qt value (AP plot) (GeV/c)"}; + Configurable Photonalpha{"Photonalpha", 0.95, "Max photon alpha absolute value (AP plot)"}; + + // PID (TPC) + Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 4, "TpcPidNsigmaCut"}; + Configurable allowTPConly{"allowTPConly", false, "Accept V0s that are TPC-only"}; + + // Track quality + Configurable minTPCrows{"minTPCrows", 70, "minimum TPC crossed rows"}; + + // Lambda: + Configurable lambdaWindow{"lambdaWindow", 0.01, "Accept +/- this wrt Lambda mass (GeV/c^{2})"}; + Configurable v0cospa{"v0cospa", 0.97, "min V0 CosPA"}; + Configurable dcav0dau{"dcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; + Configurable dcanegtopv{"dcanegtopv", .05, "min DCA Neg To PV (cm)"}; + Configurable dcapostopv{"dcapostopv", .05, "min DCA Pos To PV (cm)"}; + Configurable v0radius{"v0radius", 1.2, "minimum V0 radius (cm)"}; + + // Axis + // base properties + ConfigurableAxis vertexZ{"vertexZ", {30, -15.0f, 15.0f}, ""}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "p_{T} (GeV/c)"}; + ConfigurableAxis axisRadius{"axisRadius", {200, 0.0f, 100.0f}, "V0 radius (cm)"}; + + // Invariant Mass + ConfigurableAxis axisSigmaMass{"axisSigmaMass", {200, 1.16f, 1.23f}, "M_{#Sigma^{0}} (GeV/c^{2})"}; + ConfigurableAxis axisLambdaMass{"axisLambdaMass", {200, 1.08f, 1.16f}, "M_{#Lambda} (GeV/c^{2})"}; + ConfigurableAxis axisPhotonMass{"axisPhotonMass", {200, -0.1f, 0.1f}, "M_{#Gamma}"}; + + // AP plot axes + ConfigurableAxis axisAPAlpha{"axisAPAlpha", {220, -1.1f, 1.1f}, "V0 AP alpha"}; + ConfigurableAxis axisAPQt{"axisAPQt", {220, 0.0f, 0.5f}, "V0 AP alpha"}; + + // ML + ConfigurableAxis MLProb{"MLOutput", {100, 0.0f, 1.0f}, ""}; + + void init(InitContext const&) + { + // Event counter + histos.add("hEventVertexZ", "hEventVertexZ", kTH1F, {vertexZ}); + histos.add("hEventVertexZMC", "hEventVertexZMC", kTH1F, {vertexZ}); + + // Number of reconstructed sigma per collision as QA + histos.add("hNSigmaCandidates", "hNSigmaCandidates", kTH1F, {{100, -0.5f, 99.5f}}); + histos.add("hNSigmaCandidatesMC", "hNSigmaCandidatesMC", kTH1F, {{100, -0.5f, 99.5f}}); + + // V0 Radius + histos.add("h2dLambdaRadiusVsPt", "hLambdaRadiusVsPt", {HistType::kTH2F, {axisPt, axisRadius}}); + histos.add("h2dPhotonRadiusVsPt", "hPhotonRadiusVsPt", {HistType::kTH2F, {axisPt, axisRadius}}); + histos.add("h2dLambdaRadiusVsPtMC", "hLambdaRadiusVsPtMC", {HistType::kTH2F, {axisPt, axisRadius}}); + histos.add("h2dPhotonRadiusVsPtMC", "hPhotonRadiusVsPtMC", {HistType::kTH2F, {axisPt, axisRadius}}); + + // Invariant Mass + histos.add("h2dSigmaMassVsPt", "hSigmaMassVsPt", {HistType::kTH2F, {axisPt, axisSigmaMass}}); + histos.add("h2dLambdaMassVsPt", "hLambdaMassVsPt", {HistType::kTH2F, {axisPt, axisLambdaMass}}); + histos.add("h2dPhotonMassVsPt", "hPhotonMassVsPt", {HistType::kTH2F, {axisPt, axisPhotonMass}}); + histos.add("h2dSigmaMassVsPtMC", "hSigmaMassVsPtMC", {HistType::kTH2F, {axisPt, axisSigmaMass}}); + histos.add("h2dLambdaMassVsPtMC", "hLambdaMassVsPtMC", {HistType::kTH2F, {axisPt, axisLambdaMass}}); + histos.add("h2dPhotonMassVsPtMC", "hPhotonMassVsPtMC", {HistType::kTH2F, {axisPt, axisPhotonMass}}); + + // Exploratory Analysis with MC: + /// Armenteros-Polanski plot: + histos.add("h2dMCArmenterosPolanski", "h2dMCArmenterosPolanski", {HistType::kTH2F, {axisAPAlpha, axisAPQt}}); + + /// Lambda + histos.add("hMCLambdaCosPA", "hMCLambdaCosPA", kTH1F, {{100, 0.9f, 1.0f}}); + histos.add("hMCLambdaDCA_V0Dau", "hMCLambdaDCA_V0Dau", kTH1F, {{100, 0.0f, 3.0f}}); + histos.add("hMCLambdaDCA_V0Pos", "hMCLambdaDCA_V0Pos", kTH1F, {{100, 0.0f, 2.0f}}); + histos.add("hMCLambdaDCA_V0Neg", "hMCLambdaDCA_V0Neg", kTH1F, {{100, 0.0f, 2.0f}}); + histos.add("hMCLambda_V0Radius", "hMCLambda_V0Radius", kTH1F, {{100, 0.0f, 40.0f}}); + + /// Photon: + histos.add("hMCPhoton_ConversionRadius", "hMCPhoton_ConversionRadius", kTH1F, {{100, 0.0f, 150.0f}}); + histos.add("hMCPhotonCosPA", "hMCPhotonCosPA", kTH1F, {{100, 0.9f, 1.0f}}); + histos.add("hMCPhotonDCA_V0Dau", "hMCPhotonDCA_V0Dau", kTH1F, {{100, 0.0f, 5.0}}); + histos.add("hMCPhotonDCA_V0Pos", "hMCPhotonDCA_V0Pos", kTH1F, {{100, 0.0f, 5.0f}}); + histos.add("hMCPhotonDCA_V0Neg", "hMCPhotonDCA_V0Neg", kTH1F, {{100, 0.0f, 5.0f}}); + + // ML Analysis + histos.add("hMLOutputLambda", "hMLOutputLambda", kTH1F, {MLProb}); + histos.add("hMLOutputGamma", "hMLOutputGamma", kTH1F, {MLProb}); + + if (doprocessCounterQA) { + histos.add("hGammaIndices", "hGammaIndices", {HistType::kTH1F, {{4000, 0.0f, 400000.0f}}}); + histos.add("hCollIndices", "hCollIndices", {HistType::kTH1F, {{4000, 0.0f, 4000.0f}}}); + histos.add("h2dIndices", "h2dIndices", {HistType::kTH2F, {{4000, 0.0f, 40000.0f}, {4000, 0.0f, 400000.0f}}}); + } + } + + // Helper struct to pass v0 information + struct { + float mass; + float pT; + } sigmaCandidate; + + // Process sigma candidate and store properties in object + template + bool processSigmaCandidate(TCollision const& collision, TV0Object const& lambda, TV0Object const& gamma) + { + // FIXME: this should be at the single particle level, preferably partitions + if (!allowTPConly && (lambda.v0Type() > 1 || gamma.v0Type() > 1)) + return false; + + // Gamma selection criteria: + if (gamma.mGamma() > maxPhotonMass) + return false; + if (gamma.v0radius() < minPhotonRadius) + return false; + if (gamma.v0radius() > maxPhotonRadius) + return false; + if (gamma.pt() < minPhotonPt) + return false; + if (gamma.qtarm() > maxPhotonqt) + return false; + if (TMath::Abs(gamma.alpha()) > Photonalpha) + return false; + + // Lambda selection criteria: + if (TMath::Abs(lambda.mLambda() - 1.115683) > lambdaWindow) + return false; + if (lambda.v0radius() < v0radius) + return false; + if (lambda.v0cosPA() < v0cospa) + return false; + if (lambda.dcapostopv() < dcapostopv) + return false; + if (lambda.dcanegtopv() < dcanegtopv) + return false; + if (lambda.dcaV0daughters() > dcav0dau) + return false; + + std::array pVecPhotons{gamma.px(), gamma.py(), gamma.pz()}; + std::array pVecLambda{lambda.px(), lambda.py(), lambda.pz()}; + auto arrMom = std::array{pVecPhotons, pVecLambda}; + sigmaCandidate.mass = RecoDecay::m(arrMom, std::array{o2::constants::physics::MassPhoton, o2::constants::physics::MassLambda0}); + sigmaCandidate.pT = RecoDecay::pt(array{gamma.px() + lambda.px(), gamma.py() + lambda.py()}); + return true; + } + + // This process function cross-checks index correctness + void processCounterQA(soa::Join const& v0s) + { + for (auto& gamma : v0s) { + histos.fill(HIST("hGammaIndices"), gamma.globalIndex()); + histos.fill(HIST("hCollIndices"), gamma.straCollisionId()); + histos.fill(HIST("h2dIndices"), gamma.straCollisionId(), gamma.globalIndex()); + } + } + + void processMonteCarlo(aod::StraCollision const& coll, soa::Join const& v0s) + { + int SigmaCounter = 0; + + histos.fill(HIST("hEventVertexZMC"), coll.posZ()); + + for (auto& gamma : v0s) { // selecting photons from Sigma0 + + if ((gamma.pdgCode() != 22 || gamma.pdgCodeMother() != 3212) && (gamma.pdgCode() != -22 || gamma.pdgCodeMother() != -3212)) + continue; + + for (auto& lambda : v0s) { // selecting lambdas from Sigma0 + if ((lambda.pdgCode() != 3122 || lambda.pdgCodeMother() != 3212) && (lambda.pdgCode() != -3122 || lambda.pdgCodeMother() != -3212)) + continue; + if (gamma.motherMCPartId() != lambda.motherMCPartId()) + continue; // selecting pair from exactly the same mother + + // Exploratory Analysis histograms: + + // Lambda + histos.fill(HIST("hMCLambdaCosPA"), lambda.v0cosPA()); + histos.fill(HIST("hMCLambdaDCA_V0Dau"), TMath::Abs(lambda.dcaV0daughters())); + histos.fill(HIST("hMCLambdaDCA_V0Pos"), TMath::Abs(lambda.dcapostopv())); + histos.fill(HIST("hMCLambdaDCA_V0Neg"), TMath::Abs(lambda.dcanegtopv())); + histos.fill(HIST("hMCLambda_V0Radius"), lambda.v0radius()); + + // Photon + histos.fill(HIST("hMCPhoton_ConversionRadius"), gamma.v0radius()); + histos.fill(HIST("hMCPhotonCosPA"), gamma.v0cosPA()); + histos.fill(HIST("hMCPhotonDCA_V0Dau"), TMath::Abs(gamma.dcaV0daughters())); + histos.fill(HIST("hMCPhotonDCA_V0Pos"), TMath::Abs(gamma.dcapostopv())); + histos.fill(HIST("hMCPhotonDCA_V0Neg"), TMath::Abs(gamma.dcanegtopv())); + + // Armenteros-Polanski plot: + histos.fill(HIST("h2dMCArmenterosPolanski"), gamma.alpha(), gamma.qtarm()); + histos.fill(HIST("h2dMCArmenterosPolanski"), lambda.alpha(), lambda.qtarm()); + + if (!processSigmaCandidate(coll, lambda, gamma)) + continue; + SigmaCounter++; + + histos.fill(HIST("h2dLambdaRadiusVsPtMC"), sigmaCandidate.pT, lambda.v0radius()); + histos.fill(HIST("h2dPhotonRadiusVsPtMC"), sigmaCandidate.pT, gamma.v0radius()); + + // Inv Mass + histos.fill(HIST("h2dLambdaMassVsPtMC"), sigmaCandidate.pT, lambda.mLambda()); + histos.fill(HIST("h2dPhotonMassVsPtMC"), sigmaCandidate.pT, gamma.mGamma()); + histos.fill(HIST("h2dSigmaMassVsPtMC"), sigmaCandidate.pT, sigmaCandidate.mass); + } + } + histos.fill(HIST("hNSigmaCandidatesMC"), SigmaCounter); + } + + void processRealData(aod::StraCollision const& coll, soa::Join const& v0s) + { + int SigmaCounter = 0; + + histos.fill(HIST("hEventVertexZ"), coll.posZ()); + + for (auto& gamma : v0s) { // selecting photons from Sigma0 + for (auto& lambda : v0s) { // selecting lambdas from Sigma0 + if (!processSigmaCandidate(coll, lambda, gamma)) + continue; + SigmaCounter++; + + histos.fill(HIST("h2dLambdaRadiusVsPt"), sigmaCandidate.pT, lambda.v0radius()); + histos.fill(HIST("h2dPhotonRadiusVsPt"), sigmaCandidate.pT, gamma.v0radius()); + + // Inv Mass + histos.fill(HIST("h2dLambdaMassVsPt"), sigmaCandidate.pT, lambda.mLambda()); + histos.fill(HIST("h2dPhotonMassVsPt"), sigmaCandidate.pT, gamma.mGamma()); + histos.fill(HIST("h2dSigmaMassVsPt"), sigmaCandidate.pT, sigmaCandidate.mass); + + histos.fill(HIST("hMLOutputLambda"), lambda.lambdaBDTScore()); + histos.fill(HIST("hMLOutputGamma"), gamma.gammaBDTScore()); + } + } + histos.fill(HIST("hNSigmaCandidates"), SigmaCounter); + } + + PROCESS_SWITCH(sigmaanalysis, processCounterQA, "Check standard counter correctness", true); + PROCESS_SWITCH(sigmaanalysis, processMonteCarlo, "Do Monte-Carlo-based analysis", true); + PROCESS_SWITCH(sigmaanalysis, processRealData, "Do real data analysis", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGMM/Mult/Core/include/Functions.h b/PWGMM/Mult/Core/include/Functions.h index 18956f18bdb..4cd59894184 100644 --- a/PWGMM/Mult/Core/include/Functions.h +++ b/PWGMM/Mult/Core/include/Functions.h @@ -17,20 +17,26 @@ namespace pwgmm::mult { using namespace o2; -// clang-format off +// helper function to determine if collision/mccollison type contains centrality template -concept hasSimCent = (T*) //NOLINT +static constexpr bool hasSimCent() { - requires {T::template contains();} -}; + if constexpr (!soa::is_soa_join_v) { + return false; + } else { + return T::template contains(); + } +} template -concept hasRecoCent = (T*) //NOLINT +static constexpr bool hasRecoCent() { - requires {T::template contains() || T::template contains();} -}; - -//clang-format on + if constexpr (!soa::is_soa_join_v) { + return false; + } else { + return T::template contains() || T::template contains(); + } +} } // namespace pwgmm::mult #endif // PWGMM_MULT_CORE_INCLUDE_FUNCTIONS_H_ diff --git a/PWGMM/Mult/DataModel/ReducedTables.h b/PWGMM/Mult/DataModel/ReducedTables.h index 1a3a3759ffb..1325d52d87a 100644 --- a/PWGMM/Mult/DataModel/ReducedTables.h +++ b/PWGMM/Mult/DataModel/ReducedTables.h @@ -255,7 +255,8 @@ DECLARE_SOA_TABLE(RFeatMins, "AOD", "RFEATMIN", features::ReconstructedVertexZ, features::TimeRes, features::ReconstructedForwardMultiplicityA, - features::ReconstructedForwardMultiplicityC); + features::ReconstructedForwardMultiplicityC, + rcol::MapEtaPhi); } // namespace o2::aod namespace o2::soa diff --git a/PWGMM/Mult/TableProducer/reducerPostprocess.cxx b/PWGMM/Mult/TableProducer/reducerPostprocess.cxx index b12d9f028e1..652144e63ec 100644 --- a/PWGMM/Mult/TableProducer/reducerPostprocess.cxx +++ b/PWGMM/Mult/TableProducer/reducerPostprocess.cxx @@ -26,9 +26,18 @@ struct ReducerPostprocess { void processFull(MCFull const&, soa::Join const& cols) { + std::vector spatialMap; + bool first = true; for (auto& col : cols) { auto mccol = col.rmccollision_as(); - features(mccol.multMCNParticlesEta10(), col.multNTracksPVeta1(), mccol.processId(), mccol.impactParameter(), col.posX(), col.posY(), col.posZ(), col.collisionTimeRes(), col.multFT0A(), col.multFT0C()); + if (first) { + spatialMap.resize(col.mapetaphi().size()); + first = false; + } + for (auto i = 0U; i < col.mapetaphi().size(); ++i) { + spatialMap[i] = col.mapetaphi()[i]; + } + features(mccol.multMCNParticlesEta10(), col.multNTracksPVeta1(), mccol.processId(), mccol.impactParameter(), col.posX(), col.posY(), col.posZ(), col.collisionTimeRes(), col.multFT0A(), col.multFT0C(), spatialMap); } } @@ -38,9 +47,18 @@ struct ReducerPostprocess { void processLite(MCLite const&, soa::Join const& cols) { + std::vector spatialMap; + bool first = true; for (auto& col : cols) { auto mccol = col.rmccollision_as(); - features(mccol.multMCNParticlesEta10(), col.multNTracksPVeta1(), -1, -1.f, col.posX(), col.posY(), col.posZ(), col.collisionTimeRes(), col.multFT0A(), col.multFT0C()); + if (first) { + spatialMap.resize(col.mapetaphi().size()); + first = false; + } + for (auto i = 0U; i < col.mapetaphi().size(); ++i) { + spatialMap[i] = col.mapetaphi()[i]; + } + features(mccol.multMCNParticlesEta10(), col.multNTracksPVeta1(), -1, -1.f, col.posX(), col.posY(), col.posZ(), col.collisionTimeRes(), col.multFT0A(), col.multFT0C(), spatialMap); } } diff --git a/PWGMM/Mult/Tasks/dndeta.cxx b/PWGMM/Mult/Tasks/dndeta.cxx index aa39877c1ee..9e6606e8c5d 100644 --- a/PWGMM/Mult/Tasks/dndeta.cxx +++ b/PWGMM/Mult/Tasks/dndeta.cxx @@ -343,7 +343,7 @@ struct MultiplicityCounter { } } for (auto& col : cols) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { float c = -1; if constexpr (C::template contains()) { c = col.centFT0C(); @@ -426,7 +426,7 @@ struct MultiplicityCounter { ++Ntrks; } if constexpr (fillHistos) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(EtaZvtx), track.eta(), z, c); binnedRegistry.fill(HIST(PhiEta), track.phi(), track.eta(), c); binnedRegistry.fill(HIST(PtEta), track.pt(), track.eta(), c); @@ -450,7 +450,7 @@ struct MultiplicityCounter { FiTracks const& tracks) { float c = -1; - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { if constexpr (C::template contains()) { c = collision.centFT0C(); } else if (C::template contains()) { @@ -462,7 +462,7 @@ struct MultiplicityCounter { } if (!useEvSel || isCollisionSelected(collision)) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(EventSelection), 2., c); } else { inclusiveRegistry.fill(HIST(EventSelection), static_cast(EvSelBins::kSelected)); @@ -474,7 +474,7 @@ struct MultiplicityCounter { auto INELgt0PV = groupPVContrib.size() > 0; auto Ntrks = countTracks(tracks, z, c); - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(NtrkZvtx), Ntrks, z, c); } else { if (Ntrks > 0 || INELgt0PV) { @@ -496,7 +496,7 @@ struct MultiplicityCounter { inclusiveRegistry.fill(HIST(NtrkZvtx), Ntrks, z); } } else { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(EventSelection), 3., c); } else { inclusiveRegistry.fill(HIST(EventSelection), static_cast(EvSelBins::kRejected)); @@ -527,7 +527,7 @@ struct MultiplicityCounter { ++Ntrks; } if (fillHistos) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(EtaZvtx), otrack.eta(), z, c); binnedRegistry.fill(HIST(PhiEta), otrack.phi(), otrack.eta(), c); binnedRegistry.fill(HIST(PtEta), otrack.pt(), otrack.eta(), c); @@ -544,7 +544,7 @@ struct MultiplicityCounter { if (otrack.has_collision() && otrack.collisionId() != track.bestCollisionId()) { usedTracksIdsDF.emplace_back(track.trackId()); if constexpr (fillHistos) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(ReassignedEtaZvtx), otrack.eta(), z, c); binnedRegistry.fill(HIST(ReassignedPhiEta), otrack.phi(), otrack.eta(), c); binnedRegistry.fill(HIST(ReassignedZvtxCorr), otrack.template collision_as().posZ(), z, c); @@ -560,7 +560,7 @@ struct MultiplicityCounter { } } else if (!otrack.has_collision()) { if constexpr (fillHistos) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(ExtraEtaZvtx), otrack.eta(), z, c); binnedRegistry.fill(HIST(ExtraPhiEta), otrack.phi(), otrack.eta(), c); binnedRegistry.fill(HIST(ExtraDCAXYPt), otrack.pt(), track.bestDCAXY(), c); @@ -586,7 +586,7 @@ struct MultiplicityCounter { ++Ntrks; } if constexpr (fillHistos) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(EtaZvtx), track.eta(), z, c); binnedRegistry.fill(HIST(PhiEta), track.phi(), track.eta(), c); binnedRegistry.fill(HIST(PtEta), track.pt(), track.eta(), c); @@ -611,7 +611,7 @@ struct MultiplicityCounter { soa::SmallGroups const& atracks) { float c = -1; - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { if constexpr (C::template contains()) { c = collision.centFT0C(); } else if (C::template contains()) { @@ -623,7 +623,7 @@ struct MultiplicityCounter { } if (!useEvSel || isCollisionSelected(collision)) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(EventSelection), 2., c); } else { inclusiveRegistry.fill(HIST(EventSelection), static_cast(EvSelBins::kSelected)); @@ -635,7 +635,7 @@ struct MultiplicityCounter { auto INELgt0PV = groupPVContrib.size() > 0; auto Ntrks = countTracksAmbiguous(tracks, atracks, z, c); - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(NtrkZvtx), Ntrks, z, c); } else { if (Ntrks > 0 || INELgt0PV) { @@ -671,7 +671,7 @@ struct MultiplicityCounter { inclusiveRegistry.fill(HIST(NtrkZvtx), Ntrks, z); } } else { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(EventSelection), 3., c); } else { inclusiveRegistry.fill(HIST(EventSelection), static_cast(EvSelBins::kRejected)); @@ -768,7 +768,7 @@ struct MultiplicityCounter { } float c_rec = -1; float c_gen = -1; - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { if constexpr (C::template contains()) { c_rec = collision.centFT0C(); } else if (C::template contains()) { @@ -776,9 +776,9 @@ struct MultiplicityCounter { } } auto mcCollision = collision.mcCollision(); - if constexpr (hasSimCent) { + if constexpr (hasSimCent()) { c_gen = mcCollision.centrality(); - } else if constexpr (hasRecoCent) { + } else if constexpr (hasRecoCent()) { c_gen = c_rec; } auto sample = particles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); @@ -787,7 +787,7 @@ struct MultiplicityCounter { if (!isChargedParticle(particle.pdgCode())) { continue; } - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtGenIdxNoEtaCut), particle.pt(), c_gen); if (std::abs(particle.eta()) < estimatorEta) { binnedRegistry.fill(HIST(PtGenIdx), particle.pt(), c_gen); @@ -824,7 +824,7 @@ struct MultiplicityCounter { auto relatedTracks = particle.template filtered_tracks_as(); for (auto const& track : relatedTracks) { ++counter; - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { if (!countedNoEtaCut) { binnedRegistry.fill(HIST(PtEfficiencyIdxNoEtaCut), particle.pt(), c_gen); countedNoEtaCut = true; @@ -878,7 +878,7 @@ struct MultiplicityCounter { } } } - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { for (auto const& track : relatedTracks) { for (auto layer = 0; layer < 7; ++layer) { if (track.itsClusterMap() & (uint8_t(1) << layer)) { @@ -976,7 +976,7 @@ struct MultiplicityCounter { } float c_rec = -1; float c_gen = -1; - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { if constexpr (C::template contains()) { c_rec = collision.centFT0C(); } else if (C::template contains()) { @@ -984,9 +984,9 @@ struct MultiplicityCounter { } } auto mcCollision = collision.mcCollision(); - if constexpr (hasSimCent) { + if constexpr (hasSimCent()) { c_gen = mcCollision.centrality(); - } else if constexpr (hasRecoCent) { + } else if constexpr (hasRecoCent()) { c_gen = c_rec; } @@ -1001,13 +1001,13 @@ struct MultiplicityCounter { } if (otrack.has_mcParticle()) { auto particle = otrack.mcParticle_as(); - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtEfficiencyNoEtaCut), particle.pt(), c_gen); } else { inclusiveRegistry.fill(HIST(PtEfficiencyNoEtaCut), particle.pt()); } if (std::abs(otrack.eta()) < estimatorEta) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtEfficiency), particle.pt(), c_gen); if (particle.pdgCode() == speciesIds[0]) { binnedRegistry.fill(HIST(prefix) + HIST(species[0]) + HIST(PtEffSuff), particle.pt(), c_gen); @@ -1032,7 +1032,7 @@ struct MultiplicityCounter { } } } else { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtEfficiencyFakes), otrack.pt(), c_gen); } else { inclusiveRegistry.fill(HIST(PtEfficiencyFakes), otrack.pt()); @@ -1048,13 +1048,13 @@ struct MultiplicityCounter { } if (track.has_mcParticle()) { auto particle = track.template mcParticle_as(); - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtEfficiencyNoEtaCut), particle.pt(), c_gen); } else { inclusiveRegistry.fill(HIST(PtEfficiencyNoEtaCut), particle.pt()); } if (std::abs(track.eta()) < estimatorEta) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtEfficiency), particle.pt(), c_gen); if (particle.pdgCode() == speciesIds[0]) { binnedRegistry.fill(HIST(prefix) + HIST(species[0]) + HIST(PtEffSuff), particle.pt(), c_gen); @@ -1079,7 +1079,7 @@ struct MultiplicityCounter { } } } else { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtEfficiencyFakes), track.pt(), c_gen); } else { inclusiveRegistry.fill(HIST(PtEfficiencyFakes), track.pt()); @@ -1091,7 +1091,7 @@ struct MultiplicityCounter { if (!isChargedParticle(particle.pdgCode())) { continue; } - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtGenNoEtaCut), particle.pt(), c_gen); if (std::abs(particle.eta()) < estimatorEta) { binnedRegistry.fill(HIST(PtGen), particle.pt(), c_gen); @@ -1137,7 +1137,7 @@ struct MultiplicityCounter { } float c_rec = -1; float c_gen = -1; - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { if constexpr (C::template contains()) { c_rec = collision.centFT0C(); } else if (C::template contains()) { @@ -1145,9 +1145,9 @@ struct MultiplicityCounter { } } auto mcCollision = collision.mcCollision(); - if constexpr (hasSimCent) { + if constexpr (hasSimCent()) { c_gen = mcCollision.centrality(); - } else if constexpr (hasRecoCent) { + } else if constexpr (hasRecoCent()) { c_gen = c_rec; } @@ -1157,7 +1157,7 @@ struct MultiplicityCounter { for (auto const& track : tracks) { if (track.has_mcParticle()) { auto particle = track.template mcParticle_as(); - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtEfficiencyNoEtaCut), particle.pt(), c_gen); if (std::abs(track.eta()) < estimatorEta) { binnedRegistry.fill(HIST(PtEfficiency), particle.pt(), c_gen); @@ -1187,7 +1187,7 @@ struct MultiplicityCounter { } } } else { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtEfficiencyFakes), track.pt(), c_gen); } else { inclusiveRegistry.fill(HIST(PtEfficiencyFakes), track.pt()); @@ -1199,7 +1199,7 @@ struct MultiplicityCounter { if (!isChargedParticle(particle.pdgCode())) { continue; } - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(PtGenNoEtaCut), particle.pt(), c_gen); if (std::abs(particle.eta()) < estimatorEta) { binnedRegistry.fill(HIST(PtGen), particle.pt(), c_gen); @@ -1402,7 +1402,7 @@ struct MultiplicityCounter { { float c_gen = -1; // add generated centrality estimation - if constexpr (hasSimCent) { + if constexpr (hasSimCent()) { c_gen = mcCollision.centrality(); } @@ -1423,7 +1423,7 @@ struct MultiplicityCounter { for (auto& collision : collisions) { usedTracksIds.clear(); float c_rec = -1; - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { if constexpr (C::template contains()) { c_rec = collision.centFT0C(); } else if (C::template contains()) { @@ -1437,7 +1437,7 @@ struct MultiplicityCounter { if (!useEvSel || isCollisionSelected(collision)) { auto z = collision.posZ(); ++moreThanOne; - if constexpr (hasRecoCent && !hasSimCent) { + if constexpr (hasRecoCent() && !hasSimCent()) { if (!atLeastOne) { c_gen = c_rec; // if there is no generator centrality info, fall back to reco (from the first reco collision) } @@ -1446,7 +1446,7 @@ struct MultiplicityCounter { auto groupPVcontrib = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); if (groupPVcontrib.size() > 0) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelectedPVgt0), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelectedPVgt0)); @@ -1461,14 +1461,14 @@ struct MultiplicityCounter { NPVPerCol.emplace_back(collision.numContrib()); fillFIT(collision, NFT0APerCol, NFT0CPerCol, NFDDAPerCol, NFDDCPerCol); - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelected), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelected)); } if (Nrec > 0) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelectedgt0), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelectedgt0)); @@ -1476,7 +1476,7 @@ struct MultiplicityCounter { atLeastOne_gt0 = true; } - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(NtrkZvtxGen), Nrec, collision.posZ(), c_rec); } else { inclusiveRegistry.fill(HIST(NtrkZvtxGen), Nrec, collision.posZ()); @@ -1485,7 +1485,7 @@ struct MultiplicityCounter { } auto nCharged = countParticles(particles); - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(NtrkZvtxGen_t), nCharged, mcCollision.posZ(), c_gen); binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kGen), c_gen); } else { @@ -1506,7 +1506,7 @@ struct MultiplicityCounter { } if (nCharged > 0) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kGengt0), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kGengt0)); @@ -1515,7 +1515,7 @@ struct MultiplicityCounter { if (fillResponse) { for (auto i = 0U; i < NrecPerCol.size(); ++i) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(EfficiencyMult), nCharged, mcCollision.posZ(), c_recPerCol[i]); if (addFT0 && !addFDD) { binnedRegistry.fill(HIST(Response), NrecPerCol[i], NPVPerCol[i], nCharged, NFT0APerCol[i], NFT0CPerCol[i], mcCollision.posZ(), c_recPerCol[i]); @@ -1552,7 +1552,7 @@ struct MultiplicityCounter { } } if (moreThanOne > 1) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(SplitMult), nCharged, mcCollision.posZ(), c_gen); } else { inclusiveRegistry.fill(HIST(SplitMult), nCharged, mcCollision.posZ()); @@ -1561,7 +1561,7 @@ struct MultiplicityCounter { } if (collisions.size() == 0) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(NotFoundZvtx), mcCollision.posZ(), c_gen); } else { inclusiveRegistry.fill(HIST(NotFoundZvtx), mcCollision.posZ()); @@ -1569,7 +1569,7 @@ struct MultiplicityCounter { } auto zmc = mcCollision.posZ(); - fillParticleHistos>(particles, zmc, nCharged, c_gen, atLeastOne, atLeastOne_gt0, atLeastOne_PVgt0); + fillParticleHistos()>(particles, zmc, nCharged, c_gen, atLeastOne, atLeastOne_gt0, atLeastOne_PVgt0); } template @@ -1580,7 +1580,7 @@ struct MultiplicityCounter { { float c_gen = -1; // add generated centrality estimation - if constexpr (hasSimCent) { + if constexpr (hasSimCent()) { c_gen = mcCollision.centrality(); } @@ -1601,7 +1601,7 @@ struct MultiplicityCounter { for (auto& collision : collisions) { usedTracksIds.clear(); float c_rec = -1; - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { if constexpr (C::template contains()) { c_rec = collision.centFT0C(); } else if (C::template contains()) { @@ -1615,7 +1615,7 @@ struct MultiplicityCounter { if (!useEvSel || isCollisionSelected(collision)) { auto z = collision.posZ(); ++moreThanOne; - if constexpr (hasRecoCent && !hasSimCent) { + if constexpr (hasRecoCent() && !hasSimCent()) { if (!atLeastOne) { c_gen = c_rec; // if there is no generator centrality info, fall back to reco (from the first reco collision) } @@ -1624,7 +1624,7 @@ struct MultiplicityCounter { auto groupPVcontrib = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); if (groupPVcontrib.size() > 0) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelectedPVgt0), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelectedPVgt0)); @@ -1638,14 +1638,14 @@ struct MultiplicityCounter { NPVPerCol.emplace_back(collision.numContrib()); fillFIT(collision, NFT0APerCol, NFT0CPerCol, NFDDAPerCol, NFDDCPerCol); - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelected), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelected)); } if (Nrec > 0) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelectedgt0), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kSelectedgt0)); @@ -1653,7 +1653,7 @@ struct MultiplicityCounter { atLeastOne_gt0 = true; } - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(NtrkZvtxGen), Nrec, collision.posZ(), c_rec); } else { inclusiveRegistry.fill(HIST(NtrkZvtxGen), Nrec, collision.posZ()); @@ -1662,7 +1662,7 @@ struct MultiplicityCounter { } auto nCharged = countParticles(particles); - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(NtrkZvtxGen_t), nCharged, mcCollision.posZ(), c_gen); binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kGen), c_gen); } else { @@ -1683,7 +1683,7 @@ struct MultiplicityCounter { } if (nCharged > 0) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kGengt0), c_gen); } else { inclusiveRegistry.fill(HIST(Efficiency), static_cast(EvEffBins::kGengt0)); @@ -1692,7 +1692,7 @@ struct MultiplicityCounter { if (fillResponse) { for (auto i = 0U; i < NrecPerCol.size(); ++i) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(EfficiencyMult), nCharged, mcCollision.posZ(), c_recPerCol[i]); if (addFT0 && !addFDD) { binnedRegistry.fill(HIST(Response), NrecPerCol[i], NPVPerCol[i], nCharged, NFT0APerCol[i], NFT0CPerCol[i], mcCollision.posZ(), c_recPerCol[i]); @@ -1729,7 +1729,7 @@ struct MultiplicityCounter { } } if (moreThanOne > 1) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(SplitMult), nCharged, mcCollision.posZ(), c_gen); } else { inclusiveRegistry.fill(HIST(SplitMult), nCharged, mcCollision.posZ()); @@ -1738,14 +1738,14 @@ struct MultiplicityCounter { } if (collisions.size() == 0) { - if constexpr (hasRecoCent) { + if constexpr (hasRecoCent()) { binnedRegistry.fill(HIST(NotFoundZvtx), mcCollision.posZ(), c_gen); } else { inclusiveRegistry.fill(HIST(NotFoundZvtx), mcCollision.posZ()); } } auto zmc = mcCollision.posZ(); - fillParticleHistos>(particles, zmc, nCharged, c_gen, atLeastOne, atLeastOne_gt0, atLeastOne_PVgt0); + fillParticleHistos()>(particles, zmc, nCharged, c_gen, atLeastOne, atLeastOne_gt0, atLeastOne_PVgt0); } using MC = aod::McCollisions; // soa::Join; diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index 4733b65e0c0..e38b6b9b7c0 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -88,3 +88,8 @@ o2physics_add_dpl_workflow(polarisation-rho SOURCES PolarisationRho.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(exclusive-phi + SOURCES ExclusivePhi.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) diff --git a/PWGUD/Tasks/ExclusivePhi.cxx b/PWGUD/Tasks/ExclusivePhi.cxx new file mode 100644 index 00000000000..b6fb8c6099e --- /dev/null +++ b/PWGUD/Tasks/ExclusivePhi.cxx @@ -0,0 +1,588 @@ +// 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 "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "iostream" +#include "PWGUD/DataModel/UDTables.h" +#include +#include "TLorentzVector.h" +#include "Common/DataModel/PIDResponse.h" +#include "PWGUD/Core/SGSelector.h" +using std::array; +using namespace std; +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +#define mpion 0.1396 // mass of pion +#define mkaon 0.493696 // mass of kaon +// #define mmuon 0.1057 // mass of muon + +/// \brief Exclusive phi without PID +/// \author Simone Ragoni, Creighton +/// \author Anisa Khatun, Kansas University +/// \date 14/2/2024 + +struct ExclusivePhi { + SGSelector sgSelector; + Configurable FV0_cut{"FV0", 100., "FV0A threshold"}; + Configurable ZDC_cut{"ZDC", 10., "ZDC threshold"}; + // defining histograms using histogram registry + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + //_____________________________________________________________________________ + Double_t CosThetaHelicityFrame(TLorentzVector pionPositive, + TLorentzVector pionNegative, + TLorentzVector possibleRhoZero) + { + + Double_t HalfSqrtSnn = 2680.; + Double_t MassOfLead208 = 193.6823; + Double_t MomentumBeam = TMath::Sqrt(HalfSqrtSnn * HalfSqrtSnn * 208 * 208 - MassOfLead208 * MassOfLead208); + + TLorentzVector pProjCM(0., 0., -MomentumBeam, HalfSqrtSnn * 208); // projectile + TLorentzVector pTargCM(0., 0., MomentumBeam, HalfSqrtSnn * 208); // target + + TVector3 beta = (-1. / possibleRhoZero.E()) * possibleRhoZero.Vect(); + TLorentzVector pPi1Dipion = pionPositive; + TLorentzVector pPi2Dipion = pionNegative; + TLorentzVector pProjDipion = pProjCM; + TLorentzVector pTargDipion = pTargCM; + + pPi1Dipion.Boost(beta); + pPi2Dipion.Boost(beta); + pProjDipion.Boost(beta); + pTargDipion.Boost(beta); + + TVector3 zaxis = (possibleRhoZero.Vect()).Unit(); + + Double_t CosThetaHE = zaxis.Dot((pPi1Dipion.Vect()).Unit()); + return CosThetaHE; + } + //------------------------------------------------------------------------------------------------------ + Double_t PhiHelicityFrame(TLorentzVector muonPositive, TLorentzVector muonNegative, TLorentzVector possibleJPsi) + { + + // Half of the energy per pair of the colliding nucleons. + Double_t HalfSqrtSnn = 2680.; + Double_t MassOfLead208 = 193.6823; + Double_t MomentumBeam = TMath::Sqrt(HalfSqrtSnn * HalfSqrtSnn * 208 * 208 - MassOfLead208 * MassOfLead208); + + TLorentzVector pProjCM(0., 0., -MomentumBeam, HalfSqrtSnn * 208); // projectile + TLorentzVector pTargCM(0., 0., MomentumBeam, HalfSqrtSnn * 208); // target + + // Translate the dimuon parameters in the dimuon rest frame + TVector3 beta = (-1. / possibleJPsi.E()) * possibleJPsi.Vect(); + TLorentzVector pMu1Dimu = muonPositive; + TLorentzVector pMu2Dimu = muonNegative; + TLorentzVector pProjDimu = pProjCM; + TLorentzVector pTargDimu = pTargCM; + pMu1Dimu.Boost(beta); + pMu2Dimu.Boost(beta); + pProjDimu.Boost(beta); + pTargDimu.Boost(beta); + + // Axes + TVector3 zaxis = (possibleJPsi.Vect()).Unit(); + TVector3 yaxis = ((pProjDimu.Vect()).Cross(pTargDimu.Vect())).Unit(); + TVector3 xaxis = (yaxis.Cross(zaxis)).Unit(); + // + // --- Calculation of the azimuthal angle (Helicity) + // + Double_t phi = TMath::ATan2((pMu1Dimu.Vect()).Dot(yaxis), (pMu1Dimu.Vect()).Dot(xaxis)); + return phi; + } + //----------------------------------------------------------------------------------------------------------------------- + void init(o2::framework::InitContext&) + { + registry.add("GapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + registry.add("TrueGapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + + registry.add("hTracks", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hITSCluster", "N_{cluster}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hChi2ITSTrkSegment", "N_{cluster}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hTPCCluster", "N_{cluster}", kTH1F, {{200, -0.5, 199.5}}); + registry.add("hTracksKaons", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hdEdx", "p vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon2", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hdEdxKaon3", "p_{#ka} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + registry.add("hNsigEvsKa1", "NSigmaKa(t1) vs NSigmaKa (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}}); + registry.add("hNsigEvsKa2", "NSigmaKa(t1) vs NSigmaKa (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}}); + registry.add("hMomentum", "p_{#ka};#it{p_{trk}}, GeV/c;", kTH1F, {{100, 0., 3.}}); + registry.add("hEta1", "#eta_{#ka};#it{#eta_{trk}}, GeV/c;", kTH1F, {{100, -2., 2.}}); + registry.add("hEta2", "#eta_{#ka};#it{#eta_{trk}}, GeV/c;", kTH1F, {{100, -2., 2.}}); + registry.add("hPtPhi", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{500, 0., 5.}}); + registry.add("hMassPhi", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("hMassPtPhi", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};Pt;#it{p_{t}}, GeV/c;", kTH2F, {{400, 0., 4.}, {400, 0., 4.}}); + + auto hSelectionCounter = registry.add("hSelectionCounter", "hSelectionCounter;;NEvents", HistType::kTH1I, {{10, 0., 10.}}); + + TString SelectionCuts[9] = {"NoSelection", "GAPcondition", "PVtracks", "TPCcrossrow", "|nsigmaka|<2", "doublegap", "two tracks", "Phi-peak", "pt<0.2 GeV/c"}; + // now we can set BinLabel in histogram Registry + + for (int i = 0; i < 9; i++) { + hSelectionCounter->GetXaxis()->SetBinLabel(i + 1, SelectionCuts[i].Data()); + } + + registry.add("hMassPhiWithoutPID", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("hMassPtPhiWithoutPID", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};Pt;#it{p_{t}}, GeV/c;", kTH2F, {{400, 0., 4.}, {400, 0., 4.}}); + registry.add("hMassPhiWrongMomentumWithoutPID", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1D, {{400, 0., 4.}}); + + // Phi peak region + registry.add("PHI/hPtPhiWithoutPID", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{500, 0., 5.}}); + registry.add("PHI/hMassVsPt", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};Pt;#it{p_{t}}, GeV/c;", kTH2F, {{400, 0., 4.}, {400, 0., 4.}}); + registry.add("PHI/hRapidityPhiWithoutPID", "Rapidity;#it{y_{KK}};", kTH1F, {{100, -2., 2.}}); + registry.add("PHI/hCosThetaPhiWithoutPID", "CosTheta;cos(#theta);", kTH1F, {{100, -2., 2.}}); + registry.add("PHI/hPhiPhiWithoutPID", "Phi;#varphi;", kTH1F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("PHI/hPtKaonVsKaon", "Pt1 vs Pt2;p_{T};p_{T};", kTH2F, {{100, 0., 3.}, {100, 0., 3.}}); + registry.add("PHI/hCostheta_Phi", "Phi vs Costheta;#it{#phi};#it{Cos#Theta};", kTH2F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}, {100, -2, 2}}); + registry.add("PHI/hMassPhiWithoutPIDPionHypothesis", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1D, {{400, 0., 4.}}); + registry.add("PHI/hPtPhiWithoutPIDPionHypothesis", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{500, 0., 5.}}); + + registry.add("PHI/hMassLike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hMassUnlike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hlikePt", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{500, 0., 5.}}); + registry.add("PHI/hUnlikePt", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{500, 0., 5.}}); + registry.add("PHI/hCoherentPhiWithoutPID", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hInCoherentPhiWithoutPID", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hCoherentMassLike", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHI/hInCoherentMassLike", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + + // High Mass region + registry.add("PHIHIGH/hPtPhiWithoutPID1", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{500, 0., 5.}}); + registry.add("PHIHIGH/hMassVsPt1", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};Pt;#it{p_{t}}, GeV/c;", kTH2F, {{400, 0., 4.}, {400, 0., 4.}}); + registry.add("PHIHIGH/hRapidityPhiWithoutPID1", "Rapidity;#it{y_{KK}};", kTH1F, {{100, -2., 2.}}); + registry.add("PHIHIGH/hCosThetaPhiWithoutPID1", "CosTheta;cos(#theta);", kTH1F, {{100, -2., 2.}}); + registry.add("PHIHIGH/hPhiPhiWithoutPID1", "Phi;#varphi;", kTH1F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("PHIHIGH/hPtKaonVsKaon1", "Pt1 vs Pt2;p_{T};p_{T};", kTH2F, {{100, 0., 3.}, {100, 0., 3.}}); + registry.add("PHIHIGH/hCostheta_Phi1", "Phi vs Costheta;#it{#phi};#it{Cos#Theta};", kTH2F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}, {100, -2, 2}}); + registry.add("PHIHIGH/hMassPhiWithoutPIDPionHypothesis1", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1D, {{400, 0., 4.}}); + registry.add("PHIHIGH/hPtPhiWithoutPIDPionHypothesis1", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{500, 0., 5.}}); + + registry.add("PHIHIGH/hMassLike1", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{400, 0., 4.}}); + registry.add("PHIHIGH/hMassUnlike1", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{400, 0., 4.}}); + registry.add("PHIHIGH/hlikePt1", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{400, 0., 4.}}); + registry.add("PHIHIGH/hUnlikePt1", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{400, 0., 4.}}); + registry.add("PHIHIGH/hCoherentPhiWithoutPID1", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHIHIGH/hInCoherentPhiWithoutPID1", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHIHIGH/hCoherentMassLike1", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHIHIGH/hInCoherentMassLike1", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + + // Low Mass region + + registry.add("PHILOW/hPtPhiWithoutPID2", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{500, 0., 5.}}); + registry.add("PHILOW/hMassVsPt2", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};Pt;#it{p_{t}}, GeV/c;", kTH2F, {{400, 0., 4.}, {400, 0., 4.}}); + registry.add("PHILOW/hRapidityPhiWithoutPID2", "Rapidity;#it{y_{KK}};", kTH1F, {{100, -2., 2.}}); + registry.add("PHILOW/hCosThetaPhiWithoutPID2", "CosTheta;cos(#theta);", kTH1F, {{100, -2., 2.}}); + registry.add("PHILOW/hPhiPhiWithoutPID2", "Phi;#varphi;", kTH1F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("PHILOW/hPtKaonVsKaon2", "Pt1 vs Pt2;p_{T};p_{T};", kTH2F, {{100, 0., 3.}, {100, 0., 3.}}); + registry.add("PHILOW/hCostheta_Phi2", "Phi vs Costheta;#it{#phi};#it{Cos#Theta};", kTH2F, {{100, 0. * TMath::Pi(), 2. * TMath::Pi()}, {100, -2, 2}}); + registry.add("PHILOW/hMassPhiWithoutPIDPionHypothesis2", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1D, {{400, 0., 4.}}); + registry.add("PHILOW/hPtPhiWithoutPIDPionHypothesis2", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{500, 0., 5.}}); + + registry.add("PHILOW/hMassLike2", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{400, 0., 4.}}); + registry.add("PHILOW/hMassUnlike2", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{400, 0., 4.}}); + registry.add("PHILOW/hlikePt2", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{400, 0., 4.}}); + registry.add("PHILOW/hUnlikePt2", "Pt;#it{p_{t}}, GeV/c;", kTH1F, {{400, 0., 4.}}); + registry.add("PHILOW/hCoherentPhiWithoutPID2", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHILOW/hInCoherentPhiWithoutPID2", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHILOW/hCoherentMassLike2", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + registry.add("PHILOW/hInCoherentMassLike2", "Raw Inv.M;#it{m_{KK}}, GeV/c^{2};", kTH1F, {{400, 0., 4.}}); + } + + using udtracks = soa::Join; + using udtracksfull = soa::Join; + using UDCollisionsFull = soa::Join; + //__________________________________________________________________________ + // Main process + void process(UDCollisions::iterator const& collision, udtracksfull const& tracks) + // void process(UDCollisionsFull::iterator const& collision, udtracksfull const& tracks) + { + registry.fill(HIST("hSelectionCounter"), 0); + + /*int gapSide = collision.gapSide(); + if (gapSide < 0 || gapSide > 2) + return;*/ + // if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)){ + // if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + registry.fill(HIST("hSelectionCounter"), 1); + + /* int truegapSide = sgSelector.trueGap(collision, FV0_cut, ZDC_cut); + registry.fill(HIST("GapSide"), gapSide); + registry.fill(HIST("TrueGapSide"), truegapSide); + gapSide = truegapSide;*/ + + TLorentzVector phi, phiWithoutPID, phiWithKaonPID, phiWrongMomentaWithoutPID, phiWithoutPIDPionHypothesis; // lorentz vectors of tracks and the mother + + // =================================== + // Task for phi WITH PID FROM TPC + // =================================== + // Here the tracks are allowed to have + // at most 30 TPC clusters + // TPC PID is then possible, although + // not truly reliable + // NB: from MC simulations coherent + // phi SHOULD NOT leave clusters + // in the TPC at all + std::vector onlyKaonTracks; + std::vector onlyKaonSigma; + std::vector rawKaonTracks; + + for (auto trk : tracks) { + if (!trk.isPVContributor()) { + continue; + } + registry.fill(HIST("hSelectionCounter"), 2); + + int NFindable = trk.tpcNClsFindable(); + int NMinusFound = trk.tpcNClsFindableMinusFound(); + int NCluster = NFindable - NMinusFound; + registry.fill(HIST("hTPCCluster"), NCluster); + registry.fill(HIST("hITSCluster"), trk.itsNCls()); + registry.fill(HIST("hChi2ITSTrkSegment"), trk.itsChi2NCl()); + + registry.fill(HIST("hSelectionCounter"), 3); + + double momentum = TMath::Sqrt(trk.px() * trk.px() + trk.py() * trk.py() + trk.pz() * trk.pz()); + double dEdx = trk.tpcSignal(); + registry.fill(HIST("hdEdx"), momentum, dEdx); + + /* if(trk.pt() > 0.180){ + continue; + }*/ + + TLorentzVector kaon; + kaon.SetXYZM(trk.px(), trk.py(), trk.pz(), o2::constants::physics::MassKaonCharged); + auto nSigmaKa = trk.tpcNSigmaKa(); + + if (fabs(nSigmaKa) < 2.) { + onlyKaonTracks.push_back(kaon); + onlyKaonSigma.push_back(nSigmaKa); + rawKaonTracks.push_back(trk); + registry.fill(HIST("hdEdxKaon"), momentum, dEdx); + registry.fill(HIST("hSelectionCounter"), 4); + } + + } // trk loop + + // registry.fill(HIST("hTracksKaons"), rawKaonTracks.size()); + + // Creating phis using Kaon PID + // if (gapSide == 2) { + registry.fill(HIST("hSelectionCounter"), 5); + if (onlyKaonTracks.size() == 2) { + registry.fill(HIST("hSelectionCounter"), 6); + + for (auto kaon : onlyKaonTracks) { + phi += kaon; + } + + registry.fill(HIST("hNsigEvsKa1"), rawKaonTracks[0].tpcNSigmaKa(), rawKaonTracks[1].tpcNSigmaKa()); + registry.fill(HIST("hMassPtPhi"), phi.M(), phi.Pt()); + // if(rawKaonTracks[0].sign() != rawKaonTracks[1].sign()){ + if ((phi.M() > 0.98) && (phi.M() < 1.06)) { + registry.fill(HIST("hSelectionCounter"), 7); + registry.fill(HIST("hPtPhi"), phi.Pt()); + } + if (phi.Pt() < 0.2) { + registry.fill(HIST("hMassPhi"), phi.M()); + registry.fill(HIST("hSelectionCounter"), 8); + } + + // } + } + // } // double gap + + // =================================== + // Task for phi WITHOUT PID + // =================================== + + // ==================================== + // Selections for events to be stored + // ------------------------------------ + // - PV: only PV contributors + // - only two PV contributors + // - both PV have t.hasITS() ON + // - only ITS tracks + //_____________________________________ + // Create kaons WITHOUT PID + std::vector onlyTwoTracks; + std::vector allTracksAreKaons; + std::vector allTracksArePions; + std::vector allTracksAreKaonsWrongMomentum; + + int counter = 0; + for (auto t : tracks) { + if (!t.isPVContributor()) { + continue; + } + + registry.fill(HIST("hTracks"), t.size()); + + /* if(t.itsNCls() < 4) { + continue; + }*/ + + double momentum = TMath::Sqrt(t.px() * t.px() + t.py() * t.py() + t.pz() * t.pz()); + double dEdx = t.tpcSignal(); + + registry.fill(HIST("hMomentum"), momentum); + + /* if ((!t.hasITS()) && (t.hasTPC()) && (t.hasTOF())) { + continue; + } // not working*/ + + int NFindable = t.tpcNClsFindable(); + int NMinusFound = t.tpcNClsFindableMinusFound(); + int NCluster = NFindable - NMinusFound; + // registry.fill(HIST("hTPCCluster"), NCluster); + + if (NCluster > 50) { + continue; + } + + registry.fill(HIST("hdEdxKaon2"), momentum, dEdx); + if (t.pt() > 0.180) { + continue; + } + + registry.fill(HIST("hdEdxKaon3"), momentum, dEdx); + + onlyTwoTracks.push_back(t); + + TLorentzVector a; + a.SetXYZM(t.px(), t.py(), t.pz(), o2::constants::physics::MassKaonCharged); + TLorentzVector b; + b.SetXYZM(t.px(), t.py(), t.pz(), o2::constants::physics::MassPionCharged); + TLorentzVector a2; + a2.SetXYZM(-1. * t.px(), -1. * t.py(), -1. * t.pz(), o2::constants::physics::MassKaonCharged); + + if (-0.6 > a.Eta() || a.Eta() > 0.6) + continue; + + allTracksAreKaons.push_back(a); + allTracksArePions.push_back(b); + + if (counter < 1) { + allTracksAreKaonsWrongMomentum.push_back(a); + } else { + allTracksAreKaonsWrongMomentum.push_back(a2); + } + counter += 1; + } // track loop + + //_____________________________________ + // Creating phis and saving all the information + // in the case that there are ONLY 2 PV + /* int hasITS[2] = {-1, -1}; + int hasTPC[2] = {-1, -1}; + int hasTOF[2] = {-1, -1}; + bool goodFirstTrack = false; + bool goodSecondTrack = false; + bool goodEvent = false; + if (onlyTwoTracks.size() == 2) { + hasITS[0] = onlyTwoTracks[0].hasITS(); + hasTPC[0] = onlyTwoTracks[0].hasTPC(); + hasTOF[0] = onlyTwoTracks[0].hasTOF(); + hasITS[1] = onlyTwoTracks[1].hasITS(); + hasTPC[1] = onlyTwoTracks[1].hasTPC(); + hasTOF[1] = onlyTwoTracks[1].hasTOF(); + if ((hasITS[0]) && (hasTPC[0]) && (!hasTOF[0])) { + goodFirstTrack = true; + } + + if ((hasITS[1]) && (hasTPC[1]) && (!hasTOF[1])) { + goodSecondTrack = true; + } + + if (goodFirstTrack || goodSecondTrack) { + goodEvent = true; + } + + }*/ + + // if (gapSide == 2) { + if (allTracksAreKaons.size() == 2) { + + for (auto kaon : allTracksAreKaons) { + phiWithoutPID += kaon; + } + registry.fill(HIST("hTracksKaons"), allTracksAreKaons.size()); + // kaon mass hypothesis with wrong momentum for one track + for (auto kaon : allTracksAreKaonsWrongMomentum) { + phiWrongMomentaWithoutPID += kaon; + } + // pion mass hypothesis + for (auto pion : allTracksArePions) { + phiWithoutPIDPionHypothesis += pion; + } + + // TLorentzVector kaons[2], kaonsLikeSign[2], phiLikeSignWithoutPID; + registry.fill(HIST("hNsigEvsKa2"), onlyTwoTracks[0].tpcNSigmaKa(), onlyTwoTracks[1].tpcNSigmaKa()); + registry.fill(HIST("hEta1"), allTracksAreKaons[0].Eta()); + registry.fill(HIST("hEta2"), allTracksAreKaons[1].Eta()); + + /* if (-0.6 > allTracksAreKaons[0].Eta() || allTracksAreKaons[0].Eta() > 0.6) + return; + if (-0.6 > allTracksAreKaons[1].Eta() || allTracksAreKaons[1].Eta() > 0.6) + return;*/ + + // kaons[0].SetXYZM(onlyTwoTracks[0].px(), onlyTwoTracks[0].py(), onlyTwoTracks[0].pz(), o2::constants::physics::MassKaonCharged); + // kaons[1].SetXYZM(onlyTwoTracks[1].px(), onlyTwoTracks[1].py(), onlyTwoTracks[1].pz(), o2::constants::physics::MassKaonCharged); + + // phiWithoutPID += kaons[0]; + // phiWithoutPID += kaons[1]; + /*phiLikeSignWithoutPID += kaonsLikeSign[0]; + phiLikeSignWithoutPID += kaonsLikeSign[1];*/ + + auto costhetaPhi = CosThetaHelicityFrame(allTracksAreKaons[0], allTracksAreKaons[1], phiWithoutPID); + auto phiPhi = 1. * TMath::Pi() + PhiHelicityFrame(allTracksAreKaons[0], allTracksAreKaons[1], phiWithoutPID); + + // All invariant mass region + registry.fill(HIST("hMassPhiWithoutPID"), phiWithoutPID.M()); + registry.fill(HIST("hMassPtPhiWithoutPID"), phiWithoutPID.M(), phiWithoutPID.Pt()); + registry.fill(HIST("hMassPhiWrongMomentumWithoutPID"), phiWrongMomentaWithoutPID.M()); + + // Phi peak region + // if ((phiWithoutPID.Rapidity()>-0.6)&&(phiWithoutPID.Rapidity()<0.6)){ + // if ((phiWithoutPID.M() > 0.98) && (phiWithoutPID.M() < 1.06)) { + registry.fill(HIST("PHI/hPtPhiWithoutPID"), phiWithoutPID.Pt()); + registry.fill(HIST("PHI/hMassVsPt"), phiWithoutPID.M(), phiWithoutPID.Pt()); + registry.fill(HIST("PHI/hRapidityPhiWithoutPID"), phiWithoutPID.Rapidity()); + registry.fill(HIST("PHI/hPtKaonVsKaon"), allTracksAreKaons[0].Pt(), allTracksAreKaons[1].Pt()); + + registry.fill(HIST("PHI/hPtPhiWithoutPIDPionHypothesis"), phiWithoutPIDPionHypothesis.Pt()); + registry.fill(HIST("PHI/hMassPhiWithoutPIDPionHypothesis"), phiWithoutPIDPionHypothesis.M()); + + // unlike-sign + if (onlyTwoTracks[0].sign() != onlyTwoTracks[1].sign()) { + registry.fill(HIST("PHI/hCosThetaPhiWithoutPID"), costhetaPhi); + registry.fill(HIST("PHI/hPhiPhiWithoutPID"), phiPhi); + registry.fill(HIST("PHI/hCostheta_Phi"), phiPhi, costhetaPhi); + registry.fill(HIST("PHI/hUnlikePt"), phiWithoutPID.Pt()); + registry.fill(HIST("PHI/hMassUnlike"), phiWithoutPID.M()); + if (phiWithoutPID.Pt() < 0.2) { + registry.fill(HIST("PHI/hCoherentPhiWithoutPID"), phiWithoutPID.M()); + } + if (phiWithoutPID.Pt() > 0.2) { + registry.fill(HIST("PHI/hInCoherentPhiWithoutPID"), phiWithoutPID.M()); + } + } + //}//Rapidity + // Likesign quantities + if (onlyTwoTracks[0].sign() == onlyTwoTracks[1].sign()) { + registry.fill(HIST("PHI/hMassLike"), phiWithoutPID.M()); + registry.fill(HIST("PHI/hlikePt"), phiWithoutPID.Pt()); + + if (phiWithoutPID.Pt() < 0.2) { + registry.fill(HIST("PHI/hCoherentMassLike"), phiWithoutPID.M()); + } + if (phiWithoutPID.Pt() > 0.2) { + registry.fill(HIST("PHI/hInCoherentMassLike"), phiWithoutPID.M()); + } + } + + // Side band above phi mass region + if (phiWithoutPID.M() > 1.06) { + + registry.fill(HIST("PHIHIGH/hPtPhiWithoutPID1"), phiWithoutPID.Pt()); + registry.fill(HIST("PHIHIGH/hMassVsPt1"), phiWithoutPID.M(), phiWithoutPID.Pt()); + registry.fill(HIST("PHIHIGH/hRapidityPhiWithoutPID1"), phiWithoutPID.Rapidity()); + + registry.fill(HIST("PHIHIGH/hPtKaonVsKaon1"), allTracksAreKaons[0].Pt(), allTracksAreKaons[1].Pt()); + registry.fill(HIST("PHIHIGH/hPtPhiWithoutPIDPionHypothesis1"), phiWithoutPIDPionHypothesis.Pt()); + registry.fill(HIST("PHIHIGH/hMassPhiWithoutPIDPionHypothesis1"), phiWithoutPIDPionHypothesis.M()); + + // unlike-sign + if (onlyTwoTracks[0].sign() != onlyTwoTracks[1].sign()) { + registry.fill(HIST("PHIHIGH/hCosThetaPhiWithoutPID1"), costhetaPhi); + registry.fill(HIST("PHIHIGH/hPhiPhiWithoutPID1"), phiPhi); + registry.fill(HIST("PHIHIGH/hCostheta_Phi1"), phiPhi, costhetaPhi); + + registry.fill(HIST("PHIHIGH/hUnlikePt1"), phiWithoutPID.Pt()); + registry.fill(HIST("PHIHIGH/hMassUnlike1"), phiWithoutPID.M()); + if (phiWithoutPID.Pt() < 0.2) { + registry.fill(HIST("PHIHIGH/hCoherentPhiWithoutPID1"), phiWithoutPID.M()); + } + if (phiWithoutPID.Pt() > 0.2) { + registry.fill(HIST("PHIHIGH/hInCoherentPhiWithoutPID1"), phiWithoutPID.M()); + } + } + + // Like sign + if (onlyTwoTracks[0].sign() == onlyTwoTracks[1].sign()) { + // Likesign quantities + registry.fill(HIST("PHIHIGH/hMassLike1"), phiWithoutPID.M()); + registry.fill(HIST("PHIHIGH/hlikePt1"), phiWithoutPID.Pt()); + + if (phiWithoutPID.Pt() < 0.2) { + registry.fill(HIST("PHIHIGH/hCoherentMassLike1"), phiWithoutPID.M()); + } + if (phiWithoutPID.Pt() > 0.2) { + registry.fill(HIST("PHIHIGH/hInCoherentMassLike1"), phiWithoutPID.M()); + } + } + } + + // Side band below phi mass region + if (phiWithoutPID.M() < 0.98) { + + registry.fill(HIST("PHILOW/hPtPhiWithoutPID2"), phiWithoutPID.Pt()); + registry.fill(HIST("PHILOW/hMassVsPt2"), phiWithoutPID.M(), phiWithoutPID.Pt()); + registry.fill(HIST("PHILOW/hRapidityPhiWithoutPID2"), phiWithoutPID.Rapidity()); + + registry.fill(HIST("PHILOW/hPtKaonVsKaon2"), allTracksAreKaons[0].Pt(), allTracksAreKaons[1].Pt()); + + registry.fill(HIST("PHILOW/hPtPhiWithoutPIDPionHypothesis2"), phiWithoutPIDPionHypothesis.Pt()); + registry.fill(HIST("PHILOW/hMassPhiWithoutPIDPionHypothesis2"), phiWithoutPIDPionHypothesis.M()); + + // unlike-sign + registry.fill(HIST("PHILOW/hCosThetaPhiWithoutPID2"), costhetaPhi); + registry.fill(HIST("PHILOW/hPhiPhiWithoutPID2"), phiPhi); + registry.fill(HIST("PHILOW/hCostheta_Phi2"), phiPhi, costhetaPhi); + registry.fill(HIST("PHILOW/hUnlikePt2"), phiWithoutPID.Pt()); + registry.fill(HIST("PHILOW/hMassUnlike2"), phiWithoutPID.M()); + if (phiWithoutPID.Pt() < 0.2) { + registry.fill(HIST("PHILOW/hCoherentPhiWithoutPID2"), phiWithoutPID.M()); + } + if (phiWithoutPID.Pt() > 0.2) { + registry.fill(HIST("PHILOW/hInCoherentPhiWithoutPID2"), phiWithoutPID.M()); + } + // like-sign + if (onlyTwoTracks[0].sign() == onlyTwoTracks[1].sign()) { + // Likesign quantities + registry.fill(HIST("PHI/hMassLike2"), phiWithoutPID.M()); + registry.fill(HIST("PHI/hlikePt2"), phiWithoutPID.Pt()); + + if (phiWithoutPID.Pt() < 0.2) { + registry.fill(HIST("PHI/hCoherentMassLike2"), phiWithoutPID.M()); + } + + if (phiWithoutPID.Pt() > 0.2) { + registry.fill(HIST("PHI/hInCoherentMassLike2"), phiWithoutPID.M()); + } + } + } + } // end of two tracks only loop + + // } // double gap + // } + } // end of process + +}; // end of struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +}