Skip to content

Commit 5d13187

Browse files
authored
[PWGLF] Add systematic mapping analysis task (AliceO2Group#13075)
- add prototask
1 parent 0754513 commit 5d13187

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

PWGLF/Tasks/QC/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,9 @@ o2physics_add_dpl_workflow(its-tpc-matching-vzeros
138138
o2physics_add_dpl_workflow(v0assoqa
139139
SOURCES v0assoqa.cxx
140140
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager
141+
COMPONENT_NAME Analysis)
142+
143+
o2physics_add_dpl_workflow(systematics-mapping
144+
SOURCES systematicsMapping.cxx
145+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
141146
COMPONENT_NAME Analysis)
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
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 systematicsMapping.cxx
13+
/// \brief Task to perform a systematics study for K0s and charged Kaons
14+
/// \author Nicolò Jacazio, Universita del Piemonte Orientale (IT)
15+
/// \since September 22, 2025
16+
17+
#include "PWGLF/DataModel/LFStrangenessTables.h"
18+
19+
#include "Common/DataModel/EventSelection.h"
20+
#include "Common/DataModel/PIDResponseTOF.h"
21+
#include "Common/DataModel/PIDResponseTPC.h"
22+
23+
#include <Framework/AnalysisDataModel.h>
24+
#include <Framework/AnalysisTask.h>
25+
#include <Framework/HistogramRegistry.h>
26+
#include <Framework/runDataProcessing.h>
27+
#include <ReconstructionDataFormats/Track.h>
28+
29+
#include <algorithm>
30+
31+
using namespace o2;
32+
using namespace o2::framework;
33+
34+
struct SystematicsMapping {
35+
// Returns a unique index for the combination of cuts
36+
ConfigurableAxis ptBins{"ptBins", {100, 0.f, 10.f}, "Binning for pT (GeV/c)"};
37+
ConfigurableAxis etaBins{"etaBins", {40, -1.0f, 1.0f}, "Binning for #eta"};
38+
ConfigurableAxis phiBins{"phiBins", {36, 0.f, o2::constants::math::TwoPI}, "Binning for #phi (rad)"};
39+
// Define the Signal axis
40+
ConfigurableAxis invariantMassBins{"invariantMassBins", {100, -0.1f, 0.1f}, "Binning for the invariant mass (GeV/c^2)"};
41+
ConfigurableAxis nsigmaBins{"nsigmaBins", {100, -10.f, 10.f}, "Binning for nSigma"};
42+
// Selection bins
43+
ConfigurableAxis tpcClusterBins{"tpcClusterBins", {5, 70, 100, 120, 135, 150}, "Min TPC clusters for tracks"};
44+
ConfigurableAxis itsClustersBins{"itsClustersBins", {5, 0, 6}, "Min ITS clusters for tracks"};
45+
// Selection configurables
46+
Configurable<float> selectionPosZ{"selectionPosZ", 10.f, "Max |z| of the primary vertex"};
47+
48+
HistogramRegistry registry{"registry"};
49+
50+
template <typename T>
51+
bool isCollisionSelected(T const& collision)
52+
{
53+
return collision.sel8() && std::abs(collision.posZ()) <= selectionPosZ;
54+
}
55+
56+
void init(InitContext const&)
57+
{
58+
const AxisSpec ptAxis{ptBins, "#it{p}_{T} (GeV/c)"};
59+
const AxisSpec etaAxis{etaBins, "#eta"};
60+
const AxisSpec phiAxis{phiBins, "#phi (rad)"};
61+
62+
if (doprocessData) {
63+
64+
// First we define the histograms on which we are cutting (tpc clusters, its clusters, ..)
65+
registry.add("K/hTPCClusters", "", HistType::kTH1F, {{100, 0, 200}});
66+
registry.add("K/hITSClusters", "", HistType::kTH1F, {{10, 0, 10}});
67+
registry.addClone("K/", "K0s/");
68+
69+
// Add the signal histograms
70+
registry.add("K/SignalPositive", "", HistType::kTHnSparseF, {ptBins, etaBins, phiBins, nsigmaBins, tpcClusterBins, itsClustersBins});
71+
registry.add("K/SignalNegative", "", HistType::kTHnSparseF, {ptBins, etaBins, phiBins, nsigmaBins, tpcClusterBins, itsClustersBins});
72+
registry.add("K0s/Signal", "", HistType::kTHnSparseF, {ptBins, etaBins, phiBins, invariantMassBins, tpcClusterBins, itsClustersBins});
73+
}
74+
75+
if (doprocessMc) {
76+
registry.add("K/GeneratedPositive", "", HistType::kTHnSparseF, {ptBins, etaBins, phiBins});
77+
registry.add("K/GeneratedNegative", "", HistType::kTHnSparseF, {ptBins, etaBins, phiBins});
78+
registry.add("K0s/Generated", "", HistType::kTHnSparseF, {ptBins, etaBins, phiBins});
79+
}
80+
}
81+
82+
using TrackType = soa::Join<aod::Tracks, aod::TracksExtra, aod::pidTPCFullKa, aod::pidTOFFullPi>;
83+
using CollisionType = soa::Join<aod::Collisions, aod::EvSels>;
84+
85+
void processData(CollisionType const& collisions,
86+
TrackType const& tracks,
87+
aod::V0Datas const& v0s)
88+
{
89+
for (const auto& collision : collisions) {
90+
if (isCollisionSelected(collision))
91+
continue; // MB selection
92+
93+
// Kaon loop
94+
for (const auto& track : tracks) {
95+
if (track.collisionId() != collision.globalIndex())
96+
continue;
97+
registry.fill(HIST("hTPCClusters"), track.tpcNClsFound());
98+
registry.fill(HIST("hITSClusters"), track.itsNCls());
99+
if (track.sign() > 0)
100+
registry.fill(HIST("K/SignalPositive"), track.pt(), track.eta(), track.phi(), track.tpcNSigmaKa(), track.tpcNClsFound(), track.itsNCls());
101+
else
102+
registry.fill(HIST("K/SignalNegative"), track.pt(), track.eta(), track.phi(), track.tpcNSigmaKa(), track.tpcNClsFound(), track.itsNCls());
103+
}
104+
105+
// K0s loop
106+
for (const auto& v0 : v0s) {
107+
if (v0.collisionId() != collision.globalIndex())
108+
continue;
109+
const auto& posTrack = v0.posTrack_as<TrackType>();
110+
const auto& negTrack = v0.negTrack_as<TrackType>();
111+
registry.fill(HIST("K0s/Signal"), v0.pt(), v0.eta(), v0.phi(), v0.mK0Short() - constants::physics::MassK0Short, std::min(posTrack.tpcNClsFound(), negTrack.tpcNClsFound()), std::min(posTrack.itsNCls(), negTrack.itsNCls()));
112+
}
113+
}
114+
}
115+
PROCESS_SWITCH(SystematicsMapping, processData, "Systematics study for K0s and charged Kaons", true);
116+
117+
void processMc(soa::Join<CollisionType, aod::McCollisionLabels> const& collisions,
118+
aod::McParticles const& particles,
119+
aod::McCollisions const&)
120+
{
121+
for (const auto& collision : collisions) {
122+
if (!isCollisionSelected(collision))
123+
continue; // MB selection
124+
if (!collision.has_mcCollision())
125+
continue;
126+
const auto& mcCollision = collision.mcCollision();
127+
128+
for (const auto& particle : particles) {
129+
if (particle.mcCollisionId() != mcCollision.globalIndex())
130+
continue;
131+
if (!particle.isPhysicalPrimary())
132+
continue;
133+
switch (particle.pdgCode()) {
134+
case 321: // K+
135+
registry.fill(HIST("K/GeneratedPositive"), particle.pt(), particle.eta(), particle.phi());
136+
break;
137+
case -321: // K-
138+
registry.fill(HIST("K/GeneratedNegative"), particle.pt(), particle.eta(), particle.phi());
139+
break;
140+
case 310: // K0s
141+
registry.fill(HIST("K0s/Generated"), particle.pt(), particle.eta(), particle.phi());
142+
break;
143+
default:
144+
break;
145+
}
146+
}
147+
}
148+
}
149+
PROCESS_SWITCH(SystematicsMapping, processMc, "Systematics study for K0s and charged Kaons on MC", false);
150+
};
151+
152+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask<SystematicsMapping>(cfgc)}; }

0 commit comments

Comments
 (0)