From 483d20a25b5010052a982a9b920c6af0ebe80d50 Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Fri, 7 Nov 2025 23:02:51 +0530 Subject: [PATCH 1/8] [PWGCF] : Lambda Correlation --- .../Tasks/lambdaSpinCorrelation.cxx | 1088 +++++++++++++++++ 1 file changed, 1088 insertions(+) create mode 100644 PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinCorrelation.cxx diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinCorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinCorrelation.cxx new file mode 100644 index 00000000000..5e5338ffa05 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinCorrelation.cxx @@ -0,0 +1,1088 @@ +// 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 LambdaSpinCorrelation.cxx +/// \brief Spin Correlation of Lambda baryons. +/// \author Yash Patley + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; +using namespace o2::constants::math; + +namespace o2::aod +{ +namespace lambdacollision +{ +DECLARE_SOA_COLUMN(Cent, cent, float); +DECLARE_SOA_COLUMN(Mult, mult, float); +} // namespace lambdacollision +DECLARE_SOA_TABLE(LambdaCollisions, "AOD", "LAMBDACOLS", o2::soa::Index<>, + lambdacollision::Cent, + lambdacollision::Mult, + aod::collision::PosX, + aod::collision::PosY, + aod::collision::PosZ); +using LambdaCollision = LambdaCollisions::iterator; + +namespace lambdatrack +{ +DECLARE_SOA_INDEX_COLUMN(LambdaCollision, lambdaCollision); +DECLARE_SOA_COLUMN(Px, px, float); +DECLARE_SOA_COLUMN(Py, py, float); +DECLARE_SOA_COLUMN(Pz, pz, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Rap, rap, float); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(PosTrackId, posTrackId, int64_t); +DECLARE_SOA_COLUMN(NegTrackId, negTrackId, int64_t); +DECLARE_SOA_COLUMN(PrPx, prPx, float); +DECLARE_SOA_COLUMN(PrPy, prPy, float); +DECLARE_SOA_COLUMN(PrPz, prPz, float); +DECLARE_SOA_COLUMN(V0Type, v0Type, int8_t); +} // namespace lambdatrack +DECLARE_SOA_TABLE(LambdaTracks, "AOD", "LAMBDATRACKS", o2::soa::Index<>, + lambdatrack::LambdaCollisionId, + lambdatrack::Px, + lambdatrack::Py, + lambdatrack::Pz, + lambdatrack::Pt, + lambdatrack::Eta, + lambdatrack::Phi, + lambdatrack::Rap, + lambdatrack::Mass, + lambdatrack::PosTrackId, + lambdatrack::NegTrackId, + lambdatrack::PrPx, + lambdatrack::PrPy, + lambdatrack::PrPz, + lambdatrack::V0Type); +using LambdaTrack = LambdaTracks::iterator; + +namespace lambdatrackext +{ +DECLARE_SOA_COLUMN(LambdaSharingDaughter, lambdaSharingDaughter, bool); +DECLARE_SOA_COLUMN(LambdaSharingDauIds, lambdaSharingDauIds, std::vector); +DECLARE_SOA_COLUMN(TrueLambdaFlag, trueLambdaFlag, bool); +} // namespace lambdatrackext +DECLARE_SOA_TABLE(LambdaTracksExt, "AOD", "LAMBDATRACKSEXT", + lambdatrackext::LambdaSharingDaughter, + lambdatrackext::LambdaSharingDauIds, + lambdatrackext::TrueLambdaFlag); + +using LambdaTrackExt = LambdaTracksExt::iterator; +} // namespace o2::aod + +enum CollisionLabels { + kTotColBeforeHasMcCollision = 1, + kTotCol, + kPassSelCol +}; + +enum TrackLabels { + kTracksBeforeHasMcParticle = 1, + kAllV0Tracks, + kV0KShortMassRej, + kNotLambdaNotAntiLambda, + kV0IsBothLambdaAntiLambda, + kNotLambdaAfterSel, + kV0IsLambdaOrAntiLambda, + kPassV0DauTrackSel, + kPassV0KinCuts, + kPassV0TopoSel, + kAllSelPassed, +}; + +enum CentEstType { + kCentFT0M = 0, + kCentFT0C +}; + +enum RunType { + kRun3 = 0, + kRun2 +}; + +enum ParticleType { + kLambda = 0, + kAntiLambda +}; + +enum ParticlePairType { + kLambdaAntiLambda = 0, + kLambdaLambda, + kAntiLambdaAntiLambda +}; + +enum ShareDauLambda { + kUniqueLambda = 0, + kLambdaShareDau +}; + +struct LambdaTableProducer { + + Produces lambdaCollisionTable; + Produces lambdaTrackTable; + + // Collisions + Configurable cCentEstimator{"cCentEstimator", 0, "Centrality Estimator : 0-FT0M, 1-FT0C"}; + Configurable cMinZVtx{"cMinZVtx", -10.0, "Min VtxZ cut"}; + Configurable cMaxZVtx{"cMaxZVtx", 10.0, "Max VtxZ cut"}; + Configurable cMinMult{"cMinMult", 0., "Minumum Multiplicity"}; + Configurable cMaxMult{"cMaxMult", 100.0, "Maximum Multiplicity"}; + Configurable cSel8Trig{"cSel8Trig", true, "Sel8 (T0A + T0C) Selection Run3"}; + Configurable cInt7Trig{"cInt7Trig", false, "kINT7 MB Trigger"}; + Configurable cSel7Trig{"cSel7Trig", false, "Sel7 (V0A + V0C) Selection Run2"}; + Configurable cTriggerTvxSel{"cTriggerTvxSel", false, "Trigger Time and Vertex Selection"}; + Configurable cTFBorder{"cTFBorder", false, "Timeframe Border Selection"}; + Configurable cNoItsROBorder{"cNoItsROBorder", false, "No ITSRO Border Cut"}; + Configurable cItsTpcVtx{"cItsTpcVtx", false, "ITS+TPC Vertex Selection"}; + Configurable cPileupReject{"cPileupReject", false, "Pileup rejection"}; + Configurable cZVtxTimeDiff{"cZVtxTimeDiff", false, "z-vtx time diff selection"}; + Configurable cIsGoodITSLayers{"cIsGoodITSLayers", false, "Good ITS Layers All"}; + + // Tracks + Configurable cTrackMinPt{"cTrackMinPt", 0.15, "p_{T} minimum"}; + Configurable cTrackMaxPt{"cTrackMaxPt", 999.0, "p_{T} maximum"}; + Configurable cTrackEtaCut{"cTrackEtaCut", 0.8, "Pseudorapidity cut"}; + Configurable cMinTpcCrossedRows{"cMinTpcCrossedRows", 70, "TPC Min Crossed Rows"}; + Configurable cMinTpcCROverCls{"cMinTpcCROverCls", 0.8, "Tpc Min Crossed Rows Over Findable Clusters"}; + Configurable cMaxTpcSharedClusters{"cMaxTpcSharedClusters", 0.4, "Tpc Max Shared Clusters"}; + Configurable cMaxChi2Tpc{"cMaxChi2Tpc", 4, "Max Chi2 Tpc"}; + Configurable cTpcNsigmaCut{"cTpcNsigmaCut", 3.0, "TPC NSigma Selection Cut"}; + Configurable cRemoveAmbiguousTracks{"cRemoveAmbiguousTracks", false, "Remove Ambiguous Tracks"}; + + // V0s + Configurable cMinDcaProtonToPV{"cMinDcaProtonToPV", 0.02, "Minimum Proton DCAr to PV"}; + Configurable cMinDcaPionToPV{"cMinDcaPionToPV", 0.06, "Minimum Pion DCAr to PV"}; + Configurable cMinV0DcaDaughters{"cMinV0DcaDaughters", 0., "Minimum DCA between V0 daughters"}; + Configurable cMaxV0DcaDaughters{"cMaxV0DcaDaughters", 1., "Maximum DCA between V0 daughters"}; + Configurable cMinDcaV0ToPV{"cMinDcaV0ToPV", 0.0, "Minimum DCA V0 to PV"}; + Configurable cMaxDcaV0ToPV{"cMaxDcaV0ToPV", 999.0, "Maximum DCA V0 to PV"}; + Configurable cMinV0TransRadius{"cMinV0TransRadius", 0.5, "Minimum V0 radius from PV"}; + Configurable cMaxV0TransRadius{"cMaxV0TransRadius", 999.0, "Maximum V0 radius from PV"}; + Configurable cMinV0CTau{"cMinV0CTau", 0.0, "Minimum ctau"}; + Configurable cMaxV0CTau{"cMaxV0CTau", 30.0, "Maximum ctau"}; + Configurable cMinV0CosPA{"cMinV0CosPA", 0.995, "Minimum V0 CosPA to PV"}; + Configurable cKshortRejMassWindow{"cKshortRejMassWindow", 0.01, "Reject K0Short Candidates"}; + Configurable cKshortRejFlag{"cKshortRejFlag", true, "K0short Mass Rej Flag"}; + + // V0s kinmatic acceptance + Configurable cMinV0Mass{"cMinV0Mass", 1.10, "V0 Mass Min"}; + Configurable cMaxV0Mass{"cMaxV0Mass", 1.12, "V0 Mass Min"}; + Configurable cMinV0Pt{"cMinV0Pt", 0.8, "Minimum V0 pT"}; + Configurable cMaxV0Pt{"cMaxV0Pt", 4.2, "Minimum V0 pT"}; + Configurable cMaxV0Rap{"cMaxV0Rap", 0.5, "|rap| cut"}; + Configurable cDoEtaAnalysis{"cDoEtaAnalysis", false, "Do Eta Analysis"}; + Configurable cV0TypeSelFlag{"cV0TypeSelFlag", false, "V0 Type Selection Flag"}; + Configurable cV0TypeSelection{"cV0TypeSelection", 1, "V0 Type Selection"}; + + // V0s MC + Configurable cHasMcFlag{"cHasMcFlag", true, "Has Mc Tag"}; + Configurable cSelectTrueLambda{"cSelectTrueLambda", true, "Select True Lambda"}; + Configurable cSelMCPSV0{"cSelMCPSV0", true, "Select Primary/Secondary V0"}; + Configurable cCheckRecoDauFlag{"cCheckRecoDauFlag", true, "Check for reco daughter PID"}; + Configurable cGenPrimaryLambda{"cGenPrimaryLambda", true, "Primary Generated Lambda"}; + Configurable cGenSecondaryLambda{"cGenSecondaryLambda", false, "Secondary Generated Lambda"}; + Configurable cGenDecayChannel{"cGenDecayChannel", true, "Gen Level Decay Channel Flag"}; + Configurable cRecoMomResoFlag{"cRecoMomResoFlag", false, "Check effect of momentum space smearing on balance function"}; + + // Histogram Registry. + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Initialize Global Variables + float cent = 0., mult = 0.; + float pt = 0., eta = 0., rap = 0., phi = 0.; + + void init(InitContext const&) + { + // initialize axis specifications + const AxisSpec axisCols(5, 0.5, 5.5, ""); + const AxisSpec axisTrks(30, 0.5, 30.5, ""); + const AxisSpec axisCent(100, 0, 100, "FT0M (%)"); + const AxisSpec axisMult(10, 0, 10, "N_{#Lambda}"); + const AxisSpec axisVz(220, -11, 11, "V_{z} (cm)"); + const AxisSpec axisPID(8000, -4000, 4000, "PdgCode"); + + const AxisSpec axisV0Mass(140, 1.08, 1.15, "M_{p#pi} (GeV/#it{c}^{2})"); + const AxisSpec axisV0Pt(100., 0., 10., "p_{T} (GeV/#it{c})"); + const AxisSpec axisV0Rap(48, -1.2, 1.2, "y"); + const AxisSpec axisV0Eta(48, -1.2, 1.2, "#eta"); + const AxisSpec axisV0Phi(36, 0., TwoPI, "#phi (rad)"); + + const AxisSpec axisRadius(2000, 0, 200, "r(cm)"); + const AxisSpec axisCosPA(300, 0.97, 1.0, "cos(#theta_{PA})"); + const AxisSpec axisDcaV0PV(1000, 0., 10., "dca (cm)"); + const AxisSpec axisDcaProngPV(5000, -50., 50., "dca (cm)"); + const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); + const AxisSpec axisCTau(2000, 0, 200, "c#tau (cm)"); + const AxisSpec axisGCTau(2000, 0, 200, "#gammac#tau (cm)"); + const AxisSpec axisAlpha(40, -1, 1, "#alpha"); + const AxisSpec axisQtarm(40, 0, 0.4, "q_{T}"); + + const AxisSpec axisTrackPt(40, 0, 4, "p_{T} (GeV/#it{c})"); + const AxisSpec axisTrackDCA(200, -1, 1, "dca_{XY} (cm)"); + const AxisSpec axisMomPID(80, 0, 4, "p (GeV/#it{c})"); + const AxisSpec axisNsigma(401, -10.025, 10.025, {"n#sigma"}); + const AxisSpec axisdEdx(360, 20, 200, "#frac{dE}{dx}"); + + // Create Histograms. + // Event histograms + histos.add("Events/h1f_collisions_info", "# of Collisions", kTH1F, {axisCols}); + histos.add("Events/h1f_collision_posZ", "V_{z}-distribution", kTH1F, {axisVz}); + + // QA + histos.add("Tracks/h1f_tracks_info", "# of tracks", kTH1F, {axisTrks}); + histos.add("Tracks/h2f_armpod_before_sel", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("Tracks/h2f_armpod_after_sel", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("Tracks/h1f_lambda_pt_vs_invm", "p_{T} vs M_{#Lambda}", kTH2F, {axisV0Mass, axisV0Pt}); + histos.add("Tracks/h1f_antilambda_pt_vs_invm", "p_{T} vs M_{#bar{#Lambda}}", kTH2F, {axisV0Mass, axisV0Pt}); + + // QA Lambda + histos.add("QA/Lambda/h2f_qt_vs_alpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("QA/Lambda/h1f_dca_V0_daughters", "DCA between V0 daughters", kTH1F, {axisDcaDau}); + histos.add("QA/Lambda/h1f_dca_pos_to_PV", "DCA positive prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("QA/Lambda/h1f_dca_neg_to_PV", "DCA negative prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("QA/Lambda/h1f_dca_V0_to_PV", "DCA V0 to PV", kTH1F, {axisDcaV0PV}); + histos.add("QA/Lambda/h1f_V0_cospa", "cos(#theta_{PA})", kTH1F, {axisCosPA}); + histos.add("QA/Lambda/h1f_V0_radius", "V_{0} Decay Radius in XY plane", kTH1F, {axisRadius}); + histos.add("QA/Lambda/h1f_V0_ctau", "V_{0} c#tau", kTH1F, {axisCTau}); + histos.add("QA/Lambda/h1f_V0_gctau", "V_{0} #gammac#tau", kTH1F, {axisGCTau}); + + histos.add("QA/Lambda/h1f_pos_prong_pt", "Pos-Prong p_{T}", kTH1F, {axisTrackPt}); + histos.add("QA/Lambda/h1f_neg_prong_pt", "Neg-Prong p_{T}", kTH1F, {axisTrackPt}); + histos.add("QA/Lambda/h1f_pos_prong_eta", "Pos-Prong #eta-distribution", kTH1F, {axisV0Eta}); + histos.add("QA/Lambda/h1f_neg_prong_eta", "Neg-Prong #eta-distribution", kTH1F, {axisV0Eta}); + histos.add("QA/Lambda/h1f_pos_prong_phi", "Pos-Prong #phi-distribution", kTH1F, {axisV0Phi}); + histos.add("QA/Lambda/h1f_neg_prong_phi", "Neg-Prong #phi-distribution", kTH1F, {axisV0Phi}); + + histos.add("QA/Lambda/h2f_pos_prong_dcaXY_vs_pt", "DCA vs p_{T}", kTH2F, {axisTrackPt, axisTrackDCA}); + histos.add("QA/Lambda/h2f_neg_prong_dcaXY_vs_pt", "DCA vs p_{T}", kTH2F, {axisTrackPt, axisTrackDCA}); + histos.add("QA/Lambda/h2f_pos_prong_dEdx_vs_p", "TPC Signal Pos-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("QA/Lambda/h2f_neg_prong_dEdx_vs_p", "TPC Signal Neg-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); + + // Kinematic Histograms + histos.add("McRec/Lambda/hPt", "Transverse Momentum", kTH1F, {axisV0Pt}); + histos.add("McRec/Lambda/hEta", "Pseudorapidity", kTH1F, {axisV0Eta}); + histos.add("McRec/Lambda/hRap", "Rapidity", kTH1F, {axisV0Rap}); + histos.add("McRec/Lambda/hPhi", "Azimuthal Angle", kTH1F, {axisV0Phi}); + + // QA Anti-Lambda + histos.addClone("QA/Lambda/", "QA/AntiLambda/"); + histos.addClone("McRec/Lambda/", "McRec/AntiLambda/"); + + // set bin labels + histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); + histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllV0Tracks, "kAllV0Tracks"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0KShortMassRej, "kV0KShortMassRej"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotLambdaNotAntiLambda, "kNotLambdaNotAntiLambda"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0IsBothLambdaAntiLambda, "kV0IsBothLambdaAntiLambda"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotLambdaAfterSel, "kNotLambdaAfterSel"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0IsLambdaOrAntiLambda, "kV0IsLambdaOrAntiLambda"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0DauTrackSel, "kPassV0DauTrackSel"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0KinCuts, "kPassV0KinCuts"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0TopoSel, "kPassV0TopoSel"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllSelPassed, "kAllSelPassed"); + } + + template + bool selCollision(C const& col) + { + // VtxZ Selection + if (col.posZ() <= cMinZVtx || col.posZ() >= cMaxZVtx) { + return false; + } + + if constexpr (run == kRun3) { // Run3 Min-Bias Trigger + // select centrality estimator + if (cCentEstimator == kCentFT0M) { + cent = col.centFT0M(); + } else if (cCentEstimator == kCentFT0C) { + cent = col.centFT0C(); + } + if (cSel8Trig && !col.sel8()) { + return false; + } + } else { // Run2 Min-Bias Trigger + cent = col.centRun2V0M(); + if (cInt7Trig && !col.alias_bit(kINT7)) { + return false; + } + if (cSel7Trig && !col.sel7()) { + return false; + } + } + + if (cent <= cMinMult || cent >= cMaxMult) { // select centrality percentile class + return false; + } + + if (cTriggerTvxSel && !col.selection_bit(aod::evsel::kIsTriggerTVX)) { + return false; + } + + if (cTFBorder && !col.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + + if (cNoItsROBorder && !col.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return false; + } + + if (cItsTpcVtx && !col.selection_bit(aod::evsel::kIsVertexITSTPC)) { + return false; + } + + if (cPileupReject && !col.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return false; + } + + if (cZVtxTimeDiff && !col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + + if (cIsGoodITSLayers && !col.selection_bit(aod::evsel::kIsGoodITSLayersAll)) { + return false; + } + + // Set Multiplicity + mult = col.multNTracksPV(); + + return true; + } + + // Kinematic Selection + bool kinCutSelection(float const& pt, float const& rap, float const& ptMin, float const& ptMax, float const& rapMax) + { + if (pt <= ptMin || pt >= ptMax || rap >= rapMax) { + return false; + } + + return true; + } + + // Track Selection + template + bool selTrack(T const& track) + { + if (!kinCutSelection(track.pt(), std::abs(track.eta()), cTrackMinPt, cTrackMaxPt, cTrackEtaCut)) { + return false; + } + + if (track.tpcNClsCrossedRows() <= cMinTpcCrossedRows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < cMinTpcCROverCls) { + return false; + } + + if (track.tpcNClsShared() > cMaxTpcSharedClusters) { + return false; + } + + if (track.tpcChi2NCl() > cMaxChi2Tpc) { + return false; + } + + return true; + } + + // Daughter Track Selection + template + bool selDaughterTracks(V const& v0, T const&, ParticleType const& v0Type) + { + auto posTrack = v0.template posTrack_as(); + auto negTrack = v0.template negTrack_as(); + + if (!selTrack(posTrack) || !selTrack(negTrack)) { + return false; + } + + // Apply DCA Selection on Daughter Tracks Based on Lambda/AntiLambda daughters + float dcaProton = 0., dcaPion = 0.; + if (v0Type == kLambda) { + dcaProton = std::abs(v0.dcapostopv()); + dcaPion = std::abs(v0.dcanegtopv()); + } else if (v0Type == kAntiLambda) { + dcaPion = std::abs(v0.dcapostopv()); + dcaProton = std::abs(v0.dcanegtopv()); + } + + if (dcaProton < cMinDcaProtonToPV || dcaPion < cMinDcaPionToPV) { + return false; + } + + return true; + } + + template + bool topoCutSelection(C const& col, V const& v0, T const&) + { + // DCA + if (v0.dcaV0daughters() <= cMinV0DcaDaughters || v0.dcaV0daughters() >= cMaxV0DcaDaughters) { + return false; + } + + if (v0.dcav0topv() <= cMinDcaV0ToPV || v0.dcav0topv() >= cMaxDcaV0ToPV) { + return false; + } + + if (v0.v0radius() <= cMinV0TransRadius || v0.v0radius() >= cMaxV0TransRadius) { + return false; + } + + // ctau + float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; + if (ctau <= cMinV0CTau || ctau >= cMaxV0CTau) { + return false; + } + + // cosine of pointing angle + if (v0.v0cosPA() <= cMinV0CosPA) { + return false; + } + + // all selection criterion passed (Return True) + return true; + } + + template + bool selLambdaDauWithTpcPid(T const& postrack, T const& negtrack) + { + bool returnFlag = false; + float tpcNSigmaPr = 0., tpcNSigmaPi = 0.; + + switch (part) { + // postrack = Proton, negtrack = Pion + case kLambda: + tpcNSigmaPr = postrack.tpcNSigmaPr(); + tpcNSigmaPi = negtrack.tpcNSigmaPi(); + break; + + // negtrack = Proton, postrack = Pion + case kAntiLambda: + tpcNSigmaPr = negtrack.tpcNSigmaPr(); + tpcNSigmaPi = postrack.tpcNSigmaPi(); + break; + } + + if (std::abs(tpcNSigmaPr) < cTpcNsigmaCut && std::abs(tpcNSigmaPi) < cTpcNsigmaCut) { + returnFlag = true; + } + + return returnFlag; + } + + template + bool selLambdaMassWindow(V const& v0, T const&, ParticleType& v0type) + { + // Kshort mass rejection hypothesis + if (cKshortRejFlag && (std::abs(v0.mK0Short() - MassK0Short) <= cKshortRejMassWindow)) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kV0KShortMassRej); + return false; + } + + // initialize daughter tracks + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + // initialize selection flags + bool lambdaFlag = false, antiLambdaFlag = false; + + // get v0 track as lambda + if ((v0.mLambda() > cMinV0Mass && v0.mLambda() < cMaxV0Mass) && (selLambdaDauWithTpcPid(postrack, negtrack))) { + lambdaFlag = true; + v0type = kLambda; + } + + // get v0 track as anti-lambda + if ((v0.mAntiLambda() > cMinV0Mass && v0.mAntiLambda() < cMaxV0Mass) && (selLambdaDauWithTpcPid(postrack, negtrack))) { + antiLambdaFlag = true; + v0type = kAntiLambda; + } + + if (!lambdaFlag && !antiLambdaFlag) { // neither Lambda nor Anti-Lambda + histos.fill(HIST("Tracks/h1f_tracks_info"), kNotLambdaNotAntiLambda); + return false; + } else if (lambdaFlag && antiLambdaFlag) { // check if the track is identified as lambda and anti-lambda both (DISCARD THIS TRACK) + histos.fill(HIST("Tracks/h1f_tracks_info"), kV0IsBothLambdaAntiLambda); + return false; + } + + if (lambdaFlag || antiLambdaFlag) { + return true; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kNotLambdaAfterSel); + + return false; + } + + template + bool selV0Particle(C const& col, V const& v0, T const& tracks, ParticleType& v0Type) + { + // Apply Lambda Mass Hypothesis + if (!selLambdaMassWindow(v0, tracks, v0Type)) { + return false; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kV0IsLambdaOrAntiLambda); + + // Apply Daughter Track Selection + if (!selDaughterTracks(v0, tracks, v0Type)) { + return false; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0DauTrackSel); + + // Apply Kinematic Selection + float rap = 0.; + if (!cDoEtaAnalysis) { + rap = std::abs(v0.yLambda()); + } else { + rap = std::abs(v0.eta()); + } + + if (!kinCutSelection(v0.pt(), rap, cMinV0Pt, cMaxV0Pt, cMaxV0Rap)) { + return false; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0KinCuts); + + // Apply Topological Selection + if (!topoCutSelection(col, v0, tracks)) { + return false; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0TopoSel); + + // All Selection Criterion Passed + return true; + } + + template + bool hasAmbiguousDaughters(V const& v0, T const&) + { + auto posTrack = v0.template posTrack_as(); + auto negTrack = v0.template negTrack_as(); + + auto posTrackCompCols = posTrack.compatibleCollIds(); + auto negTrackCompCols = negTrack.compatibleCollIds(); + + // Check if daughter tracks belongs to more than one collision (Ambiguous Tracks) + if (posTrackCompCols.size() > 1 || negTrackCompCols.size() > 1) { + return true; + } + + // Check if compatible collision index matches the track collision index + if (((posTrackCompCols.size() != 0) && (posTrackCompCols[0] != posTrack.collisionId())) || + ((negTrackCompCols.size() != 0) && (negTrackCompCols[0] != negTrack.collisionId()))) { + return true; + } + + // Pass as not ambiguous + return false; + } + + template + void fillLambdaQAHistos(C const& col, V const& v0, T const&) + { + static constexpr std::string_view SubDir[] = {"QA/Lambda/", "QA/AntiLambda/"}; + + // daugthers + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + float mass = 0.; + + if constexpr (part == kLambda) { + mass = v0.mLambda(); + } else { + mass = v0.mAntiLambda(); + } + + // ctau + float e = RecoDecay::e(v0.px(), v0.py(), v0.pz(), mass); + float gamma = e / mass; + float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; + float gctau = ctau * gamma; + + histos.fill(HIST(SubDir[part]) + HIST("h2f_qt_vs_alpha"), v0.alpha(), v0.qtarm()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_V0_daughters"), v0.dcaV0daughters()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_pos_to_PV"), v0.dcapostopv()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_neg_to_PV"), v0.dcanegtopv()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_V0_to_PV"), v0.dcav0topv()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_cospa"), v0.v0cosPA()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_radius"), v0.v0radius()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_ctau"), ctau); + histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_gctau"), gctau); + + histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_pt"), postrack.pt()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_eta"), postrack.eta()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_phi"), postrack.phi()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_pt"), negtrack.pt()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_eta"), negtrack.eta()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_phi"), negtrack.phi()); + + histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_dcaXY_vs_pt"), postrack.pt(), postrack.dcaXY()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_dcaXY_vs_pt"), negtrack.pt(), negtrack.dcaXY()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_dEdx_vs_p"), postrack.tpcInnerParam(), postrack.tpcSignal()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_dEdx_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcSignal()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_tpc_nsigma_pr_vs_p"), postrack.tpcInnerParam(), postrack.tpcNSigmaPr()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_tpc_nsigma_pr_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPr()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_tpc_nsigma_pi_vs_p"), postrack.tpcInnerParam(), postrack.tpcNSigmaPi()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_tpc_nsigma_pi_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPi()); + } + + // Reconstructed Level Tables + template + void fillLambdaRecoTables(C const& collision, V const& v0tracks, T const& tracks) + { + // Total Collisions + histos.fill(HIST("Events/h1f_collisions_info"), kTotCol); + if (!selCollision(collision)) { + return; + } + + histos.fill(HIST("Events/h1f_collisions_info"), kPassSelCol); + histos.fill(HIST("Events/h1f_collision_posZ"), collision.posZ()); + + // Fill Collision Table + lambdaCollisionTable(cent, mult, collision.posX(), collision.posY(), collision.posZ()); + + // initialize v0track objects + ParticleType v0Type = kLambda; + float mass = 0.; + float prPx = 0., prPy = 0., prPz = 0.; + + for (auto const& v0 : v0tracks) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kAllV0Tracks); + histos.fill(HIST("Tracks/h2f_armpod_before_sel"), v0.alpha(), v0.qtarm()); + + // Select V0 Particle as Lambda/AntiLambda + if (!selV0Particle(collision, v0, tracks, v0Type)) { + continue; + } + + // Select V0 Type Selection + if (cV0TypeSelFlag && v0.v0Type() != cV0TypeSelection) { + continue; + } + + // we have v0 as lambda + histos.fill(HIST("Tracks/h1f_tracks_info"), kAllSelPassed); + + // Remove lambda with ambiguous daughters (Only for run3) + if constexpr (run == kRun3) { + if (cRemoveAmbiguousTracks && hasAmbiguousDaughters(v0, tracks)) { + continue; + } + } + + // Get Lambda mass + mass = (v0Type == kLambda) ? v0.mLambda() : v0.mAntiLambda(); + histos.fill(HIST("Tracks/h2f_armpod_after_sel"), v0.alpha(), v0.qtarm()); + + // fill lambda qa + if (v0Type == kLambda) { + // Assign proton Eta Phi + prPx = v0.template posTrack_as().px(); + prPy = v0.template posTrack_as().py(); + prPz = v0.template posTrack_as().pz(); + histos.fill(HIST("Tracks/h1f_lambda_pt_vs_invm"), mass, v0.pt()); + fillLambdaQAHistos(collision, v0, tracks); + } else { + // Assign proton Eta Phi + prPx = v0.template negTrack_as().px(); + prPy = v0.template negTrack_as().py(); + prPz = v0.template negTrack_as().pz(); + histos.fill(HIST("Tracks/h1f_antilambda_pt_vs_invm"), mass, v0.pt()); + fillLambdaQAHistos(collision, v0, tracks); + } + + // Fill Lambda/AntiLambda Table + lambdaTrackTable(lambdaCollisionTable.lastIndex(), + v0.px(), v0.py(), v0.pz(), + v0.pt(), v0.eta(), v0.phi(), v0.yLambda(), mass, + v0.template posTrack_as().index(), v0.template negTrack_as().index(), + prPx, prPy, prPz, (int8_t)v0Type); + } + } + + SliceCache cache; + Preslice> perCollision = aod::v0data::collisionId; + + using CollisionsRun3 = soa::Join; + using CollisionsRun2 = soa::Join; + using Tracks = soa::Join; + using TracksRun2 = soa::Join; + + void processDataRun3(CollisionsRun3::iterator const& collision, aod::V0Datas const& V0s, Tracks const& tracks) + { + fillLambdaRecoTables(collision, V0s, tracks); + } + + PROCESS_SWITCH(LambdaTableProducer, processDataRun3, "Process for Run3 DATA", true); + + void processDataRun2(CollisionsRun2::iterator const& collision, aod::V0Datas const& V0s, TracksRun2 const& tracks) + { + fillLambdaRecoTables(collision, V0s, tracks); + } + + PROCESS_SWITCH(LambdaTableProducer, processDataRun2, "Process for Run2 DATA", false); +}; + +struct LambdaTracksExtProducer { + // Table + Produces lambdaTrackExtTable; + + // Configurables + Configurable cAcceptAllLambda{"cAcceptAllLambda", false, "Accept all Lambda"}; + Configurable cRejAllLambdaShaDau{"cRejAllLambdaShaDau", true, "Reject all Lambda sharing daughters"}; + + // Histogram Registry. + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + // Axis Specifications + const AxisSpec axisMult(10, 0, 10); + const AxisSpec axisMass(100, 1.06, 1.16, "Inv Mass (GeV/#it{c}^{2})"); + const AxisSpec axisCPA(100, 0.995, 1.0, "cos(#theta_{PA})"); + const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); + const AxisSpec axisDEta(320, -1.6, 1.6, "#Delta#eta"); + const AxisSpec axisDPhi(640, -PIHalf, 3. * PIHalf, "#Delta#varphi"); + + // Histograms Booking + histos.add("h1i_totlambda_mult", "Multiplicity", kTH1I, {axisMult}); + histos.add("h1i_totantilambda_mult", "Multiplicity", kTH1I, {axisMult}); + histos.add("h1i_lambda_mult", "Multiplicity", kTH1I, {axisMult}); + histos.add("h1i_antilambda_mult", "Multiplicity", kTH1I, {axisMult}); + histos.add("h2d_n2_etaphi_LaP_LaM", "#rho_{2}^{SharePair}", kTH2D, {axisDEta, axisDPhi}); + histos.add("h2d_n2_etaphi_LaP_LaP", "#rho_{2}^{SharePair}", kTH2D, {axisDEta, axisDPhi}); + histos.add("h2d_n2_etaphi_LaM_LaM", "#rho_{2}^{SharePair}", kTH2D, {axisDEta, axisDPhi}); + } + + void process(aod::LambdaCollisions::iterator const&, aod::LambdaTracks const& tracks) + { + + int nTotLambda = 0, nTotAntiLambda = 0, nSelLambda = 0, nSelAntiLambda = 0; + + for (auto const& lambda : tracks) { + bool lambdaSharingDauFlag = false, trueLambdaFlag = false; + std::vector vSharedDauLambdaIndex; + + if (lambda.v0Type() == kLambda) { + ++nTotLambda; + } else if (lambda.v0Type() == kAntiLambda) { + ++nTotAntiLambda; + } + + for (auto const& track : tracks) { + // check lambda index (don't analyze same lambda track !!!) + if (lambda.index() == track.index()) { + continue; + } + + // check if lambda shares daughters with any other track + if (lambda.posTrackId() == track.posTrackId() || lambda.negTrackId() == track.negTrackId()) { + vSharedDauLambdaIndex.push_back(track.index()); + lambdaSharingDauFlag = true; + + // Fill DEta-DPhi Histogram + if ((lambda.v0Type() == kLambda && track.v0Type() == kAntiLambda) || (lambda.v0Type() == kAntiLambda && track.v0Type() == kLambda)) { + histos.fill(HIST("h2d_n2_etaphi_LaP_LaM"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); + } else if (lambda.v0Type() == kLambda && track.v0Type() == kLambda) { + histos.fill(HIST("h2d_n2_etaphi_LaP_LaP"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); + } else if (lambda.v0Type() == kAntiLambda && track.v0Type() == kAntiLambda) { + histos.fill(HIST("h2d_n2_etaphi_LaM_LaM"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); + } + } + } + + if (cAcceptAllLambda) { // Accept all lambda + trueLambdaFlag = true; + } else if (cRejAllLambdaShaDau && !lambdaSharingDauFlag) { // Reject all lambda sharing daughter + trueLambdaFlag = true; + } else { + trueLambdaFlag = false; + } + + // Multiplicity of selected lambda + if (trueLambdaFlag) { + if (lambda.v0Type() == kLambda) { + ++nSelLambda; + } else if (lambda.v0Type() == kAntiLambda) { + ++nSelAntiLambda; + } + } + + // fill LambdaTrackExt table + lambdaTrackExtTable(lambdaSharingDauFlag, vSharedDauLambdaIndex, trueLambdaFlag); + } + + // fill multiplicity histograms + if (nTotLambda != 0) { + histos.fill(HIST("h1i_totlambda_mult"), nTotLambda); + } + + if (nTotAntiLambda != 0) { + histos.fill(HIST("h1i_totantilambda_mult"), nTotAntiLambda); + } + + if (nSelLambda != 0) { + histos.fill(HIST("h1i_lambda_mult"), nSelLambda); + } + + if (nSelAntiLambda != 0) { + histos.fill(HIST("h1i_antilambda_mult"), nSelAntiLambda); + } + } +}; + +struct LambdaSpinCorrelation { + // Global Configurables + Configurable cNPtBins{"cNPtBins", 30, "N pT Bins"}; + Configurable cMinPt{"cMinPt", 0.5, "pT Min"}; + Configurable cMaxPt{"cMaxPt", 3.5, "pT Max"}; + Configurable cNRapBins{"cNRapBins", 20, "N Rapidity Bins"}; + Configurable cMinRap{"cMinRap", -0.5, "Minimum Rapidity"}; + Configurable cMaxRap{"cMaxRap", 0.5, "Maximum Rapidity"}; + Configurable cNPhiBins{"cNPhiBins", 36, "N Phi Bins"}; + Configurable cAnaPairs{"cAnaPairs", false, "Analyze Pairs Flag"}; + Configurable cInvBoostFlag{"cInvBoostFlag", true, "Inverse Boost Flag"}; + + // Centrality Axis + ConfigurableAxis cMultBins{"cMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 30.0f, 50.f, 80.0f, 100.f}, "Variable Mult-Bins"}; + + // Histogram Registry. + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Global variables + float cent = 0.; + + void init(InitContext const&) + { + const AxisSpec axisCheck(1, 0, 1, ""); + const AxisSpec axisPosZ(220, -11, 11, "V_{z} (cm)"); + const AxisSpec axisCent(cMultBins, "FT0M (%)"); + const AxisSpec axisChMult(200, 0, 200, "N_{ch}"); + const AxisSpec axisMult(10, 0, 10, "N_{#Lambda}"); + const AxisSpec axisMass(100, 1.06, 1.16, "M_{#Lambda} (GeV/#it{c}^{2})"); + const AxisSpec axisPt(cNPtBins, cMinPt, cMaxPt, "p_{T} (GeV/#it{c})"); + const AxisSpec axisEta(cNRapBins, cMinRap, cMaxRap, "#eta"); + const AxisSpec axisRap(cNRapBins, cMinRap, cMaxRap, "y"); + const AxisSpec axisPhi(cNPhiBins, 0., TwoPI, "#varphi (rad)"); + const AxisSpec axisDPhi(cNPhiBins, -PI, PI, "#Delta#varphi"); + + // Create Histograms. + // Event + histos.add("Event/h1f_collision_posz", "V_{Z} Distribution", kTH1F, {axisPosZ}); + histos.add("Event/h1f_ft0m_mult_percentile", "FT0M (%)", kTH1F, {axisCent}); + histos.add("Event/h2f_Mult_vs_Centrality", "N_{ch} vs FT0M(%)", kTH2F, {axisCent, axisChMult}); + histos.add("Event/h2f_lambda_mult", "#Lambda - Multiplicity", kTH2F, {axisCent, axisMult}); + histos.add("Event/h2f_antilambda_mult", "#bar{#Lambda} - Multiplicity", kTH2F, {axisCent, axisMult}); + + // Single and Two Particle Densities + // 1D Histograms + histos.add("Reco/h3f_n1_centmasspt_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisMass, axisPt}); + histos.add("Reco/h3f_n1_centmasspt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisMass, axisPt}); + histos.add("Reco/h2f_n1_pt_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPt}); + histos.add("Reco/h2f_n1_pt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPt}); + histos.add("Reco/h2f_n1_eta_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisEta}); + histos.add("Reco/h2f_n1_eta_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisEta}); + histos.add("Reco/h2f_n1_rap_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisRap}); + histos.add("Reco/h2f_n1_rap_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisRap}); + histos.add("Reco/h2f_n1_phi_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPhi}); + histos.add("Reco/h2f_n1_phi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPhi}); + histos.add("Reco/h2f_n2_mass_LaPLaM", "m_{inv}^{#Lambda} vs m_{inv}^{#bar{#Lambda}}", kTH2F, {axisMass, axisMass}); + histos.add("Reco/h2f_n2_mass_LaPLaP", "m_{inv}^{#Lambda} vs m_{inv}^{#Lambda}", kTH2F, {axisMass, axisMass}); + histos.add("Reco/h2f_n2_mass_LaMLaM", "m_{inv}^{#bar{#Lambda}} vs m_{inv}^{#bar{#Lambda}}", kTH2F, {axisMass, axisMass}); + + // rho1 for C2 + histos.add("RecoCorr/h2f_n1_phi_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPhi}); + histos.add("RecoCorr/h2f_n1_phi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPhi}); + + // rho2 for C2 + histos.add("RecoCorr/h2f_n2_dphi_LaPLaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH2F, {axisCent, axisDPhi}); + histos.add("RecoCorr/h2f_n2_dphi_LaPLaP", "#rho_{2}^{#Lambda#Lambda}", kTH2F, {axisCent, axisDPhi}); + histos.add("RecoCorr/h2f_n2_dphi_LaMLaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2F, {axisCent, axisDPhi}); + histos.add("RecoCorr/h2f_n2_phiphi_LaPLaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); + histos.add("RecoCorr/h2f_n2_phiphi_LaPLaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisPhi, axisPhi}); + histos.add("RecoCorr/h2f_n2_phiphi_LaMLaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); + } + + void getBoostVector(std::array const& p, std::array& v, bool inverseBoostFlag = true) + { + int n = p.size(); + for (int i = 0; i < n - 1; ++i) { + if (inverseBoostFlag) { + v[i] = -p[i] / RecoDecay::e(p[0], p[1], p[2], p[3]); + } else { + v[i] = p[i] / RecoDecay::e(p[0], p[1], p[2], p[3]); + } + } + } + + void boost(std::array& p, std::array const& b) + { + float e = RecoDecay::e(p[0], p[1], p[2], p[3]); + float b2 = b[0] * b[0] + b[1] * b[1] + b[2] * b[2]; + float gamma = 1. / std::sqrt(1 - b2); + float bp = b[0] * p[0] + b[1] * p[1] + b[2] * p[2]; + float gamma2 = b2 > 0 ? (gamma - 1.) / b2 : 0.; + + p[0] = p[0] + gamma2 * bp * b[0] + gamma * b[0] * e; + p[1] = p[1] + gamma2 * bp * b[1] + gamma * b[1] * e; + p[2] = p[2] + gamma2 * bp * b[2] + gamma * b[2] * e; + } + + template + void fillPairHistos(U& p1, U& p2) + { + static constexpr std::string_view SubDirHist[] = {"LaPLaM", "LaPLaP", "LaMLaM"}; + + // Fill lambda pair mass + histos.fill(HIST("Reco/h2f_n2_mass_") + HIST(SubDirHist[part_pair]), p1.mass(), p2.mass()); + + // Get Lambda-Proton four-momentum + std::array l1 = {p1.px(), p1.py(), p1.pz(), MassLambda0}; + std::array l2 = {p2.px(), p2.py(), p2.pz(), MassLambda0}; + std::array pr1 = {p1.prPx(), p1.prPy(), p1.prPz(), MassProton}; + std::array pr2 = {p2.prPx(), p2.prPy(), p2.prPz(), MassProton}; + std::array v1, v2; + getBoostVector(l1, v1, cInvBoostFlag); + getBoostVector(l2, v2, cInvBoostFlag); + boost(pr1, v1); + boost(pr2, v2); + + // Fill pair density + histos.fill(HIST("RecoCorr/h2f_n2_phiphi_") + HIST(SubDirHist[part_pair]), cent, RecoDecay::constrainAngle(RecoDecay::phi(pr1)), RecoDecay::phi(pr2)); + histos.fill(HIST("RecoCorr/h2f_n2_dphi_") + HIST(SubDirHist[part_pair]), cent, RecoDecay::constrainAngle(RecoDecay::phi(pr1) - RecoDecay::phi(pr2), -PI)); + } + + template + void analyzeSingles(T const& tracks) + { + static constexpr std::string_view SubDirHist[] = {"LaP", "LaM"}; + int ntrk = 0; + for (auto const& track : tracks) { + // Count tracks + ++ntrk; + + // Fill histograms + histos.fill(HIST("Reco/h3f_n1_centmasspt_") + HIST(SubDirHist[part]), cent, track.mass(), track.pt()); + histos.fill(HIST("Reco/h2f_n1_pt_") + HIST(SubDirHist[part]), cent, track.pt()); + histos.fill(HIST("Reco/h2f_n1_eta_") + HIST(SubDirHist[part]), cent, track.eta()); + histos.fill(HIST("Reco/h2f_n1_phi_") + HIST(SubDirHist[part]), cent, track.phi()); + histos.fill(HIST("Reco/h2f_n1_rap_") + HIST(SubDirHist[part]), cent, track.rap()); + + // Get four-momentum of lambda + std::array l = {MassLambda0, track.px(), track.py(), track.pz()}; + std::array p = {MassProton, track.prPx(), track.prPy(), track.prPz()}; + std::array v; + getBoostVector(l, v, cInvBoostFlag); + boost(p, v); + + // Fill single histograms + histos.fill(HIST("RecoCorr/h2f_n1_phi_") + HIST(SubDirHist[part]), cent, RecoDecay::constrainAngle(RecoDecay::phi(p))); + } + + // fill multiplicity histograms + if (ntrk != 0) { + if (part == kLambda) { + histos.fill(HIST("Event/h2f_lambda_mult"), cent, ntrk); + } else { + histos.fill(HIST("Event/h2f_antilambda_mult"), cent, ntrk); + } + } + } + + template + void analyzePairs(T const& trks_1, T const& trks_2) + { + for (auto const& trk_1 : trks_1) { + for (auto const& trk_2 : trks_2) { + // check for same index for Lambda-Lambda / AntiLambda-AntiLambda + if (samelambda && ((trk_1.index() == trk_2.index()))) { + continue; + } + fillPairHistos(trk_1, trk_2); + } + } + } + + // Initialize tables + using LambdaCollisions = aod::LambdaCollisions; + using LambdaTracks = soa::Join; + + SliceCache cache; + Partition partLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrackext::trueLambdaFlag == true); + Partition partAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrackext::trueLambdaFlag == true); + + void processDataReco(LambdaCollisions::iterator const& collision, LambdaTracks const&) + { + histos.fill(HIST("Event/h1f_collision_posz"), collision.posZ()); + histos.fill(HIST("Event/h1f_ft0m_mult_percentile"), collision.cent()); + histos.fill(HIST("Event/h2f_Mult_vs_Centrality"), collision.cent(), collision.mult()); + + cent = collision.cent(); + + auto lambdaTracks = partLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + auto antiLambdaTracks = partAntiLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + + analyzeSingles(lambdaTracks); + analyzeSingles(antiLambdaTracks); + + if (cAnaPairs) { + analyzePairs(lambdaTracks, antiLambdaTracks); + analyzePairs(lambdaTracks, lambdaTracks); + analyzePairs(antiLambdaTracks, antiLambdaTracks); + } + } + + PROCESS_SWITCH(LambdaSpinCorrelation, processDataReco, "Process for Data and MCReco", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} From 07573c193c051cbf4c3b79e4c96318180e5705bb Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Fri, 7 Nov 2025 23:03:45 +0530 Subject: [PATCH 2/8] Update CMakeLists.txt --- PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt index 0fca88628ef..ac7a8c510f0 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -23,6 +23,11 @@ o2physics_add_dpl_workflow(lambdacorr PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(lambda-spin-correlation + SOURCES lambdaSpinCorrelation.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(dpt-dpt-efficiency-and-qc SOURCES dptDptEfficiencyAndQc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore From 143274577a04e49b865dfcf6f6d297553f820d7e Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Sat, 8 Nov 2025 15:47:37 +0530 Subject: [PATCH 3/8] Remove lambda-spin-correlation workflow Removed the lambda-spin-correlation workflow from CMakeLists.txt. --- PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt index 9a517b3a274..21bb0bade8e 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -23,11 +23,6 @@ o2physics_add_dpl_workflow(lambdacorr PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(lambda-spin-correlation - SOURCES lambdaSpinCorrelation.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(dpt-dpt-efficiency-and-qc SOURCES dptDptEfficiencyAndQc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore From 96ec83bdfac390d063f854036c5a2386bb91cf11 Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Sat, 8 Nov 2025 10:24:23 +0000 Subject: [PATCH 4/8] Added Lambda Spin Correlation --- .../Tasks/lambdaR2Correlation.cxx | 221 +++- .../Tasks/lambdaSpinCorrelation.cxx | 1088 ----------------- 2 files changed, 210 insertions(+), 1099 deletions(-) delete mode 100644 PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinCorrelation.cxx diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index 60d90343dd9..b69e6b5fb72 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -20,7 +20,7 @@ #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/PIDResponse.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" @@ -28,8 +28,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "TPDGCode.h" - +#include #include #include @@ -76,6 +75,9 @@ DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); DECLARE_SOA_COLUMN(Rap, rap, float); DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(PrPx, prPx, float); +DECLARE_SOA_COLUMN(PrPy, prPy, float); +DECLARE_SOA_COLUMN(PrPz, prPz, float); DECLARE_SOA_COLUMN(PosTrackId, posTrackId, int64_t); DECLARE_SOA_COLUMN(NegTrackId, negTrackId, int64_t); DECLARE_SOA_COLUMN(CosPA, cosPA, float); @@ -94,6 +96,9 @@ DECLARE_SOA_TABLE(LambdaTracks, "AOD", "LAMBDATRACKS", o2::soa::Index<>, lambdatrack::Phi, lambdatrack::Rap, lambdatrack::Mass, + lambdatrack::PrPx, + lambdatrack::PrPy, + lambdatrack::PrPz, lambdatrack::PosTrackId, lambdatrack::NegTrackId, lambdatrack::CosPA, @@ -130,6 +135,9 @@ DECLARE_SOA_TABLE(LambdaMcGenTracks, "AOD", "LMCGENTRACKS", o2::soa::Index<>, lambdatrack::Phi, lambdatrack::Rap, lambdatrack::Mass, + lambdatrack::PrPx, + lambdatrack::PrPy, + lambdatrack::PrPz, lambdatrack::PosTrackId, lambdatrack::NegTrackId, lambdatrack::V0Type, @@ -178,7 +186,7 @@ enum TrackLabels { enum CentEstType { kCentFT0M = 0, - kCentFV0A + kCentFT0C }; enum RunType { @@ -238,7 +246,7 @@ struct LambdaTableProducer { Produces lambdaMCGenTrackTable; // Collisions - Configurable cCentEstimator{"cCentEstimator", 0, "Centrality Estimator : 0-FT0M, 1-FV0A"}; + Configurable cCentEstimator{"cCentEstimator", 0, "Centrality Estimator : 0-FT0M, 1-FT0C"}; Configurable cMinZVtx{"cMinZVtx", -10.0, "Min VtxZ cut"}; Configurable cMaxZVtx{"cMaxZVtx", 10.0, "Max VtxZ cut"}; Configurable cMinMult{"cMinMult", 0., "Minumum Multiplicity"}; @@ -491,8 +499,8 @@ struct LambdaTableProducer { // select centrality estimator if (cCentEstimator == kCentFT0M) { cent = col.centFT0M(); - } else if (cCentEstimator == kCentFV0A) { - cent = col.centFV0A(); + } else if (cCentEstimator == kCentFT0C) { + cent = col.centFT0C(); } if (cSel8Trig && !col.sel8()) { return false; @@ -989,6 +997,7 @@ struct LambdaTableProducer { ParticleType v0Type = kLambda; PrmScdType v0PrmScdType = kPrimary; float mass = 0., corr_fact = 1.; + float prPx = 0., prPy = 0., prPz = 0.; for (auto const& v0 : v0tracks) { // check for corresponding MCGen Particle @@ -1072,10 +1081,18 @@ struct LambdaTableProducer { // fill lambda qa if (v0Type == kLambda) { + // Assign proton Eta Phi + prPx = v0.template posTrack_as().px(); + prPy = v0.template posTrack_as().py(); + prPz = v0.template posTrack_as().pz(); histos.fill(HIST("Tracks/h1f_lambda_pt_vs_invm"), mass, v0.pt()); fillLambdaQAHistos(collision, v0, tracks); fillKinematicHists(v0.pt(), v0.eta(), v0.yLambda(), v0.phi()); } else { + // Assign proton Eta Phi + prPx = v0.template negTrack_as().px(); + prPy = v0.template negTrack_as().py(); + prPz = v0.template negTrack_as().pz(); histos.fill(HIST("Tracks/h1f_antilambda_pt_vs_invm"), mass, v0.pt()); fillLambdaQAHistos(collision, v0, tracks); fillKinematicHists(v0.pt(), v0.eta(), v0.yLambda(), v0.phi()); @@ -1083,7 +1100,8 @@ struct LambdaTableProducer { // Fill Lambda/AntiLambda Table lambdaTrackTable(lambdaCollisionTable.lastIndex(), v0.px(), v0.py(), v0.pz(), - pt, eta, phi, rap, mass, v0.template posTrack_as().index(), v0.template negTrack_as().index(), + pt, eta, phi, rap, mass, prPx, prPy, prPz, + v0.template posTrack_as().index(), v0.template negTrack_as().index(), v0.v0cosPA(), v0.dcaV0daughters(), (int8_t)v0Type, v0PrmScdType, corr_fact); } } @@ -1099,6 +1117,7 @@ struct LambdaTableProducer { ParticleType v0Type = kLambda; PrmScdType v0PrmScdType = kPrimary; float rap = 0.; + float prPx = 0., prPy = 0., prPz = 0.; for (auto const& mcpart : mcParticles) { // check for Lambda first @@ -1139,6 +1158,7 @@ struct LambdaTableProducer { auto dautracks = mcpart.template daughters_as(); std::vector daughterPDGs, daughterIDs; std::vector vDauPt, vDauEta, vDauRap, vDauPhi; + std::vector vDauPx, vDauPy, vDauPz; for (auto const& dautrack : dautracks) { daughterPDGs.push_back(dautrack.pdgCode()); daughterIDs.push_back(dautrack.globalIndex()); @@ -1146,6 +1166,9 @@ struct LambdaTableProducer { vDauEta.push_back(dautrack.eta()); vDauRap.push_back(dautrack.y()); vDauPhi.push_back(dautrack.phi()); + vDauPx.push_back(dautrack.px()); + vDauPy.push_back(dautrack.py()); + vDauPz.push_back(dautrack.pz()); } if (cGenDecayChannel) { // check decay channel if (v0Type == kLambda) { @@ -1162,6 +1185,10 @@ struct LambdaTableProducer { histos.fill(HIST("Tracks/h1f_tracks_info"), kGenLambdaToPrPi); if (v0Type == kLambda) { + // Assign proton p-vec + prPx = vDauPx[0]; + prPy = vDauPy[0]; + prPz = vDauPz[0]; histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), daughterPDGs[0]); histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), daughterPDGs[1]); histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), mcpart.pdgCode()); @@ -1175,6 +1202,10 @@ struct LambdaTableProducer { histos.fill(HIST("McGen/Lambda/Pion/hPhi"), vDauPhi[1]); fillKinematicHists(mcpart.pt(), mcpart.eta(), mcpart.y(), mcpart.phi()); } else { + // Assign anti-proton p-vec + prPx = vDauPx[1]; + prPy = vDauPy[1]; + prPz = vDauPz[1]; histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), daughterPDGs[0]); histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), daughterPDGs[1]); histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), mcpart.pdgCode()); @@ -1191,7 +1222,7 @@ struct LambdaTableProducer { // Fill Lambda McGen Table lambdaMCGenTrackTable(lambdaMCGenCollisionTable.lastIndex(), mcpart.px(), mcpart.py(), mcpart.pz(), - mcpart.pt(), mcpart.eta(), mcpart.phi(), mcpart.y(), RecoDecay::m(mcpart.p(), mcpart.e()), + mcpart.pt(), mcpart.eta(), mcpart.phi(), mcpart.y(), RecoDecay::m(mcpart.p(), mcpart.e()), prPx, prPy, prPz, daughterIDs[0], daughterIDs[1], (int8_t)v0Type, -999., -999., v0PrmScdType, 1.); } } @@ -1223,7 +1254,7 @@ struct LambdaTableProducer { SliceCache cache; Preslice> perCollision = aod::v0data::collisionId; - using CollisionsRun3 = soa::Join; + using CollisionsRun3 = soa::Join; using CollisionsRun2 = soa::Join; using Tracks = soa::Join; using TracksRun2 = soa::Join; @@ -1453,6 +1484,173 @@ struct LambdaTracksExtProducer { } }; +struct LambdaSpinCorrelation { + // Global Configurables + Configurable cNPtBins{"cNPtBins", 30, "N pT Bins"}; + Configurable cMinPt{"cMinPt", 0.5, "pT Min"}; + Configurable cMaxPt{"cMaxPt", 3.5, "pT Max"}; + Configurable cNRapBins{"cNRapBins", 20, "N Rapidity Bins"}; + Configurable cMinRap{"cMinRap", -0.5, "Minimum Rapidity"}; + Configurable cMaxRap{"cMaxRap", 0.5, "Maximum Rapidity"}; + Configurable cNPhiBins{"cNPhiBins", 36, "N Phi Bins"}; + Configurable cAnaPairs{"cAnaPairs", false, "Analyze Pairs Flag"}; + Configurable cInvBoostFlag{"cInvBoostFlag", true, "Inverse Boost Flag"}; + + // Centrality Axis + ConfigurableAxis cMultBins{"cMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 30.0f, 50.f, 80.0f, 100.f}, "Variable Mult-Bins"}; + + // Histogram Registry. + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Global variables + float cent = 0.; + + void init(InitContext const&) + { + const AxisSpec axisCheck(1, 0, 1, ""); + const AxisSpec axisPosZ(220, -11, 11, "V_{z} (cm)"); + const AxisSpec axisCent(cMultBins, "FT0M (%)"); + const AxisSpec axisChMult(200, 0, 200, "N_{ch}"); + const AxisSpec axisMult(10, 0, 10, "N_{#Lambda}"); + const AxisSpec axisMass(100, 1.06, 1.16, "M_{#Lambda} (GeV/#it{c}^{2})"); + const AxisSpec axisPt(cNPtBins, cMinPt, cMaxPt, "p_{T} (GeV/#it{c})"); + const AxisSpec axisEta(cNRapBins, cMinRap, cMaxRap, "#eta"); + const AxisSpec axisRap(cNRapBins, cMinRap, cMaxRap, "y"); + const AxisSpec axisPhi(cNPhiBins, 0., TwoPI, "#varphi (rad)"); + const AxisSpec axisDPhi(cNPhiBins, -PI, PI, "#Delta#varphi"); + + // Single and Two Particle Densities + // 1D Histograms + histos.add("Reco/h2f_n2_mass_LaPLaM", "m_{inv}^{#Lambda} vs m_{inv}^{#bar{#Lambda}}", kTH2F, {axisMass, axisMass}); + histos.add("Reco/h2f_n2_mass_LaPLaP", "m_{inv}^{#Lambda} vs m_{inv}^{#Lambda}", kTH2F, {axisMass, axisMass}); + histos.add("Reco/h2f_n2_mass_LaMLaM", "m_{inv}^{#bar{#Lambda}} vs m_{inv}^{#bar{#Lambda}}", kTH2F, {axisMass, axisMass}); + + // rho1 for C2 + histos.add("RecoCorr/h2f_n1_phi_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPhi}); + histos.add("RecoCorr/h2f_n1_phi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPhi}); + + // rho2 for C2 + histos.add("RecoCorr/h2f_n2_dphi_LaPLaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH2F, {axisCent, axisDPhi}); + histos.add("RecoCorr/h2f_n2_dphi_LaPLaP", "#rho_{2}^{#Lambda#Lambda}", kTH2F, {axisCent, axisDPhi}); + histos.add("RecoCorr/h2f_n2_dphi_LaMLaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2F, {axisCent, axisDPhi}); + histos.add("RecoCorr/h2f_n2_phiphi_LaPLaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); + histos.add("RecoCorr/h2f_n2_phiphi_LaPLaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisPhi, axisPhi}); + histos.add("RecoCorr/h2f_n2_phiphi_LaMLaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); + } + + void getBoostVector(std::array const& p, std::array& v, bool inverseBoostFlag = true) + { + int n = p.size(); + for (int i = 0; i < n - 1; ++i) { + if (inverseBoostFlag) { + v[i] = -p[i] / RecoDecay::e(p[0], p[1], p[2], p[3]); + } else { + v[i] = p[i] / RecoDecay::e(p[0], p[1], p[2], p[3]); + } + } + } + + void boost(std::array& p, std::array const& b) + { + float e = RecoDecay::e(p[0], p[1], p[2], p[3]); + float b2 = b[0] * b[0] + b[1] * b[1] + b[2] * b[2]; + float gamma = 1. / std::sqrt(1 - b2); + float bp = b[0] * p[0] + b[1] * p[1] + b[2] * p[2]; + float gamma2 = b2 > 0 ? (gamma - 1.) / b2 : 0.; + + p[0] = p[0] + gamma2 * bp * b[0] + gamma * b[0] * e; + p[1] = p[1] + gamma2 * bp * b[1] + gamma * b[1] * e; + p[2] = p[2] + gamma2 * bp * b[2] + gamma * b[2] * e; + } + + template + void fillPairHistos(U& p1, U& p2) + { + static constexpr std::string_view SubDirHist[] = {"LaPLaM", "LaPLaP", "LaMLaM"}; + + // Fill lambda pair mass + histos.fill(HIST("Reco/h2f_n2_mass_") + HIST(SubDirHist[part_pair]), p1.mass(), p2.mass()); + + // Get Lambda-Proton four-momentum + std::array l1 = {p1.px(), p1.py(), p1.pz(), MassLambda0}; + std::array l2 = {p2.px(), p2.py(), p2.pz(), MassLambda0}; + std::array pr1 = {p1.prPx(), p1.prPy(), p1.prPz(), MassProton}; + std::array pr2 = {p2.prPx(), p2.prPy(), p2.prPz(), MassProton}; + std::array v1, v2; + getBoostVector(l1, v1, cInvBoostFlag); + getBoostVector(l2, v2, cInvBoostFlag); + boost(pr1, v1); + boost(pr2, v2); + + // Fill pair density + histos.fill(HIST("RecoCorr/h2f_n2_phiphi_") + HIST(SubDirHist[part_pair]), cent, RecoDecay::constrainAngle(RecoDecay::phi(pr1)), RecoDecay::phi(pr2)); + histos.fill(HIST("RecoCorr/h2f_n2_dphi_") + HIST(SubDirHist[part_pair]), cent, RecoDecay::constrainAngle(RecoDecay::phi(pr1) - RecoDecay::phi(pr2), -PI)); + } + + template + void analyzeSingles(T const& tracks) + { + static constexpr std::string_view SubDirHist[] = {"LaP", "LaM"}; + int ntrk = 0; + for (auto const& track : tracks) { + // Count tracks + ++ntrk; + + // Get four-momentum of lambda + std::array l = {MassLambda0, track.px(), track.py(), track.pz()}; + std::array p = {MassProton, track.prPx(), track.prPy(), track.prPz()}; + std::array v; + getBoostVector(l, v, cInvBoostFlag); + boost(p, v); + + // Fill single histograms + histos.fill(HIST("RecoCorr/h2f_n1_phi_") + HIST(SubDirHist[part]), cent, RecoDecay::constrainAngle(RecoDecay::phi(p))); + } + } + + template + void analyzePairs(T const& trks_1, T const& trks_2) + { + for (auto const& trk_1 : trks_1) { + for (auto const& trk_2 : trks_2) { + // check for same index for Lambda-Lambda / AntiLambda-AntiLambda + if (samelambda && ((trk_1.index() == trk_2.index()))) { + continue; + } + fillPairHistos(trk_1, trk_2); + } + } + } + + // Initialize tables + using LambdaCollisions = aod::LambdaCollisions; + using LambdaTracks = soa::Join; + + SliceCache cache; + Partition partLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); + Partition partAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); + + void processDataReco(LambdaCollisions::iterator const& collision, LambdaTracks const&) + { + // assign centrality + cent = collision.cent(); + + auto lambdaTracks = partLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + auto antiLambdaTracks = partAntiLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + + analyzeSingles(lambdaTracks); + analyzeSingles(antiLambdaTracks); + + if (cAnaPairs) { + analyzePairs(lambdaTracks, antiLambdaTracks); + analyzePairs(lambdaTracks, lambdaTracks); + analyzePairs(antiLambdaTracks, antiLambdaTracks); + } + } + + PROCESS_SWITCH(LambdaSpinCorrelation, processDataReco, "Process for Data and MCReco", true); +}; + struct LambdaR2Correlation { // Global Configurables Configurable cNPtBins{"cNPtBins", 34, "N pT Bins"}; @@ -1797,5 +1995,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) return WorkflowSpec{ adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; -} +} \ No newline at end of file diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinCorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinCorrelation.cxx deleted file mode 100644 index 5e5338ffa05..00000000000 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinCorrelation.cxx +++ /dev/null @@ -1,1088 +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 LambdaSpinCorrelation.cxx -/// \brief Spin Correlation of Lambda baryons. -/// \author Yash Patley - -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include -#include -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::constants::physics; -using namespace o2::constants::math; - -namespace o2::aod -{ -namespace lambdacollision -{ -DECLARE_SOA_COLUMN(Cent, cent, float); -DECLARE_SOA_COLUMN(Mult, mult, float); -} // namespace lambdacollision -DECLARE_SOA_TABLE(LambdaCollisions, "AOD", "LAMBDACOLS", o2::soa::Index<>, - lambdacollision::Cent, - lambdacollision::Mult, - aod::collision::PosX, - aod::collision::PosY, - aod::collision::PosZ); -using LambdaCollision = LambdaCollisions::iterator; - -namespace lambdatrack -{ -DECLARE_SOA_INDEX_COLUMN(LambdaCollision, lambdaCollision); -DECLARE_SOA_COLUMN(Px, px, float); -DECLARE_SOA_COLUMN(Py, py, float); -DECLARE_SOA_COLUMN(Pz, pz, float); -DECLARE_SOA_COLUMN(Pt, pt, float); -DECLARE_SOA_COLUMN(Eta, eta, float); -DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(Rap, rap, float); -DECLARE_SOA_COLUMN(Mass, mass, float); -DECLARE_SOA_COLUMN(PosTrackId, posTrackId, int64_t); -DECLARE_SOA_COLUMN(NegTrackId, negTrackId, int64_t); -DECLARE_SOA_COLUMN(PrPx, prPx, float); -DECLARE_SOA_COLUMN(PrPy, prPy, float); -DECLARE_SOA_COLUMN(PrPz, prPz, float); -DECLARE_SOA_COLUMN(V0Type, v0Type, int8_t); -} // namespace lambdatrack -DECLARE_SOA_TABLE(LambdaTracks, "AOD", "LAMBDATRACKS", o2::soa::Index<>, - lambdatrack::LambdaCollisionId, - lambdatrack::Px, - lambdatrack::Py, - lambdatrack::Pz, - lambdatrack::Pt, - lambdatrack::Eta, - lambdatrack::Phi, - lambdatrack::Rap, - lambdatrack::Mass, - lambdatrack::PosTrackId, - lambdatrack::NegTrackId, - lambdatrack::PrPx, - lambdatrack::PrPy, - lambdatrack::PrPz, - lambdatrack::V0Type); -using LambdaTrack = LambdaTracks::iterator; - -namespace lambdatrackext -{ -DECLARE_SOA_COLUMN(LambdaSharingDaughter, lambdaSharingDaughter, bool); -DECLARE_SOA_COLUMN(LambdaSharingDauIds, lambdaSharingDauIds, std::vector); -DECLARE_SOA_COLUMN(TrueLambdaFlag, trueLambdaFlag, bool); -} // namespace lambdatrackext -DECLARE_SOA_TABLE(LambdaTracksExt, "AOD", "LAMBDATRACKSEXT", - lambdatrackext::LambdaSharingDaughter, - lambdatrackext::LambdaSharingDauIds, - lambdatrackext::TrueLambdaFlag); - -using LambdaTrackExt = LambdaTracksExt::iterator; -} // namespace o2::aod - -enum CollisionLabels { - kTotColBeforeHasMcCollision = 1, - kTotCol, - kPassSelCol -}; - -enum TrackLabels { - kTracksBeforeHasMcParticle = 1, - kAllV0Tracks, - kV0KShortMassRej, - kNotLambdaNotAntiLambda, - kV0IsBothLambdaAntiLambda, - kNotLambdaAfterSel, - kV0IsLambdaOrAntiLambda, - kPassV0DauTrackSel, - kPassV0KinCuts, - kPassV0TopoSel, - kAllSelPassed, -}; - -enum CentEstType { - kCentFT0M = 0, - kCentFT0C -}; - -enum RunType { - kRun3 = 0, - kRun2 -}; - -enum ParticleType { - kLambda = 0, - kAntiLambda -}; - -enum ParticlePairType { - kLambdaAntiLambda = 0, - kLambdaLambda, - kAntiLambdaAntiLambda -}; - -enum ShareDauLambda { - kUniqueLambda = 0, - kLambdaShareDau -}; - -struct LambdaTableProducer { - - Produces lambdaCollisionTable; - Produces lambdaTrackTable; - - // Collisions - Configurable cCentEstimator{"cCentEstimator", 0, "Centrality Estimator : 0-FT0M, 1-FT0C"}; - Configurable cMinZVtx{"cMinZVtx", -10.0, "Min VtxZ cut"}; - Configurable cMaxZVtx{"cMaxZVtx", 10.0, "Max VtxZ cut"}; - Configurable cMinMult{"cMinMult", 0., "Minumum Multiplicity"}; - Configurable cMaxMult{"cMaxMult", 100.0, "Maximum Multiplicity"}; - Configurable cSel8Trig{"cSel8Trig", true, "Sel8 (T0A + T0C) Selection Run3"}; - Configurable cInt7Trig{"cInt7Trig", false, "kINT7 MB Trigger"}; - Configurable cSel7Trig{"cSel7Trig", false, "Sel7 (V0A + V0C) Selection Run2"}; - Configurable cTriggerTvxSel{"cTriggerTvxSel", false, "Trigger Time and Vertex Selection"}; - Configurable cTFBorder{"cTFBorder", false, "Timeframe Border Selection"}; - Configurable cNoItsROBorder{"cNoItsROBorder", false, "No ITSRO Border Cut"}; - Configurable cItsTpcVtx{"cItsTpcVtx", false, "ITS+TPC Vertex Selection"}; - Configurable cPileupReject{"cPileupReject", false, "Pileup rejection"}; - Configurable cZVtxTimeDiff{"cZVtxTimeDiff", false, "z-vtx time diff selection"}; - Configurable cIsGoodITSLayers{"cIsGoodITSLayers", false, "Good ITS Layers All"}; - - // Tracks - Configurable cTrackMinPt{"cTrackMinPt", 0.15, "p_{T} minimum"}; - Configurable cTrackMaxPt{"cTrackMaxPt", 999.0, "p_{T} maximum"}; - Configurable cTrackEtaCut{"cTrackEtaCut", 0.8, "Pseudorapidity cut"}; - Configurable cMinTpcCrossedRows{"cMinTpcCrossedRows", 70, "TPC Min Crossed Rows"}; - Configurable cMinTpcCROverCls{"cMinTpcCROverCls", 0.8, "Tpc Min Crossed Rows Over Findable Clusters"}; - Configurable cMaxTpcSharedClusters{"cMaxTpcSharedClusters", 0.4, "Tpc Max Shared Clusters"}; - Configurable cMaxChi2Tpc{"cMaxChi2Tpc", 4, "Max Chi2 Tpc"}; - Configurable cTpcNsigmaCut{"cTpcNsigmaCut", 3.0, "TPC NSigma Selection Cut"}; - Configurable cRemoveAmbiguousTracks{"cRemoveAmbiguousTracks", false, "Remove Ambiguous Tracks"}; - - // V0s - Configurable cMinDcaProtonToPV{"cMinDcaProtonToPV", 0.02, "Minimum Proton DCAr to PV"}; - Configurable cMinDcaPionToPV{"cMinDcaPionToPV", 0.06, "Minimum Pion DCAr to PV"}; - Configurable cMinV0DcaDaughters{"cMinV0DcaDaughters", 0., "Minimum DCA between V0 daughters"}; - Configurable cMaxV0DcaDaughters{"cMaxV0DcaDaughters", 1., "Maximum DCA between V0 daughters"}; - Configurable cMinDcaV0ToPV{"cMinDcaV0ToPV", 0.0, "Minimum DCA V0 to PV"}; - Configurable cMaxDcaV0ToPV{"cMaxDcaV0ToPV", 999.0, "Maximum DCA V0 to PV"}; - Configurable cMinV0TransRadius{"cMinV0TransRadius", 0.5, "Minimum V0 radius from PV"}; - Configurable cMaxV0TransRadius{"cMaxV0TransRadius", 999.0, "Maximum V0 radius from PV"}; - Configurable cMinV0CTau{"cMinV0CTau", 0.0, "Minimum ctau"}; - Configurable cMaxV0CTau{"cMaxV0CTau", 30.0, "Maximum ctau"}; - Configurable cMinV0CosPA{"cMinV0CosPA", 0.995, "Minimum V0 CosPA to PV"}; - Configurable cKshortRejMassWindow{"cKshortRejMassWindow", 0.01, "Reject K0Short Candidates"}; - Configurable cKshortRejFlag{"cKshortRejFlag", true, "K0short Mass Rej Flag"}; - - // V0s kinmatic acceptance - Configurable cMinV0Mass{"cMinV0Mass", 1.10, "V0 Mass Min"}; - Configurable cMaxV0Mass{"cMaxV0Mass", 1.12, "V0 Mass Min"}; - Configurable cMinV0Pt{"cMinV0Pt", 0.8, "Minimum V0 pT"}; - Configurable cMaxV0Pt{"cMaxV0Pt", 4.2, "Minimum V0 pT"}; - Configurable cMaxV0Rap{"cMaxV0Rap", 0.5, "|rap| cut"}; - Configurable cDoEtaAnalysis{"cDoEtaAnalysis", false, "Do Eta Analysis"}; - Configurable cV0TypeSelFlag{"cV0TypeSelFlag", false, "V0 Type Selection Flag"}; - Configurable cV0TypeSelection{"cV0TypeSelection", 1, "V0 Type Selection"}; - - // V0s MC - Configurable cHasMcFlag{"cHasMcFlag", true, "Has Mc Tag"}; - Configurable cSelectTrueLambda{"cSelectTrueLambda", true, "Select True Lambda"}; - Configurable cSelMCPSV0{"cSelMCPSV0", true, "Select Primary/Secondary V0"}; - Configurable cCheckRecoDauFlag{"cCheckRecoDauFlag", true, "Check for reco daughter PID"}; - Configurable cGenPrimaryLambda{"cGenPrimaryLambda", true, "Primary Generated Lambda"}; - Configurable cGenSecondaryLambda{"cGenSecondaryLambda", false, "Secondary Generated Lambda"}; - Configurable cGenDecayChannel{"cGenDecayChannel", true, "Gen Level Decay Channel Flag"}; - Configurable cRecoMomResoFlag{"cRecoMomResoFlag", false, "Check effect of momentum space smearing on balance function"}; - - // Histogram Registry. - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - // Initialize Global Variables - float cent = 0., mult = 0.; - float pt = 0., eta = 0., rap = 0., phi = 0.; - - void init(InitContext const&) - { - // initialize axis specifications - const AxisSpec axisCols(5, 0.5, 5.5, ""); - const AxisSpec axisTrks(30, 0.5, 30.5, ""); - const AxisSpec axisCent(100, 0, 100, "FT0M (%)"); - const AxisSpec axisMult(10, 0, 10, "N_{#Lambda}"); - const AxisSpec axisVz(220, -11, 11, "V_{z} (cm)"); - const AxisSpec axisPID(8000, -4000, 4000, "PdgCode"); - - const AxisSpec axisV0Mass(140, 1.08, 1.15, "M_{p#pi} (GeV/#it{c}^{2})"); - const AxisSpec axisV0Pt(100., 0., 10., "p_{T} (GeV/#it{c})"); - const AxisSpec axisV0Rap(48, -1.2, 1.2, "y"); - const AxisSpec axisV0Eta(48, -1.2, 1.2, "#eta"); - const AxisSpec axisV0Phi(36, 0., TwoPI, "#phi (rad)"); - - const AxisSpec axisRadius(2000, 0, 200, "r(cm)"); - const AxisSpec axisCosPA(300, 0.97, 1.0, "cos(#theta_{PA})"); - const AxisSpec axisDcaV0PV(1000, 0., 10., "dca (cm)"); - const AxisSpec axisDcaProngPV(5000, -50., 50., "dca (cm)"); - const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); - const AxisSpec axisCTau(2000, 0, 200, "c#tau (cm)"); - const AxisSpec axisGCTau(2000, 0, 200, "#gammac#tau (cm)"); - const AxisSpec axisAlpha(40, -1, 1, "#alpha"); - const AxisSpec axisQtarm(40, 0, 0.4, "q_{T}"); - - const AxisSpec axisTrackPt(40, 0, 4, "p_{T} (GeV/#it{c})"); - const AxisSpec axisTrackDCA(200, -1, 1, "dca_{XY} (cm)"); - const AxisSpec axisMomPID(80, 0, 4, "p (GeV/#it{c})"); - const AxisSpec axisNsigma(401, -10.025, 10.025, {"n#sigma"}); - const AxisSpec axisdEdx(360, 20, 200, "#frac{dE}{dx}"); - - // Create Histograms. - // Event histograms - histos.add("Events/h1f_collisions_info", "# of Collisions", kTH1F, {axisCols}); - histos.add("Events/h1f_collision_posZ", "V_{z}-distribution", kTH1F, {axisVz}); - - // QA - histos.add("Tracks/h1f_tracks_info", "# of tracks", kTH1F, {axisTrks}); - histos.add("Tracks/h2f_armpod_before_sel", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); - histos.add("Tracks/h2f_armpod_after_sel", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); - histos.add("Tracks/h1f_lambda_pt_vs_invm", "p_{T} vs M_{#Lambda}", kTH2F, {axisV0Mass, axisV0Pt}); - histos.add("Tracks/h1f_antilambda_pt_vs_invm", "p_{T} vs M_{#bar{#Lambda}}", kTH2F, {axisV0Mass, axisV0Pt}); - - // QA Lambda - histos.add("QA/Lambda/h2f_qt_vs_alpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); - histos.add("QA/Lambda/h1f_dca_V0_daughters", "DCA between V0 daughters", kTH1F, {axisDcaDau}); - histos.add("QA/Lambda/h1f_dca_pos_to_PV", "DCA positive prong to PV", kTH1F, {axisDcaProngPV}); - histos.add("QA/Lambda/h1f_dca_neg_to_PV", "DCA negative prong to PV", kTH1F, {axisDcaProngPV}); - histos.add("QA/Lambda/h1f_dca_V0_to_PV", "DCA V0 to PV", kTH1F, {axisDcaV0PV}); - histos.add("QA/Lambda/h1f_V0_cospa", "cos(#theta_{PA})", kTH1F, {axisCosPA}); - histos.add("QA/Lambda/h1f_V0_radius", "V_{0} Decay Radius in XY plane", kTH1F, {axisRadius}); - histos.add("QA/Lambda/h1f_V0_ctau", "V_{0} c#tau", kTH1F, {axisCTau}); - histos.add("QA/Lambda/h1f_V0_gctau", "V_{0} #gammac#tau", kTH1F, {axisGCTau}); - - histos.add("QA/Lambda/h1f_pos_prong_pt", "Pos-Prong p_{T}", kTH1F, {axisTrackPt}); - histos.add("QA/Lambda/h1f_neg_prong_pt", "Neg-Prong p_{T}", kTH1F, {axisTrackPt}); - histos.add("QA/Lambda/h1f_pos_prong_eta", "Pos-Prong #eta-distribution", kTH1F, {axisV0Eta}); - histos.add("QA/Lambda/h1f_neg_prong_eta", "Neg-Prong #eta-distribution", kTH1F, {axisV0Eta}); - histos.add("QA/Lambda/h1f_pos_prong_phi", "Pos-Prong #phi-distribution", kTH1F, {axisV0Phi}); - histos.add("QA/Lambda/h1f_neg_prong_phi", "Neg-Prong #phi-distribution", kTH1F, {axisV0Phi}); - - histos.add("QA/Lambda/h2f_pos_prong_dcaXY_vs_pt", "DCA vs p_{T}", kTH2F, {axisTrackPt, axisTrackDCA}); - histos.add("QA/Lambda/h2f_neg_prong_dcaXY_vs_pt", "DCA vs p_{T}", kTH2F, {axisTrackPt, axisTrackDCA}); - histos.add("QA/Lambda/h2f_pos_prong_dEdx_vs_p", "TPC Signal Pos-Prong", kTH2F, {axisMomPID, axisdEdx}); - histos.add("QA/Lambda/h2f_neg_prong_dEdx_vs_p", "TPC Signal Neg-Prong", kTH2F, {axisMomPID, axisdEdx}); - histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); - - // Kinematic Histograms - histos.add("McRec/Lambda/hPt", "Transverse Momentum", kTH1F, {axisV0Pt}); - histos.add("McRec/Lambda/hEta", "Pseudorapidity", kTH1F, {axisV0Eta}); - histos.add("McRec/Lambda/hRap", "Rapidity", kTH1F, {axisV0Rap}); - histos.add("McRec/Lambda/hPhi", "Azimuthal Angle", kTH1F, {axisV0Phi}); - - // QA Anti-Lambda - histos.addClone("QA/Lambda/", "QA/AntiLambda/"); - histos.addClone("McRec/Lambda/", "McRec/AntiLambda/"); - - // set bin labels - histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); - histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllV0Tracks, "kAllV0Tracks"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0KShortMassRej, "kV0KShortMassRej"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotLambdaNotAntiLambda, "kNotLambdaNotAntiLambda"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0IsBothLambdaAntiLambda, "kV0IsBothLambdaAntiLambda"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotLambdaAfterSel, "kNotLambdaAfterSel"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0IsLambdaOrAntiLambda, "kV0IsLambdaOrAntiLambda"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0DauTrackSel, "kPassV0DauTrackSel"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0KinCuts, "kPassV0KinCuts"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0TopoSel, "kPassV0TopoSel"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllSelPassed, "kAllSelPassed"); - } - - template - bool selCollision(C const& col) - { - // VtxZ Selection - if (col.posZ() <= cMinZVtx || col.posZ() >= cMaxZVtx) { - return false; - } - - if constexpr (run == kRun3) { // Run3 Min-Bias Trigger - // select centrality estimator - if (cCentEstimator == kCentFT0M) { - cent = col.centFT0M(); - } else if (cCentEstimator == kCentFT0C) { - cent = col.centFT0C(); - } - if (cSel8Trig && !col.sel8()) { - return false; - } - } else { // Run2 Min-Bias Trigger - cent = col.centRun2V0M(); - if (cInt7Trig && !col.alias_bit(kINT7)) { - return false; - } - if (cSel7Trig && !col.sel7()) { - return false; - } - } - - if (cent <= cMinMult || cent >= cMaxMult) { // select centrality percentile class - return false; - } - - if (cTriggerTvxSel && !col.selection_bit(aod::evsel::kIsTriggerTVX)) { - return false; - } - - if (cTFBorder && !col.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - return false; - } - - if (cNoItsROBorder && !col.selection_bit(aod::evsel::kNoITSROFrameBorder)) { - return false; - } - - if (cItsTpcVtx && !col.selection_bit(aod::evsel::kIsVertexITSTPC)) { - return false; - } - - if (cPileupReject && !col.selection_bit(aod::evsel::kNoSameBunchPileup)) { - return false; - } - - if (cZVtxTimeDiff && !col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { - return false; - } - - if (cIsGoodITSLayers && !col.selection_bit(aod::evsel::kIsGoodITSLayersAll)) { - return false; - } - - // Set Multiplicity - mult = col.multNTracksPV(); - - return true; - } - - // Kinematic Selection - bool kinCutSelection(float const& pt, float const& rap, float const& ptMin, float const& ptMax, float const& rapMax) - { - if (pt <= ptMin || pt >= ptMax || rap >= rapMax) { - return false; - } - - return true; - } - - // Track Selection - template - bool selTrack(T const& track) - { - if (!kinCutSelection(track.pt(), std::abs(track.eta()), cTrackMinPt, cTrackMaxPt, cTrackEtaCut)) { - return false; - } - - if (track.tpcNClsCrossedRows() <= cMinTpcCrossedRows) { - return false; - } - - if (track.tpcCrossedRowsOverFindableCls() < cMinTpcCROverCls) { - return false; - } - - if (track.tpcNClsShared() > cMaxTpcSharedClusters) { - return false; - } - - if (track.tpcChi2NCl() > cMaxChi2Tpc) { - return false; - } - - return true; - } - - // Daughter Track Selection - template - bool selDaughterTracks(V const& v0, T const&, ParticleType const& v0Type) - { - auto posTrack = v0.template posTrack_as(); - auto negTrack = v0.template negTrack_as(); - - if (!selTrack(posTrack) || !selTrack(negTrack)) { - return false; - } - - // Apply DCA Selection on Daughter Tracks Based on Lambda/AntiLambda daughters - float dcaProton = 0., dcaPion = 0.; - if (v0Type == kLambda) { - dcaProton = std::abs(v0.dcapostopv()); - dcaPion = std::abs(v0.dcanegtopv()); - } else if (v0Type == kAntiLambda) { - dcaPion = std::abs(v0.dcapostopv()); - dcaProton = std::abs(v0.dcanegtopv()); - } - - if (dcaProton < cMinDcaProtonToPV || dcaPion < cMinDcaPionToPV) { - return false; - } - - return true; - } - - template - bool topoCutSelection(C const& col, V const& v0, T const&) - { - // DCA - if (v0.dcaV0daughters() <= cMinV0DcaDaughters || v0.dcaV0daughters() >= cMaxV0DcaDaughters) { - return false; - } - - if (v0.dcav0topv() <= cMinDcaV0ToPV || v0.dcav0topv() >= cMaxDcaV0ToPV) { - return false; - } - - if (v0.v0radius() <= cMinV0TransRadius || v0.v0radius() >= cMaxV0TransRadius) { - return false; - } - - // ctau - float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; - if (ctau <= cMinV0CTau || ctau >= cMaxV0CTau) { - return false; - } - - // cosine of pointing angle - if (v0.v0cosPA() <= cMinV0CosPA) { - return false; - } - - // all selection criterion passed (Return True) - return true; - } - - template - bool selLambdaDauWithTpcPid(T const& postrack, T const& negtrack) - { - bool returnFlag = false; - float tpcNSigmaPr = 0., tpcNSigmaPi = 0.; - - switch (part) { - // postrack = Proton, negtrack = Pion - case kLambda: - tpcNSigmaPr = postrack.tpcNSigmaPr(); - tpcNSigmaPi = negtrack.tpcNSigmaPi(); - break; - - // negtrack = Proton, postrack = Pion - case kAntiLambda: - tpcNSigmaPr = negtrack.tpcNSigmaPr(); - tpcNSigmaPi = postrack.tpcNSigmaPi(); - break; - } - - if (std::abs(tpcNSigmaPr) < cTpcNsigmaCut && std::abs(tpcNSigmaPi) < cTpcNsigmaCut) { - returnFlag = true; - } - - return returnFlag; - } - - template - bool selLambdaMassWindow(V const& v0, T const&, ParticleType& v0type) - { - // Kshort mass rejection hypothesis - if (cKshortRejFlag && (std::abs(v0.mK0Short() - MassK0Short) <= cKshortRejMassWindow)) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kV0KShortMassRej); - return false; - } - - // initialize daughter tracks - auto postrack = v0.template posTrack_as(); - auto negtrack = v0.template negTrack_as(); - - // initialize selection flags - bool lambdaFlag = false, antiLambdaFlag = false; - - // get v0 track as lambda - if ((v0.mLambda() > cMinV0Mass && v0.mLambda() < cMaxV0Mass) && (selLambdaDauWithTpcPid(postrack, negtrack))) { - lambdaFlag = true; - v0type = kLambda; - } - - // get v0 track as anti-lambda - if ((v0.mAntiLambda() > cMinV0Mass && v0.mAntiLambda() < cMaxV0Mass) && (selLambdaDauWithTpcPid(postrack, negtrack))) { - antiLambdaFlag = true; - v0type = kAntiLambda; - } - - if (!lambdaFlag && !antiLambdaFlag) { // neither Lambda nor Anti-Lambda - histos.fill(HIST("Tracks/h1f_tracks_info"), kNotLambdaNotAntiLambda); - return false; - } else if (lambdaFlag && antiLambdaFlag) { // check if the track is identified as lambda and anti-lambda both (DISCARD THIS TRACK) - histos.fill(HIST("Tracks/h1f_tracks_info"), kV0IsBothLambdaAntiLambda); - return false; - } - - if (lambdaFlag || antiLambdaFlag) { - return true; - } - - histos.fill(HIST("Tracks/h1f_tracks_info"), kNotLambdaAfterSel); - - return false; - } - - template - bool selV0Particle(C const& col, V const& v0, T const& tracks, ParticleType& v0Type) - { - // Apply Lambda Mass Hypothesis - if (!selLambdaMassWindow(v0, tracks, v0Type)) { - return false; - } - - histos.fill(HIST("Tracks/h1f_tracks_info"), kV0IsLambdaOrAntiLambda); - - // Apply Daughter Track Selection - if (!selDaughterTracks(v0, tracks, v0Type)) { - return false; - } - - histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0DauTrackSel); - - // Apply Kinematic Selection - float rap = 0.; - if (!cDoEtaAnalysis) { - rap = std::abs(v0.yLambda()); - } else { - rap = std::abs(v0.eta()); - } - - if (!kinCutSelection(v0.pt(), rap, cMinV0Pt, cMaxV0Pt, cMaxV0Rap)) { - return false; - } - - histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0KinCuts); - - // Apply Topological Selection - if (!topoCutSelection(col, v0, tracks)) { - return false; - } - - histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0TopoSel); - - // All Selection Criterion Passed - return true; - } - - template - bool hasAmbiguousDaughters(V const& v0, T const&) - { - auto posTrack = v0.template posTrack_as(); - auto negTrack = v0.template negTrack_as(); - - auto posTrackCompCols = posTrack.compatibleCollIds(); - auto negTrackCompCols = negTrack.compatibleCollIds(); - - // Check if daughter tracks belongs to more than one collision (Ambiguous Tracks) - if (posTrackCompCols.size() > 1 || negTrackCompCols.size() > 1) { - return true; - } - - // Check if compatible collision index matches the track collision index - if (((posTrackCompCols.size() != 0) && (posTrackCompCols[0] != posTrack.collisionId())) || - ((negTrackCompCols.size() != 0) && (negTrackCompCols[0] != negTrack.collisionId()))) { - return true; - } - - // Pass as not ambiguous - return false; - } - - template - void fillLambdaQAHistos(C const& col, V const& v0, T const&) - { - static constexpr std::string_view SubDir[] = {"QA/Lambda/", "QA/AntiLambda/"}; - - // daugthers - auto postrack = v0.template posTrack_as(); - auto negtrack = v0.template negTrack_as(); - float mass = 0.; - - if constexpr (part == kLambda) { - mass = v0.mLambda(); - } else { - mass = v0.mAntiLambda(); - } - - // ctau - float e = RecoDecay::e(v0.px(), v0.py(), v0.pz(), mass); - float gamma = e / mass; - float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; - float gctau = ctau * gamma; - - histos.fill(HIST(SubDir[part]) + HIST("h2f_qt_vs_alpha"), v0.alpha(), v0.qtarm()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_V0_daughters"), v0.dcaV0daughters()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_pos_to_PV"), v0.dcapostopv()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_neg_to_PV"), v0.dcanegtopv()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_V0_to_PV"), v0.dcav0topv()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_cospa"), v0.v0cosPA()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_radius"), v0.v0radius()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_ctau"), ctau); - histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_gctau"), gctau); - - histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_pt"), postrack.pt()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_eta"), postrack.eta()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_phi"), postrack.phi()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_pt"), negtrack.pt()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_eta"), negtrack.eta()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_phi"), negtrack.phi()); - - histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_dcaXY_vs_pt"), postrack.pt(), postrack.dcaXY()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_dcaXY_vs_pt"), negtrack.pt(), negtrack.dcaXY()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_dEdx_vs_p"), postrack.tpcInnerParam(), postrack.tpcSignal()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_dEdx_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcSignal()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_tpc_nsigma_pr_vs_p"), postrack.tpcInnerParam(), postrack.tpcNSigmaPr()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_tpc_nsigma_pr_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPr()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_tpc_nsigma_pi_vs_p"), postrack.tpcInnerParam(), postrack.tpcNSigmaPi()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_tpc_nsigma_pi_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPi()); - } - - // Reconstructed Level Tables - template - void fillLambdaRecoTables(C const& collision, V const& v0tracks, T const& tracks) - { - // Total Collisions - histos.fill(HIST("Events/h1f_collisions_info"), kTotCol); - if (!selCollision(collision)) { - return; - } - - histos.fill(HIST("Events/h1f_collisions_info"), kPassSelCol); - histos.fill(HIST("Events/h1f_collision_posZ"), collision.posZ()); - - // Fill Collision Table - lambdaCollisionTable(cent, mult, collision.posX(), collision.posY(), collision.posZ()); - - // initialize v0track objects - ParticleType v0Type = kLambda; - float mass = 0.; - float prPx = 0., prPy = 0., prPz = 0.; - - for (auto const& v0 : v0tracks) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kAllV0Tracks); - histos.fill(HIST("Tracks/h2f_armpod_before_sel"), v0.alpha(), v0.qtarm()); - - // Select V0 Particle as Lambda/AntiLambda - if (!selV0Particle(collision, v0, tracks, v0Type)) { - continue; - } - - // Select V0 Type Selection - if (cV0TypeSelFlag && v0.v0Type() != cV0TypeSelection) { - continue; - } - - // we have v0 as lambda - histos.fill(HIST("Tracks/h1f_tracks_info"), kAllSelPassed); - - // Remove lambda with ambiguous daughters (Only for run3) - if constexpr (run == kRun3) { - if (cRemoveAmbiguousTracks && hasAmbiguousDaughters(v0, tracks)) { - continue; - } - } - - // Get Lambda mass - mass = (v0Type == kLambda) ? v0.mLambda() : v0.mAntiLambda(); - histos.fill(HIST("Tracks/h2f_armpod_after_sel"), v0.alpha(), v0.qtarm()); - - // fill lambda qa - if (v0Type == kLambda) { - // Assign proton Eta Phi - prPx = v0.template posTrack_as().px(); - prPy = v0.template posTrack_as().py(); - prPz = v0.template posTrack_as().pz(); - histos.fill(HIST("Tracks/h1f_lambda_pt_vs_invm"), mass, v0.pt()); - fillLambdaQAHistos(collision, v0, tracks); - } else { - // Assign proton Eta Phi - prPx = v0.template negTrack_as().px(); - prPy = v0.template negTrack_as().py(); - prPz = v0.template negTrack_as().pz(); - histos.fill(HIST("Tracks/h1f_antilambda_pt_vs_invm"), mass, v0.pt()); - fillLambdaQAHistos(collision, v0, tracks); - } - - // Fill Lambda/AntiLambda Table - lambdaTrackTable(lambdaCollisionTable.lastIndex(), - v0.px(), v0.py(), v0.pz(), - v0.pt(), v0.eta(), v0.phi(), v0.yLambda(), mass, - v0.template posTrack_as().index(), v0.template negTrack_as().index(), - prPx, prPy, prPz, (int8_t)v0Type); - } - } - - SliceCache cache; - Preslice> perCollision = aod::v0data::collisionId; - - using CollisionsRun3 = soa::Join; - using CollisionsRun2 = soa::Join; - using Tracks = soa::Join; - using TracksRun2 = soa::Join; - - void processDataRun3(CollisionsRun3::iterator const& collision, aod::V0Datas const& V0s, Tracks const& tracks) - { - fillLambdaRecoTables(collision, V0s, tracks); - } - - PROCESS_SWITCH(LambdaTableProducer, processDataRun3, "Process for Run3 DATA", true); - - void processDataRun2(CollisionsRun2::iterator const& collision, aod::V0Datas const& V0s, TracksRun2 const& tracks) - { - fillLambdaRecoTables(collision, V0s, tracks); - } - - PROCESS_SWITCH(LambdaTableProducer, processDataRun2, "Process for Run2 DATA", false); -}; - -struct LambdaTracksExtProducer { - // Table - Produces lambdaTrackExtTable; - - // Configurables - Configurable cAcceptAllLambda{"cAcceptAllLambda", false, "Accept all Lambda"}; - Configurable cRejAllLambdaShaDau{"cRejAllLambdaShaDau", true, "Reject all Lambda sharing daughters"}; - - // Histogram Registry. - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - void init(InitContext const&) - { - // Axis Specifications - const AxisSpec axisMult(10, 0, 10); - const AxisSpec axisMass(100, 1.06, 1.16, "Inv Mass (GeV/#it{c}^{2})"); - const AxisSpec axisCPA(100, 0.995, 1.0, "cos(#theta_{PA})"); - const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); - const AxisSpec axisDEta(320, -1.6, 1.6, "#Delta#eta"); - const AxisSpec axisDPhi(640, -PIHalf, 3. * PIHalf, "#Delta#varphi"); - - // Histograms Booking - histos.add("h1i_totlambda_mult", "Multiplicity", kTH1I, {axisMult}); - histos.add("h1i_totantilambda_mult", "Multiplicity", kTH1I, {axisMult}); - histos.add("h1i_lambda_mult", "Multiplicity", kTH1I, {axisMult}); - histos.add("h1i_antilambda_mult", "Multiplicity", kTH1I, {axisMult}); - histos.add("h2d_n2_etaphi_LaP_LaM", "#rho_{2}^{SharePair}", kTH2D, {axisDEta, axisDPhi}); - histos.add("h2d_n2_etaphi_LaP_LaP", "#rho_{2}^{SharePair}", kTH2D, {axisDEta, axisDPhi}); - histos.add("h2d_n2_etaphi_LaM_LaM", "#rho_{2}^{SharePair}", kTH2D, {axisDEta, axisDPhi}); - } - - void process(aod::LambdaCollisions::iterator const&, aod::LambdaTracks const& tracks) - { - - int nTotLambda = 0, nTotAntiLambda = 0, nSelLambda = 0, nSelAntiLambda = 0; - - for (auto const& lambda : tracks) { - bool lambdaSharingDauFlag = false, trueLambdaFlag = false; - std::vector vSharedDauLambdaIndex; - - if (lambda.v0Type() == kLambda) { - ++nTotLambda; - } else if (lambda.v0Type() == kAntiLambda) { - ++nTotAntiLambda; - } - - for (auto const& track : tracks) { - // check lambda index (don't analyze same lambda track !!!) - if (lambda.index() == track.index()) { - continue; - } - - // check if lambda shares daughters with any other track - if (lambda.posTrackId() == track.posTrackId() || lambda.negTrackId() == track.negTrackId()) { - vSharedDauLambdaIndex.push_back(track.index()); - lambdaSharingDauFlag = true; - - // Fill DEta-DPhi Histogram - if ((lambda.v0Type() == kLambda && track.v0Type() == kAntiLambda) || (lambda.v0Type() == kAntiLambda && track.v0Type() == kLambda)) { - histos.fill(HIST("h2d_n2_etaphi_LaP_LaM"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); - } else if (lambda.v0Type() == kLambda && track.v0Type() == kLambda) { - histos.fill(HIST("h2d_n2_etaphi_LaP_LaP"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); - } else if (lambda.v0Type() == kAntiLambda && track.v0Type() == kAntiLambda) { - histos.fill(HIST("h2d_n2_etaphi_LaM_LaM"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); - } - } - } - - if (cAcceptAllLambda) { // Accept all lambda - trueLambdaFlag = true; - } else if (cRejAllLambdaShaDau && !lambdaSharingDauFlag) { // Reject all lambda sharing daughter - trueLambdaFlag = true; - } else { - trueLambdaFlag = false; - } - - // Multiplicity of selected lambda - if (trueLambdaFlag) { - if (lambda.v0Type() == kLambda) { - ++nSelLambda; - } else if (lambda.v0Type() == kAntiLambda) { - ++nSelAntiLambda; - } - } - - // fill LambdaTrackExt table - lambdaTrackExtTable(lambdaSharingDauFlag, vSharedDauLambdaIndex, trueLambdaFlag); - } - - // fill multiplicity histograms - if (nTotLambda != 0) { - histos.fill(HIST("h1i_totlambda_mult"), nTotLambda); - } - - if (nTotAntiLambda != 0) { - histos.fill(HIST("h1i_totantilambda_mult"), nTotAntiLambda); - } - - if (nSelLambda != 0) { - histos.fill(HIST("h1i_lambda_mult"), nSelLambda); - } - - if (nSelAntiLambda != 0) { - histos.fill(HIST("h1i_antilambda_mult"), nSelAntiLambda); - } - } -}; - -struct LambdaSpinCorrelation { - // Global Configurables - Configurable cNPtBins{"cNPtBins", 30, "N pT Bins"}; - Configurable cMinPt{"cMinPt", 0.5, "pT Min"}; - Configurable cMaxPt{"cMaxPt", 3.5, "pT Max"}; - Configurable cNRapBins{"cNRapBins", 20, "N Rapidity Bins"}; - Configurable cMinRap{"cMinRap", -0.5, "Minimum Rapidity"}; - Configurable cMaxRap{"cMaxRap", 0.5, "Maximum Rapidity"}; - Configurable cNPhiBins{"cNPhiBins", 36, "N Phi Bins"}; - Configurable cAnaPairs{"cAnaPairs", false, "Analyze Pairs Flag"}; - Configurable cInvBoostFlag{"cInvBoostFlag", true, "Inverse Boost Flag"}; - - // Centrality Axis - ConfigurableAxis cMultBins{"cMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 30.0f, 50.f, 80.0f, 100.f}, "Variable Mult-Bins"}; - - // Histogram Registry. - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - // Global variables - float cent = 0.; - - void init(InitContext const&) - { - const AxisSpec axisCheck(1, 0, 1, ""); - const AxisSpec axisPosZ(220, -11, 11, "V_{z} (cm)"); - const AxisSpec axisCent(cMultBins, "FT0M (%)"); - const AxisSpec axisChMult(200, 0, 200, "N_{ch}"); - const AxisSpec axisMult(10, 0, 10, "N_{#Lambda}"); - const AxisSpec axisMass(100, 1.06, 1.16, "M_{#Lambda} (GeV/#it{c}^{2})"); - const AxisSpec axisPt(cNPtBins, cMinPt, cMaxPt, "p_{T} (GeV/#it{c})"); - const AxisSpec axisEta(cNRapBins, cMinRap, cMaxRap, "#eta"); - const AxisSpec axisRap(cNRapBins, cMinRap, cMaxRap, "y"); - const AxisSpec axisPhi(cNPhiBins, 0., TwoPI, "#varphi (rad)"); - const AxisSpec axisDPhi(cNPhiBins, -PI, PI, "#Delta#varphi"); - - // Create Histograms. - // Event - histos.add("Event/h1f_collision_posz", "V_{Z} Distribution", kTH1F, {axisPosZ}); - histos.add("Event/h1f_ft0m_mult_percentile", "FT0M (%)", kTH1F, {axisCent}); - histos.add("Event/h2f_Mult_vs_Centrality", "N_{ch} vs FT0M(%)", kTH2F, {axisCent, axisChMult}); - histos.add("Event/h2f_lambda_mult", "#Lambda - Multiplicity", kTH2F, {axisCent, axisMult}); - histos.add("Event/h2f_antilambda_mult", "#bar{#Lambda} - Multiplicity", kTH2F, {axisCent, axisMult}); - - // Single and Two Particle Densities - // 1D Histograms - histos.add("Reco/h3f_n1_centmasspt_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisMass, axisPt}); - histos.add("Reco/h3f_n1_centmasspt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisMass, axisPt}); - histos.add("Reco/h2f_n1_pt_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPt}); - histos.add("Reco/h2f_n1_pt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPt}); - histos.add("Reco/h2f_n1_eta_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisEta}); - histos.add("Reco/h2f_n1_eta_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisEta}); - histos.add("Reco/h2f_n1_rap_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisRap}); - histos.add("Reco/h2f_n1_rap_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisRap}); - histos.add("Reco/h2f_n1_phi_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPhi}); - histos.add("Reco/h2f_n1_phi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPhi}); - histos.add("Reco/h2f_n2_mass_LaPLaM", "m_{inv}^{#Lambda} vs m_{inv}^{#bar{#Lambda}}", kTH2F, {axisMass, axisMass}); - histos.add("Reco/h2f_n2_mass_LaPLaP", "m_{inv}^{#Lambda} vs m_{inv}^{#Lambda}", kTH2F, {axisMass, axisMass}); - histos.add("Reco/h2f_n2_mass_LaMLaM", "m_{inv}^{#bar{#Lambda}} vs m_{inv}^{#bar{#Lambda}}", kTH2F, {axisMass, axisMass}); - - // rho1 for C2 - histos.add("RecoCorr/h2f_n1_phi_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPhi}); - histos.add("RecoCorr/h2f_n1_phi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPhi}); - - // rho2 for C2 - histos.add("RecoCorr/h2f_n2_dphi_LaPLaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH2F, {axisCent, axisDPhi}); - histos.add("RecoCorr/h2f_n2_dphi_LaPLaP", "#rho_{2}^{#Lambda#Lambda}", kTH2F, {axisCent, axisDPhi}); - histos.add("RecoCorr/h2f_n2_dphi_LaMLaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2F, {axisCent, axisDPhi}); - histos.add("RecoCorr/h2f_n2_phiphi_LaPLaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); - histos.add("RecoCorr/h2f_n2_phiphi_LaPLaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisPhi, axisPhi}); - histos.add("RecoCorr/h2f_n2_phiphi_LaMLaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); - } - - void getBoostVector(std::array const& p, std::array& v, bool inverseBoostFlag = true) - { - int n = p.size(); - for (int i = 0; i < n - 1; ++i) { - if (inverseBoostFlag) { - v[i] = -p[i] / RecoDecay::e(p[0], p[1], p[2], p[3]); - } else { - v[i] = p[i] / RecoDecay::e(p[0], p[1], p[2], p[3]); - } - } - } - - void boost(std::array& p, std::array const& b) - { - float e = RecoDecay::e(p[0], p[1], p[2], p[3]); - float b2 = b[0] * b[0] + b[1] * b[1] + b[2] * b[2]; - float gamma = 1. / std::sqrt(1 - b2); - float bp = b[0] * p[0] + b[1] * p[1] + b[2] * p[2]; - float gamma2 = b2 > 0 ? (gamma - 1.) / b2 : 0.; - - p[0] = p[0] + gamma2 * bp * b[0] + gamma * b[0] * e; - p[1] = p[1] + gamma2 * bp * b[1] + gamma * b[1] * e; - p[2] = p[2] + gamma2 * bp * b[2] + gamma * b[2] * e; - } - - template - void fillPairHistos(U& p1, U& p2) - { - static constexpr std::string_view SubDirHist[] = {"LaPLaM", "LaPLaP", "LaMLaM"}; - - // Fill lambda pair mass - histos.fill(HIST("Reco/h2f_n2_mass_") + HIST(SubDirHist[part_pair]), p1.mass(), p2.mass()); - - // Get Lambda-Proton four-momentum - std::array l1 = {p1.px(), p1.py(), p1.pz(), MassLambda0}; - std::array l2 = {p2.px(), p2.py(), p2.pz(), MassLambda0}; - std::array pr1 = {p1.prPx(), p1.prPy(), p1.prPz(), MassProton}; - std::array pr2 = {p2.prPx(), p2.prPy(), p2.prPz(), MassProton}; - std::array v1, v2; - getBoostVector(l1, v1, cInvBoostFlag); - getBoostVector(l2, v2, cInvBoostFlag); - boost(pr1, v1); - boost(pr2, v2); - - // Fill pair density - histos.fill(HIST("RecoCorr/h2f_n2_phiphi_") + HIST(SubDirHist[part_pair]), cent, RecoDecay::constrainAngle(RecoDecay::phi(pr1)), RecoDecay::phi(pr2)); - histos.fill(HIST("RecoCorr/h2f_n2_dphi_") + HIST(SubDirHist[part_pair]), cent, RecoDecay::constrainAngle(RecoDecay::phi(pr1) - RecoDecay::phi(pr2), -PI)); - } - - template - void analyzeSingles(T const& tracks) - { - static constexpr std::string_view SubDirHist[] = {"LaP", "LaM"}; - int ntrk = 0; - for (auto const& track : tracks) { - // Count tracks - ++ntrk; - - // Fill histograms - histos.fill(HIST("Reco/h3f_n1_centmasspt_") + HIST(SubDirHist[part]), cent, track.mass(), track.pt()); - histos.fill(HIST("Reco/h2f_n1_pt_") + HIST(SubDirHist[part]), cent, track.pt()); - histos.fill(HIST("Reco/h2f_n1_eta_") + HIST(SubDirHist[part]), cent, track.eta()); - histos.fill(HIST("Reco/h2f_n1_phi_") + HIST(SubDirHist[part]), cent, track.phi()); - histos.fill(HIST("Reco/h2f_n1_rap_") + HIST(SubDirHist[part]), cent, track.rap()); - - // Get four-momentum of lambda - std::array l = {MassLambda0, track.px(), track.py(), track.pz()}; - std::array p = {MassProton, track.prPx(), track.prPy(), track.prPz()}; - std::array v; - getBoostVector(l, v, cInvBoostFlag); - boost(p, v); - - // Fill single histograms - histos.fill(HIST("RecoCorr/h2f_n1_phi_") + HIST(SubDirHist[part]), cent, RecoDecay::constrainAngle(RecoDecay::phi(p))); - } - - // fill multiplicity histograms - if (ntrk != 0) { - if (part == kLambda) { - histos.fill(HIST("Event/h2f_lambda_mult"), cent, ntrk); - } else { - histos.fill(HIST("Event/h2f_antilambda_mult"), cent, ntrk); - } - } - } - - template - void analyzePairs(T const& trks_1, T const& trks_2) - { - for (auto const& trk_1 : trks_1) { - for (auto const& trk_2 : trks_2) { - // check for same index for Lambda-Lambda / AntiLambda-AntiLambda - if (samelambda && ((trk_1.index() == trk_2.index()))) { - continue; - } - fillPairHistos(trk_1, trk_2); - } - } - } - - // Initialize tables - using LambdaCollisions = aod::LambdaCollisions; - using LambdaTracks = soa::Join; - - SliceCache cache; - Partition partLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrackext::trueLambdaFlag == true); - Partition partAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrackext::trueLambdaFlag == true); - - void processDataReco(LambdaCollisions::iterator const& collision, LambdaTracks const&) - { - histos.fill(HIST("Event/h1f_collision_posz"), collision.posZ()); - histos.fill(HIST("Event/h1f_ft0m_mult_percentile"), collision.cent()); - histos.fill(HIST("Event/h2f_Mult_vs_Centrality"), collision.cent(), collision.mult()); - - cent = collision.cent(); - - auto lambdaTracks = partLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); - auto antiLambdaTracks = partAntiLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); - - analyzeSingles(lambdaTracks); - analyzeSingles(antiLambdaTracks); - - if (cAnaPairs) { - analyzePairs(lambdaTracks, antiLambdaTracks); - analyzePairs(lambdaTracks, lambdaTracks); - analyzePairs(antiLambdaTracks, antiLambdaTracks); - } - } - - PROCESS_SWITCH(LambdaSpinCorrelation, processDataReco, "Process for Data and MCReco", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; -} From 60137bfd2e5acc919be9e4be31a98782714cc55f Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Sat, 8 Nov 2025 16:08:45 +0530 Subject: [PATCH 5/8] Update lambdaR2Correlation.cxx --- PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index b69e6b5fb72..501a6d267a7 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -1997,4 +1997,4 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; -} \ No newline at end of file +} From 01c3845a828e95d474324a6a78a2e60394b0c1cc Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:18:41 +0530 Subject: [PATCH 6/8] Add dummy process --- PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index 501a6d267a7..ddef7499f3f 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -1630,6 +1630,10 @@ struct LambdaSpinCorrelation { Partition partLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); Partition partAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); + void processDummy(LambdaCollisions::iterator const&) {} + + PROCESS_SWITCH(LambdaSpinCorrelation, processDummy, "Dummy process", true); + void processDataReco(LambdaCollisions::iterator const& collision, LambdaTracks const&) { // assign centrality @@ -1648,7 +1652,7 @@ struct LambdaSpinCorrelation { } } - PROCESS_SWITCH(LambdaSpinCorrelation, processDataReco, "Process for Data and MCReco", true); + PROCESS_SWITCH(LambdaSpinCorrelation, processDataReco, "Process for Data and MCReco", false); }; struct LambdaR2Correlation { From cd29d3d5b5b3c1569fa661309399db8b8effdbcb Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:19:17 +0530 Subject: [PATCH 7/8] Replace PIDResponse with PIDResponseTPC in lambdaR2Correlation --- PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index ddef7499f3f..b08eeeabd80 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -20,7 +20,7 @@ #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" From 1b664aff26ac2d3468b9ec227677c6a4cac49e19 Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:06:12 +0530 Subject: [PATCH 8/8] Remove track counting in analyzeSingles function Removed track counting variable from analyzeSingles function. --- PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index b08eeeabd80..19f13856746 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -1591,11 +1591,7 @@ struct LambdaSpinCorrelation { void analyzeSingles(T const& tracks) { static constexpr std::string_view SubDirHist[] = {"LaP", "LaM"}; - int ntrk = 0; for (auto const& track : tracks) { - // Count tracks - ++ntrk; - // Get four-momentum of lambda std::array l = {MassLambda0, track.px(), track.py(), track.pz()}; std::array p = {MassProton, track.prPx(), track.prPy(), track.prPz()};