Skip to content

Commit 74698c3

Browse files
authored
Preparing nuclei-task for pilot testbeam and MC validation (#6698)
1 parent 090b414 commit 74698c3

3 files changed

Lines changed: 248 additions & 19 deletions

File tree

Analysis/Tasks/PWGLF/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ o2_add_dpl_workflow(nuclei-spectra
4949
PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore
5050
COMPONENT_NAME Analysis)
5151

52+
o2_add_dpl_workflow(nuclei-efficiency
53+
SOURCES NucleiSpectraEfficiency.cxx
54+
PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore
55+
COMPONENT_NAME Analysis)
56+
5257
o2_add_dpl_workflow(lambdakzerobuilder
5358
SOURCES lambdakzerobuilder.cxx
5459
PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing O2::AnalysisTasksUtils
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
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+
// O2 includes
12+
13+
#include "ReconstructionDataFormats/Track.h"
14+
#include "Framework/AnalysisTask.h"
15+
#include "Framework/AnalysisDataModel.h"
16+
#include "Framework/ASoAHelpers.h"
17+
#include "AnalysisCore/MC.h"
18+
#include "AnalysisDataModel/PID/PIDResponse.h"
19+
#include "AnalysisDataModel/TrackSelectionTables.h"
20+
21+
#include "AnalysisDataModel/EventSelection.h"
22+
#include "AnalysisDataModel/TrackSelectionTables.h"
23+
#include "AnalysisDataModel/Centrality.h"
24+
25+
#include "Framework/HistogramRegistry.h"
26+
27+
#include <TLorentzVector.h>
28+
#include <TMath.h>
29+
#include <TObjArray.h>
30+
31+
#include <cmath>
32+
33+
using namespace o2;
34+
using namespace o2::framework;
35+
using namespace o2::framework::expressions;
36+
37+
void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions)
38+
{
39+
std::vector<ConfigParamSpec> options{
40+
{"add-vertex", VariantType::Int, 1, {"Vertex plots"}},
41+
{"add-gen", VariantType::Int, 1, {"Generated plots"}},
42+
{"add-rec", VariantType::Int, 1, {"Reconstructed plots"}}};
43+
std::swap(workflowOptions, options);
44+
}
45+
46+
#include "Framework/runDataProcessing.h" // important to declare after the options
47+
48+
struct NucleiSpectraEfficienctyVtx {
49+
OutputObj<TH1F> histVertexTrueZ{TH1F("histVertexTrueZ", "MC true z position of z-vertex; vertex z (cm)", 100, -20., 20.)};
50+
51+
void process(aod::McCollision const& mcCollision)
52+
{
53+
histVertexTrueZ->Fill(mcCollision.posZ());
54+
}
55+
};
56+
57+
struct NucleiSpectraEfficiencyGen {
58+
59+
HistogramRegistry spectra{"spectraGen", {}, OutputObjHandlingPolicy::AnalysisObject, true, true};
60+
61+
void init(o2::framework::InitContext&)
62+
{
63+
std::vector<double> ptBinning = {0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6,
64+
1.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4., 5., 6., 8., 10., 12., 14.};
65+
std::vector<double> centBinning = {0., 1., 5., 10., 20., 30., 40., 50., 70., 100.};
66+
//
67+
AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"};
68+
AxisSpec centAxis = {centBinning, "V0M (%)"};
69+
//
70+
spectra.add("histGenPt", "generated particles", HistType::kTH1F, {ptAxis});
71+
}
72+
73+
void process(aod::McCollision const& mcCollision, aod::McParticles& mcParticles)
74+
{
75+
//
76+
// loop over generated particles and fill generated particles
77+
//
78+
for (auto& mcParticleGen : mcParticles) {
79+
if (mcParticleGen.pdgCode() != -1000020030) {
80+
continue;
81+
}
82+
if (!MC::isPhysicalPrimary(mcParticles, mcParticleGen)) {
83+
continue;
84+
}
85+
if (abs(mcParticleGen.y()) > 0.5) {
86+
continue;
87+
}
88+
spectra.fill(HIST("histGenPt"), mcParticleGen.pt());
89+
}
90+
}
91+
};
92+
93+
struct NucleiSpectraEfficiencyRec {
94+
95+
HistogramRegistry spectra{"spectraRec", {}, OutputObjHandlingPolicy::AnalysisObject, true, true};
96+
97+
void init(o2::framework::InitContext&)
98+
{
99+
std::vector<double> ptBinning = {0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6,
100+
1.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4., 5., 6., 8., 10., 12., 14.};
101+
std::vector<double> centBinning = {0., 1., 5., 10., 20., 30., 40., 50., 70., 100.};
102+
//
103+
AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"};
104+
AxisSpec centAxis = {centBinning, "V0M (%)"};
105+
//
106+
spectra.add("histRecVtxZ", "collision z position", HistType::kTH1F, {{600, -20., +20., "z position (cm)"}});
107+
spectra.add("histRecPt", "reconstructed particles", HistType::kTH1F, {ptAxis});
108+
spectra.add("histTpcSignal", "Specific energy loss", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}});
109+
spectra.add("histTpcNsigma", "n-sigma TPC", HistType::kTH2F, {ptAxis, {200, -100., +100., "n#sigma_{He} (a. u.)"}});
110+
}
111+
112+
Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"};
113+
Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"};
114+
Configurable<float> nsigmacutLow{"nsigmacutLow", -10.0, "Value of the Nsigma cut"};
115+
Configurable<float> nsigmacutHigh{"nsigmacutHigh", +10.0, "Value of the Nsigma cut"};
116+
117+
Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex;
118+
Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == (uint8_t) true);
119+
120+
using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::McTrackLabels, aod::pidTPCFullHe, aod::pidTOFFullHe, aod::TrackSelection>>;
121+
122+
void process(soa::Filtered<soa::Join<aod::Collisions, aod::McCollisionLabels>>::iterator const& collision,
123+
TrackCandidates const& tracks, aod::McParticles& mcParticles, aod::McCollisions const& mcCollisions)
124+
{
125+
//
126+
// check the vertex-z distribution
127+
//
128+
spectra.fill(HIST("histRecVtxZ"), collision.posZ());
129+
//
130+
// loop over reconstructed particles and fill reconstructed tracks
131+
//
132+
for (auto track : tracks) {
133+
TLorentzVector lorentzVector{};
134+
lorentzVector.SetPtEtaPhiM(track.pt() * 2.0, track.eta(), track.phi(), constants::physics::MassHelium3);
135+
if (lorentzVector.Rapidity() < -0.5 || lorentzVector.Rapidity() > 0.5) {
136+
continue;
137+
}
138+
//
139+
// fill QA histograms
140+
//
141+
float nSigmaHe3 = track.tpcNSigmaHe();
142+
nSigmaHe3 += 94.222101 * TMath::Exp(-0.905203 * track.tpcInnerParam());
143+
//
144+
spectra.fill(HIST("histTpcSignal"), track.tpcInnerParam() * track.sign(), track.tpcSignal());
145+
spectra.fill(HIST("histTpcNsigma"), track.tpcInnerParam(), nSigmaHe3);
146+
//
147+
// fill histograms
148+
//
149+
if (nSigmaHe3 > nsigmacutLow && nSigmaHe3 < nsigmacutHigh) {
150+
// check on perfect PID
151+
if (track.mcParticle().pdgCode() != -1000020030) {
152+
continue;
153+
}
154+
// fill reconstructed histogram
155+
spectra.fill(HIST("histRecPt"), track.pt() * 2.0);
156+
}
157+
}
158+
}
159+
};
160+
161+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
162+
{
163+
const bool vertex = cfgc.options().get<int>("add-vertex");
164+
const bool gen = cfgc.options().get<int>("add-gen");
165+
const bool rec = cfgc.options().get<int>("add-rec");
166+
//
167+
WorkflowSpec workflow{};
168+
//
169+
if (vertex) {
170+
workflow.push_back(adaptAnalysisTask<NucleiSpectraEfficienctyVtx>(cfgc, TaskName{"nuclei-efficiency-vtx"}));
171+
}
172+
if (gen) {
173+
workflow.push_back(adaptAnalysisTask<NucleiSpectraEfficiencyGen>(cfgc, TaskName{"nuclei-efficiency-gen"}));
174+
}
175+
if (rec) {
176+
workflow.push_back(adaptAnalysisTask<NucleiSpectraEfficiencyRec>(cfgc, TaskName{"nuclei-efficiency-rec"}));
177+
}
178+
//
179+
return workflow;
180+
}

Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@
2525
#include "Framework/HistogramRegistry.h"
2626

2727
#include <TLorentzVector.h>
28+
#include <TMath.h>
29+
#include <TObjArray.h>
2830

2931
#include <cmath>
3032

3133
using namespace o2;
3234
using namespace o2::framework;
3335
using namespace o2::framework::expressions;
3436

35-
struct NucleiSpecraTask {
37+
struct NucleiSpectraTask {
3638

3739
HistogramRegistry spectra{"spectra", {}, OutputObjHandlingPolicy::AnalysisObject, true, true};
3840

@@ -44,24 +46,27 @@ struct NucleiSpecraTask {
4446
AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"};
4547
AxisSpec centAxis = {centBinning, "V0M (%)"};
4648

47-
spectra.add("fCollZpos", "collision z position", HistType::kTH1F, {{600, -20., +20., "z position (cm)"}});
48-
spectra.add("fKeepEvent", "skimming histogram", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}});
49-
spectra.add("fTPCsignal", "Specific energy loss", HistType::kTH2F, {{600, -3., 3, "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}});
50-
spectra.add("fTPCcounts", "n-sigma TPC", HistType::kTH2F, {ptAxis, {200, -100., +100., "n#sigma_{He} (a. u.)"}});
49+
spectra.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{600, -20., +20., "z position (cm)"}});
50+
spectra.add("histKeepEventData", "skimming histogram", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}});
51+
spectra.add("histTpcSignalData", "Specific energy loss", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}});
52+
spectra.add("histTofSignalData", "TOF signal", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {500, 0.0, 1.0, "#beta (TOF)"}});
53+
spectra.add("histTpcNsigmaData", "n-sigma TPC", HistType::kTH2F, {ptAxis, {200, -100., +100., "n#sigma_{He} (a. u.)"}});
54+
spectra.add("histDcaVsPtData", "dca vs Pt", HistType::kTH2F, {ptAxis, {400, -0.2, 0.2, "dca"}});
55+
spectra.add("histInvMassData", "Invariant mass", HistType::kTH1F, {{600, 5.0, +15., "inv. mass GeV/c^{2}"}});
5156
}
5257

