Skip to content

Commit 0292740

Browse files
sdudi123sandeep dudi
andauthored
[PWGLF] new analysis for pion and kaon using kink topology (#11951)
Co-authored-by: sandeep dudi <sandeep.dudi@cern.ch>
1 parent ae7e00c commit 0292740

File tree

2 files changed

+307
-0
lines changed

2 files changed

+307
-0
lines changed

PWGLF/Tasks/Nuspex/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,10 @@ o2physics_add_dpl_workflow(antinuclei-in-jets
139139
SOURCES antinucleiInJets.cxx
140140
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib
141141
COMPONENT_NAME Analysis)
142+
143+
o2physics_add_dpl_workflow(kink-pika
144+
SOURCES spectraKinkPiKa.cxx
145+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
146+
COMPONENT_NAME Analysis)
147+
142148
endif()
Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
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 spectraKinkPiKa.cxx
13+
/// \brief Example of a simple task for the analysis of the muon from Kaon pion using kink topology
14+
/// \author sandeep dudi sandeep.dudi@cern.ch
15+
16+
#include "PWGLF/DataModel/LFKinkDecayTables.h"
17+
18+
#include "Common/DataModel/EventSelection.h"
19+
#include "Common/DataModel/PIDResponse.h"
20+
21+
#include "Framework/AnalysisTask.h"
22+
#include "Framework/O2DatabasePDGPlugin.h"
23+
#include "Framework/runDataProcessing.h"
24+
#include "ReconstructionDataFormats/PID.h"
25+
26+
#include "Math/GenVector/Boost.h"
27+
#include "Math/Vector3D.h"
28+
#include "Math/Vector4D.h"
29+
#include "TPDGCode.h"
30+
#include "TVector3.h"
31+
#include <TMath.h>
32+
#include <TString.h>
33+
34+
#include <cstdlib>
35+
#include <vector>
36+
37+
using namespace std;
38+
using namespace o2;
39+
using namespace o2::aod;
40+
using namespace o2::framework;
41+
using namespace o2::framework::expressions;
42+
using namespace o2::constants::physics;
43+
44+
using TracksFull = soa::Join<aod::TracksIU, aod::TracksExtra, aod::TracksCovIU, aod::pidTPCPi, aod::pidTPCKa, aod::pidTPCMu>;
45+
using CollisionsFull = soa::Join<aod::Collisions, aod::EvSel>;
46+
using CollisionsFullMC = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSel>;
47+
struct spectraKinkPiKa {
48+
Service<o2::framework::O2DatabasePDG> pdg;
49+
// Histograms are defined with HistogramRegistry
50+
HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true};
51+
HistogramRegistry rpiKkink{"rpiKkink", {}, OutputObjHandlingPolicy::AnalysisObject, true, true};
52+
53+
// Configurable for event selection
54+
Configurable<float> cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"};
55+
Configurable<float> cutNSigmaPi{"cutNSigmaPi", 4, "NSigmaTPCPion"};
56+
Configurable<float> cutNSigmaKa{"cutNSigmaKa", 4, "NSigmaTPCKaon"};
57+
Configurable<float> rapCut{"rapCut", 0.8, "rapCut"};
58+
59+
Configurable<int> pid{"pidMother", 321, ""};
60+
Configurable<bool> d0pid{"dopid", 0, ""};
61+
62+
Preslice<aod::KinkCands> mPerCol = aod::track::collisionId;
63+
64+
void init(InitContext const&)
65+
{
66+
// Axes
67+
const AxisSpec ptAxis{100, 0, 10, "#it{p}_{T} (GeV/#it{c})"};
68+
const AxisSpec qtAxis{2000, 0, 2, "#it{q}_{T} (GeV/#it{c})"};
69+
const AxisSpec kinkAxis{200, 0, 4, "#theta"};
70+
const AxisSpec etaAxis{200, -5.0, 5.0, "#eta"};
71+
const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"};
72+
73+
// Event selection
74+
rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}});
75+
76+
rpiKkink.add("h2_dau_pt_vs_eta_rec", "pt_vs_eta_dau", {HistType::kTH2F, {ptAxis, etaAxis}});
77+
rpiKkink.add("h2_moth_pt_vs_eta_rec", "pt_vs_eta_moth", {HistType::kTH2F, {ptAxis, etaAxis}});
78+
rpiKkink.add("h2_pt_moth_vs_dau_rec", "pt_moth_vs_dau", {HistType::kTH2F, {ptAxis, ptAxis}});
79+
80+
rpiKkink.add("h2_qt", "qt", {HistType::kTH1F, {qtAxis}});
81+
rpiKkink.add("h2_qt_vs_pt", "qt_pt", {HistType::kTH2F, {qtAxis, ptAxis}});
82+
83+
rpiKkink.add("h2_kink_angle", "kink angle", {HistType::kTH1F, {kinkAxis}});
84+
85+
// pion
86+
rpiKkink.add("h2_dau_pt_vs_eta_rec_pion", "pt_vs_eta_dau", {HistType::kTH2F, {ptAxis, etaAxis}});
87+
rpiKkink.add("h2_moth_pt_vs_eta_rec_pion", "pt_vs_eta_moth", {HistType::kTH2F, {ptAxis, etaAxis}});
88+
rpiKkink.add("h2_pt_moth_vs_dau_rec_pion", "pt_moth_vs_dau", {HistType::kTH2F, {ptAxis, ptAxis}});
89+
90+
rpiKkink.add("h2_qt_pion", "qt", {HistType::kTH1F, {qtAxis}});
91+
rpiKkink.add("h2_qt_vs_ptpion", "qt_pt", {HistType::kTH2F, {qtAxis, ptAxis}});
92+
rpiKkink.add("h2_kink_angle_pion", "kink angle", {HistType::kTH1F, {kinkAxis}});
93+
94+
if (doprocessMC) {
95+
rpiKkink.add("h2_dau_pt_vs_eta_gen", "pt_vs_eta_dau", {HistType::kTH2F, {ptAxis, etaAxis}});
96+
rpiKkink.add("h2_moth_pt_vs_eta_gen", "pt_vs_eta_moth", {HistType::kTH2F, {ptAxis, etaAxis}});
97+
rpiKkink.add("h2_pt_moth_vs_dau_gen", "pt_moth_vs_dau", {HistType::kTH2F, {ptAxis, ptAxis}});
98+
99+
rpiKkink.add("h2_qt_gen", "qt", {HistType::kTH1F, {qtAxis}});
100+
rpiKkink.add("h2_qt_rec", "qt", {HistType::kTH1F, {qtAxis}});
101+
rpiKkink.add("h2_kink_angle_gen", "kink angle", {HistType::kTH1F, {kinkAxis}});
102+
}
103+
}
104+
105+
void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& KinkCands, TracksFull const&)
106+
{
107+
ROOT::Math::PxPyPzMVector v0;
108+
ROOT::Math::PxPyPzMVector v1;
109+
110+
if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8() || !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) {
111+
return;
112+
}
113+
if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) {
114+
return;
115+
}
116+
117+
rEventSelection.fill(HIST("hVertexZRec"), collision.posZ());
118+
for (const auto& kinkCand : KinkCands) {
119+
auto dauTrack = kinkCand.trackDaug_as<TracksFull>();
120+
auto mothTrack = kinkCand.trackMoth_as<TracksFull>();
121+
bool kaon = false;
122+
bool pion = false;
123+
if (std::abs(mothTrack.tpcNSigmaKa()) < cutNSigmaKa) {
124+
kaon = true;
125+
}
126+
if (std::abs(mothTrack.tpcNSigmaPi()) < cutNSigmaPi) {
127+
pion = true;
128+
}
129+
if (!kaon && !pion)
130+
continue;
131+
v0.SetCoordinates(mothTrack.px(), mothTrack.py(), mothTrack.pz(), o2::constants::physics::MassPionCharged);
132+
v1.SetCoordinates(dauTrack.px(), dauTrack.py(), dauTrack.pz(), o2::constants::physics::MassMuon);
133+
134+
float pMoth = v0.P();
135+
float pDaug = v1.P();
136+
float spKink = mothTrack.px() * dauTrack.px() + mothTrack.py() * dauTrack.py() + mothTrack.pz() * dauTrack.pz();
137+
float kinkangle = std::acos(spKink / (pMoth * pDaug));
138+
if (kaon) {
139+
rpiKkink.fill(HIST("h2_moth_pt_vs_eta_rec"), v0.Pt(), v0.Eta());
140+
rpiKkink.fill(HIST("h2_dau_pt_vs_eta_rec"), v1.Pt(), v1.Eta());
141+
rpiKkink.fill(HIST("h2_pt_moth_vs_dau_rec"), v0.Pt(), v1.Pt());
142+
rpiKkink.fill(HIST("h2_kink_angle"), kinkangle);
143+
}
144+
if (pion) {
145+
rpiKkink.fill(HIST("h2_moth_pt_vs_eta_rec_pion"), v0.Pt(), v0.Eta());
146+
rpiKkink.fill(HIST("h2_dau_pt_vs_eta_rec_pion"), v1.Pt(), v1.Eta());
147+
rpiKkink.fill(HIST("h2_pt_moth_vs_dau_rec_pion"), v0.Pt(), v1.Pt());
148+
rpiKkink.fill(HIST("h2_kink_angle_pion"), kinkangle);
149+
}
150+
TVector3 pdlab(v1.Px(), v1.Py(), v1.Pz());
151+
// Compute transverse component
152+
TVector3 motherDir(v0.Px(), v0.Py(), v0.Pz());
153+
double ptd = pdlab.Perp(motherDir); // or p_d_lab.Mag() * sin(theta)
154+
155+
if (kaon) {
156+
rpiKkink.fill(HIST("h2_qt"), ptd);
157+
rpiKkink.fill(HIST("h2_qt_vs_pt"), ptd, v1.Pt());
158+
}
159+
if (pion) {
160+
rpiKkink.fill(HIST("h2_qt_pion"), ptd);
161+
rpiKkink.fill(HIST("h2_qt_vs_ptpion"), ptd, v1.Pt());
162+
}
163+
}
164+
}
165+
PROCESS_SWITCH(spectraKinkPiKa, processData, "Data processing", true);
166+
167+
void processMC(CollisionsFullMC const& collisions, aod::KinkCands const& KinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, TracksFull const&)
168+
{
169+
for (const auto& collision : collisions) {
170+
ROOT::Math::PxPyPzMVector v0;
171+
ROOT::Math::PxPyPzMVector v1;
172+
if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8() || !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) {
173+
continue;
174+
}
175+
if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) {
176+
continue;
177+
}
178+
rEventSelection.fill(HIST("hVertexZRec"), collision.posZ());
179+
auto kinkCandPerColl = KinkCands.sliceBy(mPerCol, collision.globalIndex());
180+
for (const auto& kinkCand : kinkCandPerColl) {
181+
auto dauTrack = kinkCand.trackDaug_as<TracksFull>();
182+
auto mothTrack = kinkCand.trackMoth_as<TracksFull>();
183+
if (dauTrack.sign() != mothTrack.sign()) {
184+
LOG(info) << "Skipping kink candidate with opposite sign daughter and mother: " << kinkCand.globalIndex();
185+
continue; // Skip if the daughter has the opposite sign as the mother
186+
}
187+
bool kaon = false;
188+
bool pion = false;
189+
if (std::abs(mothTrack.tpcNSigmaKa()) < cutNSigmaKa) {
190+
kaon = true;
191+
}
192+
if (std::abs(mothTrack.tpcNSigmaPi()) < cutNSigmaPi) {
193+
pion = true;
194+
}
195+
if (!kaon && !pion)
196+
continue;
197+
198+
v0.SetCoordinates(mothTrack.px(), mothTrack.py(), mothTrack.pz(), o2::constants::physics::MassPionCharged);
199+
v1.SetCoordinates(dauTrack.px(), dauTrack.py(), dauTrack.pz(), o2::constants::physics::MassMuon);
200+
201+
float pMoth = v0.P();
202+
float pDaug = v1.P();
203+
float spKink = mothTrack.px() * dauTrack.px() + mothTrack.py() * dauTrack.py() + mothTrack.pz() * dauTrack.pz();
204+
float kinkangle = std::acos(spKink / (pMoth * pDaug));
205+
206+
rpiKkink.fill(HIST("h2_moth_pt_vs_eta_rec"), v0.Pt(), v0.Eta());
207+
rpiKkink.fill(HIST("h2_dau_pt_vs_eta_rec"), v1.Pt(), v1.Eta());
208+
rpiKkink.fill(HIST("h2_pt_moth_vs_dau_rec"), v0.Pt(), v1.Pt());
209+
rpiKkink.fill(HIST("h2_kink_angle"), kinkangle);
210+
211+
TVector3 pdlab(v1.Px(), v1.Py(), v1.Pz());
212+
// Compute transverse component
213+
TVector3 motherDir(v0.Px(), v0.Py(), v0.Pz());
214+
double ptd = pdlab.Perp(motherDir); // or p_d_lab.Mag() * sin(theta)
215+
216+
rpiKkink.fill(HIST("h2_qt"), ptd);
217+
218+
// do MC association
219+
auto mcLabMoth = trackLabelsMC.rawIteratorAt(mothTrack.globalIndex());
220+
auto mcLabDau = trackLabelsMC.rawIteratorAt(dauTrack.globalIndex());
221+
if (mcLabMoth.has_mcParticle() && mcLabDau.has_mcParticle()) {
222+
auto mcTrackMoth = mcLabMoth.mcParticle_as<aod::McParticles>();
223+
auto mcTrackDau = mcLabDau.mcParticle_as<aod::McParticles>();
224+
if (!mcTrackDau.has_mothers()) {
225+
continue;
226+
}
227+
for (const auto& piMother : mcTrackDau.mothers_as<aod::McParticles>()) {
228+
if (piMother.globalIndex() != mcTrackMoth.globalIndex()) {
229+
continue;
230+
}
231+
if (std::abs(mcTrackMoth.pdgCode()) != pid || std::abs(mcTrackDau.pdgCode()) != kMuonPlus) {
232+
continue;
233+
}
234+
// rpiKkink.fill(HIST("h2MassPtMCRec"), kinkCand.ptMoth(), v1.Pt());
235+
rpiKkink.fill(HIST("h2_qt_rec"), ptd);
236+
}
237+
}
238+
}
239+
}
240+
for (const auto& mcPart : particlesMC) {
241+
ROOT::Math::PxPyPzMVector v0;
242+
ROOT::Math::PxPyPzMVector v1;
243+
244+
if (!d0pid && (std::abs(mcPart.pdgCode()) != pid || std::abs(mcPart.y()) > rapCut)) {
245+
continue;
246+
}
247+
if (d0pid && (std::abs(mcPart.pdgCode()) != kD0 || std::abs(mcPart.pdgCode()) != kDPlus || std::abs(mcPart.pdgCode()) != kDStar || std::abs(mcPart.y()) > rapCut)) {
248+
continue;
249+
}
250+
251+
if (!mcPart.has_daughters()) {
252+
continue; // Skip if no daughters
253+
}
254+
bool hasKaonpionDaughter = false;
255+
for (const auto& daughter : mcPart.daughters_as<aod::McParticles>()) {
256+
if (std::abs(daughter.pdgCode()) == kMuonPlus) { // muon PDG code
257+
hasKaonpionDaughter = true;
258+
v1.SetCoordinates(daughter.px(), daughter.py(), daughter.pz(), o2::constants::physics::MassMuon);
259+
break; // Found a muon daughter, exit loop
260+
}
261+
}
262+
if (!hasKaonpionDaughter) {
263+
continue; // Skip if no muon daughter found
264+
}
265+
if (pid == kKPlus) {
266+
v0.SetCoordinates(mcPart.px(), mcPart.py(), mcPart.pz(), o2::constants::physics::MassKaonCharged);
267+
}
268+
269+
if (pid == kPiPlus) {
270+
v0.SetCoordinates(mcPart.px(), mcPart.py(), mcPart.pz(), o2::constants::physics::MassPionCharged);
271+
}
272+
if (d0pid) {
273+
v0.SetCoordinates(mcPart.px(), mcPart.py(), mcPart.pz(), o2::constants::physics::MassD0);
274+
}
275+
276+
float pMoth = v0.P();
277+
float pDaug = v1.P();
278+
float spKink = v0.Px() * v1.Px() + v0.Py() * v1.Py() + v0.Pz() * v1.Pz();
279+
float kinkangle = std::acos(spKink / (pMoth * pDaug));
280+
281+
// std::cout<< kinkCand.ptMoth()<<" check "<<v0.Pt()<<std::endl;
282+
rpiKkink.fill(HIST("h2_moth_pt_vs_eta_gen"), v0.Pt(), v0.Eta());
283+
rpiKkink.fill(HIST("h2_dau_pt_vs_eta_gen"), v1.Pt(), v1.Eta());
284+
rpiKkink.fill(HIST("h2_pt_moth_vs_dau_gen"), v0.Pt(), v1.Pt());
285+
rpiKkink.fill(HIST("h2_kink_angle_gen"), kinkangle);
286+
287+
TVector3 pdlab(v1.Px(), v1.Py(), v1.Pz());
288+
// Compute transverse component
289+
TVector3 motherDir(v0.Px(), v0.Py(), v0.Pz());
290+
double ptd = pdlab.Perp(motherDir); // or p_d_lab.Mag() * sin(theta)
291+
rpiKkink.fill(HIST("h2_qt_gen"), ptd);
292+
}
293+
}
294+
PROCESS_SWITCH(spectraKinkPiKa, processMC, "MC processing", false);
295+
};
296+
297+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
298+
{
299+
return WorkflowSpec{
300+
adaptAnalysisTask<spectraKinkPiKa>(cfgc)};
301+
}

0 commit comments

Comments
 (0)