Skip to content

Commit 2752084

Browse files
rspijkersalibuild
andauthored
PWGLF: add QA histo's + autocorr check (AliceO2Group#4354)
* match default settings to those of the builders * add QA histo's + autocorr check - many QA histograms added to keep track of selection criteria - flipped the definition in TPC PID selection flags: QOL improvement for THnSparse projections - autocorrelation check added for the Omega's, where the bachelor kaon could be "reused" as a proton in the V0 of the other anti-cascade * Please consider the following formatting changes (#8) --------- Co-authored-by: ALICE Builder <alibuild@users.noreply.github.com>
1 parent 41113f5 commit 2752084

File tree

1 file changed

+125
-13
lines changed

1 file changed

+125
-13
lines changed

PWGLF/Tasks/cascadecorrelations.cxx

Lines changed: 125 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ using FullTracksExtWithPID = soa::Join<aod::Tracks, aod::TracksExtra, aod::Track
5454
using FullTracksExtIUWithPID = soa::Join<aod::TracksIU, aod::TracksExtra, aod::TracksCovIU, aod::TracksDCA, aod::pidTPCPi, aod::pidTPCKa, aod::pidTPCPr>;
5555

5656
// Add a column to the cascdataext table: IsSelected.
57-
// 0 = not selected, 1 = Xi, 2 = Omega, 3 = both
57+
// 0 = not selected, 1 = Xi, 2 = both, 3 = Omega
5858
namespace o2::aod
5959
{
6060
namespace cascadeflags
@@ -75,44 +75,119 @@ struct cascadeSelector {
7575
Configurable<float> tpcNsigmaPion{"tpcNsigmaPion", 3, "TPC NSigma pion <- lambda"};
7676
Configurable<int> minTPCCrossedRows{"minTPCCrossedRows", 80, "min N TPC crossed rows"}; // TODO: finetune! 80 > 159/2, so no split tracks?
7777
Configurable<int> minITSClusters{"minITSClusters", 4, "minimum number of ITS clusters"};
78-
// Configurable<bool> doTPConly{"doTPConly", false, "use TPC-only tracks"}; // TODO: maybe do this for high pT only? as cascade decays after IB
7978

8079
// Selection criteria - compatible with core wagon autodetect - copied from cascadeanalysis.cxx
8180
//*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*
82-
Configurable<double> v0setting_cospa{"v0setting_cospa", 0.95, "v0setting_cospa"};
81+
Configurable<double> v0setting_cospa{"v0setting_cospa", 0.995, "v0setting_cospa"};
8382
Configurable<float> v0setting_dcav0dau{"v0setting_dcav0dau", 1.0, "v0setting_dcav0dau"};
8483
Configurable<float> v0setting_dcapostopv{"v0setting_dcapostopv", 0.1, "v0setting_dcapostopv"};
8584
Configurable<float> v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.1, "v0setting_dcanegtopv"};
8685
Configurable<float> v0setting_radius{"v0setting_radius", 0.9, "v0setting_radius"};
8786
Configurable<double> cascadesetting_cospa{"cascadesetting_cospa", 0.95, "cascadesetting_cospa"};
8887
Configurable<float> cascadesetting_dcacascdau{"cascadesetting_dcacascdau", 1.0, "cascadesetting_dcacascdau"};
89-
Configurable<float> cascadesetting_dcabachtopv{"cascadesetting_dcabachtopv", 0.1, "cascadesetting_dcabachtopv"};
90-
Configurable<float> cascadesetting_cascradius{"cascadesetting_cascradius", 0.5, "cascadesetting_cascradius"};
88+
Configurable<float> cascadesetting_dcabachtopv{"cascadesetting_dcabachtopv", 0.05, "cascadesetting_dcabachtopv"};
89+
Configurable<float> cascadesetting_cascradius{"cascadesetting_cascradius", 0.9, "cascadesetting_cascradius"};
9190
Configurable<float> cascadesetting_v0masswindow{"cascadesetting_v0masswindow", 0.01, "cascadesetting_v0masswindow"};
9291
Configurable<float> cascadesetting_mindcav0topv{"cascadesetting_mindcav0topv", 0.01, "cascadesetting_mindcav0topv"};
9392
//*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*
9493

94+
// TODO: variables as function of Omega mass, only do Xi for now
95+
AxisSpec vertexAxis = {200, -10.0f, 10.0f, "cm"};
96+
AxisSpec dcaAxis = {100, 0.0f, 10.0f, "cm"};
97+
AxisSpec invMassAxis = {1000, 1.0f, 2.0f, "Inv. Mass (GeV/c^{2})"};
98+
AxisSpec ptAxis = {100, 0, 15, "#it{p}_{T}"};
99+
HistogramRegistry registry{
100+
"registry",
101+
{
102+
// basic selection variables
103+
{"hV0Radius", "hV0Radius", {HistType::kTH3F, {{100, 0.0f, 100.0f, "cm"}, invMassAxis, ptAxis}}},
104+
{"hCascRadius", "hCascRadius", {HistType::kTH3F, {{100, 0.0f, 100.0f, "cm"}, invMassAxis, ptAxis}}},
105+
{"hV0CosPA", "hV0CosPA", {HistType::kTH3F, {{100, 0.95f, 1.0f}, invMassAxis, ptAxis}}},
106+
{"hCascCosPA", "hCascCosPA", {HistType::kTH3F, {{100, 0.95f, 1.0f}, invMassAxis, ptAxis}}},
107+
{"hDCAPosToPV", "hDCAPosToPV", {HistType::kTH3F, {vertexAxis, invMassAxis, ptAxis}}},
108+
{"hDCANegToPV", "hDCANegToPV", {HistType::kTH3F, {vertexAxis, invMassAxis, ptAxis}}},
109+
{"hDCABachToPV", "hDCABachToPV", {HistType::kTH3F, {vertexAxis, invMassAxis, ptAxis}}},
110+
{"hDCAV0ToPV", "hDCAV0ToPV", {HistType::kTH3F, {vertexAxis, invMassAxis, ptAxis}}},
111+
{"hDCAV0Dau", "hDCAV0Dau", {HistType::kTH3F, {dcaAxis, invMassAxis, ptAxis}}},
112+
{"hDCACascDau", "hDCACascDau", {HistType::kTH3F, {dcaAxis, invMassAxis, ptAxis}}},
113+
{"hLambdaMass", "hLambdaMass", {HistType::kTH3F, {{100, 1.0f, 1.2f, "Inv. Mass (GeV/c^{2})"}, invMassAxis, ptAxis}}},
114+
115+
// invariant mass per cut, start with Xi
116+
{"hMassXi0", "Xi inv mass before selections", {HistType::kTH2F, {invMassAxis, ptAxis}}},
117+
{"hMassXi1", "Xi inv mass after TPCnCrossedRows cut", {HistType::kTH2F, {invMassAxis, ptAxis}}},
118+
{"hMassXi2", "Xi inv mass after ITSnClusters cut", {HistType::kTH2F, {invMassAxis, ptAxis}}},
119+
{"hMassXi3", "Xi inv mass after topo cuts", {HistType::kTH2F, {invMassAxis, ptAxis}}},
120+
{"hMassXi4", "Xi inv mass after V0 daughters PID cut", {HistType::kTH2F, {invMassAxis, ptAxis}}},
121+
{"hMassXi5", "Xi inv mass after bachelor PID cut", {HistType::kTH2F, {invMassAxis, ptAxis}}},
122+
123+
// ITS & TPC clusters, with Xi inv mass
124+
{"hTPCnCrossedRowsPos", "hTPCnCrossedRowsPos", {HistType::kTH3F, {{160, -0.5, 159.5, "TPC crossed rows"}, invMassAxis, ptAxis}}},
125+
{"hTPCnCrossedRowsNeg", "hTPCnCrossedRowsNeg", {HistType::kTH3F, {{160, -0.5, 159.5, "TPC crossed rows"}, invMassAxis, ptAxis}}},
126+
{"hTPCnCrossedRowsBach", "hTPCnCrossedRowsBach", {HistType::kTH3F, {{160, -0.5, 159.5, "TPC crossed rows"}, invMassAxis, ptAxis}}},
127+
{"hITSnClustersPos", "hITSnClustersPos", {HistType::kTH3F, {{8, -0.5, 7.5, "number of ITS clusters"}, invMassAxis, ptAxis}}},
128+
{"hITSnClustersNeg", "hITSnClustersNeg", {HistType::kTH3F, {{8, -0.5, 7.5, "number of ITS clusters"}, invMassAxis, ptAxis}}},
129+
{"hITSnClustersBach", "hITSnClustersBach", {HistType::kTH3F, {{8, -0.5, 7.5, "number of ITS clusters"}, invMassAxis, ptAxis}}},
130+
},
131+
};
132+
133+
// Keep track of which selections the candidates pass
134+
void init(InitContext const&)
135+
{
136+
auto h = registry.add<TH1>("hSelectionStatus", "hSelectionStatus", HistType::kTH1I, {{10, 0, 10, "status"}});
137+
h->GetXaxis()->SetBinLabel(1, "All");
138+
h->GetXaxis()->SetBinLabel(2, "nTPC OK");
139+
h->GetXaxis()->SetBinLabel(3, "nITS OK");
140+
h->GetXaxis()->SetBinLabel(4, "Topo OK");
141+
h->GetXaxis()->SetBinLabel(5, "V0 PID OK");
142+
h->GetXaxis()->SetBinLabel(6, "Bach PID OK");
143+
}
95144
void process(soa::Join<aod::Collisions, aod::EvSels>::iterator const& collision, aod::CascDataExt const& Cascades, FullTracksExtIUWithPID const&)
96145
{
97146
for (auto& casc : Cascades) {
98-
// TODO: make QA histo with info on where cascades fail selections
99147

100-
// Let's try to do some PID & track quality cuts
101148
// these are the tracks:
102149
auto bachTrack = casc.bachelor_as<FullTracksExtIUWithPID>();
103150
auto posTrack = casc.posTrack_as<FullTracksExtIUWithPID>();
104151
auto negTrack = casc.negTrack_as<FullTracksExtIUWithPID>();
105152

153+
// topo variables before cuts:
154+
registry.fill(HIST("hV0Radius"), casc.v0radius(), casc.mXi(), casc.pt());
155+
registry.fill(HIST("hCascRadius"), casc.cascradius(), casc.mXi(), casc.pt());
156+
registry.fill(HIST("hV0CosPA"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()), casc.mXi(), casc.pt());
157+
registry.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()), casc.mXi(), casc.pt());
158+
registry.fill(HIST("hDCAPosToPV"), casc.dcapostopv(), casc.mXi(), casc.pt());
159+
registry.fill(HIST("hDCANegToPV"), casc.dcanegtopv(), casc.mXi(), casc.pt());
160+
registry.fill(HIST("hDCABachToPV"), casc.dcabachtopv(), casc.mXi(), casc.pt());
161+
registry.fill(HIST("hDCAV0ToPV"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()), casc.mXi(), casc.pt());
162+
registry.fill(HIST("hDCAV0Dau"), casc.dcaV0daughters(), casc.mXi(), casc.pt());
163+
registry.fill(HIST("hDCACascDau"), casc.dcacascdaughters(), casc.mXi(), casc.pt());
164+
registry.fill(HIST("hLambdaMass"), casc.mLambda(), casc.mXi(), casc.pt());
165+
166+
registry.fill(HIST("hITSnClustersPos"), posTrack.itsNCls(), casc.mXi(), casc.pt());
167+
registry.fill(HIST("hITSnClustersNeg"), negTrack.itsNCls(), casc.mXi(), casc.pt());
168+
registry.fill(HIST("hITSnClustersBach"), bachTrack.itsNCls(), casc.mXi(), casc.pt());
169+
registry.fill(HIST("hTPCnCrossedRowsPos"), posTrack.tpcNClsCrossedRows(), casc.mXi(), casc.pt());
170+
registry.fill(HIST("hTPCnCrossedRowsNeg"), negTrack.tpcNClsCrossedRows(), casc.mXi(), casc.pt());
171+
registry.fill(HIST("hTPCnCrossedRowsBach"), bachTrack.tpcNClsCrossedRows(), casc.mXi(), casc.pt());
172+
173+
registry.fill(HIST("hSelectionStatus"), 0); // all the cascade before selections
174+
registry.fill(HIST("hMassXi0"), casc.mXi(), casc.pt());
175+
106176
// TPC N crossed rows
107177
if (posTrack.tpcNClsCrossedRows() < minTPCCrossedRows || negTrack.tpcNClsCrossedRows() < minTPCCrossedRows || bachTrack.tpcNClsCrossedRows() < minTPCCrossedRows) {
108178
cascflags(0);
109179
continue;
110180
}
181+
registry.fill(HIST("hSelectionStatus"), 1); // passes nTPC crossed rows
182+
registry.fill(HIST("hMassXi1"), casc.mXi(), casc.pt());
183+
111184
// ITS N clusters
112185
if (posTrack.itsNCls() < minITSClusters || negTrack.itsNCls() < minITSClusters || bachTrack.itsNCls() < minITSClusters) {
113186
cascflags(0);
114187
continue;
115188
}
189+
registry.fill(HIST("hSelectionStatus"), 2); // passes nITS clusters
190+
registry.fill(HIST("hMassXi2"), casc.mXi(), casc.pt());
116191

117192
//// TOPO CUTS //// TODO: improve!
118193
double pvx = collision.posX();
@@ -128,10 +203,12 @@ struct cascadeSelector {
128203
cascflags(0);
129204
continue;
130205
}
206+
registry.fill(HIST("hSelectionStatus"), 3); // passes topo
207+
registry.fill(HIST("hMassXi3"), casc.mXi(), casc.pt());
131208

132209
// TODO: TOF (for pT > 2 GeV per track?)
133210

134-
//// TPC ////
211+
//// TPC PID ////
135212
// Lambda check
136213
if (casc.sign() < 0) {
137214
// Proton check:
@@ -156,17 +233,25 @@ struct cascadeSelector {
156233
continue;
157234
}
158235
}
236+
registry.fill(HIST("hSelectionStatus"), 4); // fails at V0 daughters PID
237+
registry.fill(HIST("hMassXi4"), casc.mXi(), casc.pt());
238+
159239
// Bachelor check
160240
if (TMath::Abs(bachTrack.tpcNSigmaPi()) < tpcNsigmaBachelor) {
161241
if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) {
162242
// consistent with both!
163-
cascflags(3);
243+
cascflags(2);
244+
registry.fill(HIST("hSelectionStatus"), 5); // passes bach PID
245+
registry.fill(HIST("hMassXi5"), casc.mXi(), casc.pt());
164246
continue;
165247
}
166248
cascflags(1);
249+
registry.fill(HIST("hSelectionStatus"), 5); // passes bach PID
250+
registry.fill(HIST("hMassXi5"), casc.mXi(), casc.pt());
167251
continue;
168252
} else if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) {
169-
cascflags(2);
253+
cascflags(3);
254+
registry.fill(HIST("hSelectionStatus"), 5); // passes bach PID
170255
continue;
171256
}
172257
// if we reach here, the bachelor was neither pion nor kaon
@@ -207,7 +292,8 @@ struct cascadeCorrelations {
207292
{"hLambdaMass", "hLambdaMass", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "Inv. Mass (GeV/c^{2})"}}}},
208293

