Skip to content

Commit 729f4f0

Browse files
authored
[PWGCF] calculate and apply V0s and cascades local density efficiency (#10197)
1 parent da338e1 commit 729f4f0

File tree

3 files changed

+353
-47
lines changed

3 files changed

+353
-47
lines changed

PWGCF/Flow/Tasks/CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ o2physics_add_dpl_workflow(flow-pbpb-pikp
5454
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore
5555
COMPONENT_NAME Analysis)
5656

57-
o2physics_add_dpl_workflow(flow-gfw-omegaxi
58-
SOURCES flowGFWOmegaXi.cxx
57+
o2physics_add_dpl_workflow(flow-gfw-omega-xi
58+
SOURCES flowGfwOmegaXi.cxx
5959
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore
6060
COMPONENT_NAME Analysis)
6161

@@ -73,3 +73,8 @@ o2physics_add_dpl_workflow(resonances-gfw-flow
7373
SOURCES resonancesGfwFlow.cxx
7474
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore
7575
COMPONENT_NAME Analysis)
76+
77+
o2physics_add_dpl_workflow(flow-efficiency-casc
78+
SOURCES flowEfficiencyCasc.cxx
79+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore
80+
COMPONENT_NAME Analysis)
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
///
12+
/// \file flowEfficiencyCasc.cxx
13+
/// \author Fuchun Cui(fcui@cern.ch)
14+
/// \since Feb/21/2025
15+
/// \brief This task is to calculate V0s and cascades local density efficiency
16+
17+
#include <vector>
18+
#include "Common/DataModel/Centrality.h"
19+
#include "Common/DataModel/Multiplicity.h"
20+
#include "Common/DataModel/TrackSelectionTables.h"
21+
#include "Common/DataModel/EventSelection.h"
22+
#include "Framework/runDataProcessing.h"
23+
#include "Framework/AnalysisTask.h"
24+
#include "Framework/ASoAHelpers.h"
25+
#include "Common/Core/TrackSelection.h"
26+
#include "Common/Core/TrackSelectionDefaults.h"
27+
#include "Common/DataModel/PIDResponse.h"
28+
#include "PWGLF/DataModel/cascqaanalysis.h"
29+
#include "PWGLF/DataModel/LFStrangenessTables.h"
30+
#include "PWGLF/DataModel/LFStrangenessPIDTables.h"
31+
#include "CommonConstants/PhysicsConstants.h"
32+
#include <TPDGCode.h>
33+
34+
using namespace o2;
35+
using namespace o2::framework;
36+
using namespace o2::framework::expressions;
37+
38+
#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP};
39+
40+
struct FlowEfficiencyCasc {
41+
O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range")
42+
O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for tracks")
43+
O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 3.0f, "Maximal pT for tracks")
44+
O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks")
45+
O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters")
46+
// topological cut for V0
47+
O2_DEFINE_CONFIGURABLE(cfgv0_radius, float, 5.0f, "minimum decay radius")
48+
O2_DEFINE_CONFIGURABLE(cfgv0_v0cospa, float, 0.995f, "minimum cosine of pointing angle")
49+
O2_DEFINE_CONFIGURABLE(cfgv0_dcadautopv, float, 0.1f, "minimum daughter DCA to PV")
50+
O2_DEFINE_CONFIGURABLE(cfgv0_dcav0dau, float, 0.5f, "maximum DCA among V0 daughters")
51+
O2_DEFINE_CONFIGURABLE(cfgv0_mk0swindow, float, 0.1f, "Invariant mass window of K0s")
52+
O2_DEFINE_CONFIGURABLE(cfgv0_mlambdawindow, float, 0.04f, "Invariant mass window of lambda")
53+
O2_DEFINE_CONFIGURABLE(cfgv0_ArmPodocut, float, 0.2f, "Armenteros Podolski cut for K0")
54+
// topological cut for cascade
55+
O2_DEFINE_CONFIGURABLE(cfgcasc_radius, float, 0.5f, "minimum decay radius")
56+
O2_DEFINE_CONFIGURABLE(cfgcasc_casccospa, float, 0.999f, "minimum cosine of pointing angle")
57+
O2_DEFINE_CONFIGURABLE(cfgcasc_v0cospa, float, 0.998f, "minimum cosine of pointing angle")
58+
O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0topv, float, 0.01f, "minimum daughter DCA to PV")
59+
O2_DEFINE_CONFIGURABLE(cfgcasc_dcabachtopv, float, 0.01f, "minimum bachelor DCA to PV")
60+
O2_DEFINE_CONFIGURABLE(cfgcasc_dcacascdau, float, 0.3f, "maximum DCA among cascade daughters")
61+
O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0dau, float, 1.0f, "maximum DCA among V0 daughters")
62+
O2_DEFINE_CONFIGURABLE(cfgcasc_mlambdawindow, float, 0.04f, "Invariant mass window of lambda")
63+
// track quality and type selections
64+
O2_DEFINE_CONFIGURABLE(cfgtpcclusters, int, 70, "minimum number of TPC clusters requirement")
65+
O2_DEFINE_CONFIGURABLE(cfgitsclusters, int, 1, "minimum number of ITS clusters requirement")
66+
O2_DEFINE_CONFIGURABLE(cfgtpcclufindable, int, 1, "minimum number of findable TPC clusters")
67+
O2_DEFINE_CONFIGURABLE(cfgtpccrossoverfindable, int, 1, "minimum number of Ratio crossed rows over findable clusters")
68+
O2_DEFINE_CONFIGURABLE(cfgcheckDauTPC, bool, true, "check daughter tracks TPC or not")
69+
O2_DEFINE_CONFIGURABLE(cfgcheckDauTOF, bool, false, "check daughter tracks TOF or not")
70+
O2_DEFINE_CONFIGURABLE(cfgCasc_rapidity, float, 0.5, "rapidity")
71+
72+
O2_DEFINE_CONFIGURABLE(cfgNSigmatpctof, std::vector<float>, (std::vector<float>{3, 3, 3}), "tpc and tof NSigma for Pion Kaon Proton")
73+
74+
ConfigurableAxis cfgaxisPt{"cfgaxisPt", {VARIABLE_WIDTH, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.20, 2.40, 2.60, 2.80, 3.00, 3.50, 4.00, 4.50, 5.00, 5.50, 6.00, 10.0}, "pt (GeV)"};
75+
ConfigurableAxis cfgaxisPtXi{"cfgaxisPtXi", {VARIABLE_WIDTH, 0, 0.1, 0.5, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"};
76+
ConfigurableAxis cfgaxisPtOmega{"cfgaxisPtOmega", {VARIABLE_WIDTH, 0, 0.1, 0.5, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"};
77+
ConfigurableAxis cfgaxisPtV0{"cfgaxisPtV0", {VARIABLE_WIDTH, 0, 0.1, 0.5, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"};
78+
ConfigurableAxis cfgaxisMultiplicity{"cfgaxisMultiplicity", {1000, 0, 5000}, "Nch"};
79+
80+
using MyCollisions = soa::Join<aod::StraCollisions, aod::StraEvSels>;
81+
using MyMcCollisions = soa::Join<aod::StraMCCollisions, aod::StraMCCollMults>;
82+
using CascMCCandidates = soa::Join<aod::CascCollRefs, aod::CascCores, aod::CascExtras, aod::CascBBs, aod::CascCoreMCLabels>;
83+
using V0MCCandidates = soa::Join<aod::V0CollRefs, aod::V0Cores, aod::V0Extras, aod::V0CoreMCLabels>;
84+
using DaughterTracks = soa::Join<aod::DauTrackExtras, aod::DauTrackTPCPIDs>;
85+
86+
// Define the output
87+
HistogramRegistry registry{"registry"};
88+
89+
std::vector<float> cfgNSigma = cfgNSigmatpctof;
90+
91+
void init(InitContext const&)
92+
{
93+
const AxisSpec axisCounter{1, 0, +1, ""};
94+
// create histograms
95+
registry.add("eventCounter", "eventCounter", kTH1F, {axisCounter});
96+
registry.add("mcEventCounter", "Monte Carlo Truth EventCounter", kTH1F, {axisCounter});
97+
98+
registry.add("h2DGenK0s", "", {HistType::kTH2D, {cfgaxisPtV0, cfgaxisMultiplicity}});
99+
registry.add("h2DGenLambda", "", {HistType::kTH2D, {cfgaxisPtV0, cfgaxisMultiplicity}});
100+
registry.add("h2DGenXi", "", {HistType::kTH2D, {cfgaxisPtXi, cfgaxisMultiplicity}});
101+
registry.add("h2DGenOmega", "", {HistType::kTH2D, {cfgaxisPtOmega, cfgaxisMultiplicity}});
102+
registry.add("h2DRecK0s", "", {HistType::kTH2D, {cfgaxisPtV0, cfgaxisMultiplicity}});
103+
registry.add("h2DRecLambda", "", {HistType::kTH2D, {cfgaxisPtV0, cfgaxisMultiplicity}});
104+
registry.add("h2DRecXi", "", {HistType::kTH2D, {cfgaxisPtXi, cfgaxisMultiplicity}});
105+
registry.add("h2DRecOmega", "", {HistType::kTH2D, {cfgaxisPtOmega, cfgaxisMultiplicity}});
106+
}
107+
108+
void processRec(MyCollisions::iterator const& collision, V0MCCandidates const& V0s, CascMCCandidates const& Cascades, DaughterTracks const&, soa::Join<aod::CascMCCores, aod::CascMCCollRefs> const&, soa::Join<aod::V0MCCores, aod::V0MCCollRefs> const&)
109+
{
110+
registry.fill(HIST("eventCounter"), 0.5);
111+
if (!collision.sel8())
112+
return;
113+
int rectracknum = collision.multNTracksGlobal();
114+
for (const auto& casc : Cascades) {
115+
if (!casc.has_cascMCCore())
116+
continue;
117+
auto negdau = casc.negTrackExtra_as<DaughterTracks>();
118+
auto posdau = casc.posTrackExtra_as<DaughterTracks>();
119+
auto bachelor = casc.bachTrackExtra_as<DaughterTracks>();
120+
// track quality check
121+
if (bachelor.tpcNClsFound() < cfgtpcclusters)
122+
continue;
123+
if (posdau.tpcNClsFound() < cfgtpcclusters)
124+
continue;
125+
if (negdau.tpcNClsFound() < cfgtpcclusters)
126+
continue;
127+
if (bachelor.itsNCls() < cfgitsclusters)
128+
continue;
129+
if (posdau.itsNCls() < cfgitsclusters)
130+
continue;
131+
if (negdau.itsNCls() < cfgitsclusters)
132+
continue;
133+
// topological cut
134+
if (casc.cascradius() < cfgcasc_radius)
135+
continue;
136+
if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_casccospa)
137+
continue;
138+
if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_v0cospa)
139+
continue;
140+
if (std::fabs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cfgcasc_dcav0topv)
141+
continue;
142+
if (std::fabs(casc.dcabachtopv()) < cfgcasc_dcabachtopv)
143+
continue;
144+
if (casc.dcacascdaughters() > cfgcasc_dcacascdau)
145+
continue;
146+
if (casc.dcaV0daughters() > cfgcasc_dcav0dau)
147+
continue;
148+
if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cfgcasc_mlambdawindow)
149+
continue;
150+
// Omega and antiOmega
151+
if (casc.sign() < 0 && (casc.mOmega() > 1.63) && (casc.mOmega() < 1.71) && std::fabs(casc.yOmega()) < cfgCasc_rapidity &&
152+
(!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]))) {
153+
registry.fill(HIST("h2DRecOmega"), casc.pt(), rectracknum);
154+
} else if (casc.sign() < 0 && (casc.mOmega() > 1.63) && (casc.mOmega() < 1.71) && std::fabs(casc.yOmega()) < cfgCasc_rapidity &&
155+
(!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]))) {
156+
registry.fill(HIST("h2DRecOmega"), casc.pt(), rectracknum);
157+
}
158+
// Xi and antiXi
159+
if (casc.sign() < 0 && (casc.mXi() > 1.30) && (casc.mXi() < 1.37) && std::fabs(casc.yXi()) < cfgCasc_rapidity &&
160+
(!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]))) {
161+
registry.fill(HIST("h2DRecXi"), casc.pt(), rectracknum);
162+
} else if (casc.sign() < 0 && (casc.mXi() > 1.30) && (casc.mXi() < 1.37) && std::fabs(casc.yXi()) < cfgCasc_rapidity &&
163+
(!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]))) {
164+
registry.fill(HIST("h2DRecXi"), casc.pt(), rectracknum);
165+
}
166+
}
167+
168+
for (const auto& v0 : V0s) {
169+
if (!v0.has_v0MCCore())
170+
continue;
171+
auto v0negdau = v0.negTrackExtra_as<DaughterTracks>();
172+
auto v0posdau = v0.posTrackExtra_as<DaughterTracks>();
173+
174+
// track quality check
175+
if (v0posdau.tpcNClsFound() < cfgtpcclusters)
176+
continue;
177+
if (v0negdau.tpcNClsFound() < cfgtpcclusters)
178+
continue;
179+
if (v0posdau.tpcNClsFindable() < cfgtpcclufindable)
180+
continue;
181+
if (v0negdau.tpcNClsFindable() < cfgtpcclufindable)
182+
continue;
183+
if (v0posdau.tpcCrossedRowsOverFindableCls() < cfgtpccrossoverfindable)
184+
continue;
185+
if (v0posdau.itsNCls() < cfgitsclusters)
186+
continue;
187+
if (v0negdau.itsNCls() < cfgitsclusters)
188+
continue;
189+
// topological cut
190+
if (v0.v0radius() < cfgv0_radius)
191+
continue;
192+
if (v0.v0cosPA() < cfgv0_v0cospa)
193+
continue;
194+
if (v0.dcaV0daughters() > cfgv0_dcav0dau)
195+
continue;
196+
if (std::fabs(v0.dcapostopv()) < cfgv0_dcadautopv)
197+
continue;
198+
if (std::fabs(v0.dcanegtopv()) < cfgv0_dcadautopv)
199+
continue;
200+
201+
// K0short
202+
if (v0.qtarm() / std::fabs(v0.alpha()) > cfgv0_ArmPodocut && std::fabs(v0.y()) < 0.5 && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < cfgv0_mk0swindow &&
203+
(!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]))) {
204+
registry.fill(HIST("h2DRecK0s"), v0.pt(), rectracknum);
205+
}
206+
// Lambda and antiLambda
207+
if (std::fabs(v0.y()) < 0.5 && std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow &&
208+
(!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]))) {
209+
registry.fill(HIST("h2DRecLambda"), v0.pt(), rectracknum);
210+
} else if (std::fabs(v0.y()) < 0.5 && std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow &&
211+
(!cfgcheckDauTPC || (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0]))) {
212+
registry.fill(HIST("h2DRecLambda"), v0.pt(), rectracknum);
213+
}
214+
}
215+
}
216+
PROCESS_SWITCH(FlowEfficiencyCasc, processRec, "process reconstructed information", true);
217+
218+
void processGen(MyMcCollisions::iterator const&, soa::SmallGroups<soa::Join<aod::StraCollisions, aod::StraEvSels, aod::StraCollLabels>> const& coll, const soa::SmallGroups<soa::Join<aod::CascMCCores, aod::CascMCCollRefs>>& cascMCs, const soa::SmallGroups<soa::Join<aod::V0MCCores, aod::V0MCCollRefs>>& v0MCs)
219+
{
220+
registry.fill(HIST("mcEventCounter"), 0.5);
221+
int rectracknum = 0;
222+
for (const auto& col : coll) {
223+
rectracknum = col.multNTracksGlobal();
224+
}
225+
for (auto const& cascmc : cascMCs) {
226+
if (std::abs(cascmc.pdgCode()) == kXiMinus) {
227+
if (std::fabs(cascmc.yMC()) < cfgCasc_rapidity)
228+
registry.fill(HIST("h2DGenXi"), cascmc.ptMC(), rectracknum);
229+
}
230+
if (std::abs(cascmc.pdgCode()) == kOmegaMinus) {
231+
if (std::fabs(cascmc.yMC()) < cfgCasc_rapidity)
232+
registry.fill(HIST("h2DGenOmega"), cascmc.ptMC(), rectracknum);
233+
}
234+
}
235+
for (auto const& v0mc : v0MCs) {
236+
if (std::abs(v0mc.pdgCode()) == kK0Short) {
237+
if (std::fabs(v0mc.yMC()) < cfgCasc_rapidity)
238+
registry.fill(HIST("h2DGenK0s"), v0mc.ptMC(), rectracknum);
239+
}
240+
if (std::abs(v0mc.pdgCode()) == kLambda0) {
241+
if (std::fabs(v0mc.yMC()) < cfgCasc_rapidity)
242+
registry.fill(HIST("h2DGenLambda"), v0mc.ptMC(), rectracknum);
243+
}
244+
}
245+
}
246+
PROCESS_SWITCH(FlowEfficiencyCasc, processGen, "process gen information", true);
247+
};
248+
249+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
250+
{
251+
return WorkflowSpec{
252+
adaptAnalysisTask<FlowEfficiencyCasc>(cfgc)};
253+
}

0 commit comments

Comments
 (0)