Skip to content

Commit c4d8fed

Browse files
committed
treeCreatorPidTpcQa: start dev
1 parent 1884c20 commit c4d8fed

3 files changed

Lines changed: 297 additions & 0 deletions

File tree

DPG/Tasks/AOTTrack/PID/TPC/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,8 @@ o2physics_add_dpl_workflow(pid-tpc-qa-mc
2424
SOURCES qaPIDTPCMC.cxx
2525
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
2626
COMPONENT_NAME Analysis)
27+
28+
o2physics_add_dpl_workflow(tree-creator-pid-tpc-qa
29+
SOURCES treeCreatorPidTpcQa.cxx
30+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
31+
COMPONENT_NAME Analysis)
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
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 treeCreatorPidTpcQa.cxx
13+
/// \brief Task to produce table with clean selections for TPC PID calibration
14+
///
15+
/// \author Ana Marin <ana.marin@cern.ch>
16+
/// \author Oleksii Lubynets <oleksii.lubynets@cern.ch>
17+
18+
#include "treeCreatorPidTpcQa.h"
19+
20+
#include "Common/DataModel/EventSelection.h"
21+
#include "Common/DataModel/Multiplicity.h"
22+
#include "Common/DataModel/PIDResponseTOF.h"
23+
#include "Common/DataModel/PIDResponseTPC.h"
24+
#include "Common/DataModel/TrackSelectionTables.h"
25+
#include "DPG/Tasks/TPC/tpcSkimsTableCreator.h"
26+
27+
#include <Framework/ASoA.h>
28+
#include <Framework/AnalysisHelpers.h>
29+
#include <Framework/AnalysisTask.h>
30+
#include <Framework/Configurable.h>
31+
#include <Framework/InitContext.h>
32+
#include <Framework/Logger.h>
33+
#include <Framework/StaticFor.h>
34+
#include <Framework/runDataProcessing.h>
35+
#include <ReconstructionDataFormats/PID.h>
36+
37+
#include <cmath>
38+
39+
using namespace o2;
40+
using namespace o2::framework;
41+
using namespace o2::track;
42+
using namespace o2::dpg_pidtpcqa;
43+
44+
struct treeCreatorPidTpcQa {
45+
Produces<o2::aod::QaPidTpc> rowPidTpcQa;
46+
47+
Configurable<int> applyEvSel{"applyEvSel", 2, "Flag to apply event selection: 0 -> no event selection, 1 -> Run 2 event selection, 2 -> Run 3 event selection"};
48+
Configurable<float> cutVtxZ{"cutVtxZ", 10.f, "Cut on vertex Z position [cm]. Set negative value to switch this cut off"};
49+
Configurable<int> trackSelection{"trackSelection", 1, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"};
50+
Configurable<bool> requireGlobalTrack{"requireGlobalTrack", true, "Skip non-global tracks"};
51+
Configurable<bool> requireIts{"requireIts", true, "Skip tracks without ITS"};
52+
Configurable<int16_t> cutMinTPCNcls{"cutMinTPCNcls", 0, "Minimum number or TPC Clusters for tracks"};
53+
Configurable<float> cutRapidity{"cutRapidity", 0.5, "Rapidity cut. Set negative value to switch this cut off"};
54+
Configurable<float> nClNorm{"nClNorm", 152., "Number of cluster normalization. Run 2: 159, Run 3 152"};
55+
56+
using CollisionsExtra = soa::Join<aod::Collisions, aod::Mults, aod::EvSels>;
57+
using TrackCandidates = soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection>;
58+
59+
Preslice<TrackCandidates> perCollisionTracks = aod::track::collisionId;
60+
61+
int mEnabledParticles{0};
62+
63+
// Track selection
64+
template <typename TrackType>
65+
bool isTrackSelected(const TrackType& track)
66+
{
67+
bool isSelected{false};
68+
isSelected |= trackSelection == TrackSelectionNoCut;
69+
isSelected |= (trackSelection == TrackSelectionGlobalTrack) && track.isGlobalTrack();
70+
isSelected |= (trackSelection == TrackSelectionTrackWoPtEta) && track.isGlobalTrackWoPtEta();
71+
isSelected |= (trackSelection == TrackSelectionGlobalTrackWoDCA) && track.isGlobalTrackWoDCA();
72+
isSelected |= (trackSelection == TrackSelectionQualityTracks) && track.isQualityTrack();
73+
isSelected |= (trackSelection == TrackSelectionInAcceptanceTracks) && track.isInAcceptanceTrack();
74+
isSelected &= (!requireGlobalTrack || track.isGlobalTrack());
75+
isSelected &= (!requireIts || track.hasITS());
76+
isSelected &= track.hasTPC();
77+
isSelected &= (track.tpcNClsFound() >= cutMinTPCNcls);
78+
79+
return isSelected;
80+
}
81+
82+
template <o2::track::PID::ID Id>
83+
bool initPerParticle()
84+
{
85+
static_assert(Id >= 0 && Id <= PID::Alpha && "Particle index outside limits");
86+
int enabledProcesses{0};
87+
88+
switch (Id) {
89+
#define PARTICLE_CASE(ParticleId) \
90+
case PID::ParticleId: \
91+
if (!doprocess##ParticleId && !doprocessFull##ParticleId && !doprocessFullWithTOF##ParticleId) { \
92+
return false; \
93+
} \
94+
if (doprocess##ParticleId) { \
95+
++enabledProcesses; \
96+
} \
97+
if (doprocessFull##ParticleId) { \
98+
++enabledProcesses; \
99+
} \
100+
if (doprocessFullWithTOF##ParticleId) { \
101+
++enabledProcesses; \
102+
} \
103+
LOG(info) << "Enabled TPC QA for " << #ParticleId; \
104+
break;
105+
106+
PARTICLE_CASE(Electron);
107+
PARTICLE_CASE(Muon);
108+
PARTICLE_CASE(Pion);
109+
PARTICLE_CASE(Kaon);
110+
PARTICLE_CASE(Proton);
111+
PARTICLE_CASE(Deuteron);
112+
PARTICLE_CASE(Triton);
113+
PARTICLE_CASE(Helium3);
114+
PARTICLE_CASE(Alpha);
115+
#undef PARTICLE_CASE
116+
}
117+
if (enabledProcesses != 1) {
118+
LOG(fatal) << "Cannot enable more than one process function per particle, check and retry!";
119+
}
120+
return true;
121+
}
122+
123+
void init(o2::framework::InitContext&)
124+
{
125+
static_for<0, PID::Alpha>([&](auto Id) {
126+
mEnabledParticles += static_cast<int>(initPerParticle<Id>());
127+
});
128+
}
129+
130+
template <o2::track::PID::ID Id, typename TrackType>
131+
void processSingleParticle(CollisionsExtra const& collisions,
132+
TrackType const& tracks)
133+
{
134+
rowPidTpcQa.reserve(tracks.size() * mEnabledParticles);
135+
136+
for (const auto& collision : collisions) {
137+
if (!isEventSelected(collision, applyEvSel) || ((cutVtxZ > 0.f) && std::abs(collision.posZ()) > cutVtxZ)) {
138+
continue;
139+
}
140+
141+
const float ft0Occ = collision.ft0cOccupancyInTimeRange();
142+
const float multTPC = collision.multTPC() / dpg_tpcskimstablecreator::MultiplicityNorm;
143+
144+
const auto tracksFromCollision = tracks.sliceBy(perCollisionTracks, static_cast<int>(collision.globalIndex()));
145+
146+
for (const auto& track : tracksFromCollision) {
147+
if (!isTrackSelected(track)) {
148+
continue;
149+
}
150+
const float rapidity = track.rapidity(PID::getMass(Id));
151+
if (cutRapidity > 0.f && std::fabs(rapidity) > cutRapidity) {
152+
continue;
153+
}
154+
155+
const int nClNormalized = std::sqrt(nClNorm / track.tpcNClsFound());
156+
const float phi = track.phi();
157+
const float tgl = track.tgl();
158+
const float tpcInnerParam = track.tpcInnerParam();
159+
160+
rowPidTpcQa(Id, ft0Occ, multTPC, nClNormalized, phi, tgl, tpcInnerParam, rapidity);
161+
} // tracks
162+
} // collisions
163+
}
164+
165+
// QA of nsigma only tables
166+
#define MAKE_PROCESS_FUNCTION(PidTableTPC, ParticleId) \
167+
void process##ParticleId(CollisionsExtra const& collisions, \
168+
soa::Join<TrackCandidates, PidTableTPC> const& tracks) \
169+
{ \
170+
processSingleParticle<PID::ParticleId>(collisions, tracks); \
171+
} \
172+
PROCESS_SWITCH(treeCreatorPidTpcQa, process##ParticleId, Form("Process for the %s hypothesis for TPC NSigma QA", #ParticleId), false);
173+
174+
MAKE_PROCESS_FUNCTION(aod::pidTPCEl, Electron);
175+
MAKE_PROCESS_FUNCTION(aod::pidTPCMu, Muon);
176+
MAKE_PROCESS_FUNCTION(aod::pidTPCPi, Pion);
177+
MAKE_PROCESS_FUNCTION(aod::pidTPCKa, Kaon);
178+
MAKE_PROCESS_FUNCTION(aod::pidTPCPr, Proton);
179+
MAKE_PROCESS_FUNCTION(aod::pidTPCDe, Deuteron);
180+
MAKE_PROCESS_FUNCTION(aod::pidTPCTr, Triton);
181+
MAKE_PROCESS_FUNCTION(aod::pidTPCHe, Helium3);
182+
MAKE_PROCESS_FUNCTION(aod::pidTPCAl, Alpha);
183+
#undef MAKE_PROCESS_FUNCTION
184+
185+
// QA of full tables
186+
#define MAKE_PROCESS_FUNCTION(PidTableTPC, ParticleId) \
187+
void processFull##ParticleId(CollisionsExtra const& collisions, \
188+
soa::Join<TrackCandidates, PidTableTPC> const& tracks) \
189+
{ \
190+
processSingleParticle<PID::ParticleId>(collisions, tracks); \
191+
} \
192+
PROCESS_SWITCH(treeCreatorPidTpcQa, processFull##ParticleId, Form("Process for the %s hypothesis for full TPC PID QA", #ParticleId), false);
193+
194+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullEl, Electron);
195+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullMu, Muon);
196+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullPi, Pion);
197+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullKa, Kaon);
198+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullPr, Proton);
199+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullDe, Deuteron);
200+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullTr, Triton);
201+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullHe, Helium3);
202+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullAl, Alpha);
203+
#undef MAKE_PROCESS_FUNCTION
204+
205+
// QA of full tables with TOF information
206+
#define MAKE_PROCESS_FUNCTION(PidTableTPC, PidTableTOF, ParticleId) \
207+
void processFullWithTOF##ParticleId(CollisionsExtra const& collisions, \
208+
soa::Join<TrackCandidates, PidTableTPC, PidTableTOF> const& tracks) \
209+
{ \
210+
processSingleParticle<PID::ParticleId>(collisions, tracks); \
211+
} \
212+
PROCESS_SWITCH(treeCreatorPidTpcQa, processFullWithTOF##ParticleId, Form("Process for the %s hypothesis for full TPC PID QA with the TOF info added", #ParticleId), false);
213+
214+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullEl, aod::pidTOFFullEl, Electron);
215+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullMu, aod::pidTOFFullMu, Muon);
216+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullPi, aod::pidTOFFullPi, Pion);
217+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullKa, aod::pidTOFFullKa, Kaon);
218+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullPr, aod::pidTOFFullPr, Proton);
219+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullDe, aod::pidTOFFullDe, Deuteron);
220+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullTr, aod::pidTOFFullTr, Triton);
221+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullHe, aod::pidTOFFullHe, Helium3);
222+
MAKE_PROCESS_FUNCTION(aod::pidTPCFullAl, aod::pidTOFFullAl, Alpha);
223+
#undef MAKE_PROCESS_FUNCTION
224+
};
225+
226+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
227+
{
228+
return WorkflowSpec{adaptAnalysisTask<treeCreatorPidTpcQa>(cfgc)};
229+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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 treeCreatorPidTpcQa.h
13+
/// \author Ana Marin <ana.marin@cern.ch>
14+
/// \author Oleksii Lubynets <oleksii.lubynets@cern.ch>
15+
/// \brief Creates trees with PID QA variables along with variables used for NN training
16+
17+
#include "DPG/Tasks/TPC/tpcSkimsTableCreator.h"
18+
19+
#include <Framework/ASoA.h>
20+
21+
#ifndef DPG_TASKS_AOTTRACK_PID_TPC_TREECREATORPIDTPCQA_H_
22+
#define DPG_TASKS_AOTTRACK_PID_TPC_TREECREATORPIDTPCQA_H_
23+
24+
namespace o2::aod
25+
{
26+
DECLARE_SOA_TABLE(QaPidTpc, "AOD", "QAPIDTPC",
27+
tpcskims::PidIndex,
28+
tpcskims::Ft0Occ,
29+
tpcskims::NormMultTPC,
30+
tpcskims::NormNClustersTPC,
31+
o2::aod::track::Phi,
32+
o2::aod::track::Tgl,
33+
o2::aod::track::TPCInnerParam,
34+
o2::aod::track::Y)
35+
} // namespace o2::aod
36+
37+
namespace o2::dpg_pidtpcqa
38+
{
39+
enum {
40+
TrackSelectionNoCut = 0,
41+
TrackSelectionGlobalTrack,
42+
TrackSelectionTrackWoPtEta,
43+
TrackSelectionGlobalTrackWoDCA,
44+
TrackSelectionQualityTracks,
45+
TrackSelectionInAcceptanceTracks
46+
};
47+
48+
enum {
49+
EventSelectionNo = 0,
50+
EventSelectionRun2,
51+
EventSelectionRun3
52+
};
53+
54+
/// Event selection
55+
template <typename CollisionType>
56+
bool isEventSelected(const CollisionType& collision, const int applyEvSel)
57+
{
58+
return ((applyEvSel == EventSelectionRun2 && !collision.sel7()) || (applyEvSel == EventSelectionRun3 && !collision.sel8()));
59+
}
60+
61+
}; // namespace o2::dpg_pidtpcqa
62+
63+
#endif // DPG_TASKS_AOTTRACK_PID_TPC_TREECREATORPIDTPCQA_H_

0 commit comments

Comments
 (0)