Skip to content

Commit 6f41c51

Browse files
authored
PID: Merge split tasks into one configurable (#5475)
- This commit create all split tables for TPC and TOF PID response in the split tasks - The filling of the split PID tables is done based on the configuration recieved by the task - Empty tables are sent for mass hypotheses that are not requested - The creation of several tasks is now avoided because of the large memory consumption overhead that was shown in the past - Uniformized PID tasks
1 parent 3a3a4c4 commit 6f41c51

File tree

7 files changed

+367
-376
lines changed

7 files changed

+367
-376
lines changed

Analysis/DataModel/include/AnalysisDataModel/PID/PIDTPC.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,24 +39,24 @@ class ELoss
3939
~ELoss() = default;
4040

4141
/// Gets the expected signal of the measurement
42-
float GetExpectedSignal(DetectorResponse& response, const Coll& col, const Trck& trk) const;
42+
float GetExpectedSignal(const DetectorResponse& response, const Coll& col, const Trck& trk) const;
4343

4444
/// Gets the expected resolution of the measurement
45-
float GetExpectedSigma(DetectorResponse& response, const Coll& col, const Trck& trk) const;
45+
float GetExpectedSigma(const DetectorResponse& response, const Coll& col, const Trck& trk) const;
4646

4747
/// Gets the number of sigmas with respect the expected value
48-
float GetSeparation(DetectorResponse& response, const Coll& col, const Trck& trk) const { return (trk.tpcSignal() - GetExpectedSignal(response, col, trk)) / GetExpectedSigma(response, col, trk); }
48+
float GetSeparation(const DetectorResponse& response, const Coll& col, const Trck& trk) const { return (trk.tpcSignal() - GetExpectedSignal(response, col, trk)) / GetExpectedSigma(response, col, trk); }
4949
};
5050

5151
template <typename Coll, typename Trck, o2::track::PID::ID id>
52-
float ELoss<Coll, Trck, id>::GetExpectedSignal(DetectorResponse& response, const Coll& col, const Trck& trk) const
52+
float ELoss<Coll, Trck, id>::GetExpectedSignal(const DetectorResponse& response, const Coll& col, const Trck& trk) const
5353
{
5454
const float x[2] = {trk.tpcInnerParam() / o2::track::PID::getMass(id), (float)o2::track::PID::getCharge(id)};
5555
return response(DetectorResponse::kSignal, x);
5656
}
5757

5858
template <typename Coll, typename Trck, o2::track::PID::ID id>
59-
float ELoss<Coll, Trck, id>::GetExpectedSigma(DetectorResponse& response, const Coll& col, const Trck& trk) const
59+
float ELoss<Coll, Trck, id>::GetExpectedSigma(const DetectorResponse& response, const Coll& col, const Trck& trk) const
6060
{
6161
const float x[2] = {trk.tpcSignal(), (float)trk.tpcNClsFound()};
6262
return response(DetectorResponse::kSigma, x);

Analysis/Tasks/pidTOF.cxx

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions)
3737
struct pidTOFTask {
3838
using Trks = soa::Join<aod::Tracks, aod::TracksExtra>;
3939
using Coll = aod::Collisions;
40-
Produces<aod::pidRespTOF> tofpid;
41-
DetectorResponse resp;
40+
Produces<aod::pidRespTOF> tablePID;
41+
DetectorResponse response;
4242
Service<o2::ccdb::BasicCCDBManager> ccdb;
4343
Configurable<std::string> paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"};
4444
Configurable<std::string> sigmaname{"param-sigma", "TOFReso", "Name of the parametrization for the expected sigma, used in both file and CCDB mode"};
@@ -55,80 +55,83 @@ struct pidTOFTask {
5555
ccdb->setCreatedNotAfter(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
5656
//
5757
const std::vector<float> p = {0.008, 0.008, 0.002, 40.0};
58-
resp.SetParameters(DetectorResponse::kSigma, p);
58+
response.SetParameters(DetectorResponse::kSigma, p);
5959
const std::string fname = paramfile.value;
6060
if (!fname.empty()) { // Loading the parametrization from file
61-
resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma);
61+
response.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma);
6262
} else { // Loading it from CCDB
6363
const std::string path = "Analysis/PID/TOF";
64-
resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value));
64+
response.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value));
6565
}
6666
}
6767

68+
template <o2::track::PID::ID pid>
69+
using ResponseImplementation = tof::ExpTimes<Coll::iterator, Trks::iterator, pid>;
6870
void process(Coll const& collisions, Trks const& tracks)
6971
{
70-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Electron> resp_Electron = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Electron>();
71-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Muon> resp_Muon = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Muon>();
72-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Pion> resp_Pion = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Pion>();
73-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Kaon> resp_Kaon = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Kaon>();
74-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Proton> resp_Proton = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Proton>();
75-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Deuteron> resp_Deuteron = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Deuteron>();
76-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Triton> resp_Triton = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Triton>();
77-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Helium3> resp_Helium3 = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Helium3>();
78-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Alpha> resp_Alpha = tof::ExpTimes<Coll::iterator, Trks::iterator, PID::Alpha>();
79-
80-
tofpid.reserve(tracks.size());
72+
constexpr auto responseEl = ResponseImplementation<PID::Electron>();
73+
constexpr auto responseMu = ResponseImplementation<PID::Muon>();
74+
constexpr auto responsePi = ResponseImplementation<PID::Pion>();
75+
constexpr auto responseKa = ResponseImplementation<PID::Kaon>();
76+
constexpr auto responsePr = ResponseImplementation<PID::Proton>();
77+
constexpr auto responseDe = ResponseImplementation<PID::Deuteron>();
78+
constexpr auto responseTr = ResponseImplementation<PID::Triton>();
79+
constexpr auto responseHe = ResponseImplementation<PID::Helium3>();
80+
constexpr auto responseAl = ResponseImplementation<PID::Alpha>();
81+
82+
tablePID.reserve(tracks.size());
8183
for (auto const& trk : tracks) {
82-
tofpid(resp_Electron.GetExpectedSigma(resp, trk.collision(), trk),
83-
resp_Muon.GetExpectedSigma(resp, trk.collision(), trk),
84-
resp_Pion.GetExpectedSigma(resp, trk.collision(), trk),
85-
resp_Kaon.GetExpectedSigma(resp, trk.collision(), trk),
86-
resp_Proton.GetExpectedSigma(resp, trk.collision(), trk),
87-
resp_Deuteron.GetExpectedSigma(resp, trk.collision(), trk),
88-
resp_Triton.GetExpectedSigma(resp, trk.collision(), trk),
89-
resp_Helium3.GetExpectedSigma(resp, trk.collision(), trk),
90-
resp_Alpha.GetExpectedSigma(resp, trk.collision(), trk),
91-
resp_Electron.GetSeparation(resp, trk.collision(), trk),
92-
resp_Muon.GetSeparation(resp, trk.collision(), trk),
93-
resp_Pion.GetSeparation(resp, trk.collision(), trk),
94-
resp_Kaon.GetSeparation(resp, trk.collision(), trk),
95-
resp_Proton.GetSeparation(resp, trk.collision(), trk),
96-
resp_Deuteron.GetSeparation(resp, trk.collision(), trk),
97-
resp_Triton.GetSeparation(resp, trk.collision(), trk),
98-
resp_Helium3.GetSeparation(resp, trk.collision(), trk),
99-
resp_Alpha.GetSeparation(resp, trk.collision(), trk));
84+
tablePID(responseEl.GetExpectedSigma(response, trk.collision(), trk),
85+
responseMu.GetExpectedSigma(response, trk.collision(), trk),
86+
responsePi.GetExpectedSigma(response, trk.collision(), trk),
87+
responseKa.GetExpectedSigma(response, trk.collision(), trk),
88+
responsePr.GetExpectedSigma(response, trk.collision(), trk),
89+
responseDe.GetExpectedSigma(response, trk.collision(), trk),
90+
responseTr.GetExpectedSigma(response, trk.collision(), trk),
91+
responseHe.GetExpectedSigma(response, trk.collision(), trk),
92+
responseAl.GetExpectedSigma(response, trk.collision(), trk),
93+
responseEl.GetSeparation(response, trk.collision(), trk),
94+
responseMu.GetSeparation(response, trk.collision(), trk),
95+
responsePi.GetSeparation(response, trk.collision(), trk),
96+
responseKa.GetSeparation(response, trk.collision(), trk),
97+
responsePr.GetSeparation(response, trk.collision(), trk),
98+
responseDe.GetSeparation(response, trk.collision(), trk),
99+
responseTr.GetSeparation(response, trk.collision(), trk),
100+
responseHe.GetSeparation(response, trk.collision(), trk),
101+
responseAl.GetSeparation(response, trk.collision(), trk));
100102
}
101103
}
102104
};
103105

104106
struct pidTOFTaskBeta {
105107
using Trks = soa::Join<aod::Tracks, aod::TracksExtra>;
106108
using Coll = aod::Collision;
107-
Produces<aod::pidRespTOFbeta> tofpidbeta;
108-
tof::Beta<Coll, Trks::iterator, PID::Electron> resp_Electron;
109+
Produces<aod::pidRespTOFbeta> tablePIDBeta;
110+
tof::Beta<Coll, Trks::iterator, PID::Electron> responseElectron;
109111
Configurable<float> expreso{"tof-expreso", 80, "Expected resolution for the computation of the expected beta"};
110112

111113
void init(o2::framework::InitContext&)
112114
{
113-
resp_Electron.mExpectedResolution = expreso.value;
115+
responseElectron.mExpectedResolution = expreso.value;
114116
}
115117

116118
void process(Coll const& collision, Trks const& tracks)
117119
{
118-
tofpidbeta.reserve(tracks.size());
120+
tablePIDBeta.reserve(tracks.size());
119121
for (auto const& trk : tracks) {
120-
tofpidbeta(resp_Electron.GetBeta(collision, trk),
121-
resp_Electron.GetExpectedSigma(collision, trk),
122-
resp_Electron.GetExpectedSignal(collision, trk),
123-
resp_Electron.GetExpectedSigma(collision, trk),
124-
resp_Electron.GetSeparation(collision, trk));
122+
tablePIDBeta(responseElectron.GetBeta(collision, trk),
123+
responseElectron.GetExpectedSigma(collision, trk),
124+
responseElectron.GetExpectedSignal(collision, trk),
125+
responseElectron.GetExpectedSigma(collision, trk),
126+
responseElectron.GetSeparation(collision, trk));
125127
}
126128
}
127129
};
128130

