diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index dd59bcb8ef2..938926a5688 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -124,8 +124,8 @@ o2physics_add_dpl_workflow(chargedkstaranalysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(lambda1520-pbpb - SOURCES lambda1520_PbPb.cxx +o2physics_add_dpl_workflow(lambda1520pbpb + SOURCES lambda1520pbpb.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx b/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx deleted file mode 100644 index 192b605b07f..00000000000 --- a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx +++ /dev/null @@ -1,1012 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file -/// /// Invariant Mass Reconstruction of Lambda(1520) Resonance. -/// -/// \author Yash Patley -/// \author Nasir Mehdi Malik - -#include "PWGLF/DataModel/LFResonanceTables.h" - -#include "Common/Core/RecoDecay.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::constants::physics; - -struct lambdaAnalysis_pb { - SliceCache cache; - Preslice perRCol = aod::resodaughter::resoCollisionId; - Preslice perCollision = aod::track::collisionId; - // Configurables. - aod::ResoMCParents const* mResoParents = nullptr; - Configurable ConfEvtOccupancyInTimeRange{"ConfEvtOccupancyInTimeRange", false, "occupancy selection true or false"}; - Configurable nBinsPt{"nBinsPt", 100, "N bins in pT histogram"}; - Configurable nBinsInvM{"nBinsInvM", 120, "N bins in InvMass histogram"}; - Configurable lambda1520id{"lambda1520id", 3124, "pdg"}; - Configurable doRotate{"doRotate", true, "rotated inv mass spectra"}; - // Tracks - Configurable cPtMin{"cPtMin", 0.15, "Minimum Track pT"}; - Configurable cPMin{"cPMin", 0., "Minimum Track p"}; - Configurable cEtaCut{"cEtaCut", 0.8, "Pseudorapidity cut"}; - Configurable cDcaz{"cDcazMin", 1., "Minimum DCAz"}; - Configurable cfgRapidityShift{"cfgRapidityShift", 0., " rapidity shift"}; - Configurable cfgRapidityCut{"cfgRapidityCut", 0.5, "Rapidity window"}; - // TPC crossed rows (absolute) - Configurable cfgMinCrossedRows{"cfgMinCrossedRows", 70, "min TPC crossed rows"}; - Configurable cfgUseCrossedRows{"cfgUseCrossedRows", false, "apply crossed rows cut"}; - - Configurable cfgMinTPCcls{"cfgMinTPCcls", 70, "min TPC clusters found"}; - Configurable cfgUseTPCcls{"cfgUseTPCcls", false, "apply TPC clusters cut"}; - - Configurable> cDcaPtBinsPr{"cDcaPtBinsPr", {0.0f, 0.5f, 1.0f, 2.0f, 3.0f, 5.0f, 1000.0f}, "Proton pT bin edges for DCAxy cut"}; - - Configurable> cDcaXYBinsPr{"cDcaXYBinsPr", {0.020f, 0.015f, 0.010f, 0.007f, 0.005f, 0.004f}, "Proton max |DCAxy| per pT bin (cm)"}; - - // Kaon DCAxy — pT binned - Configurable> cDcaPtBinsKa{"cDcaPtBinsKa", {0.0f, 0.3f, 0.6f, 1.0f, 2.0f, 1000.0f}, "Kaon pT bin edges for DCAxy cut"}; - - Configurable> cDcaXYBinsKa{"cDcaXYBinsKa", {0.025f, 0.018f, 0.012f, 0.008f, 0.004f}, "Kaon max |DCAxy| per pT bin (cm)"}; - Configurable isonlyQC{"isonlyQC", false, "only QC"}; - Configurable isDeepAngle{"isDeepAngle", false, "Deep Angle cut"}; - Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; - Configurable cKinCuts{"cKinCuts", false, "Kinematic Cuts for p-K pair opening angle"}; - Configurable cPrimaryTrack{"cPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cGlobalWoDCATrack{"cGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) - Configurable cPVContributor{"cPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor - - // PID Selections - Configurable cUseOnlyTOFTrackPr{"cUseOnlyTOFTrackPr", false, "Use only TOF track for PID selection"}; // Use only TOF track for Proton PID selection - Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon PID selection - Configurable cUseTpcOnly{"cUseTpcOnly", false, "Use TPC Only selection"}; // TPC And TOF tracks - Configurable cRejNsigmaTpc{"cRejNsigmaTpc", 3.0, "Reject tracks to improve purity of TPC PID"}; // Reject missidentified particles when tpc bands merge - Configurable cRejNsigmaTpcPi{"cRejNsigmaTpcPi", 3.0, "Reject tracks to improve purity of TPC PID"}; // TPC And TOF tracks - // Configurable cRejNsigmaTpcPr{"cRejNsigmaTpcPr", 3.0, "Reject tracks to improve purity of TPC PID"}; - Configurable cRejNsigmaTpcKa{"cRejNsigmaTpcKa", 3.0, "Reject tracks to improve purity of TPC PID"}; - Configurable cRejNsigmakTpcPi{"cRejNsigmakTpcPi", 3.0, "Reject tracks to improve purity of TPC PID"}; - Configurable cRejNsigmakTpcPr{"cRejNsigmakTpcPr", 3.0, "Reject tracks to improve purity of TPC PID"}; - Configurable minnsigmatpcKa{"minnsigmatpcKa", -6.0, "Reject tracks to improve purity of TPC PID"}; - Configurable minnsigmatpcPr{"minnsigmatpcPr", -6.0, "Reject tracks to improve purity of TPC PID"}; - Configurable minnsigmatofKa{"minnsigmatofKa", -6.0, "Reject tracks to improve purity of TofPID"}; - Configurable minnsigmatofPr{"minnsigmatofPr", -6.0, "Reject tracks to improve purity of Tof PID"}; - Configurable minnsigmatpctofKa{"minnsigmatpctofKa", -6.0, "Reject tracks to improve purity of TPC PID"}; - Configurable minnsigmatpctofPr{"minnsigmatpctofPr", -6.0, "Reject tracks to improve purity of TPC PID"}; - // Configurable cRejNsigmaTpcPr{"cRejNsigmaTpcPr", 3.0, "Reject tracks to improve purity of TPC PID"}; - Configurable cRejNsigmaTpcVeto{"cRejNsigmaTpcVeto", 3.0, "Reject tracks to improve purity of TPC PID"}; // Reject missidentified particles when tpc bands merge - Configurable cRejNsigmaTof{"cRejNsigmaTof", 3.0, "Reject tracks to improve purity of TOF PID"}; // Reject missidentified particles when tpc bands merge - // Proton - Configurable cMaxTPCnSigmaProton{"cMaxTPCnSigmaProton", 3.0, "TPC nSigma cut for Proton"}; // TPC - // Configurable cMaxTOFnSigmaProton{"cMaxTOFnSigmaProton", 3.0, "TOF nSigma cut for Proton"}; // TOF - Configurable nsigmaCutCombinedProton{"nsigmaCutCombinedProton", 3.0, "Combined nSigma cut for Proton"}; // Combined - Configurable> protonTPCPIDp{"protonTPCPIDp", {0, 0.5, 0.7, 0.8}, "p dependent TPC cuts protons"}; - Configurable> protonTPCPIDcut{"protonTPCPIDcut", {5., 3.5, 2.5}, "TPC nsigma cuts protons"}; - Configurable> protonTOFPIDp{"protonTOFPIDp", {0., 999.}, "p dependent TOF cuts protons"}; - Configurable> protonTOFPIDcut{"protonTOFPIDcut", {3.0}, "TOF nsigma cuts protons"}; - // Kaon - Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; // TPC - // Configurable cMaxTOFnSigmaKaon{"cMaxTOFnSigmaKaon", 3.0, "TOF nSigma cut for Kaon"}; // TOF - Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", 3.0, "Combined nSigma cut for Kaon"}; // Combined - Configurable> kaonTPCPIDp{"kaonTPCPIDp", {0., 0.25, 0.3, 0.45}, "pT dependent TPC cuts kaons"}; - Configurable> kaonTPCPIDcut{"kaonTPCPIDcut", {6, 3.5, 2.5}, "TPC nsigma cuts kaons"}; - Configurable> kaonTOFPIDp{"kaonTOFPIDp", {0., 999.}, "p dependent TOF cuts kaons"}; - Configurable> kaonTOFPIDcut{"kaonTOFPIDcut", {3.0}, "TOF nsigma cuts kaons"}; - // Event Mixing. - Configurable cNumMixEv{"cNumMixEv", 20, "Number of Events to be mixed"}; - ConfigurableAxis cDCAzBins{"dcazbins", {VARIABLE_WIDTH, -1.2f, -1.0f, -0.9f, -0.8f, -0.7f, -0.6f, -0.5f, -0.4f, -0.3f, -0.2f, -0.1f, 0.f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f}, "DCA - z-vertex"}; - - ConfigurableAxis cMixVtxBins{"cMixVtxBins", {VARIABLE_WIDTH, -10.0f, -9.f, -8.f, -7.f, -6.f, -5.f, -4.f, -3.f, -2.f, -1.f, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis cMixMultBins{"cMixMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 200.0f}, "Mixing bins - multiplicity"}; - ConfigurableAxis cMixEPAngle{"cMixEPAngle", {VARIABLE_WIDTH, -1.5708f, -1.25664f, -0.942478f, -0.628319f, 0.f, 0.628319f, 0.942478f, 1.25664f, 1.5708f}, "event plane"}; - ConfigurableAxis occupancy_bins{"occupancy_bins", {VARIABLE_WIDTH, 0.0, 100, 500, 600, 1000, 1100, 1500, 1600, 2000, 2100, 2500, 2600, 3000, 3100, 3500, 3600, 4000, 4100, 4500, 4600, 5000, 5100, 9999}, "Binning of the occupancy axis"}; - Configurable cNofRotations{"cNofRotations", 10, "Number of rotations for rotational background"}; - Configurable rotationalcut{"rotationalcut", 6.f, "Rotational background angle window: PI/rotationalcut"}; - - // ── MC Event Selection Configurables ───────────────────────────────────── - Configurable cEvtMCAfterAllCuts{"cEvtMCAfterAllCuts", false, "MC event sel: isInAfterAllCuts"}; - Configurable cEvtMCINELgt0{"cEvtMCINELgt0", false, "MC event sel: isINELgt0"}; - Configurable cEvtMCSel8{"cEvtMCSel8", false, "MC event sel: isInSel8"}; - Configurable cEvtMCVtxIn10{"cEvtMCVtxIn10", false, "MC event sel: isVtxIn10"}; - Configurable cEvtMCTriggerTVX{"cEvtMCTriggerTVX", false, "MC event sel: isTriggerTVX"}; - Configurable cEvtRecINELgt0{"cEvtMCRecINELgt0", false, "MC event sel: isRecINELgt0"}; - // Histogram Registry. - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - void init(InitContext const&) - { - const AxisSpec axisCent(110, 0, 110, "FT0 (%)"); - const AxisSpec axisP_pid(200, 0., 10., "p (GeV/c)"); - const AxisSpec axisPt_pid(200, 0., 10., "p_{T} (GeV/c)"); - const AxisSpec axisPt(nBinsPt, 0., 10., "p_{T} (GeV/c)"); - const AxisSpec axisEta(40, -1, 1, "#eta"); - // const AxisSpec axisDCAz(500, -0.5, 0.5, {"DCA_{z} (cm)"}); - const AxisSpec axisDCAxy(240, -0.12, 0.12, {"DCA_{xy} (cm)"}); - const AxisSpec axisTPCNCls(200, 0, 200, {"TPCNCls"}); - const AxisSpec axisTPCNsigma(401, -10.025, 10.025, {"n#sigma^{TPC}"}); - const AxisSpec axisTOFNsigma(401, -10.025, 10.025, {"n#sigma^{TOF}"}); - const AxisSpec axisdEdx(380, 10, 200, {"#frac{dE}{dx}"}); - const AxisSpec axisVz(120, -12, 12, {"vz"}); - const AxisSpec axisEP(120, -3.14, 3.14, {"#theta"}); - const AxisSpec axisInvM(nBinsInvM, 1.4, 2.0, {"M_{inv} (GeV/c^{2})"}); - AxisSpec axisOccupancy = {occupancy_bins, "Occupancy [-40,100]"}; - AxisSpec axisDCAz = {cDCAzBins, "DCA_{z} (cm)"}; - - histos.add("Event/h1d_ft0_mult_percentile", "FT0 (%)", kTH2F, {axisCent, axisOccupancy}); - histos.add("Event/h_ft0_vz", "Collision Vertex Z position", kTH1F, {{100, -15., 15.}}); - if (doprocessMix || doprocessMixDF || doprocessMixepDF) { - histos.add("Event/mixing_vzVsmultpercentile", "FT0(%)", kTH3F, {axisCent, axisVz, axisEP}); - } - // QA Beforei - histos.add("QAbefore/hEta_rec", "Reco dN/d#eta; #eta; dN/d#eta", kTH1F, {{50, -1.0, 1.0}}); - histos.add("QAbefore/hPt_rec", "Reco pT; p_{T} (GeV/c); Tracks", kTH1F, {axisP_pid}); - histos.add("QAbefore/hPhi_rec", "Reco #varphi; #varphi (rad); Tracks", kTH1F, {{72, 0, 6.2832}}); - histos.add("QAbefore/hEtaPhi_rec", "Reco #eta vs #varphi; #eta; #varphi", kTH2F, {axisEta, {72, 0, 6.2832}}); - histos.add("QAbefore/Proton/h2d_pr_nsigma_tpc_p", "n#sigma^{TPC} Protons", kTH2F, {axisP_pid, axisTPCNsigma}); - histos.add("QAbefore/Proton/h2d_pr_nsigma_tof_p", "n#sigma^{TOF} Protons", kTH2F, {axisP_pid, axisTOFNsigma}); - histos.add("QAbefore/Proton/h2d_pr_nsigma_tof_vs_tpc", "n#sigma^{TPC} vs n#sigma^{TOF} Protons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); - histos.add("QAbefore/Kaon/h2d_ka_nsigma_tpc_p", "n#sigma^{TPC} Kaons", kTH2F, {axisP_pid, axisTPCNsigma}); - histos.add("QAbefore/Kaon/h2d_ka_nsigma_tof_p", "n#sigma^{TOF} Kaons", kTH2F, {axisP_pid, axisTOFNsigma}); - histos.add("QAbefore/Kaon/h2d_ka_nsigma_tof_vs_tpc", "n#sigma^{TPC} vs n#sigma^{TOF} Kaons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); - - // QA After - histos.add("QAafter/Proton/hd_pr_pt", "p_{T}-spectra Protons", kTH2F, {axisPt_pid, axisCent}); - histos.add("QAafter/Proton/h2d_pr_dca_z", "dca_{z} Protons", kTH2F, {axisPt_pid, axisDCAz}); - histos.add("QAafter/Proton/h2d_pr_dca_xy", "dca_{xy} Protons", kTH2F, {axisPt_pid, axisDCAxy}); - histos.add("QAafter/Proton/h2d_pr_dEdx_p", "TPC Signal Protons", kTH2F, {axisP_pid, axisdEdx}); - histos.add("QAafter/Proton/h2d_pr_nsigma_tpc_pt", " Protons", kTH2F, {axisPt_pid, axisTPCNsigma}); - histos.add("QAafter/Proton/h2d_Prpi_nsigma_tpc_p", " Protons pion", kTH2F, {axisPt_pid, axisTPCNsigma}); - histos.add("QAafter/Proton/h2d_Prka_nsigma_tpc_p", " Protons kaon", kTH2F, {axisPt_pid, axisTPCNsigma}); - histos.add("QAafter/Proton/h2d_pr_nsigma_tpc_p", " Protons", kTH2F, {axisP_pid, axisTPCNsigma}); - histos.add("QAafter/Proton/h2d_pr_nsigma_tof_pt", " Protons", kTH2F, {axisPt_pid, axisTOFNsigma}); - histos.add("QAafter/Proton/h2d_pr_nsigma_tof_p", " Protons", kTH2F, {axisP_pid, axisTOFNsigma}); - histos.add("QAafter/Proton/h2d_Prpi_nsigma_tof_p", " Protons pion", kTH2F, {axisP_pid, axisTOFNsigma}); - histos.add("QAafter/Proton/h2d_Prka_nsigma_tof_p", " Protons kaon", kTH2F, {axisP_pid, axisTOFNsigma}); - histos.add("QAafter/Proton/h2d_pr_nsigma_tof_vs_tpc", "n#sigma(TOF) vs n#sigma(TPC) Protons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); - histos.add("QAafter/Proton/hTPCNClsCrossedRowsVsPt", "TPC Crossed Rows vs pT;p_{T} (GeV/c);N_{cls,crossed};Counts", kTH2F, {axisPt_pid, {200, 0, 200}}); - histos.add("QAafter/Proton/hTPCNClsFoundVsPt", "TPC Found Clusters vs pT;p_{T} (GeV/c);N_{cls,found};Counts", kTH2F, {axisPt_pid, {200, 0, 200}}); - histos.add("QAafter/Kaon/hd_ka_pt", "p_{T}-spectra Kaons", kTH2F, {axisPt_pid, axisCent}); - histos.add("QAafter/Kaon/h2d_ka_dca_z", "dca_{z} Kaons", kTH2F, {axisPt_pid, axisDCAz}); - histos.add("QAafter/Kaon/h2d_ka_dca_xy", "dca_{xy} Kaons", kTH2F, {axisPt_pid, axisDCAxy}); - histos.add("QAafter/Kaon/h2d_ka_dEdx_p", "TPC Signal Kaon", kTH2F, {axisP_pid, axisdEdx}); - histos.add("QAafter/Kaon/h2d_Kapi_nsigma_tpc_p", " Kaons pion", kTH2F, {axisPt_pid, axisTPCNsigma}); - histos.add("QAafter/Kaon/h2d_Kapr_nsigma_tpc_p", " Kaons proton", kTH2F, {axisP_pid, axisTPCNsigma}); - histos.add("QAafter/Kaon/h2d_ka_nsigma_tpc_pt", " Kaons", kTH2F, {axisPt_pid, axisTPCNsigma}); - histos.add("QAafter/Kaon/h2d_ka_nsigma_tpc_p", " Kaons", kTH2F, {axisP_pid, axisTPCNsigma}); - histos.add("QAafter/Kaon/h2d_ka_nsigma_tof_pt", " Kaons", kTH2F, {axisPt_pid, axisTOFNsigma}); - histos.add("QAafter/Kaon/h2d_ka_nsigma_tof_p", " Kaons", kTH2F, {axisP_pid, axisTOFNsigma}); - histos.add("QAafter/Kaon/h2d_Kapi_nsigma_tof_p", " Kaons pion", kTH2F, {axisP_pid, axisTOFNsigma}); - histos.add("QAafter/Kaon/h2d_Kapr_nsigma_tof_p", " Kaons proton", kTH2F, {axisP_pid, axisTOFNsigma}); - histos.add("QAafter/Kaon/h2d_ka_nsigma_tof_vs_tpc", "n#sigma(TOF) vs n#sigma(TPC) Kaons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); - histos.add("QAafter/Kaon/hTPCNClsCrossedRowsVsPt", "TPC Crossed Rows vs pT;p_{T} (GeV/c);N_{cls,crossed};Counts", kTH2F, {axisPt_pid, {200, 0, 200}}); - histos.add("QAafter/Kaon/hTPCNClsFoundVsPt", "TPC Found Clusters vs pT;p_{T} (GeV/c);N_{cls,found};Counts", kTH2F, {axisPt_pid, {200, 0, 200}}); - // Analysis - // Lambda Invariant Mass - if (!doprocessMC) { - histos.add("Analysis/h4d_lstar_invm_US_PM", "THn #Lambda(1520)", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_US_MP", "THn #bar #Lambda(1520)", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_PP", "THn Like Signs p K^{+}", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_MM", "THn Like Signs #bar{p} K^{-}", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_rot_PM", "THn Rotated", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_rot_MP", "THn Rotated", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_US_PM_mix", "THn Mixed Events", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_US_MP_mix", "THn anti Mixed Events", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_LS_PP_mix", "THn Mixed Events PP", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_LS_MM_mix", "THn Mixed Events MM", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - } - // MC - if (doprocessMC) { - histos.add("Event/hMCEventCutflow", "MC Event Cutflow", kTH1F, {{7, 0, 7}}); - histos.add("QAChecks/h1d_pr_rec_pt", "Reconstructed p_{T}-spectra Protons", kTH1F, {axisPt_pid}); - histos.add("QAChecks/h1d_ka_rec_pt", "Recondstucted p_{T}-spectra Kaons", kTH1F, {axisPt_pid}); - histos.add("QAChecks/h1d_pr_gen_pt", "Generated p_{T}-spectra Protons", kTH1F, {axisPt_pid}); - histos.add("QAChecks/h1d_ka_gen_pt", "Generated p_{T}-spectra Kaons", kTH1F, {axisPt_pid}); - - histos.add("Analysis/h3d_gen_lstar_PM", "Generated #Lambda(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); - histos.add("Analysis/h3d_gen_lstar_MP", "Generated #bar{#Lambda}(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); - histos.add("Analysis/h3d_rec_lstar_PM", "Reconstructed #Lambda(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); - histos.add("Analysis/h3d_rec_lstar_MP", "Reconstructed #bar{#Lambda}(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); - histos.add("Analysis/h3d_reso_lstar_PM", "Resolution #Lambda(1520) p_{T}", kTHnSparseF, {{200, -0.05, 0.05}, axisPt, axisCent}); - histos.add("Analysis/h3d_reso_lstar_MP", "Resolution #bar{#Lambda}(1520) p_{T}", kTHnSparseF, {{200, -0.05, 0.05}, axisPt, axisCent}); - } - - if (doprocessMCGen) { - histos.add("SignalLoss/hMCEventCutflow", "MC Event Cutflow", kTH1F, {{7, 0, 7}}); - histos.add("SignalLoss/hGen_mT_scaled_Proton", "mT Scaled #Lambda(1520) from Proton", kTHnSparseF, {axisPt, axisCent}); - histos.add("SignalLoss/hGen_mT_scaled_AntiProton", "mT Scaled #bar{#Lambda}(1520) from AntiProton", kTHnSparseF, {axisPt, axisCent}); - - histos.add("SignalLoss/hGen_mT_scaled_Lambda0", "mT Scaled #Lambda(1520) from Lambda0", kTHnSparseF, {axisPt, axisCent}); - histos.add("SignalLoss/hGen_mT_scaled_AntiLambda0", "mT Scaled #bar{#Lambda}(1520) from AntiLambda0", kTHnSparseF, {axisPt, axisCent}); - - histos.add("SignalLoss/hGen_mT_scaled_XiMinus", "mT Scaled #Lambda(1520) from Xi-", kTHnSparseF, {axisPt, axisCent}); - histos.add("SignalLoss/hGen_mT_scaled_XiPlus", "mT Scaled #bar{#Lambda}(1520) from Xi+", kTHnSparseF, {axisPt, axisCent}); - - histos.add("SignalLoss/hGen_mT_scaled_Xi0", "mT Scaled #Lambda(1520) from Xi0", kTHnSparseF, {axisPt, axisCent}); - histos.add("SignalLoss/hGen_mT_scaled_AntiXi0", "mT Scaled #bar{#Lambda}(1520) from AntiXi0", kTHnSparseF, {axisPt, axisCent}); - - histos.add("SignalLoss/hGen_mT_scaled_OmegaMinus", "mT Scaled #Lambda(1520) from Omega-", kTHnSparseF, {axisPt, axisCent}); - histos.add("SignalLoss/hGen_mT_scaled_OmegaPlus", "mT Scaled #bar{#Lambda}(1520) from Omega+", kTHnSparseF, {axisPt, axisCent}); - } - } - - template - bool selTracks(T const& track) - { - if (track.pt() < cPtMin) - return false; - - if (std::abs(track.eta()) > cEtaCut) - return false; - - if (cPrimaryTrack && !track.isPrimaryTrack()) - return false; - - if (cGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) - return false; - - if (cPVContributor && !track.isPVContributor()) - return false; - - if (cfgUseCrossedRows && track.tpcNClsCrossedRows() < cfgMinCrossedRows) - return false; - - if (cfgUseTPCcls && track.tpcNClsFound() < cfgMinTPCcls) - return false; - - return true; - } - - template - bool dcaSelectionProton(T const& track, float p) - { - auto ptBinsPr = static_cast>(cDcaPtBinsPr); - auto dcaXYPr = static_cast>(cDcaXYBinsPr); - int nBinsPr = static_cast(ptBinsPr.size()) - 1; - - bool dcaXYPassed = false; - for (int i = 0; i < nBinsPr; i++) { - if (p >= ptBinsPr[i] && p < ptBinsPr[i + 1] && - std::abs(track.dcaXY()) < dcaXYPr[i]) - dcaXYPassed = true; - } - if (!dcaXYPassed) - return false; - - if (std::abs(track.dcaZ()) > cDcaz) - return false; - - return true; - } - - // ── Kaon DCA Selection ──────────────────────────────────────────────────── - template - bool dcaSelectionKaon(T const& track, float p) - { - auto ptBinsKa = static_cast>(cDcaPtBinsKa); - auto dcaXYKa = static_cast>(cDcaXYBinsKa); - int nBinsKa = static_cast(ptBinsKa.size()) - 1; - - bool dcaXYPassed = false; - for (int i = 0; i < nBinsKa; i++) { - if (p >= ptBinsKa[i] && p < ptBinsKa[i + 1] && - std::abs(track.dcaXY()) < dcaXYKa[i]) - dcaXYPassed = true; - } - if (!dcaXYPassed) - return false; - - if (std::abs(track.dcaZ()) > cDcaz) - return false; - - return true; - } - // PID selection tools - template - bool selectionPIDProton(const T& candidate, float p) - { - bool tpcPIDPassed{false}, tofPIDPassed{false}; - auto tpcPIDp = static_cast>(protonTPCPIDp); - auto tpcPIDcut = static_cast>(protonTPCPIDcut); - auto tofPIDp = static_cast>(protonTOFPIDp); - auto tofPIDcut = static_cast>(protonTOFPIDcut); - int nitr = static_cast(tpcPIDp.size()); - int nitrtof = static_cast(tofPIDp.size()); - - float tpcNsigmaPi = std::abs(candidate.tpcNSigmaPi()); - float tpcNsigmaKa = std::abs(candidate.tpcNSigmaKa()); - float tpcNsigmaPr = std::abs(candidate.tpcNSigmaPr()); - float tofNsigmaPi = std::abs(candidate.tofNSigmaPi()); - float tofNsigmaKa = std::abs(candidate.tofNSigmaKa()); - float tofNsigmaPr = std::abs(candidate.tofNSigmaPr()); - - float tpcTofNsigmaPi = tpcNsigmaPi * tpcNsigmaPi + tofNsigmaPi * tofNsigmaPi; - float tpcTofNsigmaKa = tpcNsigmaKa * tpcNsigmaKa + tofNsigmaKa * tofNsigmaKa; - float tpcTofNsigmaPr = tpcNsigmaPr * tpcNsigmaPr + tofNsigmaPr * tofNsigmaPr; - float combinedCut = nsigmaCutCombinedProton * nsigmaCutCombinedProton; - float combinedRejCut = cRejNsigmaTof * cRejNsigmaTpc; - - if (!cUseTpcOnly && candidate.hasTOF()) { - if (candidate.tofNSigmaPr() < minnsigmatofPr) - return false; - if (nsigmaCutCombinedProton < 0 && p >= cPMin) { - - for (int i = 0; i < nitrtof - 1; ++i) { - if (p >= tofPIDp[i] && p < tofPIDp[i + 1] && (tofNsigmaPr < tofPIDcut[i] && tofNsigmaPi > cRejNsigmaTof && tofNsigmaKa > cRejNsigmaTof)) - tofPIDPassed = true; - } - if (candidate.tpcNSigmaPr() < minnsigmatpctofPr) - return false; - if (tpcNsigmaPr < cMaxTPCnSigmaProton && tpcNsigmaPi > cRejNsigmaTpcVeto && tpcNsigmaKa > cRejNsigmaTpcVeto) - tpcPIDPassed = true; - } - - // circular cut - if ((nsigmaCutCombinedProton > 0) && p >= cPMin && (tpcTofNsigmaPr < combinedCut && tpcTofNsigmaPi > combinedRejCut && tpcTofNsigmaKa > combinedRejCut)) { - tofPIDPassed = true; - tpcPIDPassed = true; - } - - if (p < cPMin && tpcNsigmaPr < cMaxTPCnSigmaProton) { - - tofPIDPassed = true; - tpcPIDPassed = true; - } - } else { - tofPIDPassed = true; - if (candidate.tpcNSigmaPr() < minnsigmatpcPr) - return false; - for (int i = 0; i < nitr - 1; ++i) { - if (p >= tpcPIDp[i] && p < tpcPIDp[i + 1] && (tpcNsigmaPr < tpcPIDcut[i] && tpcNsigmaPi > cRejNsigmaTpcPi && tpcNsigmaKa > cRejNsigmaTpcKa)) { - tpcPIDPassed = true; - } - } - } - if (tpcPIDPassed && tofPIDPassed) { - - return true; - } - return false; - } - template - bool selectionPIDKaon(const T& candidate, float p) - { - bool tpcPIDPassed{false}, tofPIDPassed{false}; - auto tpcPIDp = static_cast>(kaonTPCPIDp); - auto tpcPIDcut = static_cast>(kaonTPCPIDcut); - auto tofPIDp = static_cast>(kaonTOFPIDp); - auto tofPIDcut = static_cast>(kaonTOFPIDcut); - int nitr = static_cast(tpcPIDp.size()); - int nitrtof = static_cast(tofPIDp.size()); - - float tpcNsigmaPi = std::abs(candidate.tpcNSigmaPi()); - float tpcNsigmaKa = std::abs(candidate.tpcNSigmaKa()); - float tpcNsigmaPr = std::abs(candidate.tpcNSigmaPr()); - float tofNsigmaPi = std::abs(candidate.tofNSigmaPi()); - float tofNsigmaKa = std::abs(candidate.tofNSigmaKa()); - float tofNsigmaPr = std::abs(candidate.tofNSigmaPr()); - - float tpcTofNsigmaPi = tpcNsigmaPi * tpcNsigmaPi + tofNsigmaPi * tofNsigmaPi; - float tpcTofNsigmaKa = tpcNsigmaKa * tpcNsigmaKa + tofNsigmaKa * tofNsigmaKa; - float tpcTofNsigmaPr = tpcNsigmaPr * tpcNsigmaPr + tofNsigmaPr * tofNsigmaPr; - float combinedCut = nsigmaCutCombinedKaon * nsigmaCutCombinedKaon; - float combinedRejCut = cRejNsigmaTpc * cRejNsigmaTof; - - if (!cUseTpcOnly && candidate.hasTOF()) { - if (candidate.tofNSigmaKa() < minnsigmatofKa) - return false; - if (nsigmaCutCombinedKaon < 0 && p >= cPMin) { - - for (int i = 0; i < nitrtof - 1; ++i) { - if (p >= tofPIDp[i] && p < tofPIDp[i + 1] && (tofNsigmaKa < tofPIDcut[i] && tofNsigmaPi > cRejNsigmaTof && tofNsigmaPr > cRejNsigmaTof)) - tofPIDPassed = true; - } - if (candidate.tpcNSigmaKa() < minnsigmatpctofKa) - return false; - if (tpcNsigmaKa < cMaxTPCnSigmaKaon && tpcNsigmaPi > cRejNsigmaTpcVeto && tpcNsigmaPr > cRejNsigmaTpcVeto) - tpcPIDPassed = true; - } - - // circular - if ((nsigmaCutCombinedKaon > 0) && p >= cPMin && (tpcTofNsigmaKa < combinedCut && tpcTofNsigmaPi > combinedRejCut && tpcTofNsigmaPr > combinedRejCut)) { - tofPIDPassed = true; - tpcPIDPassed = true; - } - - if (p < cPMin && tpcNsigmaKa < cMaxTPCnSigmaKaon) { - - tofPIDPassed = true; - tpcPIDPassed = true; - } - - } else { - tofPIDPassed = true; - if (candidate.tpcNSigmaKa() < minnsigmatpcKa) - return false; - for (int i = 0; i < nitr - 1; ++i) { - if (p >= tpcPIDp[i] && p < tpcPIDp[i + 1] && (tpcNsigmaKa < tpcPIDcut[i] && tpcNsigmaPi > cRejNsigmakTpcPi && tpcNsigmaPr > cRejNsigmakTpcPr)) { - tpcPIDPassed = true; - } - } - } - if (tpcPIDPassed && tofPIDPassed) { - - return true; - } - return false; - } - - template - void fillDataHistos(trackType const& trk1, trackType const& trk2, float mult, int occup = 100) - { - - float p_ptot = 0., k_ptot = 0.; - - for (auto const& [trkPr, trkKa] : soa::combinations(soa::CombinationsFullIndexPolicy(trk1, trk2))) { - // Do not analyse same index tracks. - if (trkPr.index() == trkKa.index()) // && !mix) - continue; - // pT, DCA, Global Tracks and PVcontrib selection. - if (!selTracks(trkPr) || !selTracks(trkKa)) - continue; - - // LOGF(info, "eork 4 %d, %d %d ",trkPr.index(),trk1.size(),trkPr.size()); - auto _pxPr = trkPr.px(); - auto _pyPr = trkPr.py(); - auto _pzPr = trkPr.pz(); - auto _pxKa = trkKa.px(); - auto _pyKa = trkKa.py(); - auto _pzKa = trkKa.pz(); - - p_ptot = TMath::Sqrt(_pxPr * _pxPr + _pyPr * _pyPr + _pzPr * _pzPr); - k_ptot = TMath::Sqrt(_pxKa * _pxKa + _pyKa * _pyKa + _pzKa * _pzKa); - - // Fill QA before track selection. - if (!mix) { - auto _tpcnsigmaPr = trkPr.tpcNSigmaPr(); - histos.fill(HIST("QAbefore/Proton/h2d_pr_nsigma_tpc_p"), p_ptot, _tpcnsigmaPr); - if (trkPr.hasTOF()) { - auto _tofnsigmaPr = trkPr.tofNSigmaPr(); - histos.fill(HIST("QAbefore/Proton/h2d_pr_nsigma_tof_p"), p_ptot, _tofnsigmaPr); - histos.fill(HIST("QAbefore/Proton/h2d_pr_nsigma_tof_vs_tpc"), _tpcnsigmaPr, _tofnsigmaPr); - } - auto _tpcnsigmaKa = trkKa.tpcNSigmaKa(); - histos.fill(HIST("QAbefore/Kaon/h2d_ka_nsigma_tpc_p"), k_ptot, _tpcnsigmaKa); - if (trkKa.hasTOF()) { - auto _tofnsigmaKa = trkKa.tofNSigmaKa(); - histos.fill(HIST("QAbefore/Kaon/h2d_ka_nsigma_tof_p"), k_ptot, _tofnsigmaKa); - histos.fill(HIST("QAbefore/Kaon/h2d_ka_nsigma_tof_vs_tpc"), _tpcnsigmaKa, _tofnsigmaKa); - } - } - - // Apply PID Selection - if (cUseOnlyTOFTrackPr && !trkPr.hasTOF()) - continue; - if (cUseOnlyTOFTrackKa && !trkKa.hasTOF()) - continue; - if (!selectionPIDProton(trkPr, p_ptot) || !selectionPIDKaon(trkKa, k_ptot)) - continue; - if (!dcaSelectionProton(trkPr, p_ptot) || !dcaSelectionKaon(trkKa, k_ptot)) - continue; - - if (isDeepAngle && TMath::ACos((trkPr.pt() * trkKa.pt() + _pzPr * _pzKa) / (p_ptot * k_ptot)) < cfgDeepAngle) - continue; - - // Fill QA after track selection. - if constexpr (!mix) { - auto _ptPr = trkPr.pt(); - auto _tpcnsigmaPr = trkPr.tpcNSigmaPr(); - - // Proton - histos.fill(HIST("QAafter/Proton/hd_pr_pt"), _ptPr, mult); - histos.fill(HIST("QAafter/Proton/h2d_pr_dca_z"), _ptPr, trkPr.dcaZ()); - histos.fill(HIST("QAafter/Proton/h2d_pr_dca_xy"), _ptPr, trkPr.dcaXY()); - histos.fill(HIST("QAafter/Proton/h2d_pr_dEdx_p"), p_ptot, trkPr.tpcSignal()); - histos.fill(HIST("QAafter/Proton/h2d_Prpi_nsigma_tpc_p"), p_ptot, trkPr.tpcNSigmaPi()); - histos.fill(HIST("QAafter/Proton/h2d_Prka_nsigma_tpc_p"), p_ptot, trkPr.tpcNSigmaKa()); - histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tpc_p"), p_ptot, _tpcnsigmaPr); - histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tpc_pt"), _ptPr, _tpcnsigmaPr); - histos.fill(HIST("QAafter/Proton/hTPCNClsCrossedRowsVsPt"), _ptPr, trkPr.tpcNClsCrossedRows()); - histos.fill(HIST("QAafter/Proton/hTPCNClsFoundVsPt"), _ptPr, trkPr.tpcNClsFound()); - - if (!cUseTpcOnly && trkPr.hasTOF()) { - auto _tofnsigmaPr = trkPr.tofNSigmaPr(); - histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tof_p"), p_ptot, _tofnsigmaPr); - histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tof_pt"), _ptPr, _tofnsigmaPr); - histos.fill(HIST("QAafter/Proton/h2d_Prpi_nsigma_tof_p"), p_ptot, trkPr.tofNSigmaPi()); - histos.fill(HIST("QAafter/Proton/h2d_Prka_nsigma_tof_p"), p_ptot, trkPr.tofNSigmaKa()); - histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tof_vs_tpc"), _tpcnsigmaPr, _tofnsigmaPr); - } - auto _ptKa = trkKa.pt(); - auto _tpcnsigmaKa = trkKa.tpcNSigmaKa(); - - // Kaon - histos.fill(HIST("QAafter/Kaon/hd_ka_pt"), _ptKa, mult); - histos.fill(HIST("QAafter/Kaon/h2d_ka_dca_z"), _ptKa, trkKa.dcaZ()); - histos.fill(HIST("QAafter/Kaon/h2d_ka_dca_xy"), _ptKa, trkKa.dcaXY()); - histos.fill(HIST("QAafter/Kaon/h2d_ka_dEdx_p"), k_ptot, trkKa.tpcSignal()); - histos.fill(HIST("QAafter/Kaon/h2d_Kapi_nsigma_tpc_p"), k_ptot, trkKa.tpcNSigmaPi()); - histos.fill(HIST("QAafter/Kaon/h2d_Kapr_nsigma_tpc_p"), k_ptot, trkKa.tpcNSigmaPr()); - histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tpc_p"), k_ptot, _tpcnsigmaKa); - histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tpc_pt"), _ptKa, _tpcnsigmaKa); - histos.fill(HIST("QAafter/Kaon/hTPCNClsCrossedRowsVsPt"), _ptKa, trkKa.tpcNClsCrossedRows()); - histos.fill(HIST("QAafter/Kaon/hTPCNClsFoundVsPt"), _ptKa, trkKa.tpcNClsFound()); - - if (!cUseTpcOnly && trkKa.hasTOF()) { - auto _tofnsigmaKa = trkKa.tofNSigmaKa(); - histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tof_p"), k_ptot, _tofnsigmaKa); - histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tof_pt"), _ptKa, _tofnsigmaKa); - histos.fill(HIST("QAafter/Kaon/h2d_Kapi_nsigma_tof_p"), k_ptot, trkKa.tofNSigmaPi()); - histos.fill(HIST("QAafter/Kaon/h2d_Kapr_nsigma_tof_p"), k_ptot, trkKa.tofNSigmaPr()); - histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tof_vs_tpc"), _tpcnsigmaKa, _tofnsigmaKa); - } - } - - if (isonlyQC) - continue; - - std::array pvec0 = {_pxPr, _pyPr, _pzPr}; - std::array pvec1 = {_pxKa, _pyKa, _pzKa}; - std::array, 2> arrMomrec = {pvec0, pvec1}; - - float _M = RecoDecay::m(arrMomrec, std::array{MassProton, MassKaonCharged}); - float _pt = RecoDecay::pt(std::array{_pxPr + _pxKa, _pyPr + _pyKa}); - - float _y = std::abs(RecoDecay::y(std::array{_pxPr + _pxKa, _pyPr + _pyKa, _pzPr + _pzKa}, _M)); - - float _yshift = _y - cfgRapidityShift; - - if (std::abs(_yshift) > cfgRapidityCut) - continue; - // Apply kinematic cuts. - - // Fill Invariant Mass Histograms. - if constexpr (!mix && !mc) { - if (trkPr.sign() * trkKa.sign() < 0) { - - if (trkPr.sign() > 0) - histos.fill(HIST("Analysis/h4d_lstar_invm_US_PM"), _M, _pt, mult, occup); - else - histos.fill(HIST("Analysis/h4d_lstar_invm_US_MP"), _M, _pt, mult, occup); - - if (doRotate) { - for (int i = 0; i < cNofRotations; i++) { - - float delta = o2::constants::math::PI / rotationalcut; - float theta2; - if (cNofRotations == 1) { - // Single rotation — just rotate by exactly PI - theta2 = o2::constants::math::PI; - } else { - theta2 = (o2::constants::math::PI - delta) + - i * (2.f * delta / (cNofRotations - 1)); - } - - float phiRot = trkKa.phi() + theta2; - if (phiRot > o2::constants::math::TwoPI) - phiRot -= o2::constants::math::TwoPI; - if (phiRot < 0.f) - phiRot += o2::constants::math::TwoPI; - - float _pxKaRot = trkKa.pt() * std::cos(phiRot); - float _pyKaRot = trkKa.pt() * std::sin(phiRot); - - std::array pvec0rot = {_pxPr, _pyPr, _pzPr}; - std::array pvec1rot = {_pxKaRot, _pyKaRot, _pzKa}; - std::array, 2> arrMomRot = {pvec0rot, pvec1rot}; - - float _Mrot = RecoDecay::m(arrMomRot, std::array{MassProton, MassKaonCharged}); - float _ptRot = RecoDecay::pt(std::array{_pxPr + _pxKaRot, _pyPr + _pyKaRot}); - - float _yrot = std::abs(RecoDecay::y(std::array{_pxPr + _pxKaRot, _pyPr + _pyKaRot, _pzPr + _pzKa}, MassLambda1520)); - - float _yshiftrot = _yrot - cfgRapidityShift; - - if (std::abs(_yshiftrot) > cfgRapidityCut) - continue; - - if (trkPr.sign() * trkKa.sign() < 0) { - if (trkPr.sign() > 0) - histos.fill(HIST("Analysis/h4d_lstar_invm_rot_PM"), _Mrot, _ptRot, mult, occup); - else - histos.fill(HIST("Analysis/h4d_lstar_invm_rot_MP"), _Mrot, _ptRot, mult, occup); - } - } - } - } else { - if (trkPr.sign() > 0) { - histos.fill(HIST("Analysis/h4d_lstar_invm_PP"), _M, _pt, mult, occup); - } else { - histos.fill(HIST("Analysis/h4d_lstar_invm_MM"), _M, _pt, mult, occup); - } - } - } - - if constexpr (mix) { - if (trkPr.sign() * trkKa.sign() < 0) { - if (trkPr.sign() > 0) - histos.fill(HIST("Analysis/h4d_lstar_invm_US_PM_mix"), _M, _pt, mult, occup); - else - histos.fill(HIST("Analysis/h4d_lstar_invm_US_MP_mix"), _M, _pt, mult, occup); - } else { - if (trkPr.sign() > 0) - histos.fill(HIST("Analysis/h4d_lstar_invm_LS_PP_mix"), _M, _pt, mult, occup); - else - histos.fill(HIST("Analysis/h4d_lstar_invm_LS_MM_mix"), _M, _pt, mult, occup); - } - } - if constexpr (mc) { - if (trkPr.sign() * trkKa.sign() < 0) { - if (std::abs(trkPr.pdgCode()) != 2212 || std::abs(trkKa.pdgCode()) != 321) - continue; - - if (trkPr.motherId() != trkKa.motherId()) - continue; - if (trkPr.motherPDG() != trkKa.motherPDG()) - continue; - - if (trkPr.pdgCode() == 0 || trkKa.pdgCode() == 0) - continue; - - if (trkPr.motherPDG() == -1 || trkKa.motherPDG() == -1) - continue; - - if (std::abs(trkPr.motherPDG()) != lambda1520id) // L* pdg_code = 3124 - continue; - - float massParent = 0.; - for (auto const& _part : *mResoParents) { - if (_part.mcParticleId() == trkPr.motherId()) { - std::array pvecParent = {_part.px(), _part.py(), _part.pz()}; - massParent = RecoDecay::m(pvecParent, _part.e()); - break; - } - } - - float _MRes = _M - massParent; - if (trkPr.motherPDG() > 0) { - histos.fill(HIST("Analysis/h3d_rec_lstar_PM"), _M, _pt, mult); - histos.fill(HIST("Analysis/h3d_reso_lstar_PM"), _MRes, _pt, mult); - } else { - histos.fill(HIST("Analysis/h3d_rec_lstar_MP"), _M, _pt, mult); - histos.fill(HIST("Analysis/h3d_reso_lstar_MP"), _MRes, _pt, mult); - } - } - } - } - } - - using resoCols = soa::Join; - using resoMCCols = soa::Join; - - using resoTracks = aod::ResoTracks; - - void processData(resoCols::iterator const& collision, resoTracks const& tracks) - { - - if (cEvtRecINELgt0 && !collision.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; - - // LOGF(info, " collisions: Index = %d %d", collision.globalIndex(),tracks.size()); - histos.fill(HIST("Event/h1d_ft0_mult_percentile"), collision.cent(), 100); - histos.fill(HIST("Event/h_ft0_vz"), collision.posZ()); - - fillDataHistos(tracks, tracks, collision.cent()); - } - - PROCESS_SWITCH(lambdaAnalysis_pb, processData, "Process for Same Event Data", true); - - void processMC(resoMCCols::iterator const& collision, - soa::Join const& tracks, aod::ResoMCParents const& resoParents) - { - histos.fill(HIST("Event/hMCEventCutflow"), 0); // All collisions - - if (cEvtMCTriggerTVX && !collision.isTriggerTVX()) - return; - histos.fill(HIST("Event/hMCEventCutflow"), 1); // After TriggerTVX - - if (cEvtMCVtxIn10 && !collision.isVtxIn10()) - return; - histos.fill(HIST("Event/hMCEventCutflow"), 2); // After VtxIn10 - - if (cEvtMCINELgt0 && !collision.isINELgt0()) - return; - histos.fill(HIST("Event/hMCEventCutflow"), 3); // After INELgt0 - - if (cEvtMCSel8 && !collision.isInSel8()) - return; - histos.fill(HIST("Event/hMCEventCutflow"), 4); // After Sel8 - - if (cEvtRecINELgt0 && !collision.isRecINELgt0()) - return; - histos.fill(HIST("Event/hMCEventCutflow"), 5); // After RecINELgt0 - - if (cEvtMCAfterAllCuts && !collision.isInAfterAllCuts()) - return; - histos.fill(HIST("Event/hMCEventCutflow"), 6); // After AfterAllCuts auto mult = collision.cent(); - - auto mult = collision.cent(); - histos.fill(HIST("Event/h1d_ft0_mult_percentile"), mult, 100); - histos.fill(HIST("Event/h_ft0_vz"), collision.posZ()); - mResoParents = &resoParents; - fillDataHistos(tracks, tracks, mult); - - // get MC pT-spectra - for (auto const& track : tracks) { - histos.fill(HIST("QAbefore/hEta_rec"), track.eta()); - histos.fill(HIST("QAbefore/hPt_rec"), track.pt()); - histos.fill(HIST("QAbefore/hPhi_rec"), track.phi()); - histos.fill(HIST("QAbefore/hEtaPhi_rec"), track.eta(), track.phi()); - // get the generated level pT spectra of protons and kaons - if (std::abs(track.pdgCode()) == 321) - histos.fill(HIST("QAChecks/h1d_ka_gen_pt"), track.pt()); - if (std::abs(track.pdgCode()) == 2212) - histos.fill(HIST("QAChecks/h1d_pr_gen_pt"), track.pt()); - // get the reconstructed level pT spectra of protons and kaons - if (!selTracks(track)) - continue; - - float p = TMath::Sqrt(track.px() * track.px() + track.py() * track.py() + track.pz() * track.pz()); - - if (selectionPIDKaon(track, p)) { - if (std::abs(track.pdgCode()) == 321) { - histos.fill(HIST("QAChecks/h1d_ka_rec_pt"), track.pt()); - } - } - - if (selectionPIDProton(track, p)) { - if (std::abs(track.pdgCode()) == 2212) { - histos.fill(HIST("QAChecks/h1d_pr_rec_pt"), track.pt()); - } - } - } - - for (auto const& part : resoParents) { - if (std::abs(part.pdgCode()) != lambda1520id) // // L* pdg_code = 3124 - continue; - - float yshift = std::abs(part.y()) - cfgRapidityShift; - - if (std::abs(yshift) > cfgRapidityCut) - continue; - bool pass1 = false; - bool pass2 = false; - - if (abs(part.daughterPDG1()) == 2212 || abs(part.daughterPDG2()) == 2212) { // At least one decay to Proton - pass1 = true; - } - if (abs(part.daughterPDG1()) == 321 || abs(part.daughterPDG2()) == 321) { // At least one decay to Kaon - pass2 = true; - } - - if (!pass1 || !pass2) // If we have both decay products - continue; - std::array pvec = {part.px(), part.py(), part.pz()}; - float mass = RecoDecay::m(pvec, part.e()); - if (part.pdgCode() > 0) - histos.fill(HIST("Analysis/h3d_gen_lstar_PM"), mass, part.pt(), mult); - else - histos.fill(HIST("Analysis/h3d_gen_lstar_MP"), mass, part.pt(), mult); - } - } - PROCESS_SWITCH(lambdaAnalysis_pb, processMC, "Process Event for MC", false); - - void processMCGen(resoMCCols::iterator const& collision, - aod::ResoMCParents const& resoParents) - { - - float centrality = collision.cent(); - - histos.fill(HIST("SignalLoss/hMCEventCutflow"), 0); // All collisions - - if (cEvtMCTriggerTVX && !collision.isTriggerTVX()) - return; - histos.fill(HIST("SignalLoss/hMCEventCutflow"), 1); // After TriggerTVX - - if (cEvtMCVtxIn10 && !collision.isVtxIn10()) - return; - histos.fill(HIST("SignalLoss/hMCEventCutflow"), 2); // After VtxIn10 - - if (cEvtMCINELgt0 && !collision.isINELgt0()) - return; - histos.fill(HIST("SignalLoss/hMCEventCutflow"), 3); // After INELgt0 - - if (cEvtMCSel8 && !collision.isInSel8()) - return; - histos.fill(HIST("SignalLoss/hMCEventCutflow"), 4); // After Sel8 - - if (cEvtRecINELgt0 && !collision.isRecINELgt0()) - return; - histos.fill(HIST("SignalLoss/hMCEventCutflow"), 5); // After RecINELgt0 - - if (cEvtMCAfterAllCuts && !collision.isInAfterAllCuts()) - return; - histos.fill(HIST("SignalLoss/hMCEventCutflow"), 6); // After AfterAllCuts - - for (auto const& part : resoParents) { - - float yshift = std::abs(part.y()) - cfgRapidityShift; - - if (std::abs(yshift) > cfgRapidityCut) - continue; - - int pdg = part.pdgCode(); - float ptRef = part.pt(); - double ptSq = -1.0; - - std::array pvec = {part.px(), part.py(), part.pz()}; - float mass = RecoDecay::m(pvec, part.e()); - - if (pdg == 2212) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_Proton"), std::sqrt(ptSq), centrality); - } else if (pdg == -2212) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_AntiProton"), std::sqrt(ptSq), centrality); - } else if (pdg == 3122) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_Lambda0"), std::sqrt(ptSq), centrality); - } else if (pdg == -3122) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_AntiLambda0"), std::sqrt(ptSq), centrality); - } else if (pdg == 3312) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_XiMinus"), std::sqrt(ptSq), centrality); - } else if (pdg == -3312) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_XiPlus"), std::sqrt(ptSq), centrality); - } else if (pdg == 3322) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_Xi0"), std::sqrt(ptSq), centrality); - } else if (pdg == -3322) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_AntiXi0"), std::sqrt(ptSq), centrality); - } else if (pdg == 3334) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_OmegaMinus"), std::sqrt(ptSq), centrality); - } else if (pdg == -3334) { - ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); - if (ptSq > 0) - histos.fill(HIST("SignalLoss/hGen_mT_scaled_OmegaPlus"), std::sqrt(ptSq), centrality); - } - } - } - - PROCESS_SWITCH(lambdaAnalysis_pb, processMCGen, "Process Event for MC", false); - - using BinningType2 = ColumnBinningPolicy; - - void processMix(resoCols& collisions, resoTracks const& tracks) - { - LOGF(debug, "Event Mixing Started"); - - BinningType2 binningPositions2{{cMixVtxBins, cMixMultBins}, true}; - auto tracksTuple = std::make_tuple(tracks); - - SameKindPair pairs{binningPositions2, cNumMixEv, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto& [c1, t1, c2, t2] : pairs) { - - if (cEvtRecINELgt0 && !c1.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; - - // LOGF(info, "processMCMixedDerived: Mixed collisions : %d (%.3f, %.3f,%d), %d (%.3f, %.3f,%d)",c1.globalIndex(), c1.posZ(), c1.cent(),c1.mult(), c2.globalIndex(), c2.posZ(), c2.cent(),c2.mult()); - histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ(), c1.evtPl()); - fillDataHistos(t1, t2, c1.cent()); - } - } - - PROCESS_SWITCH(lambdaAnalysis_pb, processMix, "Process for Mixed Events", true); - - Preslice perRColdf = aod::resodaughter::resoCollisionDFId; - - using resoColDFs = aod::ResoCollisionDFs; - using resoTrackDFs = aod::ResoTrackDFs; - - void processDatadf(resoColDFs::iterator const& collision, resoTrackDFs const& tracks) - { - - if (doprocessData) - LOG(error) << "Disable processData() first!"; - if (cEvtRecINELgt0 && !collision.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; - - auto _occup = 100; - if (ConfEvtOccupancyInTimeRange) - _occup = collision.trackOccupancyInTimeRange(); - - // LOGF(info, "inside df collisions: Index = %d %d", collision.globalIndex(),tracks.size()); - histos.fill(HIST("Event/h1d_ft0_mult_percentile"), collision.cent(), _occup); - fillDataHistos(tracks, tracks, collision.cent(), _occup); - } - - PROCESS_SWITCH(lambdaAnalysis_pb, processDatadf, "Process for data merged DF", false); - - using BinningTypeDF = ColumnBinningPolicy; - void processMixDF(resoColDFs& collisions, resoTrackDFs const& tracks) - { - if (doprocessMix) - LOG(fatal) << "Disable processMix() first!"; - LOGF(debug, "Event Mixing Started"); - - BinningTypeDF binningPositions2{{cMixVtxBins, cMixMultBins}, true}; - auto tracksTuple = std::make_tuple(tracks); - - SameKindPair pairs{binningPositions2, cNumMixEv, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto& [c1, t1, c2, t2] : pairs) { - if (cEvtRecINELgt0 && !c1.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; - - auto _occup = 100; - if (ConfEvtOccupancyInTimeRange) - _occup = c1.trackOccupancyInTimeRange(); - - // LOGF(info, "processMCMixedDerived: Mixed collisions : %d (%.3f, %.3f,%d), %d (%.3f, %.3f,%d)",c1.globalIndex(), c1.posZ(), c1.cent(),c1.mult(), c2.globalIndex(), c2.posZ(), c2.cent(),c2.mult()); - histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ(), c1.evtPl()); - fillDataHistos(t1, t2, c1.cent(), _occup); - } - } - - PROCESS_SWITCH(lambdaAnalysis_pb, processMixDF, "Process for merged DF Mixed Events", false); - - using BinningTypeEP = ColumnBinningPolicy; - void processMixepDF(resoColDFs& collisions, resoTrackDFs const& tracks) - { - if (doprocessMix || doprocessMixDF) - LOG(fatal) << "Disable processMix() or processMixDF() first!"; - LOGF(debug, "Event Mixing Started"); - BinningTypeEP binningPositions2{{cMixVtxBins, cMixMultBins, cMixEPAngle}, true}; - auto tracksTuple = std::make_tuple(tracks); - - SameKindPair pairs{binningPositions2, cNumMixEv, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto& [c1, t1, c2, t2] : pairs) { - // LOGF(info, "processMCMixedDerived: Mixed collisions : %d (%.3f, %.3f,%.3f), %d (%.3f, %.3f, %.3f)",c1.globalIndex(), c1.posZ(), c1.cent(),c1.evtPl(), c2.globalIndex(), c2.posZ(), c2.cent(),c2.evtPl()); - histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ(), c1.evtPl()); - fillDataHistos(t1, t2, c1.cent()); - } - } - - PROCESS_SWITCH(lambdaAnalysis_pb, processMixepDF, "Process for merged DF Mixed Events", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} diff --git a/PWGLF/Tasks/Resonances/lambda1520pbpb.cxx b/PWGLF/Tasks/Resonances/lambda1520pbpb.cxx new file mode 100644 index 00000000000..8cc51ed2294 --- /dev/null +++ b/PWGLF/Tasks/Resonances/lambda1520pbpb.cxx @@ -0,0 +1,1245 @@ +// 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 lambda1520pbpb.cxx +/// \brief Invariant-mass reconstruction and cosThetaStar polarization/spin-alignment +/// analysis (Helicity / Collins-Soper / Production / Beam-axis / Random frames) +/// of the Lambda(1520) resonance in Pb-Pb collisions. +/// +/// \author Dukhishyam Mallick +/// \author Nasir Mehdi Malik + +#include "PWGLF/DataModel/LFResonanceTables.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +struct Lambda1520pbpb { + SliceCache cache; + Preslice perRCol = aod::resodaughter::resoCollisionId; + Preslice perCollision = aod::track::collisionId; + // Configurables. + aod::ResoMCParents const* mResoParents = nullptr; + Configurable cfgEvtOccupancyInTimeRange{"cfgEvtOccupancyInTimeRange", false, "occupancy selection true or false"}; + Configurable nBinsPt{"nBinsPt", 100, "N bins in pT histogram"}; + Configurable nBinsInvM{"nBinsInvM", 120, "N bins in InvMass histogram"}; + Configurable lambda1520id{"lambda1520id", 3124, "pdg"}; + Configurable doRotate{"doRotate", true, "rotated inv mass spectra"}; + // Tracks + Configurable cPtMin{"cPtMin", 0.15, "Minimum Track pT"}; + Configurable cPMin{"cPMin", 0., "Minimum Track p"}; + Configurable cEtaCut{"cEtaCut", 0.8, "Pseudorapidity cut"}; + Configurable cDcazMin{"cDcazMin", 1., "Minimum DCAz"}; + Configurable cfgRapidityShift{"cfgRapidityShift", 0., " rapidity shift"}; + Configurable cfgRapidityCut{"cfgRapidityCut", 0.5, "Rapidity window"}; + // TPC crossed rows (absolute) + Configurable cfgMinCrossedRows{"cfgMinCrossedRows", 70, "min TPC crossed rows"}; + Configurable cfgUseCrossedRows{"cfgUseCrossedRows", false, "apply crossed rows cut"}; + + Configurable cfgMinTPCcls{"cfgMinTPCcls", 70, "min TPC clusters found"}; + Configurable cfgUseTPCcls{"cfgUseTPCcls", false, "apply TPC clusters cut"}; + + Configurable> cDcaPtBinsPr{"cDcaPtBinsPr", {0.0f, 0.5f, 1.0f, 2.0f, 3.0f, 5.0f, 1000.0f}, "Proton pT bin edges for DCAxy cut"}; + Configurable> cDcaXYBinsPr{"cDcaXYBinsPr", {0.020f, 0.015f, 0.010f, 0.007f, 0.005f, 0.004f}, "Proton max |DCAxy| per pT bin (cm)"}; + + // Kaon DCAxy — pT binned + Configurable> cDcaPtBinsKa{"cDcaPtBinsKa", {0.0f, 0.3f, 0.6f, 1.0f, 2.0f, 1000.0f}, "Kaon pT bin edges for DCAxy cut"}; + Configurable> cDcaXYBinsKa{"cDcaXYBinsKa", {0.025f, 0.018f, 0.012f, 0.008f, 0.004f}, "Kaon max |DCAxy| per pT bin (cm)"}; + + Configurable isonlyQC{"isonlyQC", false, "only QC"}; + Configurable isDeepAngle{"isDeepAngle", false, "Deep Angle cut"}; + Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; + Configurable cKinCuts{"cKinCuts", false, "Kinematic Cuts for p-K pair opening angle"}; + Configurable cPrimaryTrack{"cPrimaryTrack", true, "Primary track selection"}; + Configurable cGlobalWoDCATrack{"cGlobalWoDCATrack", true, "Global track selection without DCA"}; + Configurable cPVContributor{"cPVContributor", true, "PV contributor track selection"}; + + // PID Selections + Configurable cUseOnlyTOFTrackPr{"cUseOnlyTOFTrackPr", false, "Use only TOF track for PID selection"}; + Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; + Configurable cUseTpcOnly{"cUseTpcOnly", false, "Use TPC Only selection"}; + Configurable cRejNsigmaTpc{"cRejNsigmaTpc", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmaTpcPi{"cRejNsigmaTpcPi", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmaTpcKa{"cRejNsigmaTpcKa", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmakTpcPi{"cRejNsigmakTpcPi", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmakTpcPr{"cRejNsigmakTpcPr", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable minnsigmatpcKa{"minnsigmatpcKa", -6.0, "Reject tracks to improve purity of TPC PID"}; + Configurable minnsigmatpcPr{"minnsigmatpcPr", -6.0, "Reject tracks to improve purity of TPC PID"}; + Configurable minnsigmatofKa{"minnsigmatofKa", -6.0, "Reject tracks to improve purity of TofPID"}; + Configurable minnsigmatofPr{"minnsigmatofPr", -6.0, "Reject tracks to improve purity of Tof PID"}; + Configurable minnsigmatpctofKa{"minnsigmatpctofKa", -6.0, "Reject tracks to improve purity of TPC PID"}; + Configurable minnsigmatpctofPr{"minnsigmatpctofPr", -6.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmaTpcVeto{"cRejNsigmaTpcVeto", 3.0, "Reject tracks to improve purity of TPC PID"}; + Configurable cRejNsigmaTof{"cRejNsigmaTof", 3.0, "Reject tracks to improve purity of TOF PID"}; + + // Proton + Configurable cMaxTPCnSigmaProton{"cMaxTPCnSigmaProton", 3.0, "TPC nSigma cut for Proton"}; + Configurable nsigmaCutCombinedProton{"nsigmaCutCombinedProton", 3.0, "Combined nSigma cut for Proton"}; + Configurable> protonTPCPIDp{"protonTPCPIDp", {0, 0.5, 0.7, 0.8}, "p dependent TPC cuts protons"}; + Configurable> protonTPCPIDcut{"protonTPCPIDcut", {5., 3.5, 2.5}, "TPC nsigma cuts protons"}; + Configurable> protonTOFPIDp{"protonTOFPIDp", {0., 999.}, "p dependent TOF cuts protons"}; + Configurable> protonTOFPIDcut{"protonTOFPIDcut", {3.0}, "TOF nsigma cuts protons"}; + + // Kaon + Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; + Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", 3.0, "Combined nSigma cut for Kaon"}; + Configurable> kaonTPCPIDp{"kaonTPCPIDp", {0., 0.25, 0.3, 0.45}, "pT dependent TPC cuts kaons"}; + Configurable> kaonTPCPIDcut{"kaonTPCPIDcut", {6, 3.5, 2.5}, "TPC nsigma cuts kaons"}; + Configurable> kaonTOFPIDp{"kaonTOFPIDp", {0., 999.}, "p dependent TOF cuts kaons"}; + Configurable> kaonTOFPIDcut{"kaonTOFPIDcut", {3.0}, "TOF nsigma cuts kaons"}; + + // Event Mixing. + Configurable cNumMixEv{"cNumMixEv", 20, "Number of Events to be mixed"}; + ConfigurableAxis cDcaZBins{"cDcaZBins", {VARIABLE_WIDTH, -1.2f, -1.0f, -0.9f, -0.8f, -0.7f, -0.6f, -0.5f, -0.4f, -0.3f, -0.2f, -0.1f, 0.f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f}, "DCA - z-vertex"}; + ConfigurableAxis cMixVtxBins{"cMixVtxBins", {VARIABLE_WIDTH, -10.0f, -9.f, -8.f, -7.f, -6.f, -5.f, -4.f, -3.f, -2.f, -1.f, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis cMixMultBins{"cMixMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 200.0f}, "Mixing bins - multiplicity"}; + ConfigurableAxis cMixEPAngle{"cMixEPAngle", {VARIABLE_WIDTH, -1.5708f, -1.25664f, -0.942478f, -0.628319f, 0.f, 0.628319f, 0.942478f, 1.25664f, 1.5708f}, "event plane"}; + ConfigurableAxis occupancyBins{"occupancyBins", {VARIABLE_WIDTH, 0.0, 100, 500, 600, 1000, 1100, 1500, 1600, 2000, 2100, 2500, 2600, 3000, 3100, 3500, 3600, 4000, 4100, 4500, 4600, 5000, 5100, 9999}, "Binning of the occupancy axis"}; + Configurable cNofRotations{"cNofRotations", 10, "Number of rotations for rotational background"}; + Configurable rotationalcut{"rotationalcut", 6.f, "Rotational background angle window: PI/rotationalcut"}; + + // ── MC Event Selection Configurables ───────────────────────────────────── + Configurable cEvtMCAfterAllCuts{"cEvtMCAfterAllCuts", false, "MC event sel: isInAfterAllCuts"}; + Configurable cEvtMCINELgt0{"cEvtMCINELgt0", false, "MC event sel: isINELgt0"}; + Configurable cEvtMCSel8{"cEvtMCSel8", false, "MC event sel: isInSel8"}; + Configurable cEvtMCVtxIn10{"cEvtMCVtxIn10", false, "MC event sel: isVtxIn10"}; + Configurable cEvtMCTriggerTVX{"cEvtMCTriggerTVX", false, "MC event sel: isTriggerTVX"}; + Configurable cEvtMCRecINELgt0{"cEvtMCRecINELgt0", false, "MC event sel: isRecINELgt0"}; + + // ── Polarization / angular-distribution (cosThetaStar) Configurables ───── + Configurable cPolarizationRefDaughter{"cPolarizationRefDaughter", 0, "Reference daughter for cosThetaStar: 0 = proton, 1 = kaon"}; + Configurable cActivateHelicityFrame{"cActivateHelicityFrame", false, "Compute cosThetaStar in the Helicity frame"}; + Configurable cActivateCollinsSoperFrame{"cActivateCollinsSoperFrame", false, "Compute cosThetaStar in the Collins-Soper frame"}; + Configurable cActivateProductionFrame{"cActivateProductionFrame", false, "Compute cosThetaStar wrt the production-plane normal"}; + Configurable cActivateBeamAxisFrame{"cActivateBeamAxisFrame", false, "Compute cosThetaStar in the beam-axis (Gottfried-Jackson) frame"}; + Configurable cActivateRandomFrame{"cActivateRandomFrame", false, "Compute cosThetaStar wrt a random axis (null/control test, should be flat)"}; + Configurable doPolarizationRot{"doPolarizationRot", false, "Also fill rotated-background polarization histograms"}; + Configurable doPolarizationMix{"doPolarizationMix", false, "Also fill mixed-event-background polarization histograms"}; + Configurable cfgBeamEnergy{"cfgBeamEnergy", 13600.0, "sqrt(s) beam energy in GeV (used for Collins-Soper/beam-axis/production frames)"}; + ConfigurableAxis cCosThetaBins{"cCosThetaBins", {20, -1.0f, 1.0f}, "cosThetaStar binning"}; + + float beam1E = 0.f; + std::array beam1P{}; + float beam2E = 0.f; + std::array beam2P{}; + + std::mt19937 randGen{std::random_device{}()}; + std::uniform_real_distribution randUniform01{0., 1.}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + const AxisSpec axisCent(110, 0, 110, "FT0 (%)"); + const AxisSpec axisPpid(200, 0., 10., "p (GeV/c)"); + const AxisSpec axisPtpid(200, 0., 10., "p_{T} (GeV/c)"); + const AxisSpec axisPt(nBinsPt, 0., 10., "p_{T} (GeV/c)"); + const AxisSpec axisEta(40, -1, 1, "#eta"); + const AxisSpec axisDCAxy(240, -0.12, 0.12, {"DCA_{xy} (cm)"}); + const AxisSpec axisTPCNsigma(401, -10.025, 10.025, {"n#sigma^{TPC}"}); + const AxisSpec axisTOFNsigma(401, -10.025, 10.025, {"n#sigma^{TOF}"}); + const AxisSpec axisdEdx(380, 10, 200, {"#frac{dE}{dx}"}); + const AxisSpec axisVz(120, -12, 12, {"vz"}); + const AxisSpec axisEP(120, -3.14, 3.14, {"#theta"}); + const AxisSpec axisInvM(nBinsInvM, 1.4, 2.0, {"M_{inv} (GeV/c^{2})"}); + AxisSpec axisOccupancy = {occupancyBins, "Occupancy [-40,100]"}; + AxisSpec axisDCAz = {cDcaZBins, "DCA_{z} (cm)"}; + + double beamMomentum = std::sqrt(cfgBeamEnergy * cfgBeamEnergy / 4. - MassProton * MassProton); + beam1E = static_cast(cfgBeamEnergy * 0.5); + beam1P = {0.f, 0.f, static_cast(-beamMomentum)}; + beam2E = static_cast(cfgBeamEnergy * 0.5); + beam2P = {0.f, 0.f, static_cast(beamMomentum)}; + + histos.add("Event/h1d_ft0_mult_percentile", "FT0 (%)", kTH2F, {axisCent, axisOccupancy}); + histos.add("Event/h_ft0_vz", "Collision Vertex Z position", kTH1F, {{100, -15., 15.}}); + if (doprocessMix || doprocessMixDF || doprocessMixepDF) { + histos.add("Event/mixing_vzVsmultpercentile", "FT0(%)", kTH3F, {axisCent, axisVz, axisEP}); + } + + // QA Before + histos.add("QAbefore/hEta_rec", "Reco dN/d#eta; #eta; dN/d#eta", kTH1F, {{50, -1.0, 1.0}}); + histos.add("QAbefore/hPt_rec", "Reco pT; p_{T} (GeV/c); Tracks", kTH1F, {axisPpid}); + histos.add("QAbefore/hPhi_rec", "Reco #varphi; #varphi (rad); Tracks", kTH1F, {{72, 0, 6.2832}}); + histos.add("QAbefore/hEtaPhi_rec", "Reco #eta vs #varphi; #eta; #varphi", kTH2F, {axisEta, {72, 0, 6.2832}}); + histos.add("QAbefore/Proton/h2d_pr_nsigma_tpc_p", "n#sigma^{TPC} Protons", kTH2F, {axisPpid, axisTPCNsigma}); + histos.add("QAbefore/Proton/h2d_pr_nsigma_tof_p", "n#sigma^{TOF} Protons", kTH2F, {axisPpid, axisTOFNsigma}); + histos.add("QAbefore/Proton/h2d_pr_nsigma_tof_vs_tpc", "n#sigma^{TPC} vs n#sigma^{TOF} Protons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); + histos.add("QAbefore/Kaon/h2d_ka_nsigma_tpc_p", "n#sigma^{TPC} Kaons", kTH2F, {axisPpid, axisTPCNsigma}); + histos.add("QAbefore/Kaon/h2d_ka_nsigma_tof_p", "n#sigma^{TOF} Kaons", kTH2F, {axisPpid, axisTOFNsigma}); + histos.add("QAbefore/Kaon/h2d_ka_nsigma_tof_vs_tpc", "n#sigma^{TPC} vs n#sigma^{TOF} Kaons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); + + // ======================================================================== + // QA After - Protons + // ======================================================================== + // 1. Base QA (Filled for all tracks) + histos.add("QAafter/Proton/h2d_pr_dca_z", "dca_{z} Protons", kTH2F, {axisPtpid, axisDCAz}); + histos.add("QAafter/Proton/h2d_pr_dca_xy", "dca_{xy} Protons", kTH2F, {axisPtpid, axisDCAxy}); + histos.add("QAafter/Proton/h2d_pr_dEdx_p", "TPC Signal Protons", kTH2F, {axisPpid, axisdEdx}); + histos.add("QAafter/Proton/hTPCNClsCrossedRowsVsPt", "TPC Crossed Rows vs pT;p_{T} (GeV/c);N_{cls,crossed};Counts", kTH2F, {axisPtpid, {200, 0, 200}}); + histos.add("QAafter/Proton/hTPCNClsFoundVsPt", "TPC Found Clusters vs pT;p_{T} (GeV/c);N_{cls,found};Counts", kTH2F, {axisPtpid, {200, 0, 200}}); + histos.add("QAafter/Proton/hFracTPConly_Proton", "Proton candidates using TPC-only PID;p (GeV/c);TPC-only (0=no,1=yes)", kTH2F, {axisPpid, {2, 0, 2}}); + + // 2. TPC-Only Split + histos.add("QAafter/Proton/hd_pr_pt_TPConly", "p_{T}-spectra Protons, TPC-only PID", kTH2F, {axisPtpid, axisCent}); + histos.add("QAafter/Proton/h2d_pr_nsigma_tpc_pt_TPConly", "Protons, TPC-only PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Proton/h2d_Prpi_nsigma_tpc_p_TPConly", "Protons pion, TPC-only PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Proton/h2d_Prka_nsigma_tpc_p_TPConly", "Protons kaon, TPC-only PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Proton/h2d_pr_nsigma_tpc_p_TPConly", "Protons, TPC-only PID", kTH2F, {axisPpid, axisTPCNsigma}); + + // 3. hasTOF Split + histos.add("QAafter/Proton/hd_pr_pt_hasTOF", "p_{T}-spectra Protons, hasTOF PID", kTH2F, {axisPtpid, axisCent}); + histos.add("QAafter/Proton/h2d_pr_nsigma_tpc_pt_hasTOF", "Protons, hasTOF PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Proton/h2d_Prpi_nsigma_tpc_p_hasTOF", "Protons pion, hasTOF PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Proton/h2d_Prka_nsigma_tpc_p_hasTOF", "Protons kaon, hasTOF PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Proton/h2d_pr_nsigma_tpc_p_hasTOF", "Protons, hasTOF PID", kTH2F, {axisPpid, axisTPCNsigma}); + + // 4. TOF-Specific (Only possible if hasTOF) + histos.add("QAafter/Proton/h2d_pr_nsigma_tof_pt", " Protons", kTH2F, {axisPtpid, axisTOFNsigma}); + histos.add("QAafter/Proton/h2d_pr_nsigma_tof_p", " Protons", kTH2F, {axisPpid, axisTOFNsigma}); + histos.add("QAafter/Proton/h2d_Prpi_nsigma_tof_p", " Protons pion", kTH2F, {axisPpid, axisTOFNsigma}); + histos.add("QAafter/Proton/h2d_Prka_nsigma_tof_p", " Protons kaon", kTH2F, {axisPpid, axisTOFNsigma}); + histos.add("QAafter/Proton/h2d_pr_nsigma_tof_vs_tpc", "n#sigma(TOF) vs n#sigma(TPC) Protons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); + + // ======================================================================== + // QA After - Kaons + // ======================================================================== + // 1. Base QA (Filled for all tracks) + histos.add("QAafter/Kaon/h2d_ka_dca_z", "dca_{z} Kaons", kTH2F, {axisPtpid, axisDCAz}); + histos.add("QAafter/Kaon/h2d_ka_dca_xy", "dca_{xy} Kaons", kTH2F, {axisPtpid, axisDCAxy}); + histos.add("QAafter/Kaon/h2d_ka_dEdx_p", "TPC Signal Kaon", kTH2F, {axisPpid, axisdEdx}); + histos.add("QAafter/Kaon/hTPCNClsCrossedRowsVsPt", "TPC Crossed Rows vs pT;p_{T} (GeV/c);N_{cls,crossed};Counts", kTH2F, {axisPtpid, {200, 0, 200}}); + histos.add("QAafter/Kaon/hTPCNClsFoundVsPt", "TPC Found Clusters vs pT;p_{T} (GeV/c);N_{cls,found};Counts", kTH2F, {axisPtpid, {200, 0, 200}}); + histos.add("QAafter/Kaon/hFracTPConly_Kaon", "Kaon candidates using TPC-only PID;p (GeV/c);TPC-only (0=no,1=yes)", kTH2F, {axisPpid, {2, 0, 2}}); + + // 2. TPC-Only Split + histos.add("QAafter/Kaon/hd_ka_pt_TPConly", "p_{T}-spectra Kaons, TPC-only PID", kTH2F, {axisPtpid, axisCent}); + histos.add("QAafter/Kaon/h2d_ka_nsigma_tpc_pt_TPConly", "Kaons, TPC-only PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Kaon/h2d_Kapi_nsigma_tpc_p_TPConly", "Kaons pion, TPC-only PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Kaon/h2d_Kapr_nsigma_tpc_p_TPConly", "Kaons proton, TPC-only PID", kTH2F, {axisPpid, axisTPCNsigma}); + histos.add("QAafter/Kaon/h2d_ka_nsigma_tpc_p_TPConly", "Kaons, TPC-only PID", kTH2F, {axisPpid, axisTPCNsigma}); + + // 3. hasTOF Split + histos.add("QAafter/Kaon/hd_ka_pt_hasTOF", "p_{T}-spectra Kaons, hasTOF PID", kTH2F, {axisPtpid, axisCent}); + histos.add("QAafter/Kaon/h2d_ka_nsigma_tpc_pt_hasTOF", "Kaons, hasTOF PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Kaon/h2d_Kapi_nsigma_tpc_p_hasTOF", "Kaons pion, hasTOF PID", kTH2F, {axisPtpid, axisTPCNsigma}); + histos.add("QAafter/Kaon/h2d_Kapr_nsigma_tpc_p_hasTOF", "Kaons proton, hasTOF PID", kTH2F, {axisPpid, axisTPCNsigma}); + histos.add("QAafter/Kaon/h2d_ka_nsigma_tpc_p_hasTOF", "Kaons, hasTOF PID", kTH2F, {axisPpid, axisTPCNsigma}); + + // 4. TOF-Specific (Only possible if hasTOF) + histos.add("QAafter/Kaon/h2d_ka_nsigma_tof_pt", " Kaons", kTH2F, {axisPtpid, axisTOFNsigma}); + histos.add("QAafter/Kaon/h2d_ka_nsigma_tof_p", " Kaons", kTH2F, {axisPpid, axisTOFNsigma}); + histos.add("QAafter/Kaon/h2d_Kapi_nsigma_tof_p", " Kaons pion", kTH2F, {axisPpid, axisTOFNsigma}); + histos.add("QAafter/Kaon/h2d_Kapr_nsigma_tof_p", " Kaons proton", kTH2F, {axisPpid, axisTOFNsigma}); + histos.add("QAafter/Kaon/h2d_ka_nsigma_tof_vs_tpc", "n#sigma(TOF) vs n#sigma(TPC) Kaons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); + + // Analysis + if (!doprocessMC) { + int nActiveFrames = static_cast(cActivateHelicityFrame) + + static_cast(cActivateCollinsSoperFrame) + + static_cast(cActivateProductionFrame) + + static_cast(cActivateBeamAxisFrame) + + static_cast(cActivateRandomFrame); + + bool polActive = nActiveFrames > 0; + + if (nActiveFrames > 1) { + LOG(fatal) << "Multiple polarization frames activated, but axisPolFrame was removed! " + << "Please activate only ONE frame at a time to prevent data mixing in the 4D sparse."; + } + + if (!polActive) { + histos.add("Analysis/h4d_lstar_invm_US_PM", "THn #Lambda(1520)", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + histos.add("Analysis/h4d_lstar_invm_US_MP", "THn #bar #Lambda(1520)", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + histos.add("Analysis/h4d_lstar_invm_PP", "THn Like Signs p K^{+}", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + histos.add("Analysis/h4d_lstar_invm_MM", "THn Like Signs #bar{p} K^{-}", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + + if (doRotate) { + histos.add("Analysis/h4d_lstar_invm_rot_PM", "THn Rotated", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + histos.add("Analysis/h4d_lstar_invm_rot_MP", "THn Rotated", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + } + + if (doprocessMix || doprocessMixDF || doprocessMixepDF) { + histos.add("Analysis/h4d_lstar_invm_US_PM_mix", "THn Mixed Events", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + histos.add("Analysis/h4d_lstar_invm_US_MP_mix", "THn anti Mixed Events", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + histos.add("Analysis/h4d_lstar_invm_LS_PP_mix", "THn Mixed Events PP", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + histos.add("Analysis/h4d_lstar_invm_LS_MM_mix", "THn Mixed Events MM", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + } + } + + // ── 4D Polarization / cosThetaStar histograms ────────────────────────── + if (polActive) { + const AxisSpec axisCosTheta{cCosThetaBins, "cos#theta*"}; + + histos.add("Analysis/h4d_pol_US_PM", "cos#theta* #Lambda(1520)", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + histos.add("Analysis/h4d_pol_US_MP", "cos#theta* #bar{#Lambda}(1520)", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + histos.add("Analysis/h4d_pol_LS_PP", "cos#theta* Like Signs p K^{+}", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + histos.add("Analysis/h4d_pol_LS_MM", "cos#theta* Like Signs #bar{p} K^{-}", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + + if (doPolarizationRot) { + histos.add("Analysis/h4d_pol_rot_PM", "cos#theta* Rotated bkg", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + histos.add("Analysis/h4d_pol_rot_MP", "cos#theta* Rotated bkg", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + } + + if (doPolarizationMix && (doprocessMix || doprocessMixDF || doprocessMixepDF)) { + histos.add("Analysis/h4d_pol_mix_PM", "cos#theta* Mixed-event bkg", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + histos.add("Analysis/h4d_pol_mix_MP", "cos#theta* Mixed-event bkg", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + histos.add("Analysis/h4d_pol_LS_PP_mix", "cos#theta* Mixed PP", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + histos.add("Analysis/h4d_pol_LS_MM_mix", "cos#theta* Mixed MM", kTHnSparseF, {axisInvM, axisPt, axisCent, axisCosTheta}); + } + } + } + + // MC + if (doprocessMC) { + histos.add("Event/hMCEventCutflow", "MC Event Cutflow", kTH1F, {{7, 0, 7}}); + histos.add("QAChecks/h1d_pr_rec_pt", "Reconstructed p_{T}-spectra Protons", kTH1F, {axisPtpid}); + histos.add("QAChecks/h1d_ka_rec_pt", "Recondstucted p_{T}-spectra Kaons", kTH1F, {axisPtpid}); + histos.add("QAChecks/h1d_pr_gen_pt", "Generated p_{T}-spectra Protons", kTH1F, {axisPtpid}); + histos.add("QAChecks/h1d_ka_gen_pt", "Generated p_{T}-spectra Kaons", kTH1F, {axisPtpid}); + + histos.add("Analysis/h3d_gen_lstar_PM", "Generated #Lambda(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); + histos.add("Analysis/h3d_gen_lstar_MP", "Generated #bar{#Lambda}(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); + histos.add("Analysis/h3d_rec_lstar_PM", "Reconstructed #Lambda(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); + histos.add("Analysis/h3d_rec_lstar_MP", "Reconstructed #bar{#Lambda}(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); + histos.add("Analysis/h3d_reso_lstar_PM", "Resolution #Lambda(1520) p_{T}", kTHnSparseF, {{200, -0.05, 0.05}, axisPt, axisCent}); + histos.add("Analysis/h3d_reso_lstar_MP", "Resolution #bar{#Lambda}(1520) p_{T}", kTHnSparseF, {{200, -0.05, 0.05}, axisPt, axisCent}); + } + + if (doprocessMCGen) { + histos.add("SignalLoss/hMCEventCutflow", "MC Event Cutflow", kTH1F, {{7, 0, 7}}); + histos.add("SignalLoss/hGen_mT_scaled_Proton", "mT Scaled #Lambda(1520) from Proton", kTHnSparseF, {axisPt, axisCent}); + histos.add("SignalLoss/hGen_mT_scaled_AntiProton", "mT Scaled #bar{#Lambda}(1520) from AntiProton", kTHnSparseF, {axisPt, axisCent}); + histos.add("SignalLoss/hGen_mT_scaled_Lambda0", "mT Scaled #Lambda(1520) from Lambda0", kTHnSparseF, {axisPt, axisCent}); + histos.add("SignalLoss/hGen_mT_scaled_AntiLambda0", "mT Scaled #bar{#Lambda}(1520) from AntiLambda0", kTHnSparseF, {axisPt, axisCent}); + histos.add("SignalLoss/hGen_mT_scaled_XiMinus", "mT Scaled #Lambda(1520) from Xi-", kTHnSparseF, {axisPt, axisCent}); + histos.add("SignalLoss/hGen_mT_scaled_XiPlus", "mT Scaled #bar{#Lambda}(1520) from Xi+", kTHnSparseF, {axisPt, axisCent}); + histos.add("SignalLoss/hGen_mT_scaled_Xi0", "mT Scaled #Lambda(1520) from Xi0", kTHnSparseF, {axisPt, axisCent}); + histos.add("SignalLoss/hGen_mT_scaled_AntiXi0", "mT Scaled #bar{#Lambda}(1520) from AntiXi0", kTHnSparseF, {axisPt, axisCent}); + histos.add("SignalLoss/hGen_mT_scaled_OmegaMinus", "mT Scaled #Lambda(1520) from Omega-", kTHnSparseF, {axisPt, axisCent}); + histos.add("SignalLoss/hGen_mT_scaled_OmegaPlus", "mT Scaled #bar{#Lambda}(1520) from Omega+", kTHnSparseF, {axisPt, axisCent}); + } + } + + template + bool selTracks(T const& track) + { + if (track.pt() < cPtMin) + return false; + if (std::abs(track.eta()) > cEtaCut) + return false; + if (cPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cPVContributor && !track.isPVContributor()) + return false; + if (cfgUseCrossedRows && track.tpcNClsCrossedRows() < cfgMinCrossedRows) + return false; + if (cfgUseTPCcls && track.tpcNClsFound() < cfgMinTPCcls) + return false; + return true; + } + + template + bool dcaSelectionProton(T const& track, float p) + { + auto ptBinsPr = static_cast>(cDcaPtBinsPr); + auto dcaXYPr = static_cast>(cDcaXYBinsPr); + int nBinsPr = static_cast(ptBinsPr.size()) - 1; + + bool dcaXYPassed = false; + for (int i = 0; i < nBinsPr; i++) { + if (p >= ptBinsPr[i] && p < ptBinsPr[i + 1] && + std::abs(track.dcaXY()) < dcaXYPr[i]) + dcaXYPassed = true; + } + if (!dcaXYPassed) + return false; + if (std::abs(track.dcaZ()) > cDcazMin) + return false; + return true; + } + + template + bool dcaSelectionKaon(T const& track, float p) + { + auto ptBinsKa = static_cast>(cDcaPtBinsKa); + auto dcaXYKa = static_cast>(cDcaXYBinsKa); + int nBinsKa = static_cast(ptBinsKa.size()) - 1; + + bool dcaXYPassed = false; + for (int i = 0; i < nBinsKa; i++) { + if (p >= ptBinsKa[i] && p < ptBinsKa[i + 1] && + std::abs(track.dcaXY()) < dcaXYKa[i]) + dcaXYPassed = true; + } + if (!dcaXYPassed) + return false; + if (std::abs(track.dcaZ()) > cDcazMin) + return false; + return true; + } + + template + bool selectionPIDProton(const T& candidate, float p) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + auto tpcPIDp = static_cast>(protonTPCPIDp); + auto tpcPIDcut = static_cast>(protonTPCPIDcut); + auto tofPIDp = static_cast>(protonTOFPIDp); + auto tofPIDcut = static_cast>(protonTOFPIDcut); + int nitr = static_cast(tpcPIDp.size()); + int nitrtof = static_cast(tofPIDp.size()); + + float tpcNsigmaPi = std::abs(candidate.tpcNSigmaPi()); + float tpcNsigmaKa = std::abs(candidate.tpcNSigmaKa()); + float tpcNsigmaPr = std::abs(candidate.tpcNSigmaPr()); + float tofNsigmaPi = std::abs(candidate.tofNSigmaPi()); + float tofNsigmaKa = std::abs(candidate.tofNSigmaKa()); + float tofNsigmaPr = std::abs(candidate.tofNSigmaPr()); + + float tpcTofNsigmaPi = tpcNsigmaPi * tpcNsigmaPi + tofNsigmaPi * tofNsigmaPi; + float tpcTofNsigmaKa = tpcNsigmaKa * tpcNsigmaKa + tofNsigmaKa * tofNsigmaKa; + float tpcTofNsigmaPr = tpcNsigmaPr * tpcNsigmaPr + tofNsigmaPr * tofNsigmaPr; + float combinedCut = nsigmaCutCombinedProton * nsigmaCutCombinedProton; + float combinedRejCut = cRejNsigmaTof * cRejNsigmaTpc; + + if (!cUseTpcOnly && candidate.hasTOF()) { + if (candidate.tofNSigmaPr() < minnsigmatofPr) + return false; + if (nsigmaCutCombinedProton < 0 && p >= cPMin) { + for (int i = 0; i < nitrtof - 1; ++i) { + if (p >= tofPIDp[i] && p < tofPIDp[i + 1] && (tofNsigmaPr < tofPIDcut[i] && tofNsigmaPi > cRejNsigmaTof && tofNsigmaKa > cRejNsigmaTof)) + tofPIDPassed = true; + } + if (candidate.tpcNSigmaPr() < minnsigmatpctofPr) + return false; + if (tpcNsigmaPr < cMaxTPCnSigmaProton && tpcNsigmaPi > cRejNsigmaTpcVeto && tpcNsigmaKa > cRejNsigmaTpcVeto) + tpcPIDPassed = true; + } + + if ((nsigmaCutCombinedProton > 0) && p >= cPMin && (tpcTofNsigmaPr < combinedCut && tpcTofNsigmaPi > combinedRejCut && tpcTofNsigmaKa > combinedRejCut)) { + tofPIDPassed = true; + tpcPIDPassed = true; + } + + if (p < cPMin && tpcNsigmaPr < cMaxTPCnSigmaProton) { + tofPIDPassed = true; + tpcPIDPassed = true; + } + } else { + tofPIDPassed = true; + if (candidate.tpcNSigmaPr() < minnsigmatpcPr) + return false; + for (int i = 0; i < nitr - 1; ++i) { + if (p >= tpcPIDp[i] && p < tpcPIDp[i + 1] && (tpcNsigmaPr < tpcPIDcut[i] && tpcNsigmaPi > cRejNsigmaTpcPi && tpcNsigmaKa > cRejNsigmaTpcKa)) { + tpcPIDPassed = true; + } + } + } + if (tpcPIDPassed && tofPIDPassed) + return true; + return false; + } + + template + bool selectionPIDKaon(const T& candidate, float p) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + auto tpcPIDp = static_cast>(kaonTPCPIDp); + auto tpcPIDcut = static_cast>(kaonTPCPIDcut); + auto tofPIDp = static_cast>(kaonTOFPIDp); + auto tofPIDcut = static_cast>(kaonTOFPIDcut); + int nitr = static_cast(tpcPIDp.size()); + int nitrtof = static_cast(tofPIDp.size()); + + float tpcNsigmaPi = std::abs(candidate.tpcNSigmaPi()); + float tpcNsigmaKa = std::abs(candidate.tpcNSigmaKa()); + float tpcNsigmaPr = std::abs(candidate.tpcNSigmaPr()); + float tofNsigmaPi = std::abs(candidate.tofNSigmaPi()); + float tofNsigmaKa = std::abs(candidate.tofNSigmaKa()); + float tofNsigmaPr = std::abs(candidate.tofNSigmaPr()); + + float tpcTofNsigmaPi = tpcNsigmaPi * tpcNsigmaPi + tofNsigmaPi * tofNsigmaPi; + float tpcTofNsigmaKa = tpcNsigmaKa * tpcNsigmaKa + tofNsigmaKa * tofNsigmaKa; + float tpcTofNsigmaPr = tpcNsigmaPr * tpcNsigmaPr + tofNsigmaPr * tofNsigmaPr; + float combinedCut = nsigmaCutCombinedKaon * nsigmaCutCombinedKaon; + float combinedRejCut = cRejNsigmaTpc * cRejNsigmaTof; + + if (!cUseTpcOnly && candidate.hasTOF()) { + if (candidate.tofNSigmaKa() < minnsigmatofKa) + return false; + if (nsigmaCutCombinedKaon < 0 && p >= cPMin) { + for (int i = 0; i < nitrtof - 1; ++i) { + if (p >= tofPIDp[i] && p < tofPIDp[i + 1] && (tofNsigmaKa < tofPIDcut[i] && tofNsigmaPi > cRejNsigmaTof && tofNsigmaPr > cRejNsigmaTof)) + tofPIDPassed = true; + } + if (candidate.tpcNSigmaKa() < minnsigmatpctofKa) + return false; + if (tpcNsigmaKa < cMaxTPCnSigmaKaon && tpcNsigmaPi > cRejNsigmaTpcVeto && tpcNsigmaPr > cRejNsigmaTpcVeto) + tpcPIDPassed = true; + } + + if ((nsigmaCutCombinedKaon > 0) && p >= cPMin && (tpcTofNsigmaKa < combinedCut && tpcTofNsigmaPi > combinedRejCut && tpcTofNsigmaPr > combinedRejCut)) { + tofPIDPassed = true; + tpcPIDPassed = true; + } + + if (p < cPMin && tpcNsigmaKa < cMaxTPCnSigmaKaon) { + tofPIDPassed = true; + tpcPIDPassed = true; + } + } else { + tofPIDPassed = true; + if (candidate.tpcNSigmaKa() < minnsigmatpcKa) + return false; + for (int i = 0; i < nitr - 1; ++i) { + if (p >= tpcPIDp[i] && p < tpcPIDp[i + 1] && (tpcNsigmaKa < tpcPIDcut[i] && tpcNsigmaPi > cRejNsigmakTpcPi && tpcNsigmaPr > cRejNsigmakTpcPr)) { + tpcPIDPassed = true; + } + } + } + if (tpcPIDPassed && tofPIDPassed) + return true; + return false; + } + + static constexpr float VecUnitEpsilon = 1e-9f; + static constexpr float MomentumEpsilon = 1e-6f; + + static float vecDot(const std::array& a, const std::array& b) + { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + } + + static std::array vecSub(const std::array& a, const std::array& b) + { + return {a[0] - b[0], a[1] - b[1], a[2] - b[2]}; + } + + static std::array vecCross(const std::array& a, const std::array& b) + { + return {a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]}; + } + + static std::array vecUnit(const std::array& a) + { + float mag = std::sqrt(vecDot(a, a)); + if (mag < VecUnitEpsilon) + return {0.f, 0.f, 0.f}; + return {a[0] / mag, a[1] / mag, a[2] / mag}; + } + + static std::array boostToRestFrame(float motherE, const std::array& motherP, + float dE, const std::array& dP) + { + float pMag2 = vecDot(motherP, motherP); + float pMag = std::sqrt(pMag2); + if (pMag < MomentumEpsilon) + return dP; + + std::array nHat = {motherP[0] / pMag, motherP[1] / pMag, motherP[2] / pMag}; + float beta = pMag / motherE; + float motherMass2 = motherE * motherE - pMag2; + float gamma = motherMass2 > 0.f ? motherE / std::sqrt(motherMass2) : 1.f; + + float pParallel = vecDot(dP, nHat); + std::array pPerp = {dP[0] - pParallel * nHat[0], dP[1] - pParallel * nHat[1], dP[2] - pParallel * nHat[2]}; + float pParallelPrime = gamma * (pParallel - beta * dE); + + return {pPerp[0] + pParallelPrime * nHat[0], pPerp[1] + pParallelPrime * nHat[1], pPerp[2] + pParallelPrime * nHat[2]}; + } + + enum class PolBkgMode { Signal, + Rotated, + Mixed, + LikeSign, + LikeSignMixed }; + + template + void fillPolarization(float candMass, float candPt, + const std::array& motherP, float motherE, + const std::array& protonP, float protonE, + const std::array& kaonP, float kaonE, + float mult, bool protonIsPositive) + { + if (!cActivateHelicityFrame && !cActivateCollinsSoperFrame && !cActivateProductionFrame && + !cActivateBeamAxisFrame && !cActivateRandomFrame) + return; + + std::array protonCM = boostToRestFrame(motherE, motherP, protonE, protonP); + std::array kaonCM = boostToRestFrame(motherE, motherP, kaonE, kaonP); + std::array refCM = vecUnit(cPolarizationRefDaughter == 0 ? protonCM : kaonCM); + + auto fillFrame = [&](float cosTheta) { + if constexpr (Mode == PolBkgMode::Rotated) { + if (protonIsPositive) + histos.fill(HIST("Analysis/h4d_pol_rot_PM"), candMass, candPt, mult, cosTheta); + else + histos.fill(HIST("Analysis/h4d_pol_rot_MP"), candMass, candPt, mult, cosTheta); + } else if constexpr (Mode == PolBkgMode::Mixed) { + if (protonIsPositive) + histos.fill(HIST("Analysis/h4d_pol_mix_PM"), candMass, candPt, mult, cosTheta); + else + histos.fill(HIST("Analysis/h4d_pol_mix_MP"), candMass, candPt, mult, cosTheta); + } else if constexpr (Mode == PolBkgMode::LikeSign) { + if (protonIsPositive) + histos.fill(HIST("Analysis/h4d_pol_LS_PP"), candMass, candPt, mult, cosTheta); + else + histos.fill(HIST("Analysis/h4d_pol_LS_MM"), candMass, candPt, mult, cosTheta); + } else if constexpr (Mode == PolBkgMode::LikeSignMixed) { + if (protonIsPositive) + histos.fill(HIST("Analysis/h4d_pol_LS_PP_mix"), candMass, candPt, mult, cosTheta); + else + histos.fill(HIST("Analysis/h4d_pol_LS_MM_mix"), candMass, candPt, mult, cosTheta); + } else { + if (protonIsPositive) + histos.fill(HIST("Analysis/h4d_pol_US_PM"), candMass, candPt, mult, cosTheta); + else + histos.fill(HIST("Analysis/h4d_pol_US_MP"), candMass, candPt, mult, cosTheta); + } + }; + + if (cActivateHelicityFrame) { + std::array zAxisHE = vecUnit(motherP); + fillFrame(vecDot(refCM, zAxisHE)); + } + + if (cActivateCollinsSoperFrame || cActivateProductionFrame || cActivateBeamAxisFrame) { + std::array beam1CM = vecUnit(boostToRestFrame(motherE, motherP, beam1E, beam1P)); + std::array beam2CM = vecUnit(boostToRestFrame(motherE, motherP, beam2E, beam2P)); + + if (cActivateCollinsSoperFrame) { + std::array zAxisCS = vecUnit(vecSub(beam1CM, beam2CM)); + fillFrame(vecDot(refCM, zAxisCS)); + } + if (cActivateProductionFrame) { + std::array motherDir = vecUnit(motherP); + std::array yAxisPR = vecUnit(vecCross(beam1CM, motherDir)); + fillFrame(vecDot(refCM, yAxisPR)); + } + if (cActivateBeamAxisFrame) { + fillFrame(vecDot(refCM, beam1CM)); + } + } + + if (cActivateRandomFrame) { + double randCos = randUniform01(randGen) * 2. - 1.; + double randPhi = randUniform01(randGen) * o2::constants::math::TwoPI; + double randSin = std::sqrt(1. - randCos * randCos); + std::array zAxisRD = {static_cast(randSin * std::cos(randPhi)), + static_cast(randSin * std::sin(randPhi)), + static_cast(randCos)}; + fillFrame(vecDot(refCM, zAxisRD)); + } + } + + template + void fillDataHistos(trackType const& trk1, trackType const& trk2, float mult, int occup = 100) + { + float prptot = 0., kaptot = 0.; + bool polActive = static_cast(cActivateHelicityFrame) || + static_cast(cActivateCollinsSoperFrame) || + static_cast(cActivateProductionFrame) || + static_cast(cActivateBeamAxisFrame) || + static_cast(cActivateRandomFrame); + + for (auto const& [trkPr, trkKa] : soa::combinations(soa::CombinationsFullIndexPolicy(trk1, trk2))) { + if (trkPr.index() == trkKa.index()) + continue; + if (!selTracks(trkPr) || !selTracks(trkKa)) + continue; + + auto pxPr = trkPr.px(); + auto pyPr = trkPr.py(); + auto pzPr = trkPr.pz(); + auto pxKa = trkKa.px(); + auto pyKa = trkKa.py(); + auto pzKa = trkKa.pz(); + + prptot = std::sqrt(pxPr * pxPr + pyPr * pyPr + pzPr * pzPr); + kaptot = std::sqrt(pxKa * pxKa + pyKa * pyKa + pzKa * pzKa); + + if (!mix) { + auto tpcNsigmaPr = trkPr.tpcNSigmaPr(); + histos.fill(HIST("QAbefore/Proton/h2d_pr_nsigma_tpc_p"), prptot, tpcNsigmaPr); + if (trkPr.hasTOF()) { + auto tofNsigmaPr = trkPr.tofNSigmaPr(); + histos.fill(HIST("QAbefore/Proton/h2d_pr_nsigma_tof_p"), prptot, tofNsigmaPr); + histos.fill(HIST("QAbefore/Proton/h2d_pr_nsigma_tof_vs_tpc"), tpcNsigmaPr, tofNsigmaPr); + } + auto tpcNsigmaKa = trkKa.tpcNSigmaKa(); + histos.fill(HIST("QAbefore/Kaon/h2d_ka_nsigma_tpc_p"), kaptot, tpcNsigmaKa); + if (trkKa.hasTOF()) { + auto tofNsigmaKa = trkKa.tofNSigmaKa(); + histos.fill(HIST("QAbefore/Kaon/h2d_ka_nsigma_tof_p"), kaptot, tofNsigmaKa); + histos.fill(HIST("QAbefore/Kaon/h2d_ka_nsigma_tof_vs_tpc"), tpcNsigmaKa, tofNsigmaKa); + } + } + + if (cUseOnlyTOFTrackPr && !trkPr.hasTOF()) + continue; + if (cUseOnlyTOFTrackKa && !trkKa.hasTOF()) + continue; + if (!selectionPIDProton(trkPr, prptot) || !selectionPIDKaon(trkKa, kaptot)) + continue; + if (!dcaSelectionProton(trkPr, prptot) || !dcaSelectionKaon(trkKa, kaptot)) + continue; + + if (isDeepAngle && std::acos((trkPr.pt() * trkKa.pt() + pzPr * pzKa) / (prptot * kaptot)) < cfgDeepAngle) + continue; + + if constexpr (!mix) { + // ==================================================================== + // Proton QA Fills + // ==================================================================== + auto ptPr = trkPr.pt(); + auto tpcNsigmaPr = trkPr.tpcNSigmaPr(); + + // 1. Base QA (Filled for all) + histos.fill(HIST("QAafter/Proton/h2d_pr_dca_z"), ptPr, trkPr.dcaZ()); + histos.fill(HIST("QAafter/Proton/h2d_pr_dca_xy"), ptPr, trkPr.dcaXY()); + histos.fill(HIST("QAafter/Proton/h2d_pr_dEdx_p"), prptot, trkPr.tpcSignal()); + histos.fill(HIST("QAafter/Proton/hTPCNClsCrossedRowsVsPt"), ptPr, trkPr.tpcNClsCrossedRows()); + histos.fill(HIST("QAafter/Proton/hTPCNClsFoundVsPt"), ptPr, trkPr.tpcNClsFound()); + + bool prIsTpcOnly = cUseTpcOnly || !trkPr.hasTOF(); + histos.fill(HIST("QAafter/Proton/hFracTPConly_Proton"), prptot, prIsTpcOnly ? 1 : 0); + + // 2 & 3. Mutually Exclusive TPC vs hasTOF Split + if (prIsTpcOnly) { + histos.fill(HIST("QAafter/Proton/hd_pr_pt_TPConly"), ptPr, mult); + histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tpc_pt_TPConly"), ptPr, tpcNsigmaPr); + histos.fill(HIST("QAafter/Proton/h2d_Prpi_nsigma_tpc_p_TPConly"), ptPr, trkPr.tpcNSigmaPi()); + histos.fill(HIST("QAafter/Proton/h2d_Prka_nsigma_tpc_p_TPConly"), ptPr, trkPr.tpcNSigmaKa()); + histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tpc_p_TPConly"), prptot, tpcNsigmaPr); + } else { + histos.fill(HIST("QAafter/Proton/hd_pr_pt_hasTOF"), ptPr, mult); + histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tpc_pt_hasTOF"), ptPr, tpcNsigmaPr); + histos.fill(HIST("QAafter/Proton/h2d_Prpi_nsigma_tpc_p_hasTOF"), ptPr, trkPr.tpcNSigmaPi()); + histos.fill(HIST("QAafter/Proton/h2d_Prka_nsigma_tpc_p_hasTOF"), ptPr, trkPr.tpcNSigmaKa()); + histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tpc_p_hasTOF"), prptot, tpcNsigmaPr); + + // 4. TOF-Specific (Only possible if hasTOF) + auto tofNsigmaPr = trkPr.tofNSigmaPr(); + histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tof_pt"), ptPr, tofNsigmaPr); + histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tof_p"), prptot, tofNsigmaPr); + histos.fill(HIST("QAafter/Proton/h2d_Prpi_nsigma_tof_p"), prptot, trkPr.tofNSigmaPi()); + histos.fill(HIST("QAafter/Proton/h2d_Prka_nsigma_tof_p"), prptot, trkPr.tofNSigmaKa()); + histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tof_vs_tpc"), tpcNsigmaPr, tofNsigmaPr); + } + + // ==================================================================== + // Kaon QA Fills + // ==================================================================== + auto ptKa = trkKa.pt(); + auto tpcNsigmaKa = trkKa.tpcNSigmaKa(); + + // 1. Base QA (Filled for all) + histos.fill(HIST("QAafter/Kaon/h2d_ka_dca_z"), ptKa, trkKa.dcaZ()); + histos.fill(HIST("QAafter/Kaon/h2d_ka_dca_xy"), ptKa, trkKa.dcaXY()); + histos.fill(HIST("QAafter/Kaon/h2d_ka_dEdx_p"), kaptot, trkKa.tpcSignal()); + histos.fill(HIST("QAafter/Kaon/hTPCNClsCrossedRowsVsPt"), ptKa, trkKa.tpcNClsCrossedRows()); + histos.fill(HIST("QAafter/Kaon/hTPCNClsFoundVsPt"), ptKa, trkKa.tpcNClsFound()); + + bool kaIsTpcOnly = cUseTpcOnly || !trkKa.hasTOF(); + histos.fill(HIST("QAafter/Kaon/hFracTPConly_Kaon"), kaptot, kaIsTpcOnly ? 1 : 0); + + // 2 & 3. Mutually Exclusive TPC vs hasTOF Split + if (kaIsTpcOnly) { + histos.fill(HIST("QAafter/Kaon/hd_ka_pt_TPConly"), ptKa, mult); + histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tpc_pt_TPConly"), ptKa, tpcNsigmaKa); + histos.fill(HIST("QAafter/Kaon/h2d_Kapi_nsigma_tpc_p_TPConly"), ptKa, trkKa.tpcNSigmaPi()); + histos.fill(HIST("QAafter/Kaon/h2d_Kapr_nsigma_tpc_p_TPConly"), kaptot, trkKa.tpcNSigmaPr()); + histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tpc_p_TPConly"), kaptot, tpcNsigmaKa); + } else { + histos.fill(HIST("QAafter/Kaon/hd_ka_pt_hasTOF"), ptKa, mult); + histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tpc_pt_hasTOF"), ptKa, tpcNsigmaKa); + histos.fill(HIST("QAafter/Kaon/h2d_Kapi_nsigma_tpc_p_hasTOF"), ptKa, trkKa.tpcNSigmaPi()); + histos.fill(HIST("QAafter/Kaon/h2d_Kapr_nsigma_tpc_p_hasTOF"), kaptot, trkKa.tpcNSigmaPr()); + histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tpc_p_hasTOF"), kaptot, tpcNsigmaKa); + + // 4. TOF-Specific (Only possible if hasTOF) + auto tofNsigmaKa = trkKa.tofNSigmaKa(); + histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tof_pt"), ptKa, tofNsigmaKa); + histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tof_p"), kaptot, tofNsigmaKa); + histos.fill(HIST("QAafter/Kaon/h2d_Kapi_nsigma_tof_p"), kaptot, trkKa.tofNSigmaPi()); + histos.fill(HIST("QAafter/Kaon/h2d_Kapr_nsigma_tof_p"), kaptot, trkKa.tofNSigmaPr()); + histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tof_vs_tpc"), tpcNsigmaKa, tofNsigmaKa); + } + } + + if (isonlyQC) + continue; + + std::array pvec0 = {pxPr, pyPr, pzPr}; + std::array pvec1 = {pxKa, pyKa, pzKa}; + std::array, 2> arrMomrec = {pvec0, pvec1}; + float candMass = RecoDecay::m(arrMomrec, std::array{MassProton, MassKaonCharged}); + float candPt = RecoDecay::pt(std::array{pxPr + pxKa, pyPr + pyKa}); + float candY = std::abs(RecoDecay::y(std::array{pxPr + pxKa, pyPr + pyKa, pzPr + pzKa}, candMass)); + float candYShift = candY - cfgRapidityShift; + + if (std::abs(candYShift) > cfgRapidityCut) + continue; + + if constexpr (!mix && !mc) { + if (trkPr.sign() * trkKa.sign() < 0) { + if (!polActive) { + if (trkPr.sign() > 0) + histos.fill(HIST("Analysis/h4d_lstar_invm_US_PM"), candMass, candPt, mult, occup); + else + histos.fill(HIST("Analysis/h4d_lstar_invm_US_MP"), candMass, candPt, mult, occup); + } + + if (polActive) { + float eProton = std::sqrt(pxPr * pxPr + pyPr * pyPr + pzPr * pzPr + MassProton * MassProton); + float eKaon = std::sqrt(pxKa * pxKa + pyKa * pyKa + pzKa * pzKa + MassKaonCharged * MassKaonCharged); + std::array protonP = {pxPr, pyPr, pzPr}; + std::array kaonP = {pxKa, pyKa, pzKa}; + std::array motherP = {pxPr + pxKa, pyPr + pyKa, pzPr + pzKa}; + float motherE = eProton + eKaon; + fillPolarization(candMass, candPt, motherP, motherE, protonP, eProton, kaonP, eKaon, mult, trkPr.sign() > 0); + + if (doRotate) { + for (int i = 0; i < cNofRotations; i++) { + float delta = o2::constants::math::PI / rotationalcut; + float theta2 = (cNofRotations == 1) ? o2::constants::math::PI : (o2::constants::math::PI - delta) + i * (2.f * delta / (cNofRotations - 1)); + float phiRot = RecoDecay::constrainAngle(trkKa.phi() + theta2, 0.f); + float pxKaRot = trkKa.pt() * std::cos(phiRot); + float pyKaRot = trkKa.pt() * std::sin(phiRot); + + std::array pvec0rot = {pxPr, pyPr, pzPr}; + std::array pvec1rot = {pxKaRot, pyKaRot, pzKa}; + std::array, 2> arrMomRot = {pvec0rot, pvec1rot}; + + float candMassRot = RecoDecay::m(arrMomRot, std::array{MassProton, MassKaonCharged}); + float candPtRot = RecoDecay::pt(std::array{pxPr + pxKaRot, pyPr + pyKaRot}); + float candYRot = std::abs(RecoDecay::y(std::array{pxPr + pxKaRot, pyPr + pyKaRot, pzPr + pzKa}, MassLambda1520)); + float candYShiftRot = candYRot - cfgRapidityShift; + + if (std::abs(candYShiftRot) > cfgRapidityCut) + continue; + + if (doPolarizationRot) { + float eKaonRot = std::sqrt(pxKaRot * pxKaRot + pyKaRot * pyKaRot + pzKa * pzKa + MassKaonCharged * MassKaonCharged); + std::array kaonRotP = {pxKaRot, pyKaRot, pzKa}; + std::array motherRotP = {pxPr + pxKaRot, pyPr + pyKaRot, pzPr + pzKa}; + float motherRotE = eProton + eKaonRot; + fillPolarization(candMassRot, candPtRot, motherRotP, motherRotE, protonP, eProton, kaonRotP, eKaonRot, mult, trkPr.sign() > 0); + } + } + } + } else if (doRotate) { + for (int i = 0; i < cNofRotations; i++) { + float delta = o2::constants::math::PI / rotationalcut; + float theta2 = (cNofRotations == 1) ? o2::constants::math::PI : (o2::constants::math::PI - delta) + i * (2.f * delta / (cNofRotations - 1)); + float phiRot = RecoDecay::constrainAngle(trkKa.phi() + theta2, 0.f); + float pxKaRot = trkKa.pt() * std::cos(phiRot); + float pyKaRot = trkKa.pt() * std::sin(phiRot); + std::array pvec0rot = {pxPr, pyPr, pzPr}; + std::array pvec1rot = {pxKaRot, pyKaRot, pzKa}; + std::array, 2> arrMomRot = {pvec0rot, pvec1rot}; + float candMassRot = RecoDecay::m(arrMomRot, std::array{MassProton, MassKaonCharged}); + float candPtRot = RecoDecay::pt(std::array{pxPr + pxKaRot, pyPr + pyKaRot}); + float candYRot = std::abs(RecoDecay::y(std::array{pxPr + pxKaRot, pyPr + pyKaRot, pzPr + pzKa}, MassLambda1520)); + + if (std::abs(candYRot - cfgRapidityShift) > cfgRapidityCut) + continue; + + if (trkPr.sign() > 0) + histos.fill(HIST("Analysis/h4d_lstar_invm_rot_PM"), candMassRot, candPtRot, mult, occup); + else + histos.fill(HIST("Analysis/h4d_lstar_invm_rot_MP"), candMassRot, candPtRot, mult, occup); + } + } + } else { + if (!polActive) { + if (trkPr.sign() > 0) + histos.fill(HIST("Analysis/h4d_lstar_invm_PP"), candMass, candPt, mult, occup); + else + histos.fill(HIST("Analysis/h4d_lstar_invm_MM"), candMass, candPt, mult, occup); + } else { + float eProton = std::sqrt(pxPr * pxPr + pyPr * pyPr + pzPr * pzPr + MassProton * MassProton); + float eKaon = std::sqrt(pxKa * pxKa + pyKa * pyKa + pzKa * pzKa + MassKaonCharged * MassKaonCharged); + std::array protonP = {pxPr, pyPr, pzPr}; + std::array kaonP = {pxKa, pyKa, pzKa}; + std::array motherP = {pxPr + pxKa, pyPr + pyKa, pzPr + pzKa}; + float motherE = eProton + eKaon; + fillPolarization(candMass, candPt, motherP, motherE, protonP, eProton, kaonP, eKaon, mult, trkPr.sign() > 0); + } + } + } + + if constexpr (mix) { + if (trkPr.sign() * trkKa.sign() < 0) { + if (!polActive) { + if (trkPr.sign() > 0) + histos.fill(HIST("Analysis/h4d_lstar_invm_US_PM_mix"), candMass, candPt, mult, occup); + else + histos.fill(HIST("Analysis/h4d_lstar_invm_US_MP_mix"), candMass, candPt, mult, occup); + } + if (doPolarizationMix && polActive) { + float eProton = std::sqrt(pxPr * pxPr + pyPr * pyPr + pzPr * pzPr + MassProton * MassProton); + float eKaon = std::sqrt(pxKa * pxKa + pyKa * pyKa + pzKa * pzKa + MassKaonCharged * MassKaonCharged); + std::array protonP = {pxPr, pyPr, pzPr}; + std::array kaonP = {pxKa, pyKa, pzKa}; + std::array motherP = {pxPr + pxKa, pyPr + pyKa, pzPr + pzKa}; + float motherE = eProton + eKaon; + fillPolarization(candMass, candPt, motherP, motherE, protonP, eProton, kaonP, eKaon, mult, trkPr.sign() > 0); + } + } else { + if (!polActive) { + if (trkPr.sign() > 0) + histos.fill(HIST("Analysis/h4d_lstar_invm_LS_PP_mix"), candMass, candPt, mult, occup); + else + histos.fill(HIST("Analysis/h4d_lstar_invm_LS_MM_mix"), candMass, candPt, mult, occup); + } + if (doPolarizationMix && polActive) { + float eProton = std::sqrt(pxPr * pxPr + pyPr * pyPr + pzPr * pzPr + MassProton * MassProton); + float eKaon = std::sqrt(pxKa * pxKa + pyKa * pyKa + pzKa * pzKa + MassKaonCharged * MassKaonCharged); + std::array protonP = {pxPr, pyPr, pzPr}; + std::array kaonP = {pxKa, pyKa, pzKa}; + std::array motherP = {pxPr + pxKa, pyPr + pyKa, pzPr + pzKa}; + float motherE = eProton + eKaon; + fillPolarization(candMass, candPt, motherP, motherE, protonP, eProton, kaonP, eKaon, mult, trkPr.sign() > 0); + } + } + } + if constexpr (mc) { + if (trkPr.sign() * trkKa.sign() < 0) { + if (std::abs(trkPr.pdgCode()) != kProton || std::abs(trkKa.pdgCode()) != kKPlus) + continue; + if (trkPr.motherId() != trkKa.motherId()) + continue; + if (trkPr.motherPDG() != trkKa.motherPDG()) + continue; + if (trkPr.pdgCode() == 0 || trkKa.pdgCode() == 0) + continue; + if (trkPr.motherPDG() == -1 || trkKa.motherPDG() == -1) + continue; + if (std::abs(trkPr.motherPDG()) != lambda1520id) + continue; + + float massParent = 0.; + for (auto const& resoParent : *mResoParents) { + if (resoParent.mcParticleId() == trkPr.motherId()) { + std::array pvecParent = {resoParent.px(), resoParent.py(), resoParent.pz()}; + massParent = RecoDecay::m(pvecParent, resoParent.e()); + break; + } + } + + float candMassRes = candMass - massParent; + if (trkPr.motherPDG() > 0) { + histos.fill(HIST("Analysis/h3d_rec_lstar_PM"), candMass, candPt, mult); + histos.fill(HIST("Analysis/h3d_reso_lstar_PM"), candMassRes, candPt, mult); + } else { + histos.fill(HIST("Analysis/h3d_rec_lstar_MP"), candMass, candPt, mult); + histos.fill(HIST("Analysis/h3d_reso_lstar_MP"), candMassRes, candPt, mult); + } + } + } + } + } + + using ResoCols = soa::Join; + using ResoMCCols = soa::Join; + using ResoTracks = aod::ResoTracks; + + void processData(ResoCols::iterator const& collision, ResoTracks const& tracks) + { + if (cEvtMCRecINELgt0 && !collision.isRecINELgt0()) + return; + histos.fill(HIST("Event/h1d_ft0_mult_percentile"), collision.cent(), 100); + histos.fill(HIST("Event/h_ft0_vz"), collision.posZ()); + fillDataHistos(tracks, tracks, collision.cent()); + } + + PROCESS_SWITCH(Lambda1520pbpb, processData, "Process for Same Event Data", true); + + void processMC(ResoMCCols::iterator const& collision, soa::Join const& tracks, aod::ResoMCParents const& resoParents) + { + histos.fill(HIST("Event/hMCEventCutflow"), 0); + if (cEvtMCTriggerTVX && !collision.isTriggerTVX()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 1); + if (cEvtMCVtxIn10 && !collision.isVtxIn10()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 2); + if (cEvtMCINELgt0 && !collision.isINELgt0()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 3); + if (cEvtMCSel8 && !collision.isInSel8()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 4); + if (cEvtMCRecINELgt0 && !collision.isRecINELgt0()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 5); + if (cEvtMCAfterAllCuts && !collision.isInAfterAllCuts()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 6); + + auto mult = collision.cent(); + histos.fill(HIST("Event/h1d_ft0_mult_percentile"), mult, 100); + histos.fill(HIST("Event/h_ft0_vz"), collision.posZ()); + mResoParents = &resoParents; + fillDataHistos(tracks, tracks, mult); + + for (auto const& track : tracks) { + histos.fill(HIST("QAbefore/hEta_rec"), track.eta()); + histos.fill(HIST("QAbefore/hPt_rec"), track.pt()); + histos.fill(HIST("QAbefore/hPhi_rec"), track.phi()); + histos.fill(HIST("QAbefore/hEtaPhi_rec"), track.eta(), track.phi()); + + if (std::abs(track.pdgCode()) == kKPlus) + histos.fill(HIST("QAChecks/h1d_ka_gen_pt"), track.pt()); + if (std::abs(track.pdgCode()) == kProton) + histos.fill(HIST("QAChecks/h1d_pr_gen_pt"), track.pt()); + + if (!selTracks(track)) + continue; + float p = std::sqrt(track.px() * track.px() + track.py() * track.py() + track.pz() * track.pz()); + + if (selectionPIDKaon(track, p)) { + if (std::abs(track.pdgCode()) == kKPlus) + histos.fill(HIST("QAChecks/h1d_ka_rec_pt"), track.pt()); + } + if (selectionPIDProton(track, p)) { + if (std::abs(track.pdgCode()) == kProton) + histos.fill(HIST("QAChecks/h1d_pr_rec_pt"), track.pt()); + } + } + + for (auto const& part : resoParents) { + if (std::abs(part.pdgCode()) != lambda1520id) + continue; + float yshift = std::abs(part.y()) - cfgRapidityShift; + if (std::abs(yshift) > cfgRapidityCut) + continue; + + bool pass1 = false, pass2 = false; + if (std::abs(part.daughterPDG1()) == kProton || std::abs(part.daughterPDG2()) == kProton) + pass1 = true; + if (std::abs(part.daughterPDG1()) == kKPlus || std::abs(part.daughterPDG2()) == kKPlus) + pass2 = true; + + if (!pass1 || !pass2) + continue; + std::array pvec = {part.px(), part.py(), part.pz()}; + float mass = RecoDecay::m(pvec, part.e()); + if (part.pdgCode() > 0) + histos.fill(HIST("Analysis/h3d_gen_lstar_PM"), mass, part.pt(), mult); + else + histos.fill(HIST("Analysis/h3d_gen_lstar_MP"), mass, part.pt(), mult); + } + } + PROCESS_SWITCH(Lambda1520pbpb, processMC, "Process Event for MC", false); + + void processMCGen(ResoMCCols::iterator const& collision, aod::ResoMCParents const& resoParents) + { + float centrality = collision.cent(); + histos.fill(HIST("SignalLoss/hMCEventCutflow"), 0); + if (cEvtMCTriggerTVX && !collision.isTriggerTVX()) + return; + histos.fill(HIST("SignalLoss/hMCEventCutflow"), 1); + if (cEvtMCVtxIn10 && !collision.isVtxIn10()) + return; + histos.fill(HIST("SignalLoss/hMCEventCutflow"), 2); + if (cEvtMCINELgt0 && !collision.isINELgt0()) + return; + histos.fill(HIST("SignalLoss/hMCEventCutflow"), 3); + if (cEvtMCSel8 && !collision.isInSel8()) + return; + histos.fill(HIST("SignalLoss/hMCEventCutflow"), 4); + if (cEvtMCRecINELgt0 && !collision.isRecINELgt0()) + return; + histos.fill(HIST("SignalLoss/hMCEventCutflow"), 5); + if (cEvtMCAfterAllCuts && !collision.isInAfterAllCuts()) + return; + histos.fill(HIST("SignalLoss/hMCEventCutflow"), 6); + + for (auto const& part : resoParents) { + float yshift = std::abs(part.y()) - cfgRapidityShift; + if (std::abs(yshift) > cfgRapidityCut) + continue; + + int pdg = part.pdgCode(); + float ptRef = part.pt(); + double ptSq = -1.0; + + std::array pvec = {part.px(), part.py(), part.pz()}; + float mass = RecoDecay::m(pvec, part.e()); + + if (pdg == kProton) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_Proton"), std::sqrt(ptSq), centrality); + } else if (pdg == -kProton) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_AntiProton"), std::sqrt(ptSq), centrality); + } else if (pdg == kLambda0) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_Lambda0"), std::sqrt(ptSq), centrality); + } else if (pdg == -kLambda0) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_AntiLambda0"), std::sqrt(ptSq), centrality); + } else if (pdg == kXiMinus) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_XiMinus"), std::sqrt(ptSq), centrality); + } else if (pdg == -kXiMinus) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_XiPlus"), std::sqrt(ptSq), centrality); + } else if (pdg == kXi0) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_Xi0"), std::sqrt(ptSq), centrality); + } else if (pdg == -kXi0) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_AntiXi0"), std::sqrt(ptSq), centrality); + } else if (pdg == kOmegaMinus) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_OmegaMinus"), std::sqrt(ptSq), centrality); + } else if (pdg == -kOmegaMinus) { + ptSq = (ptRef * ptRef) + (mass * mass) - (o2::constants::physics::MassLambda1520 * o2::constants::physics::MassLambda1520); + if (ptSq > 0) + histos.fill(HIST("SignalLoss/hGen_mT_scaled_OmegaPlus"), std::sqrt(ptSq), centrality); + } + } + } + + PROCESS_SWITCH(Lambda1520pbpb, processMCGen, "Process Event for MC", false); + + using BinningType2 = ColumnBinningPolicy; + + void processMix(ResoCols const& collisions, ResoTracks const& tracks) + { + LOGF(debug, "Event Mixing Started"); + BinningType2 binningPositions2{{cMixVtxBins, cMixMultBins}, true}; + auto tracksTuple = std::make_tuple(tracks); + + SameKindPair pairs{binningPositions2, cNumMixEv, -1, collisions, tracksTuple, &cache}; + for (auto const& [c1, t1, c2, t2] : pairs) { + if (cEvtMCRecINELgt0 && !c1.isRecINELgt0()) + return; + histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ(), c1.evtPl()); + fillDataHistos(t1, t2, c1.cent()); + } + } + + PROCESS_SWITCH(Lambda1520pbpb, processMix, "Process for Mixed Events", true); + + Preslice perRColdf = aod::resodaughter::resoCollisionDFId; + using ResoColDFs = aod::ResoCollisionDFs; + using ResoTrackDFs = aod::ResoTrackDFs; + + void processDatadf(ResoColDFs::iterator const& collision, ResoTrackDFs const& tracks) + { + if (doprocessData) + LOG(error) << "Disable processData() first!"; + if (cEvtMCRecINELgt0 && !collision.isRecINELgt0()) + return; + + auto occup = 100; + if (cfgEvtOccupancyInTimeRange) + occup = collision.trackOccupancyInTimeRange(); + + histos.fill(HIST("Event/h1d_ft0_mult_percentile"), collision.cent(), occup); + fillDataHistos(tracks, tracks, collision.cent(), occup); + } + + PROCESS_SWITCH(Lambda1520pbpb, processDatadf, "Process for data merged DF", false); + + using BinningTypeDF = ColumnBinningPolicy; + void processMixDF(ResoColDFs const& collisions, ResoTrackDFs const& tracks) + { + if (doprocessMix) + LOG(fatal) << "Disable processMix() first!"; + LOGF(debug, "Event Mixing Started"); + + BinningTypeDF binningPositions2{{cMixVtxBins, cMixMultBins}, true}; + auto tracksTuple = std::make_tuple(tracks); + + SameKindPair pairs{binningPositions2, cNumMixEv, -1, collisions, tracksTuple, &cache}; + for (auto const& [c1, t1, c2, t2] : pairs) { + if (cEvtMCRecINELgt0 && !c1.isRecINELgt0()) + return; + + auto occup = 100; + if (cfgEvtOccupancyInTimeRange) + occup = c1.trackOccupancyInTimeRange(); + + histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ(), c1.evtPl()); + fillDataHistos(t1, t2, c1.cent(), occup); + } + } + + PROCESS_SWITCH(Lambda1520pbpb, processMixDF, "Process for merged DF Mixed Events", false); + + using BinningTypeEP = ColumnBinningPolicy; + void processMixepDF(ResoColDFs const& collisions, ResoTrackDFs const& tracks) + { + if (doprocessMix || doprocessMixDF) + LOG(fatal) << "Disable processMix() or processMixDF() first!"; + LOGF(debug, "Event Mixing Started"); + BinningTypeEP binningPositions2{{cMixVtxBins, cMixMultBins, cMixEPAngle}, true}; + auto tracksTuple = std::make_tuple(tracks); + + SameKindPair pairs{binningPositions2, cNumMixEv, -1, collisions, tracksTuple, &cache}; + for (auto const& [c1, t1, c2, t2] : pairs) { + histos.fill(HIST("Event/mixing_vzVsmultpercentile"), c1.cent(), c1.posZ(), c1.evtPl()); + fillDataHistos(t1, t2, c1.cent()); + } + } + + PROCESS_SWITCH(Lambda1520pbpb, processMixepDF, "Process for merged DF Mixed Events", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +}