Skip to content

Commit a4f7ea6

Browse files
authored
[ALICE3] A3: add qa tasks (#11377)
1 parent 4808833 commit a4f7ea6

File tree

3 files changed

+220
-1
lines changed

3 files changed

+220
-1
lines changed

ALICE3/Tasks/CMakeLists.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ o2physics_add_dpl_workflow(alice3-pid-ftof-qa
3939
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
4040
COMPONENT_NAME Analysis)
4141

42+
o2physics_add_dpl_workflow(alice3-pid-separation-power
43+
SOURCES alice3SeparationPower.cxx
44+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
45+
COMPONENT_NAME Analysis)
46+
4247
o2physics_add_dpl_workflow(alice3-cdeuteron
4348
SOURCES alice3-cdeuteron.cxx
4449
PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore
@@ -52,4 +57,9 @@ o2physics_add_dpl_workflow(alice3-dilepton
5257
o2physics_add_dpl_workflow(alice3-taskcorrelationddbar
5358
SOURCES alice3-taskcorrelationDDbar.cxx
5459
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
55-
COMPONENT_NAME Analysis)
60+
COMPONENT_NAME Analysis)
61+
62+
o2physics_add_dpl_workflow(alice3-efficiency
63+
SOURCES alice3Efficiency.cxx
64+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
65+
COMPONENT_NAME Analysis)

ALICE3/Tasks/alice3Efficiency.cxx

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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 alice3Efficiency.cxx
13+
///
14+
/// \brief This task produces the efficiency
15+
///
16+
/// \author Nicolò Jacazio, Universita del Piemonte Orientale (IT)
17+
/// \since May 27, 2025
18+
///
19+
20+
#include <map>
21+
#include <vector>
22+
23+
#include "Framework/AnalysisTask.h"
24+
#include "Framework/runDataProcessing.h"
25+
#include "Framework/HistogramRegistry.h"
26+
#include "Framework/ConfigParamRegistry.h"
27+
#include "TEfficiency.h"
28+
#include "THashList.h"
29+
30+
using namespace o2;
31+
using namespace o2::framework;
32+
std::map<int, TEfficiency*> effVsPt;
33+
std::map<int, TEfficiency*> effVsEta;
34+
35+
struct alice3Efficiency {
36+
Configurable<std::vector<int>> pdgCodes{"pdgCodes", {211}, "List of PDG codes to consider for efficiency calculation"};
37+
OutputObj<THashList> outList{"output"};
38+
Configurable<std::pair<float, float>> etaRange{"etaRange", {-5.f, 5.f}, "Eta range for efficiency calculation"};
39+
void init(o2::framework::InitContext&)
40+
{
41+
outList.setObject(new THashList);
42+
auto createEff = [&](const char* baseName, const char* axisTitle, int pdg, int nBins, double min, double max) {
43+
auto eff = new TEfficiency(Form("%s_pdg%d", baseName, pdg),
44+
Form("Efficiency for PDG %d; %s; Efficiency", pdg, axisTitle),
45+
nBins, min, max);
46+
outList->Add(eff);
47+
return eff;
48+
};
49+
for (auto pdg : pdgCodes.value) {
50+
effVsPt[pdg] = createEff("efficiency", "p_{T} (GeV/c)", pdg, 100, 0, 10);
51+
effVsEta[pdg] = createEff("efficiency_eta", "#eta", pdg, 100, -5, 5);
52+
}
53+
}
54+
55+
void process(soa::Join<aod::Tracks, o2::aod::McTrackLabels> const& tracks,
56+
aod::McParticles const& mcParticles)
57+
{
58+
std::map<int, std::vector<int64_t>> pdgIndices;
59+
60+
// Lambda function to select particles after all cuts
61+
auto isParticleSelected = [&](const o2::aod::McParticle& p) {
62+
if (!p.isPhysicalPrimary()) {
63+
return false;
64+
}
65+
if (p.eta() < etaRange.value.first) {
66+
return false;
67+
}
68+
if (p.eta() > etaRange.value.second) {
69+
return false;
70+
}
71+
return true;
72+
};
73+
for (const auto& track : tracks) {
74+
if (!track.has_mcParticle()) {
75+
continue;
76+
}
77+
const auto& mcParticle = track.mcParticle();
78+
if (!isParticleSelected(mcParticle)) {
79+
continue;
80+
}
81+
pdgIndices[mcParticle.pdgCode()].push_back(mcParticle.globalIndex());
82+
}
83+
84+
for (auto& mc : mcParticles) {
85+
if (effVsPt.find(mc.pdgCode()) == effVsPt.end()) {
86+
continue;
87+
}
88+
if (!isParticleSelected(mc)) {
89+
continue;
90+
}
91+
std::vector<int64_t>& indices = pdgIndices[mc.pdgCode()];
92+
// Fill efficiency histogram
93+
const bool found = std::find(indices.begin(), indices.end(), mc.globalIndex()) != indices.end();
94+
effVsPt[mc.pdgCode()]->Fill(found, mc.pt());
95+
effVsEta[mc.pdgCode()]->Fill(found, mc.eta());
96+
}
97+
}
98+
};
99+
100+
WorkflowSpec defineDataProcessing(ConfigContext const& ctx)
101+
{
102+
return WorkflowSpec{adaptAnalysisTask<alice3Efficiency>(ctx)};
103+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
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 alice3SeparationPower.cxx
13+
///
14+
/// \brief This task produces the separation power of the ALICE3 detector
15+
///
16+
/// \author Nicolò Jacazio, Universita del Piemonte Orientale (IT)
17+
/// \since May 13, 2025
18+
///
19+
20+
#include <utility>
21+
#include <map>
22+
#include <string>
23+
#include <vector>
24+
25+
#include "Framework/AnalysisDataModel.h"
26+
#include "Framework/AnalysisTask.h"
27+
#include "Framework/runDataProcessing.h"
28+
#include "Framework/RunningWorkflowInfo.h"
29+
#include "Framework/HistogramRegistry.h"
30+
#include "TProfile2D.h"
31+
#include "THashList.h"
32+
#include "ALICE3/DataModel/OTFTOF.h"
33+
#include "ALICE3/DataModel/OTFRICH.h"
34+
35+
using namespace o2;
36+
using namespace o2::framework;
37+
38+
std::array<TProfile2D*, 5> separationInnerTOF;
39+
std::array<TProfile2D*, 5> separationOuterTOF;
40+
std::array<TProfile2D*, 5> separationRICH;
41+
struct alice3SeparationPower {
42+
43+
ConfigurableAxis etaAxis{"etaAxis", {100, -1.f, 1.f}, "Binning in eta"};
44+
HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject};
45+
OutputObj<THashList> listSeparation{"separationPower"};
46+
void init(o2::framework::InitContext&)
47+
{
48+
listSeparation.setObject(new THashList);
49+
for (int i = 0; i < 5; i++) {
50+
auto createEfficiency = [&](const char* name, const char* title) {
51+
TProfile2D* eff = new TProfile2D(Form("%s_%d", name, i),
52+
Form("%s_%d;%s", title, i, "#it{p}_{T} (GeV/#it{c});#it{#eta}"),
53+
100, 0.f, 10.f,
54+
100, 0.f, 10.f);
55+
listSeparation->Add(eff);
56+
return eff;
57+
};
58+
separationInnerTOF[i] = createEfficiency("separationInnerTOF", "separationInnerTOF");
59+
separationOuterTOF[i] = createEfficiency("separationOuterTOF", "separationOuterTOF");
60+
separationRICH[i] = createEfficiency("separationRICH", "separationRICH");
61+
}
62+
}
63+
64+
void process(soa::Join<aod::Collisions, aod::McCollisionLabels>::iterator const& /*collision*/,
65+
soa::Join<aod::Tracks, aod::TracksCov, aod::McTrackLabels, aod::UpgradeTofMC, aod::UpgradeTof> const& tracks,
66+
aod::McParticles const&,
67+
aod::McCollisions const&)
68+
{
69+
for (const auto& track : tracks) {
70+
if (!track.has_mcParticle()) {
71+
continue;
72+
}
73+
// Check that all the nsigmas are numbers (sanity check)
74+
for (int i = 0; i < 5; i++) {
75+
if (std::isnan(track.nSigmaInnerTOF(i)) || std::isnan(track.nSigmaOuterTOF(i))) {
76+
LOG(fatal) << "Unrecognized nsigma for " << i << " " << track.nSigmaInnerTOF(i) << " " << track.nSigmaOuterTOF(i);
77+
}
78+
}
79+
80+
const auto& mcParticle = track.mcParticle();
81+
// Separation electron pion
82+
switch (std::abs(mcParticle.pdgCode())) {
83+
{
84+
case 211: // electron-pion separation
85+
separationInnerTOF[0]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(0));
86+
separationOuterTOF[0]->Fill(track.pt(), track.eta(), track.nSigmaOuterTOF(0));
87+
// separationRICH[0]->Fill(track.pt(), track.eta(), track.nSigmaElectronRich() );
88+
break;
89+
case 321: // pion-kaon separation
90+
separationInnerTOF[1]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(1));
91+
separationOuterTOF[1]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(1));
92+
// separationRICH[1]->Fill(track.pt(), track.eta(), track.nSigmaPionRich() );
93+
break;
94+
case 2212: // kaon-proton separation
95+
separationInnerTOF[2]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(2));
96+
separationOuterTOF[2]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(2));
97+
// separationRICH[2]->Fill((track.nSigmaKaonRich() > 3.f), track.pt(), track.eta());
98+
default:
99+
break;
100+
}
101+
}
102+
}
103+
}
104+
};
105+
106+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask<alice3SeparationPower>(cfgc)}; }

0 commit comments

Comments
 (0)