Skip to content

Commit 40c8f91

Browse files
[PWGLF] rename task and implement systematic cut variations (#12447)
1 parent 0e5a239 commit 40c8f91

File tree

2 files changed

+137
-64
lines changed

2 files changed

+137
-64
lines changed

PWGLF/Tasks/Nuspex/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ o2physics_add_dpl_workflow(spectra-tpc-tiny-pikapr
7979
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
8080
COMPONENT_NAME Analysis)
8181

82-
o2physics_add_dpl_workflow(spectra-charged
83-
SOURCES spectraCharged.cxx
82+
o2physics_add_dpl_workflow(charged-particles
83+
SOURCES chargedParticles.cxx
8484
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
8585
COMPONENT_NAME Analysis)
8686

Lines changed: 135 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -9,52 +9,80 @@
99
// granted to it by virtue of its status as an Intergovernmental Organization
1010
// or submit itself to any jurisdiction.
1111

12-
// task for charged particle pt spectra vs multiplicity analysis with 2d unfolding for run3+
13-
// mimics https://github.com/alisw/AliPhysics/blob/master/PWGLF/SPECTRA/ChargedHadrons/MultDepSpec/AliMultDepSpecAnalysisTask.cxx
14-
15-
#include "Framework/HistogramRegistry.h"
16-
#include "ReconstructionDataFormats/Track.h"
17-
#include "Framework/runDataProcessing.h"
18-
#include "Framework/AnalysisTask.h"
19-
#include "Framework/O2DatabasePDGPlugin.h"
20-
#include "Common/DataModel/EventSelection.h"
12+
/// \file chargedParticles.cxx
13+
/// \brief Task for analysis of charged particle pt spectra vs multiplicity with 2d unfolding.
14+
/// \author Mario Krüger <mario.kruger@cern.ch>
15+
16+
#include "Common/Core/TrackSelection.h"
17+
#include "Common/Core/TrackSelectionDefaults.h"
2118
#include "Common/DataModel/Centrality.h"
19+
#include "Common/DataModel/EventSelection.h"
2220
#include "Common/DataModel/TrackSelectionTables.h"
23-
#include "TDatabasePDG.h"
21+
22+
#include <Framework/AnalysisTask.h>
23+
#include <Framework/HistogramRegistry.h>
24+
#include <Framework/O2DatabasePDGPlugin.h>
25+
#include <Framework/runDataProcessing.h>
26+
#include <ReconstructionDataFormats/Track.h>
27+
28+
#include <unordered_set>
29+
#include <vector>
2430

2531
using namespace o2;
2632
using namespace o2::framework;
33+
using aod::track::TrackSelectionFlags;
2734

2835
//--------------------------------------------------------------------------------------------------
2936
//--------------------------------------------------------------------------------------------------
3037
// Task declaration
3138
//--------------------------------------------------------------------------------------------------
3239
//--------------------------------------------------------------------------------------------------
33-
struct chargedSpectra {
40+
struct ChargedParticles {
3441

3542
HistogramRegistry histos;
3643
Service<o2::framework::O2DatabasePDG> pdg;
3744

38-
// task settings that can be steered via hyperloop
3945
Configurable<bool> isRun3{"isRun3", true, "is Run3 dataset"};
4046
Configurable<uint32_t> maxMultMeas{"maxMultMeas", 100, "max measured multiplicity"};
4147
Configurable<uint32_t> maxMultTrue{"maxMultTrue", 100, "max true multiplicity"};
4248
Configurable<float> etaCut{"etaCut", 0.8f, "eta cut"};
4349
Configurable<float> ptMinCut{"ptMinCut", 0.15f, "pt min cut"};
4450
Configurable<float> ptMaxCut{"ptMaxCut", 10.f, "pt max cut"};
45-
4651
Configurable<bool> normINELGT0{"normINELGT0", false, "normalize INEL>0 according to MC"};
4752

53+
enum : uint32_t {
54+
kSystNominal = 100,
55+
kSystDownChi2PerClusterITS,
56+
kSystUpChi2PerClusterITS,
57+
kSystDownChi2PerClusterTPC,
58+
kSystUpChi2PerClusterTPC,
59+
kSystDownTPCCrossedRowsOverNCls,
60+
kSystUpTPCCrossedRowsOverNCls,
61+
kSystDownDCAxy = 111,
62+
kSystUpDCAxy,
63+
kSystDownDCAz,
64+
kSystUpDCAz,
65+
kSystITSHits,
66+
kSystDownTPCCrossedRows,
67+
kSystUpTPCCrossedRows
68+
};
69+
Configurable<uint32_t> systMode{"systMode", kSystNominal, "variation for systematic uncertainties"};
70+
uint16_t trackSelMask{TrackSelectionFlags::kGlobalTrackWoPtEta}; // track selection bitmask (without cut that is being varied)
71+
uint16_t cutVarFlag{0};
72+
TrackSelection trackSel;
73+
TrackSelection::TrackCuts trackSelFlag;
74+
4875
// helper struct to store transient properties
49-
struct varContainer {
76+
struct VarContainer {
5077
uint32_t multMeas{0u};
5178
uint32_t multTrue{0u};
5279
bool isAcceptedEvent{false};
5380
bool isAcceptedEventMC{false};
5481
bool isINELGT0EventMC{false};
5582
bool isChargedPrimary{false};
5683
};
57-
varContainer vars;
84+
VarContainer vars;
85+
static constexpr float kMaxVtxZ = 10.f;
5886

5987
void init(InitContext const&);
6088

@@ -70,43 +98,29 @@ struct chargedSpectra {
7098
template <typename C, typename P>
7199
void initEventMC(const C& collision, const P& particles);
72100

73-
template <bool IS_MC, typename C, typename T>
74-
void processMeas(const C& collision, const T& tracks);
101+
template <bool IS_MC, typename T>
102+
void processMeas(const T& tracks);
75103

76-
template <typename C, typename P>
77-
void processTrue(const C& collision, const P& particles);
104+
template <typename P>
105+
void processTrue(const P& particles);
78106

79107
using CollisionTableData = soa::Join<aod::Collisions, aod::EvSels>;
80-
using TrackTableData = soa::Join<aod::Tracks, aod::TrackSelection>;
108+
using TrackTableData = soa::Join<aod::FullTracks, aod::TracksDCA, aod::TrackSelection>;
81109
void processData(CollisionTableData::iterator const& collision, TrackTableData const& tracks);
82-
PROCESS_SWITCH(chargedSpectra, processData, "process data", false);
110+
PROCESS_SWITCH(ChargedParticles, processData, "process data", false);
83111

84112
using CollisionTableMCTrue = aod::McCollisions;
85113
using CollisionTableMC = soa::SmallGroups<soa::Join<aod::McCollisionLabels, aod::Collisions, aod::EvSels>>;
86-
using TrackTableMC = soa::Join<aod::Tracks, aod::McTrackLabels, aod::TrackSelection>;
114+
using TrackTableMC = soa::Join<aod::FullTracks, aod::TracksDCA, aod::TrackSelection, aod::McTrackLabels>;
87115
using ParticleTableMC = aod::McParticles;
88116
Preslice<TrackTableMC> perCollision = aod::track::collisionId;
89117
void processMC(CollisionTableMCTrue::iterator const& mcCollision, CollisionTableMC const& collisions, TrackTableMC const& tracks, ParticleTableMC const& particles);
90-
PROCESS_SWITCH(chargedSpectra, processMC, "process mc", true);
91-
92-
// TODO: - Milestone - express most of the selections on events and tracks in a declarative way to improve performance
93-
/*
94-
add
95-
Filter xy;
96-
soa::Filtered<Table>
97-
98-
For the collision and track tables (data and MC):
99-
- collision z pos < 10cm
100-
- trigger condition + event selection
101-
- track selection + is in kine range
102-
103-
For the MC tables we need to keep everything that EITHER fulfils the conditions in data OR in MC to get correct efficiencies and contamination!
104-
*/
118+
PROCESS_SWITCH(ChargedParticles, processMC, "process mc", true);
105119
};
106120

107121
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
108122
{
109-
return WorkflowSpec{adaptAnalysisTask<chargedSpectra>(cfgc)};
123+
return WorkflowSpec{adaptAnalysisTask<ChargedParticles>(cfgc)};
110124
}
111125

112126
//--------------------------------------------------------------------------------------------------
@@ -120,7 +134,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
120134
* Initialise the task and add histograms.
121135
*/
122136
//**************************************************************************************************
123-
void chargedSpectra::init(InitContext const&)
137+
void ChargedParticles::init(InitContext const&)
124138
{
125139
std::vector<double> ptBinEdges = {0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75,
126140
0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9,
@@ -162,25 +176,81 @@ void chargedSpectra::init(InitContext const&)
162176
histos.add("multPtSpec_trk_meas_evtcont", "", kTH2D, {multMeasAxis, ptMeasAxis}); // tracks from events that are measured, but do not belong to the desired class of events
163177
histos.add("multPtSpec_trk_inter", "", kTH2D, {multTrueAxis, ptMeasAxis});
164178
}
179+
180+
trackSel = getGlobalTrackSelection();
181+
if (systMode == kSystDownChi2PerClusterITS) {
182+
trackSel.SetMaxChi2PerClusterITS(25.);
183+
cutVarFlag = TrackSelectionFlags::kITSChi2NDF;
184+
trackSelFlag = TrackSelection::TrackCuts::kITSChi2NDF;
185+
} else if (systMode == kSystUpChi2PerClusterITS) {
186+
trackSel.SetMaxChi2PerClusterITS(49.);
187+
cutVarFlag = TrackSelectionFlags::kITSChi2NDF;
188+
trackSelFlag = TrackSelection::TrackCuts::kITSChi2NDF;
189+
} else if (systMode == kSystDownChi2PerClusterTPC) {
190+
trackSel.SetMaxChi2PerClusterTPC(3.0);
191+
cutVarFlag = TrackSelectionFlags::kTPCChi2NDF;
192+
trackSelFlag = TrackSelection::TrackCuts::kTPCChi2NDF;
193+
} else if (systMode == kSystUpChi2PerClusterTPC) {
194+
trackSel.SetMaxChi2PerClusterTPC(5.0);
195+
cutVarFlag = TrackSelectionFlags::kTPCChi2NDF;
196+
trackSelFlag = TrackSelection::TrackCuts::kTPCChi2NDF;
197+
} else if (systMode == kSystDownTPCCrossedRowsOverNCls) {
198+
trackSel.SetMinNCrossedRowsOverFindableClustersTPC(0.7);
199+
cutVarFlag = TrackSelectionFlags::kTPCCrossedRowsOverNCls;
200+
trackSelFlag = TrackSelection::TrackCuts::kTPCCrossedRowsOverNCls;
201+
} else if (systMode == kSystUpTPCCrossedRowsOverNCls) {
202+
trackSel.SetMinNCrossedRowsOverFindableClustersTPC(0.9);
203+
cutVarFlag = TrackSelectionFlags::kTPCCrossedRowsOverNCls;
204+
trackSelFlag = TrackSelection::TrackCuts::kTPCCrossedRowsOverNCls;
205+
} else if (systMode == kSystDownDCAxy) {
206+
trackSel.SetMaxDcaXYPtDep([](float pt) { return 4. / 7. * (0.0105f + 0.0350f / std::pow(pt, 1.1f)); });
207+
cutVarFlag = TrackSelectionFlags::kDCAxy;
208+
trackSelFlag = TrackSelection::TrackCuts::kDCAxy;
209+
} else if (systMode == kSystUpDCAxy) {
210+
trackSel.SetMaxDcaXYPtDep([](float pt) { return 10. / 7. * (0.0105f + 0.0350f / std::pow(pt, 1.1f)); });
211+
cutVarFlag = TrackSelectionFlags::kDCAxy;
212+
trackSelFlag = TrackSelection::TrackCuts::kDCAxy;
213+
} else if (systMode == kSystDownDCAz) {
214+
trackSel.SetMaxDcaZ(1.0);
215+
cutVarFlag = TrackSelectionFlags::kDCAz;
216+
trackSelFlag = TrackSelection::TrackCuts::kDCAz;
217+
} else if (systMode == kSystUpDCAz) {
218+
trackSel.SetMaxDcaZ(5.0);
219+
cutVarFlag = TrackSelectionFlags::kDCAz;
220+
trackSelFlag = TrackSelection::TrackCuts::kDCAz;
221+
} else if (systMode == kSystITSHits) {
222+
trackSel.ResetITSRequirements();
223+
cutVarFlag = TrackSelectionFlags::kITSHits;
224+
trackSelFlag = TrackSelection::TrackCuts::kITSHits;
225+
} else if (systMode == kSystDownTPCCrossedRows) {
226+
trackSel.SetMinNCrossedRowsTPC(60);
227+
cutVarFlag = TrackSelectionFlags::kTPCCrossedRows;
228+
trackSelFlag = TrackSelection::TrackCuts::kTPCCrossedRows;
229+
} else if (systMode == kSystUpTPCCrossedRows) {
230+
trackSel.SetMinNCrossedRowsTPC(80);
231+
cutVarFlag = TrackSelectionFlags::kTPCCrossedRows;
232+
trackSelFlag = TrackSelection::TrackCuts::kTPCCrossedRows;
233+
}
234+
trackSelMask &= (~cutVarFlag);
165235
}
166236

167237
//**************************************************************************************************
168238
/**
169239
* Entrypoint to processes data.
170240
*/
171241
//**************************************************************************************************
172-
void chargedSpectra::processData(CollisionTableData::iterator const& collision, TrackTableData const& tracks)
242+
void ChargedParticles::processData(CollisionTableData::iterator const& collision, TrackTableData const& tracks)
173243
{
174244
initEvent(collision, tracks);
175-
processMeas<false>(collision, tracks);
245+
processMeas<false>(tracks);
176246
}
177247

178248
//**************************************************************************************************
179249
/**
180250
* Entrypoint to processes mc.
181251
*/
182252
//**************************************************************************************************
183-
void chargedSpectra::processMC(CollisionTableMCTrue::iterator const& mcCollision, CollisionTableMC const& collisions, TrackTableMC const& tracks, ParticleTableMC const& particles)
253+
void ChargedParticles::processMC(CollisionTableMCTrue::iterator const& mcCollision, CollisionTableMC const& collisions, TrackTableMC const& tracks, ParticleTableMC const& particles)
184254
{
185255
histos.fill(HIST("collision_ambiguity"), collisions.size());
186256

@@ -198,14 +268,14 @@ void chargedSpectra::processMC(CollisionTableMCTrue::iterator const& mcCollision
198268
if (collisions.size() == 0) {
199269
vars.isAcceptedEvent = false;
200270
} else {
201-
for (auto& collision : collisions) {
271+
for (const auto& collision : collisions) {
202272
auto curTracks = tracks.sliceBy(perCollision, collision.globalIndex());
203273
initEvent(collision, curTracks);
204-
processMeas<true>(collision, curTracks);
274+
processMeas<true>(curTracks);
205275
break; // for now look only at first collision...
206276
}
207277
}
208-
processTrue(mcCollision, particles);
278+
processTrue(particles);
209279
}
210280

211281
//**************************************************************************************************
@@ -214,7 +284,7 @@ void chargedSpectra::processMC(CollisionTableMCTrue::iterator const& mcCollision
214284
*/
215285
//**************************************************************************************************
216286
template <typename P>
217-
bool chargedSpectra::initParticle(const P& particle)
287+
bool ChargedParticles::initParticle(const P& particle)
218288
{
219289
vars.isChargedPrimary = false;
220290
auto pdgParticle = pdg->GetParticle(particle.pdgCode());
@@ -241,15 +311,19 @@ bool chargedSpectra::initParticle(const P& particle)
241311
*/
242312
//**************************************************************************************************
243313
template <typename T>
244-
bool chargedSpectra::initTrack(const T& track)
314+
bool ChargedParticles::initTrack(const T& track)
245315
{
246316
if (std::abs(track.eta()) >= etaCut) {
247317
return false;
248318
}
249319
if (track.pt() <= ptMinCut || track.pt() >= ptMaxCut) {
250320
return false;
251321
}
252-
if (!track.isGlobalTrackWoPtEta()) {
322+
if (!TrackSelectionFlags::checkFlag(track.trackCutFlag(), trackSelMask)) {
323+
return false;
324+
}
325+
// for systematic variation of standard selections, check if the varied cut is passed
326+
if (cutVarFlag && !trackSel.IsSelected(track, trackSelFlag)) {
253327
return false;
254328
}
255329
return true;
@@ -261,17 +335,17 @@ bool chargedSpectra::initTrack(const T& track)
261335
*/
262336
//**************************************************************************************************
263337
template <typename C, typename T>
264-
void chargedSpectra::initEvent(const C& collision, const T& tracks)
338+
void ChargedParticles::initEvent(const C& collision, const T& tracks)
265339
{
266340
vars.multMeas = 0;
267-
for (auto& track : tracks) {
341+
for (const auto& track : tracks) {
268342
if (initTrack(track)) {
269343
++vars.multMeas;
270344
}
271345
}
272346

273347
vars.isAcceptedEvent = false;
274-
if (std::abs(collision.posZ()) < 10.f) {
348+
if (std::abs(collision.posZ()) < kMaxVtxZ) {
275349
if (isRun3 ? collision.sel8() : collision.sel7()) {
276350
if ((isRun3 || doprocessMC) ? true : collision.alias_bit(kINT7)) {
277351
vars.isAcceptedEvent = true;
@@ -286,35 +360,35 @@ void chargedSpectra::initEvent(const C& collision, const T& tracks)
286360
*/
287361
//**************************************************************************************************
288362
template <typename C, typename P>
289-
void chargedSpectra::initEventMC(const C& collision, const P& particles)
363+
void ChargedParticles::initEventMC(const C& collision, const P& particles)
290364
{
291365
vars.isINELGT0EventMC = false; // will be set to true in case a charged particle within eta +-1 is found
292366
vars.multTrue = 0;
293-
for (auto& particle : particles) {
367+
for (const auto& particle : particles) {
294368
if (!initParticle(particle) || !vars.isChargedPrimary) {
295369
continue;
296370
}
297371
++vars.multTrue;
298372
}
299373
bool isGoodEventClass = (normINELGT0) ? vars.isINELGT0EventMC : (vars.multTrue > 0);
300-
vars.isAcceptedEventMC = isGoodEventClass && (std::abs(collision.posZ()) < 10.f);
374+
vars.isAcceptedEventMC = isGoodEventClass && (std::abs(collision.posZ()) < kMaxVtxZ);
301375
}
302376

303377
//**************************************************************************************************
304378
/**
305379
* Function to processes MC truth info. Assumes initEvent and initEventMC have been called previously.
306380
*/
307381
//**************************************************************************************************
308-
template <typename C, typename P>
309-
void chargedSpectra::processTrue(const C& /*collision*/, const P& particles)
382+
template <typename P>
383+
void ChargedParticles::processTrue(const P& particles)
310384
{
311385
if (!vars.isAcceptedEventMC) {
312386
return;
313387
}
314388

315389
histos.fill(HIST("multDist_evt_gen"), vars.multTrue);
316390

317-
for (auto& particle : particles) {
391+
for (const auto& particle : particles) {
318392
if (initParticle(particle) && vars.isChargedPrimary) {
319393
histos.fill(HIST("multPtSpec_prim_gen"), vars.multTrue, particle.pt());
320394
if (!vars.isAcceptedEvent) {
@@ -329,8 +403,8 @@ void chargedSpectra::processTrue(const C& /*collision*/, const P& particles)
329403
* Function to process reconstructed data and MC. Assumes initEvent (and initEventMC in case of MC) have been called previously.
330404
*/
331405
//**************************************************************************************************
332-
template <bool IS_MC, typename C, typename T>
333-
void chargedSpectra::processMeas(const C& /*collision*/, const T& tracks)
406+
template <bool IS_MC, typename T>
407+
void ChargedParticles::processMeas(const T& tracks)
334408
{
335409
if (!vars.isAcceptedEvent) {
336410
return;
@@ -345,8 +419,7 @@ void chargedSpectra::processMeas(const C& /*collision*/, const T& tracks)
345419
}
346420

347421
std::vector<int> foundParticles;
348-
for (auto& track : tracks) {
349-
422+
for (const auto& track : tracks) {
350423
if (!initTrack(track)) {
351424
continue;
352425
}
@@ -390,7 +463,7 @@ void chargedSpectra::processMeas(const C& /*collision*/, const T& tracks)
390463
}
391464

392465
std::unordered_set<int> uniqueIndices(foundParticles.begin(), foundParticles.end());
393-
for (auto mcParticleID : uniqueIndices) {
466+
for (const auto& mcParticleID : uniqueIndices) {
394467
histos.fill(HIST("track_ambiguity"), std::count(foundParticles.begin(), foundParticles.end(), mcParticleID));
395468
}
396469
}

0 commit comments

Comments
 (0)