Skip to content

Commit 4640af3

Browse files
rspijkersalibuild
andauthored
Analysis task for cascade correlations (#2722)
* First version of cascade correlations * Formatting changes * fix PID, remove obsolete comments, disable LOG msgs * Please consider the following formatting changes (#4) * Implement comments: - Add configurable PID - Use phi() from LFStrangenessTable - Remove unnecessary dependencies in CMakeList.txt * Remove nsigma>10 cut, use constrainPhi() --------- Co-authored-by: ALICE Builder <alibuild@users.noreply.github.com>
1 parent 4d46a66 commit 4640af3

File tree

2 files changed

+241
-0
lines changed

2 files changed

+241
-0
lines changed

PWGLF/Tasks/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,8 @@ o2physics_add_dpl_workflow(antimatter-abs-hmpid
160160
SOURCES AntimatterAbsorptionHMPID.cxx
161161
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
162162
COMPONENT_NAME Analysis)
163+
164+
o2physics_add_dpl_workflow(cascadecorrelations
165+
SOURCES cascadecorrelations.cxx
166+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
167+
COMPONENT_NAME Analysis)
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
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+
// 2-particle correlations for cascades
13+
// =============================
14+
//
15+
// Author: Rik Spijkers (rik.spijkers@cern.ch)
16+
//
17+
18+
#include <Math/Vector4D.h>
19+
#include <cmath>
20+
#include <array>
21+
#include <cstdlib>
22+
23+
#include "Framework/runDataProcessing.h"
24+
#include "Framework/AnalysisTask.h"
25+
#include "Framework/AnalysisDataModel.h"
26+
#include "Framework/ASoAHelpers.h"
27+
#include "ReconstructionDataFormats/Track.h"
28+
#include "Common/Core/RecoDecay.h"
29+
#include "Common/Core/trackUtilities.h"
30+
#include "PWGLF/DataModel/LFStrangenessTables.h"
31+
#include "Common/Core/TrackSelection.h"
32+
#include "Common/DataModel/TrackSelectionTables.h"
33+
#include "Common/DataModel/EventSelection.h"
34+
#include "Common/DataModel/Centrality.h"
35+
#include "Common/DataModel/PIDResponse.h"
36+
#include <TFile.h>
37+
#include <TH2F.h>
38+
#include <TProfile.h>
39+
#include <TLorentzVector.h>
40+
#include <TPDGCode.h>
41+
#include <TDatabasePDG.h>
42+
43+
using namespace o2;
44+
using namespace o2::framework;
45+
using namespace o2::framework::expressions;
46+
using std::array;
47+
48+
// use parameters + cov mat non-propagated, aux info + (extension propagated)
49+
using FullTracksExt = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::TracksDCA>;
50+
using FullTracksExtIU = soa::Join<aod::TracksIU, aod::TracksExtra, aod::TracksCovIU, aod::TracksDCA>;
51+
using FullTracksExtWithPID = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksCov, aod::TracksDCA, aod::pidTPCPi, aod::pidTPCKa, aod::pidTPCPr>;
52+
using FullTracksExtIUWithPID = soa::Join<aod::TracksIU, aod::TracksExtra, aod::TracksCovIU, aod::TracksDCA, aod::pidTPCPi, aod::pidTPCKa, aod::pidTPCPr>;
53+
54+
// Add a column to the cascdataext table: IsSelected.
55+
// 0 = not selected, 1 = Xi, 2 = Omega
56+
namespace o2::aod
57+
{
58+
namespace cascadeflags
59+
{
60+
DECLARE_SOA_COLUMN(IsSelected, isSelected, int); //~!
61+
} // namespace cascadeflags
62+
DECLARE_SOA_TABLE(CascadeFlags, "AOD", "CASCADEFLAGS", //!
63+
cascadeflags::IsSelected);
64+
using CascDataExtSelected = soa::Join<CascDataExt, CascadeFlags>;
65+
} // namespace o2::aod
66+
67+
struct cascadeSelector {
68+
Produces<aod::CascadeFlags> cascflags;
69+
70+
// histo's
71+
HistogramRegistry registry{
72+
"registry",
73+
{
74+
{"hMassXiMinus", "hMassXiMinus", {HistType::kTH1F, {{3000, 0.0f, 3.0f, "Inv. Mass (GeV/c^{2})"}}}},
75+
},
76+
};
77+
78+
// Configurables
79+
Configurable<float> tpcNsigmaBachelor{"tpcNsigmaBachelor", 3, "TPC NSigma bachelor (>10 is no cut)"};
80+
Configurable<float> tpcNsigmaProton{"tpcNsigmaProton", 3, "TPC NSigma proton <- lambda (>10 is no cut)"};
81+
Configurable<float> tpcNsigmaPion{"tpcNsigmaPion", 3, "TPC NSigma pion <- lambda (>10 is no cut)"};
82+
83+
void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& collision, aod::CascDataExt const& Cascades, aod::V0sLinked const&, aod::V0Datas const&, FullTracksExtIUWithPID const&)
84+
{
85+
for (auto& casc : Cascades) {
86+
auto v0 = casc.v0_as<o2::aod::V0sLinked>();
87+
if (!(v0.has_v0Data())) {
88+
cascflags(0);
89+
continue; // reject if no v0data
90+
}
91+
auto v0data = v0.v0Data();
92+
93+
// Let's try to do some PID
94+
// these are the tracks:
95+
auto bachTrack = casc.bachelor_as<FullTracksExtIUWithPID>();
96+
auto posTrack = v0data.posTrack_as<FullTracksExtIUWithPID>();
97+
auto negTrack = v0data.negTrack_as<FullTracksExtIUWithPID>();
98+
99+
// PID
100+
// Lambda check
101+
if (casc.sign() < 0) {
102+
// Proton check:
103+
if (TMath::Abs(posTrack.tpcNSigmaPr()) > tpcNsigmaProton && tpcNsigmaProton < 9.99) {
104+
cascflags(0);
105+
continue;
106+
}
107+
// Pion check:
108+
if (TMath::Abs(negTrack.tpcNSigmaPi()) > tpcNsigmaPion) {
109+
cascflags(0);
110+
continue;
111+
}
112+
} else {
113+
// Proton check:
114+
if (TMath::Abs(negTrack.tpcNSigmaPr()) > tpcNsigmaProton) {
115+
cascflags(0);
116+
continue;
117+
}
118+
// Pion check:
119+
if (TMath::Abs(posTrack.tpcNSigmaPi()) > tpcNsigmaPion) {
120+
cascflags(0);
121+
continue;
122+
}
123+
}
124+
// Bachelor check
125+
if (TMath::Abs(bachTrack.tpcNSigmaPi()) < tpcNsigmaBachelor) {
126+
if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) {
127+
// TODO: ambiguous! ignore for now
128+
cascflags(0);
129+
continue;
130+
}
131+
cascflags(1);
132+
continue;
133+
} else if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) {
134+
cascflags(2);
135+
continue;
136+
}
137+
// if we reach here, the bachelor was neither pion nor kaon
138+
cascflags(0);
139+
} // cascade loop
140+
} // process
141+
}; // struct
142+
143+
struct cascadeCorrelations {
144+
HistogramRegistry registry{
145+
"registry",
146+
{
147+
{"hMassXiMinus", "hMassXiMinus", {HistType::kTH1F, {{3000, 0.0f, 3.0f, "Inv. Mass (GeV/c^{2})"}}}},
148+
{"hMassXiPlus", "hMassXiPlus", {HistType::kTH1F, {{3000, 0.0f, 3.0f, "Inv. Mass (GeV/c^{2})"}}}},
149+
{"hMassOmegaMinus", "hMassOmegaMinus", {HistType::kTH1F, {{3000, 0.0f, 3.0f, "Inv. Mass (GeV/c^{2})"}}}},
150+
{"hMassOmegaPlus", "hMassOmegaPlus", {HistType::kTH1F, {{3000, 0.0f, 3.0f, "Inv. Mass (GeV/c^{2})"}}}},
151+
{"hPhi", "hPhi", {HistType::kTH1F, {{100, 0, 2 * PI, "#varphi"}}}},
152+
{"hDeltaPhiSS", "hDeltaPhiSS", {HistType::kTH1F, {{100, -PI / 2, 1.5 * PI, "#Delta#varphi"}}}},
153+
{"hDeltaPhiOS", "hDeltaPhiOS", {HistType::kTH1F, {{100, -PI / 2, 1.5 * PI, "#Delta#varphi"}}}},
154+
},
155+
};
156+
157+
Filter Selector = aod::cascadeflags::isSelected > 0; // TODO: treat Omega's and Xi's differently
158+
159+
void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& collision, soa::Filtered<aod::CascDataExtSelected> const& Cascades, aod::V0sLinked const&, aod::V0Datas const&, FullTracksExtIU const&)
160+
{
161+
// Some QA on the cascades
162+
for (auto& casc : Cascades) {
163+
164+
auto v0 = casc.v0_as<o2::aod::V0sLinked>();
165+
if (!(v0.has_v0Data())) {
166+
continue; // reject if no v0data
167+
}
168+
169+
if (casc.sign() < 0) { // FIXME: could be done better...
170+
registry.fill(HIST("hMassXiMinus"), casc.mXi());
171+
registry.fill(HIST("hMassOmegaMinus"), casc.mOmega());
172+
} else {
173+
registry.fill(HIST("hMassXiPlus"), casc.mXi());
174+
registry.fill(HIST("hMassOmegaPlus"), casc.mOmega());
175+
}
176+
177+
registry.fill(HIST("hPhi"), casc.phi());
178+
} // casc loop
179+
180+
for (auto& [c0, c1] : combinations(Cascades, Cascades)) { // combinations automatically applies strictly upper in case of 2 identical tables
181+
auto lambda0 = c0.v0_as<o2::aod::V0sLinked>();
182+
auto lambda1 = c1.v0_as<o2::aod::V0sLinked>();
183+
if (!(lambda0.has_v0Data()) || !(lambda1.has_v0Data())) {
184+
continue; // reject if no v0data in either of the lambda's
185+
}
186+
auto v0data0 = lambda0.v0Data();
187+
auto v0data1 = lambda1.v0Data();
188+
189+
double dphi = RecoDecay::constrainAngle(c0.phi() - c1.phi(), -0.5 * PI);
190+
if (c0.sign() * c1.sign() < 0) { // opposite-sign
191+
registry.fill(HIST("hDeltaPhiOS"), dphi);
192+
} else { // same-sign
193+
// make sure to check for autocorrelations - only possible in same-sign correlations
194+
// TODO: make QA histo to quantify autocorrelations
195+
if (v0data0.v0Id() == v0data1.v0Id()) {
196+
// LOGF(info, "same v0 in SS correlation! %d %d", v0data0.v0Id(), v0data1.v0Id());
197+
continue;
198+
}
199+
int bachId0 = c0.bachelorId();
200+
int bachId1 = c1.bachelorId();
201+
int posId0 = v0data0.posTrackId();
202+
int negId0 = v0data0.negTrackId();
203+
int posId1 = v0data1.posTrackId();
204+
int negId1 = v0data1.negTrackId();
205+
if (bachId0 == bachId1) {
206+
// LOGF(info, "same bachelor in SS correlation! %d %d", bachId0, bachId1);
207+
continue;
208+
}
209+
// check for same tracks in v0's of cascades
210+
if (negId0 == negId1 || posId0 == posId1) {
211+
// LOGF(info, "cascades have a v0-track in common in SS correlation!");
212+
continue;
213+
}
214+
if (c0.sign() < 0) { // min cascade
215+
if (negId0 == bachId1 || negId1 == bachId0) {
216+
// LOGF(info, "bach of casc == v0-pion of other casc in neg SS correlation!");
217+
continue;
218+
}
219+
} else { // pos cascade
220+
if (posId0 == bachId1 || posId1 == bachId0) {
221+
// LOGF(info, "bach of casc == v0-pion of other casc in pos SS correlation!");
222+
continue;
223+
}
224+
}
225+
registry.fill(HIST("hDeltaPhiSS"), dphi);
226+
}
227+
} // correlations
228+
} // process
229+
}; // struct
230+
231+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
232+
{
233+
return WorkflowSpec{
234+
adaptAnalysisTask<cascadeSelector>(cfgc),
235+
adaptAnalysisTask<cascadeCorrelations>(cfgc)};
236+
}

0 commit comments

Comments
 (0)