Project
Loading...
Searching...
No Matches
PID.cxx
Go to the documentation of this file.
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#define _USE_MATH_DEFINES
13
14#include <cmath>
15// for std::find
16#include <algorithm>
17
18// root includes
19#include "TStyle.h"
20#include "TFile.h"
21#include "TMathBase.h"
22#include "TObjArray.h"
23
24// o2 includes
27#include "TPCQC/PID.h"
28#include "TPCQC/Helpers.h"
29
31using namespace o2::tpc::qc;
32
33struct binning {
34 int bins;
35 double min;
36 double max;
37};
38
39constexpr std::array<float, 5> xks{90.f, 108.475f, 151.7f, 188.8f, 227.65f};
40const std::vector<std::string_view> rocNames{"TPC", "IROC", "OROC1", "OROC2", "OROC3"};
41const std::vector<int> nclCuts{60, 25, 14, 12, 10};
42const std::vector<int> nclMax{152, 63, 34, 30, 25};
43const int mipTot = 50;
44const int mipMax = 50;
45const binning binsdEdxMIPTot{100, mipTot / 3., mipTot * 3.};
46const binning binsdEdxMIPMax{100, mipMax / 3., mipMax * 3.};
47const int binsPerSector = 5;
48const binning binsSec{36 * binsPerSector, 0., 36.};
49const auto bins = o2::tpc::qc::helpers::makeLogBinning(200, 0.05, 20);
50const int binNumber = 200;
51const float binsdEdxTot_MaxValue = 6000.;
54
55//______________________________________________________________________________
56void PID::initializeHistograms()
57{
58 TH1::AddDirectory(false);
59 const auto& name = rocNames[0];
60 mMapHist["hdEdxTotVspPos"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxTotVsP_Pos_{}", name).data(), (fmt::format("Q_{{Tot}} positive particles {}", name) + ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), 200, bins.data(), binNumber, binsdEdxTot_Log.data()));
61 mMapHist["hdEdxTotVspNeg"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxTotVsP_Neg_{}", name).data(), (fmt::format("Q_{{Tot}} negative particles {}", name) + ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), 200, bins.data(), binNumber, binsdEdxTot_Log.data()));
62 mMapHist["hNClsPID"].emplace_back(std::make_unique<TH1F>("hNClsPID", "Number of clusters (after cuts); # of clusters; counts", 160, 0, 160));
63 mMapHist["hNClsSubPID"].emplace_back(std::make_unique<TH1F>("hNClsSubPID", "Number of clusters (after cuts); # of clusters; counts", 160, 0, 160));
64
65 mMapHist["hdEdxVsTgl"].emplace_back(std::make_unique<TH2F>("hdEdxVsTgl", "dEdx (a.u.) vs tan#lambda; tan#lambda; dEdx (a.u.)", 60, -2, 2, 300, 0, 300));
66
67 const auto logPtBinning = helpers::makeLogBinning(200, 0.05, 20);
68 if (logPtBinning.size() > 0) {
69 mMapHist["hdEdxTotVspBeforeCuts"].emplace_back(std::make_unique<TH2F>("hdEdxTotVspBeforeCuts", "dEdx (a.u.) vs p (GeV/#it{c}) (before cuts); p (GeV/#it{c}); dEdx (a.u.)", logPtBinning.size() - 1, logPtBinning.data(), binNumber, binsdEdxTot_Log.data()));
70 mMapHist["hdEdxMaxVspBeforeCuts"].emplace_back(std::make_unique<TH2F>("hdEdxMaxVspBeforeCuts", "dEdx_Max (a.u.) vs p (GeV/#it{c}) (before cuts); p (GeV/#it{c}); dEdx (a.u.)", logPtBinning.size() - 1, logPtBinning.data(), binNumber, binsdEdxMax_Log.data()));
71 }
72 if (!mTurnOffHistosForAsync) {
73 mMapHist["hdEdxVsPhiMipsAside"].emplace_back(std::make_unique<TH2F>("hdEdxVsPhiMipsAside", "dEdx (a.u.) vs #phi (rad) of MIPs (A side); #phi (rad); dEdx (a.u.)", 180, 0., 2 * M_PI, 25, 35, 60));
74 mMapHist["hdEdxVsPhiMipsCside"].emplace_back(std::make_unique<TH2F>("hdEdxVsPhiMipsCside", "dEdx (a.u.) vs #phi (rad) of MIPs (C side); #phi (rad); dEdx (a.u.)", 180, 0., 2 * M_PI, 25, 35, 60));
75 mMapHist["hdEdxVsPhi"].emplace_back(std::make_unique<TH2F>("hdEdxVsPhi", "dEdx (a.u.) vs #phi (rad); #phi (rad); dEdx (a.u.)", 180, 0., 2 * M_PI, 300, 0, 300));
76 mMapHist["hdEdxVsncls"].emplace_back(std::make_unique<TH2F>("hdEdxVsncls", "dEdx (a.u.) vs ncls; ncls; dEdx (a.u.)", 80, 0, 160, 300, 0, 300));
77 }
78
79 for (size_t idEdxType = 0; idEdxType < rocNames.size(); ++idEdxType) {
80 const auto& name = rocNames[idEdxType];
81 mMapHist["hdEdxTotVsp"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxTotVsP_{}", name).data(), (fmt::format("Q_{{Tot}} {}", name) + ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), 200, bins.data(), binNumber, binsdEdxTot_Log.data()));
82 mMapHist["hdEdxMaxVsp"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxMaxVsP_{}", name).data(), (fmt::format("Q_{{Max}} {}", name) + ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{Max} (arb. unit)").data(), 200, bins.data(), binNumber, binsdEdxMax_Log.data()));
83 mMapHist["hdEdxTotMIP"].emplace_back(std::make_unique<TH1F>(fmt::format("hdEdxTotMIP_{}", name).data(), (fmt::format("MIP Q_{{Tot}} {}", name) + ";d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), binsdEdxMIPTot.bins, binsdEdxMIPTot.min, binsdEdxMIPTot.max));
84 mMapHist["hdEdxMaxMIP"].emplace_back(std::make_unique<TH1F>(fmt::format("hdEdxMaxMIP_{}", name).data(), (fmt::format("MIP Q_{{Max}} {}", name) + ";d#it{E}/d#it{x}_{Max} (arb. unit)").data(), binsdEdxMIPMax.bins, binsdEdxMIPMax.min, binsdEdxMIPMax.max));
85 mMapHist["hdEdxTotMIPVsTgl"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxTotMIPVsTgl_{}", name).data(), (fmt::format("MIP Q_{{Tot}} {}", name) + ";#tan(#lambda);d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), 50, -2, 2, binsdEdxMIPTot.bins, binsdEdxMIPTot.min, binsdEdxMIPTot.max));
86 mMapHist["hdEdxMaxMIPVsTgl"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxMaxMIPVsTgl_{}", name).data(), (fmt::format("MIP Q_{{Max}} {}", name) + ";#tan(#lambda);d#it{E}/d#it{x}_{Max} (arb. unit)").data(), 50, -2, 2, binsdEdxMIPMax.bins, binsdEdxMIPMax.min, binsdEdxMIPMax.max));
87 mMapHist["hdEdxTotMIPVsSnp"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxTotMIPVsSnp_{}", name).data(), (fmt::format("MIP Q_{{Tot}} {}", name) + ";#sin(#phi);d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), 50, -1, 1, binsdEdxMIPTot.bins, binsdEdxMIPTot.min, binsdEdxMIPTot.max));
88 mMapHist["hdEdxMaxMIPVsSnp"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxMaxMIPVsSnp_{}", name).data(), (fmt::format("MIP Q_{{Max}} {}", name) + ";#sin(#phi);d#it{E}/d#it{x}_{Max} (arb. unit)").data(), 50, -1, 1, binsdEdxMIPMax.bins, binsdEdxMIPMax.min, binsdEdxMIPMax.max));
89 mMapHist["hdEdxTotMIPVsNcl"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxTotMIPVsNcl_{}", name).data(), (fmt::format("MIP Q_{{Tot}} {}", name) + ";N_{clusters};d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), nclMax[idEdxType] - nclCuts[idEdxType], nclCuts[idEdxType], nclMax[idEdxType], binsdEdxMIPTot.bins, binsdEdxMIPTot.min, binsdEdxMIPTot.max));
90 mMapHist["hdEdxMaxMIPVsNcl"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxMaxMIPVsNcl_{}", name).data(), (fmt::format("MIP Q_{{Max}} {}", name) + ";N_{clusters};d#it{E}/d#it{x}_{Max} (arb. unit)").data(), nclMax[idEdxType] - nclCuts[idEdxType], nclCuts[idEdxType], nclMax[idEdxType], binsdEdxMIPMax.bins, binsdEdxMIPMax.min, binsdEdxMIPMax.max));
91 mMapHist["hdEdxTotMIPVsSec"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxTotMIPVsSec_{}", name).data(), (fmt::format("MIP Q_{{Tot}} {}", name) + ";sector;d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), binsSec.bins, binsSec.min, binsSec.max, binsdEdxMIPTot.bins, binsdEdxMIPTot.min, binsdEdxMIPTot.max));
92 mMapHist["hdEdxMaxMIPVsSec"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxMaxMIPVsSec_{}", name).data(), (fmt::format("MIP Q_{{Max}} {}", name) + ";sector;d#it{E}/d#it{x}_{Max} (arb. unit)").data(), binsSec.bins, binsSec.min, binsSec.max, binsdEdxMIPMax.bins, binsdEdxMIPMax.min, binsdEdxMIPMax.max));
93 mMapHist["hMIPNclVsTgl"].emplace_back(std::make_unique<TH2F>(fmt::format("hMIPNclVsTgl_{}", name).data(), (fmt::format("rec. clusters {}", name) + ";#tan(#lambda); rec clusters").data(), 50, -2, 2, nclMax[idEdxType] - nclCuts[idEdxType], nclCuts[idEdxType], nclMax[idEdxType]));
94 mMapHist["hMIPNclVsTglSub"].emplace_back(std::make_unique<TH2F>(fmt::format("hMIPNclVsTglSub_{}", name).data(), (fmt::format("sub-thrs. clusters {}", name) + ";#tan(#lambda);sub-thrs. clusters").data(), 50, -2, 2, 20, 0, 20));
95 if (mGetdEdxVspHypoHist) {
96 mMapHist["hdEdxVspHypoPos"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxVspHypoPos_{}", name).data(), (fmt::format("Q_{{Tot}} Pos {}", name) + ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), 200, bins.data(), binNumber, binsdEdxTot_Log.data()));
97 mMapHist["hdEdxVspHypoNeg"].emplace_back(std::make_unique<TH2F>(fmt::format("hdEdxVspHypoNeg_{}", name).data(), (fmt::format("Q_{{Tot}} Neg {}", name) + ";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_{Tot} (arb. unit)").data(), 200, bins.data(), binNumber, binsdEdxTot_Log.data()));
98 }
99 }
100}
101
102//______________________________________________________________________________
103void PID::resetHistograms()
104{
105 for (const auto& pair : mMapHist) {
106 for (auto& hist : pair.second) {
107 hist->Reset();
108 }
109 }
110}
111
112//______________________________________________________________________________
113
114// dummy version to make it compatible with old QC version.
115bool PID::processTrack(const o2::tpc::TrackTPC& track)
116{
117 return true;
118}
119bool PID::processTrack(const o2::tpc::TrackTPC& track, size_t nTracks)
120{
121 // ===| variables required for cutting and filling |===
122 const auto& dEdx = track.getdEdx();
123 const auto absCharge = track.getAbsCharge();
124 const auto pTPC = (absCharge > 0) ? (track.getP() / absCharge) : track.getP(); // charge magnitude is divided getP() via getPtInv for pTPC/Z [fix for He3]
125 const auto tgl = track.getTgl();
126 const auto snp = track.getSnp();
127 const auto phi = track.getPhi();
128 const auto ncl = uint8_t(track.getNClusters());
129
130 const auto eta = track.getEta();
131 mMapHist["hdEdxTotVspBeforeCuts"][0]->Fill(pTPC, dEdx.dEdxTotTPC);
132 mMapHist["hdEdxMaxVspBeforeCuts"][0]->Fill(pTPC, dEdx.dEdxMaxTPC);
133
134 if (pTPC < mCutMinpTPC || pTPC > mCutMaxpTPC || ncl < mCutMinnCls) {
135 return true;
136 }
137
138 const std::vector<float> dEdxTot{dEdx.dEdxTotTPC, dEdx.dEdxTotIROC, dEdx.dEdxTotOROC1, dEdx.dEdxTotOROC2, dEdx.dEdxTotOROC3};
139 const std::vector<float> dEdxMax{dEdx.dEdxMaxTPC, dEdx.dEdxMaxIROC, dEdx.dEdxMaxOROC1, dEdx.dEdxMaxOROC2, dEdx.dEdxMaxOROC3};
140 const std::vector<uint8_t> dEdxNcl{static_cast<uint8_t>(dEdx.NHitsIROC + dEdx.NHitsOROC1 + dEdx.NHitsOROC2 + dEdx.NHitsOROC3), dEdx.NHitsIROC, dEdx.NHitsOROC1, dEdx.NHitsOROC2, dEdx.NHitsOROC3};
141 const std::vector<uint8_t> dEdxNclSub{static_cast<uint8_t>(dEdx.NHitsSubThresholdIROC + dEdx.NHitsSubThresholdOROC1 + dEdx.NHitsSubThresholdOROC2 + dEdx.NHitsSubThresholdOROC3 - (dEdx.NHitsIROC + dEdx.NHitsOROC1 + dEdx.NHitsOROC2 + dEdx.NHitsOROC3)), static_cast<uint8_t>(dEdx.NHitsSubThresholdIROC - dEdx.NHitsIROC), static_cast<uint8_t>(dEdx.NHitsSubThresholdOROC1 - dEdx.NHitsOROC1), static_cast<uint8_t>(dEdx.NHitsSubThresholdOROC2 - dEdx.NHitsOROC2), static_cast<uint8_t>(dEdx.NHitsSubThresholdOROC3 - dEdx.NHitsOROC3)};
142 mMapHist["hdEdxVsTgl"][0]->Fill(tgl, dEdxTot[0]);
143
144 if (dEdx.dEdxTotTPC <= 0.) {
145 return true;
146 }
147 if (std::abs(tgl) < mCutAbsTgl) {
148 if (!mTurnOffHistosForAsync) {
149 mMapHist["hdEdxVsPhi"][0]->Fill(phi, dEdxTot[0]);
150 mMapHist["hdEdxVsncls"][0]->Fill(ncl, dEdxTot[0]);
151 }
152 mMapHist["hNClsPID"][0]->Fill(dEdxNcl[0]);
153 mMapHist["hNClsSubPID"][0]->Fill(dEdxNclSub[0]);
154
155 if (track.getCharge() > 0) {
156 mMapHist["hdEdxTotVspPos"][0]->Fill(pTPC, dEdxTot[0]);
157 } else {
158 mMapHist["hdEdxTotVspNeg"][0]->Fill(pTPC, dEdxTot[0]);
159 }
160 }
161 for (size_t idEdxType = 0; idEdxType < rocNames.size(); ++idEdxType) {
162 bool ok = false;
163 float sec = 18.f * o2::math_utils::to02PiGen(track.getXYZGloAt(xks[idEdxType], 2, ok).Phi()) / o2::constants::math::TwoPI;
164 if (track.hasCSideClusters()) {
165 sec += 18.f;
166 }
167 if (!ok) {
168 sec = -1;
169 }
170
171 if (dEdxTot[idEdxType] < mCutMindEdxTot || dEdxTot[idEdxType] > binsdEdxTot_MaxValue || dEdxNcl[idEdxType] < nclCuts[idEdxType]) {
172 continue;
173 }
174 if (std::abs(tgl) < mCutAbsTgl) {
175 mMapHist["hdEdxTotVsp"][idEdxType]->Fill(pTPC, dEdxTot[idEdxType]);
176 mMapHist["hdEdxMaxVsp"][idEdxType]->Fill(pTPC, dEdxMax[idEdxType]);
177 if (mGetdEdxVspHypoHist) {
178 const auto pidHypothesis = track.getPID().getID();
179 if (pidHypothesis <= o2::track::PID::NIDs) {
180 auto pidHist = mMapHist[(track.getCharge() > 0) ? "hdEdxVspHypoPos" : "hdEdxVspHypoNeg"][idEdxType].get();
181 pidHist->SetBinContent(pidHist->GetXaxis()->FindBin(pTPC), pidHist->GetYaxis()->FindBin(dEdxTot[idEdxType]), pidHypothesis + 1);
182 }
183 }
184 }
185
186 // ===| cuts and histogram filling for MIPs |===
187 if (pTPC > mCutMinpTPCMIPs && pTPC < mCutMaxpTPCMIPs) {
188 mMapHist["hdEdxTotMIPVsTgl"][idEdxType]->Fill(tgl, dEdxTot[idEdxType]);
189 mMapHist["hdEdxMaxMIPVsTgl"][idEdxType]->Fill(tgl, dEdxMax[idEdxType]);
190
191 if (dEdxTot[idEdxType] < mCutMaxdEdxTot) {
192 mMapHist["hMIPNclVsTgl"][idEdxType]->Fill(tgl, dEdxNcl[idEdxType]);
193 mMapHist["hMIPNclVsTglSub"][idEdxType]->Fill(tgl, dEdxNclSub[idEdxType]);
194 }
195
196 if (std::abs(tgl) < mCutAbsTgl) {
197 if (!mTurnOffHistosForAsync) {
198 if (track.hasASideClustersOnly()) {
199 mMapHist["hdEdxVsPhiMipsAside"][0]->Fill(phi, dEdxTot[0]);
200 } else if (track.hasCSideClustersOnly()) {
201 mMapHist["hdEdxVsPhiMipsCside"][0]->Fill(phi, dEdxTot[0]);
202 }
203 }
204
205 mMapHist["hdEdxTotMIP"][idEdxType]->Fill(dEdxTot[idEdxType]);
206 mMapHist["hdEdxMaxMIP"][idEdxType]->Fill(dEdxMax[idEdxType]);
207
208 mMapHist["hdEdxTotMIPVsNcl"][idEdxType]->Fill(dEdxNcl[idEdxType], dEdxTot[idEdxType]);
209 mMapHist["hdEdxMaxMIPVsNcl"][idEdxType]->Fill(dEdxNcl[idEdxType], dEdxMax[idEdxType]);
210
211 mMapHist["hdEdxTotMIPVsSec"][idEdxType]->Fill(sec, dEdxTot[idEdxType]);
212 mMapHist["hdEdxMaxMIPVsSec"][idEdxType]->Fill(sec, dEdxMax[idEdxType]);
213
214 mMapHist["hdEdxTotMIPVsSnp"][idEdxType]->Fill(snp, dEdxTot[idEdxType]);
215 mMapHist["hdEdxMaxMIPVsSnp"][idEdxType]->Fill(snp, dEdxMax[idEdxType]);
216 }
217 }
218 }
219 return true;
220}
221
222//______________________________________________________________________________
223void PID::dumpToFile(const std::string filename)
224{
225 auto f = std::unique_ptr<TFile>(TFile::Open(filename.c_str(), "recreate"));
226 for (const auto& [name, histos] : mMapHist) {
227 TObjArray arr;
228 arr.SetName(name.data());
229 for (auto& hist : histos) {
230 arr.Add(hist.get());
231 }
232 arr.Write(arr.GetName(), TObject::kSingleKey);
233 }
234 f->Close();
235}
const binning binsdEdxMIPTot
Definition PID.cxx:45
const auto binsdEdxTot_Log
Definition PID.cxx:52
const int mipMax
Definition PID.cxx:44
constexpr std::array< float, 5 > xks
Definition PID.cxx:39
const float binsdEdxTot_MaxValue
Definition PID.cxx:51
const auto bins
Definition PID.cxx:49
const binning binsdEdxMIPMax
Definition PID.cxx:46
const int binNumber
Definition PID.cxx:50
const std::vector< int > nclMax
Definition PID.cxx:42
ClassImp(o2::tpc::qc::PID)
const std::vector< std::string_view > rocNames
Definition PID.cxx:40
const binning binsSec
Definition PID.cxx:48
const auto binsdEdxMax_Log
Definition PID.cxx:53
const int binsPerSector
Definition PID.cxx:47
const std::vector< int > nclCuts
Definition PID.cxx:41
const int mipTot
Definition PID.cxx:43
PID quality control class.
Definition PID.h:51
static constexpr ID NIDs
number of defined IDs
Definition PID.h:106
GLuint const GLchar * name
Definition glcorearb.h:781
GLdouble f
Definition glcorearb.h:310
GLboolean * data
Definition glcorearb.h:298
constexpr float TwoPI
float to02PiGen(float phi)
Definition Utils.h:70
std::vector< double > makeLogBinning(const int nbins, const double min, const double max)
get a vector containing binning info for constant sized bins on a log axis
Definition Helpers.cxx:22
std::string filename()
int bins
Definition PID.cxx:34
double max
Definition PID.cxx:36
double min
Definition PID.cxx:35