209294
{"hSelectionFlag", "hSelectionFlag", {HistType::kTH1I, {selectionFlagAxis}}},
210-
{"hAutoCorrelation", "hAutoCorrelation", {HistType::kTH1I, {{4, -0.5f, 3.5f, "Types of autocorrelation"}}}},
295+
{"hAutoCorrelation", "hAutoCorrelation", {HistType::kTH1I, {{4, -0.5f, 3.5f, "Types of SS autocorrelation"}}}},
296+
{"hAutoCorrelationOS", "hAutoCorrelationOS", {HistType::kTH1I, {{2, -1.f, 1.f, "Charge of OS autocorrelated track"}}}},
211297
{"hPhi", "hPhi", {HistType::kTH1F, {{100, 0, 2 * PI, "#varphi"}}}},
212298
{"hEta", "hEta", {HistType::kTH1F, {{100, -2, 2, "#eta"}}}},
213299

@@ -237,7 +323,7 @@ struct cascadeCorrelations {
237323

238324
// Some QA on the cascades
239325
for (auto& casc : Cascades) {
240-
if (casc.isSelected() != 2) { // not exclusively an Omega --> consistent with Xi or both
326+
if (casc.isSelected() <= 2) { // not exclusively an Omega --> consistent with Xi or both
241327
if (casc.sign() < 0) {
242328
registry.fill(HIST("hMassXiMinus"), casc.mXi(), casc.pt());
243329
} else {
@@ -296,13 +382,39 @@ struct cascadeCorrelations {
296382

297383
// Fill the correct histograms based on same-sign or opposite-sign
298384
if (trigger.sign() * assoc.sign() < 0) { // opposite-sign
385+
// check for autocorrelations between mis-identified kaons (omega bach) and protons (lambda daughter) TODO: improve logic?
386+
if (trigger.isSelected() >= 2) {
387+
if (trigger.sign() > 0 && trigger.bachelorId() == posIdAssoc) {
388+
// K+ from trigger Omega is the same as proton from assoc lambda
389+
registry.fill(HIST("hAutoCorrelationOS"), 1);
390+
continue;
391+
}
392+
if (trigger.sign() < 0 && trigger.bachelorId() == negIdAssoc) {
393+
// K- from trigger Omega is the same as antiproton from assoc antilambda
394+
registry.fill(HIST("hAutoCorrelationOS"), -1);
395+
continue;
396+
}
397+
}
398+
if (assoc.isSelected() >= 2) {
399+
if (assoc.sign() > 0 && assoc.bachelorId() == posIdTrigg) {
400+
// K+ from assoc Omega is the same as proton from trigger lambda
401+
registry.fill(HIST("hAutoCorrelationOS"), 1);
402+
continue;
403+
}
404+
if (assoc.sign() < 0 && assoc.bachelorId() == negIdTrigg) {
405+
// K- from assoc Omega is the same as antiproton from trigger antilambda
406+
registry.fill(HIST("hAutoCorrelationOS"), -1);
407+
continue;
408+
}
409+
}
410+
299411
registry.fill(HIST("hDeltaPhiOS"), dphi);
300412
registry.fill(HIST("hXiXiOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M());
301413
registry.fill(HIST("hXiOmOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M());
302414
registry.fill(HIST("hOmXiOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M());
303415
registry.fill(HIST("hOmOmOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M());
304416
} else { // same-sign
305-
// make sure to check for autocorrelations - only possible in same-sign correlations
417+
// make sure to check for autocorrelations - only possible in same-sign correlations (if PID is correct)
306418
if (posIdTrigg == posIdAssoc && negIdTrigg == negIdAssoc) {
307419
// LOGF(info, "same v0 in SS correlation! %d %d", v0dataTrigg.v0Id(), v0dataAssoc.v0Id());
308420
registry.fill(HIST("hAutoCorrelation"), 0);

0 commit comments

Comments
 (0)