53-
Configurable<float> yMin{"yMin", -0.8, "Maximum rapidity"};
54-
Configurable<float> yMax{"yMax", 0.8, "Minimum rapidity"};
58+
Configurable<float> yMin{"yMin", -0.5, "Maximum rapidity"};
59+
Configurable<float> yMax{"yMax", 0.5, "Minimum rapidity"};
5560

5661
Configurable<float> cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"};
5762
Configurable<float> cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"};
58-
Configurable<float> nsigmacutLow{"nsigmacutLow", -30.0, "Value of the Nsigma cut"};
59-
Configurable<float> nsigmacutHigh{"nsigmacutHigh", +3., "Value of the Nsigma cut"};
63+
Configurable<float> nsigmacutLow{"nsigmacutLow", -10.0, "Value of the Nsigma cut"};
64+
Configurable<float> nsigmacutHigh{"nsigmacutHigh", +10.0, "Value of the Nsigma cut"};
6065

6166
Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex;
6267
Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == (uint8_t) true);
6368

64-
using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::pidTPCFullHe, aod::pidTOFFullHe, aod::TrackSelection>>;
69+
using TrackCandidates = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksExtended, aod::pidTPCFullHe, aod::pidTOFFullHe, aod::TrackSelection>>;
6570

6671
void process(soa::Filtered<soa::Join<aod::Collisions, aod::EvSels>>::iterator const& collision, TrackCandidates const& tracks)
6772
{
@@ -70,37 +75,76 @@ struct NucleiSpecraTask {
7075
//
7176
bool keepEvent = kFALSE;
7277
//
73-
spectra.fill(HIST("fCollZpos"), collision.posZ());
78+
spectra.fill(HIST("histRecVtxZData"), collision.posZ());
79+
//
80+
std::vector<TLorentzVector> posTracks;
81+
std::vector<TLorentzVector> negTracks;
7482
//
7583
for (auto track : tracks) { // start loop over tracks
7684

77-
TLorentzVector cutVector{};
78-
cutVector.SetPtEtaPhiM(track.pt() * 2.0, track.eta(), track.phi(), constants::physics::MassHelium3);
79-
if (cutVector.Rapidity() < yMin || cutVector.Rapidity() > yMax) {
85+
TLorentzVector lorentzVector{};
86+
lorentzVector.SetPtEtaPhiM(track.pt() * 2.0, track.eta(), track.phi(), constants::physics::MassHelium3);
87+
if (lorentzVector.Rapidity() < yMin || lorentzVector.Rapidity() > yMax) {
8088
continue;
8189
}
8290
//
8391
// fill QA histograms
8492
//
85-
spectra.fill(HIST("fTPCsignal"), track.tpcInnerParam() * track.sign(), track.tpcSignal());
86-
spectra.fill(HIST("fTPCcounts"), track.tpcInnerParam(), track.tpcNSigmaHe());
93+
float nSigmaHe3 = track.tpcNSigmaHe();
94+
nSigmaHe3 += 94.222101 * TMath::Exp(-0.905203 * track.tpcInnerParam());
95+
//
96+
spectra.fill(HIST("histTpcSignalData"), track.tpcInnerParam() * track.sign(), track.tpcSignal());
97+
spectra.fill(HIST("histTpcNsigmaData"), track.tpcInnerParam(), nSigmaHe3);
8798
//
8899
// check offline-trigger (skimming) condidition
89100
//
90-
if (track.tpcNSigmaHe() > nsigmacutLow && track.tpcNSigmaHe() < nsigmacutHigh) {
101+
if (nSigmaHe3 > nsigmacutLow && nSigmaHe3 < nsigmacutHigh) {
91102
keepEvent = kTRUE;
103+
if (track.sign() < 0) {
104+
spectra.fill(HIST("histDcaVsPtData"), track.pt(), track.dcaXY());
105+
}
106+
//
107+
// store tracks for invariant mass calculation
108+
//
109+
if (track.sign() < 0) {
110+
negTracks.push_back(lorentzVector);
111+
}
112+
if (track.sign() > 0) {
113+
posTracks.push_back(lorentzVector);
114+
}
115+
//
116+
// calculate beta
117+
//
118+
if (!track.hasTOF()) {
119+
continue;
120+
}
121+
Float_t tofTime = track.tofSignal();
122+
Float_t tofLength = track.length();
123+
Float_t beta = tofLength / (TMath::C() * 1e-10 * tofTime);
124+
spectra.fill(HIST("histTofSignalData"), track.tpcInnerParam() * track.sign(), beta);
92125
}
93126

94127
} // end loop over tracks
95128
//
96129
// fill trigger (skimming) results
97130
//
98-
spectra.fill(HIST("fKeepEvent"), keepEvent);
131+
spectra.fill(HIST("histKeepEventData"), keepEvent);
132+
//
133+
// calculate invariant mass
134+
//
135+
for (Int_t iPos = 0; iPos < posTracks.size(); iPos++) {
136+
TLorentzVector& vecPos = posTracks[iPos];
137+
for (Int_t jNeg = 0; jNeg < negTracks.size(); jNeg++) {
138+
TLorentzVector& vecNeg = negTracks[jNeg];
139+
TLorentzVector vecMother = vecPos + vecNeg;
140+
spectra.fill(HIST("histInvMassData"), vecMother.M());
141+
}
142+
}
99143
}
100144
};
101145

102146
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
103147
{
104148
return WorkflowSpec{
105-
adaptAnalysisTask<NucleiSpecraTask>(cfgc, TaskName{"nuclei-spectra"})};
149+
adaptAnalysisTask<NucleiSpectraTask>(cfgc, TaskName{"nuclei-spectra"})};
106150
}

0 commit comments

Comments
 (0)