129131
struct pidTOFTaskQA {
130132

131133
static constexpr int Np = 9;
134+
static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"};
132135
static constexpr std::string_view hexpected[Np] = {"expected/El", "expected/Mu", "expected/Pi",
133136
"expected/Ka", "expected/Pr", "expected/De",
134137
"expected/Tr", "expected/He", "expected/Al"};
@@ -138,7 +141,6 @@ struct pidTOFTaskQA {
138141
static constexpr std::string_view hnsigma[Np] = {"nsigma/El", "nsigma/Mu", "nsigma/Pi",
139142
"nsigma/Ka", "nsigma/Pr", "nsigma/De",
140143
"nsigma/Tr", "nsigma/He", "nsigma/Al"};
141-
static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"};
142144
HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject};
143145

144146
Configurable<int> nBinsP{"nBinsP", 400, "Number of bins for the momentum"};

Analysis/Tasks/pidTOF_split.cxx

Lines changed: 66 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@
88
// granted to it by virtue of its status as an Intergovernmental Organization
99
// or submit itself to any jurisdiction.
1010

11+
///
12+
/// \file pidTOF_split.cxx
13+
/// \author Nicolo' Jacazio
14+
/// \brief Task to produce PID tables for TOF split for each particle.
15+
/// Only the tables for the mass hypotheses requested are filled, the others are sent empty.
16+
///
17+
1118
// O2 includes
1219
#include "Framework/AnalysisTask.h"
1320
#include "Framework/AnalysisDataModel.h"
1421
#include "Framework/ASoAHelpers.h"
1522
#include "Framework/HistogramRegistry.h"
23+
#include "Framework/runDataProcessing.h"
1624
#include "ReconstructionDataFormats/Track.h"
1725
#include <CCDB/BasicCCDBManager.h>
1826
#include "AnalysisDataModel/PID/PIDResponse.h"
@@ -24,29 +32,36 @@ using namespace o2::pid;
2432
using namespace o2::framework::expressions;
2533
using namespace o2::track;
2634

27-
void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions)
28-
{
29-
std::vector<ConfigParamSpec> options{
30-
{"pid-el", VariantType::Int, 1, {"Produce PID information for the electron mass hypothesis"}},
31-
{"pid-mu", VariantType::Int, 1, {"Produce PID information for the muon mass hypothesis"}},
32-
{"pid-pikapr", VariantType::Int, 1, {"Produce PID information for the Pion, Kaon, Proton mass hypothesis"}},
33-
{"pid-nuclei", VariantType::Int, 1, {"Produce PID information for the Deuteron, Triton, Alpha mass hypothesis"}}};
34-
std::swap(workflowOptions, options);
35-
}
36-
37-
#include "Framework/runDataProcessing.h"
38-
39-
template <o2::track::PID::ID pid_type, typename table>
40-
struct pidTOFTaskPerParticle {
35+
struct pidTOFTaskSplit {
4136
using Trks = soa::Join<aod::Tracks, aod::TracksExtra>;
4237
using Coll = aod::Collisions;
43-
Produces<table> tofpid;
44-
DetectorResponse resp;
38+
// Tables to produce
39+
Produces<o2::aod::pidRespTOFEl> tablePIDEl;
40+
Produces<o2::aod::pidRespTOFMu> tablePIDMu;
41+
Produces<o2::aod::pidRespTOFPi> tablePIDPi;
42+
Produces<o2::aod::pidRespTOFKa> tablePIDKa;
43+
Produces<o2::aod::pidRespTOFPr> tablePIDPr;
44+
Produces<o2::aod::pidRespTOFDe> tablePIDDe;
45+
Produces<o2::aod::pidRespTOFTr> tablePIDTr;
46+
Produces<o2::aod::pidRespTOFHe> tablePIDHe;
47+
Produces<o2::aod::pidRespTOFAl> tablePIDAl;
48+
// Detector response and input parameters
49+
DetectorResponse response;
4550
Service<o2::ccdb::BasicCCDBManager> ccdb;
4651
Configurable<std::string> paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"};
4752
Configurable<std::string> sigmaname{"param-sigma", "TOFReso", "Name of the parametrization for the expected sigma, used in both file and CCDB mode"};
4853
Configurable<std::string> url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"};
4954
Configurable<long> timestamp{"ccdb-timestamp", -1, "timestamp of the object"};
55+
// Configuration flags to include and exclude particle hypotheses
56+
Configurable<int> pidEl{"pid-el", 0, {"Produce PID information for the Electron mass hypothesis"}};
57+
Configurable<int> pidMu{"pid-mu", 0, {"Produce PID information for the Muon mass hypothesis"}};
58+
Configurable<int> pidPi{"pid-pi", 0, {"Produce PID information for the Pion mass hypothesis"}};
59+
Configurable<int> pidKa{"pid-ka", 0, {"Produce PID information for the Kaon mass hypothesis"}};
60+
Configurable<int> pidPr{"pid-pr", 0, {"Produce PID information for the Proton mass hypothesis"}};
61+
Configurable<int> pidDe{"pid-de", 0, {"Produce PID information for the Deuterons mass hypothesis"}};
62+
Configurable<int> pidTr{"pid-tr", 0, {"Produce PID information for the Triton mass hypothesis"}};
63+
Configurable<int> pidHe{"pid-he", 0, {"Produce PID information for the Helium3 mass hypothesis"}};
64+
Configurable<int> pidAl{"pid-al", 0, {"Produce PID information for the Alpha mass hypothesis"}};
5065

5166
void init(o2::framework::InitContext&)
5267
{
@@ -58,47 +73,54 @@ struct pidTOFTaskPerParticle {
5873
ccdb->setCreatedNotAfter(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
5974
//
6075
const std::vector<float> p = {0.008, 0.008, 0.002, 40.0};
61-
resp.SetParameters(DetectorResponse::kSigma, p);
76+
response.SetParameters(DetectorResponse::kSigma, p);
6277
const std::string fname = paramfile.value;
6378
if (!fname.empty()) { // Loading the parametrization from file
64-
resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma);
79+
response.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma);
6580
} else { // Loading it from CCDB
6681
const std::string path = "Analysis/PID/TOF";
67-
resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value));
82+
response.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp<Parametrization>(path + "/" + sigmaname.value, timestamp.value));
6883
}
6984
}
7085

86+
template <o2::track::PID::ID pid>
87+
using ResponseImplementation = tof::ExpTimes<Coll::iterator, Trks::iterator, pid>;
7188
void process(Coll const& collisions, Trks const& tracks)
7289
{
73-
constexpr tof::ExpTimes<Coll::iterator, Trks::iterator, pid_type> resp_PID = tof::ExpTimes<Coll::iterator, Trks::iterator, pid_type>();
90+
constexpr auto responseEl = ResponseImplementation<PID::Electron>();
91+
constexpr auto responseMu = ResponseImplementation<PID::Muon>();
92+
constexpr auto responsePi = ResponseImplementation<PID::Pion>();
93+
constexpr auto responseKa = ResponseImplementation<PID::Kaon>();
94+
constexpr auto responsePr = ResponseImplementation<PID::Proton>();
95+
constexpr auto responseDe = ResponseImplementation<PID::Deuteron>();
96+
constexpr auto responseTr = ResponseImplementation<PID::Triton>();
97+
constexpr auto responseHe = ResponseImplementation<PID::Helium3>();
98+
constexpr auto responseAl = ResponseImplementation<PID::Alpha>();
7499

75-
tofpid.reserve(tracks.size());
76-
for (auto const& trk : tracks) {
77-
tofpid(resp_PID.GetExpectedSigma(resp, trk.collision(), trk),
78-
resp_PID.GetSeparation(resp, trk.collision(), trk));
79-
}
100+
// Check and fill enabled tables
101+
auto makeTable = [&tracks](const Configurable<int>& flag, auto& table, const DetectorResponse& response, const auto& responsePID) {
102+
if (flag.value) {
103+
// Prepare memory for enabled tables
104+
table.reserve(tracks.size());
105+
for (auto const& trk : tracks) { // Loop on Tracks
106+
table(responsePID.GetExpectedSigma(response, trk.collision(), trk),
107+
responsePID.GetSeparation(response, trk.collision(), trk));
108+
}
109+
}
110+
};
111+
makeTable(pidEl, tablePIDEl, response, responseEl);
112+
makeTable(pidMu, tablePIDMu, response, responseMu);
113+
makeTable(pidPi, tablePIDPi, response, responsePi);
114+
makeTable(pidKa, tablePIDKa, response, responseKa);
115+
makeTable(pidPr, tablePIDPr, response, responsePr);
116+
makeTable(pidDe, tablePIDDe, response, responseDe);
117+
makeTable(pidTr, tablePIDTr, response, responseTr);
118+
makeTable(pidHe, tablePIDHe, response, responseHe);
119+
makeTable(pidAl, tablePIDAl, response, responseAl);
80120
}
81121
};
82122

83123
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
84124
{
85-
WorkflowSpec workflow;
86-
if (cfgc.options().get<int>("pid-el")) {
87-
workflow.push_back(adaptAnalysisTask<pidTOFTaskPerParticle<PID::Electron, o2::aod::pidRespTOFEl>>("pidTOFEl-task"));
88-
}
89-
if (cfgc.options().get<int>("pid-mu")) {
90-
workflow.push_back(adaptAnalysisTask<pidTOFTaskPerParticle<PID::Muon, o2::aod::pidRespTOFMu>>("pidTOFMu-task"));
91-
}
92-
if (cfgc.options().get<int>("pid-pikapr")) {
93-
workflow.push_back(adaptAnalysisTask<pidTOFTaskPerParticle<PID::Pion, o2::aod::pidRespTOFPi>>("pidTOFPi-task"));
94-
workflow.push_back(adaptAnalysisTask<pidTOFTaskPerParticle<PID::Kaon, o2::aod::pidRespTOFKa>>("pidTOFKa-task"));
95-
workflow.push_back(adaptAnalysisTask<pidTOFTaskPerParticle<PID::Proton, o2::aod::pidRespTOFPr>>("pidTOFPr-task"));
96-
}
97-
if (cfgc.options().get<int>("pid-nuclei")) {
98-
workflow.push_back(adaptAnalysisTask<pidTOFTaskPerParticle<PID::Deuteron, o2::aod::pidRespTOFDe>>("pidTOFDe-task"));
99-
workflow.push_back(adaptAnalysisTask<pidTOFTaskPerParticle<PID::Triton, o2::aod::pidRespTOFTr>>("pidTOFTr-task"));
100-
workflow.push_back(adaptAnalysisTask<pidTOFTaskPerParticle<PID::Helium3, o2::aod::pidRespTOFHe>>("pidTOFHe-task"));
101-
workflow.push_back(adaptAnalysisTask<pidTOFTaskPerParticle<PID::Alpha, o2::aod::pidRespTOFAl>>("pidTOFAl-task"));
102-
}
103-
return workflow;
125+
return WorkflowSpec{adaptAnalysisTask<pidTOFTaskSplit>("pidTOF-split-task")};
104126
}

0 commit comments

Comments
 (0)