Project
Loading...
Searching...
No Matches
Draw.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#include "MCHEvaluation/Draw.h"
13#include <TCanvas.h>
14#include <TF1.h>
15#include <TFile.h>
16#include <TGraphErrors.h>
17#include <TH1.h>
18#include <TLegend.h>
19#include <TStyle.h>
20#include <fmt/format.h>
21#include <limits>
22#include <memory>
23#include <stdexcept>
24#include <utility>
25
26namespace
27{
28double CrystalBallSymmetric(double* xx, double* par)
29{
31
37
38 double tp = fabs((xx[0] - par[1]) / par[2]);
39
40 double absAlpha = fabs(par[3]);
41 double ap = pow(par[4] / absAlpha, par[4]) * exp(-0.5 * absAlpha * absAlpha);
42 double bp = par[4] / absAlpha - absAlpha;
43
44 if (tp < absAlpha) {
45 return par[0] * (exp(-0.5 * tp * tp)); // gaussian core
46 } else {
47 return par[0] * (ap / pow(bp + tp, par[4])); // left and right tails
48 }
49}
50
51std::pair<double, double> GetSigma(TH1* h, int color)
52{
54 gStyle->SetOptFit(100);
55
56 static TF1* fCrystalBall = new TF1("CrystalBall", CrystalBallSymmetric, -2., 2., 5);
57 fCrystalBall->SetLineColor(color);
58
59 if (h->GetEntries() < 10.) {
60 return std::make_pair(0., 0.);
61 }
62
63 double sigmaTrk = 0.2; // 2 mm
64 double sigmaTrkCut = 4.; // 4 sigma
65
66 // first fit
67 double xMin = -0.5 * sigmaTrkCut * sigmaTrk;
68 double xMax = 0.5 * sigmaTrkCut * sigmaTrk;
69 fCrystalBall->SetRange(xMin, xMax);
70 fCrystalBall->SetParameters(h->GetEntries(), 0., 0.1, 2., 1.5);
71 fCrystalBall->SetParLimits(1, xMin, xMax);
72 fCrystalBall->SetParLimits(2, 0., 1.);
73 fCrystalBall->FixParameter(3, 1.e6);
74 h->Fit(fCrystalBall, "RNQ");
75
76 // rebin histo
77 int rebin = 2;
78 h->Rebin(rebin);
79
80 // second fit
81 fCrystalBall->SetParameter(0, fCrystalBall->GetParameter(0) * rebin);
82 fCrystalBall->ReleaseParameter(3);
83 fCrystalBall->SetParameter(3, 2.);
84 fCrystalBall->SetParameter(4, 1.5);
85 h->Fit(fCrystalBall, "RQ");
86
87 return std::make_pair(fCrystalBall->GetParameter(2), fCrystalBall->GetParError(2));
88}
89} // namespace
90
91namespace o2::mch::eval
92
93{
94
95auto padGridSize(const std::vector<TH1*>& histos)
96{
97 // find the optimal number of pads
98 int nPadsx(1), nPadsy(1);
99 while ((int)histos.size() > nPadsx * nPadsy) {
100 if (nPadsx == nPadsy) {
101 ++nPadsx;
102 } else {
103 ++nPadsy;
104 }
105 }
106 return std::make_pair(nPadsx, nPadsy);
107}
108
109TCanvas* autoCanvas(const char* title, const char* name,
110 const std::vector<TH1*>& histos,
111 int* nPadsx, int* nPadsy)
112{
113 auto [nx, ny] = padGridSize(histos);
114 if (nPadsx) {
115 *nPadsx = nx;
116 }
117 if (nPadsy) {
118 *nPadsy = ny;
119 }
120 TCanvas* c = new TCanvas(name, title, 10, 10, TMath::Max(nx * 300, 1200), TMath::Max(ny * 300, 900));
121 c->Divide(nx, ny);
122 return c;
123}
124
125void drawTrackResiduals(std::vector<TH1*>& histos, TCanvas* c)
126{
128 gStyle->SetOptStat(111111);
129 int nPadsx = (histos.size() + 2) / 3;
130 if (!c) {
131 c = new TCanvas("residuals", "residuals", 10, 10, nPadsx * 300, 900);
132 }
133 c->Divide(nPadsx, 3);
134 int i(0);
135 for (const auto& h : histos) {
136 c->cd((i % 3) * nPadsx + i / 3 + 1);
137 if (dynamic_cast<TH1F*>(h) == nullptr) {
138 h->Draw("colz");
139 gPad->SetLogz();
140 } else {
141 h->Draw();
142 gPad->SetLogy();
143 }
144 ++i;
145 }
146}
147
148void drawClusterResiduals(const std::array<std::vector<TH1*>, 5>& histos, TCanvas* c)
149{
150 drawClusterClusterResiduals(histos[4], "ClCl", c);
151 drawClusterTrackResiduals(histos[0], histos[1], "AllTracks", c);
152 drawClusterTrackResidualsSigma(histos[0], histos[1], "AllTracks", nullptr, c);
153 drawClusterTrackResiduals(histos[2], histos[3], "SimilarTracks", c);
154 drawClusterTrackResidualsSigma(histos[2], histos[3], "SimilarTracks", nullptr, c);
155 drawClusterTrackResidualsRatio(histos[0], histos[1], "AllTracks", c);
156 drawClusterTrackResidualsRatio(histos[2], histos[3], "SimilarTracks", c);
157}
158
159void drawClusterClusterResiduals(const std::vector<TH1*>& histos, const char* extension, TCanvas* c)
160{
162 gStyle->SetOptStat(1);
163 int nPadsx = (histos.size() + 1) / 2;
164 if (!c) {
165 c = new TCanvas(Form("residual%s", extension), Form("residual%s", extension), 10, 10, nPadsx * 300, 600);
166 }
167 c->Divide(nPadsx, 2);
168 int i(0);
169 for (const auto& h : histos) {
170 c->cd((i % 2) * nPadsx + i / 2 + 1);
171 gPad->SetLogy();
172 h->Draw();
173 h->GetXaxis()->SetRangeUser(-0.02, 0.02);
174 ++i;
175 }
176}
177
178//_________________________________________________________________________________________________
179void drawClusterTrackResiduals(const std::vector<TH1*>& histos1,
180 const std::vector<TH1*>& histos2, const char* extension,
181 TCanvas* c)
182{
184 gStyle->SetOptStat(1);
185 int color[2] = {4, 2};
186 int nPadsx = (histos1.size() + 1) / 2;
187 if (!c) {
188 c = new TCanvas(Form("residual%s", extension), Form("residual%s", extension), 10, 10, nPadsx * 300, 600);
189 }
190 c->Divide(nPadsx, 2);
191 int i(0);
192 for (const auto& h : histos1) {
193 c->cd((i % 2) * nPadsx + i / 2 + 1);
194 gPad->SetLogy();
195 h->SetLineColor(color[0]);
196 h->Draw();
197 histos2[i]->SetLineColor(color[1]);
198 histos2[i]->Draw("sames");
199 ++i;
200 }
201 // add a legend
202 TLegend* lHist = new TLegend(0.2, 0.65, 0.4, 0.8);
203 lHist->SetFillStyle(0);
204 lHist->SetBorderSize(0);
205 lHist->AddEntry(histos1[0], "file 1", "l");
206 lHist->AddEntry(histos2[0], "file 2", "l");
207 c->cd(1);
208 lHist->Draw("same");
209}
210
211void drawClusterTrackResidualsSigma(const std::vector<TH1*>& histos1,
212 const std::vector<TH1*>& histos2, const char* extension,
213 TCanvas* c1, TCanvas* c2)
214{
216 gStyle->SetOptStat(1);
217
218 TGraphErrors* g[2][2] = {nullptr};
219 const char* dir[2] = {"X", "Y"};
220 int color[2] = {4, 2};
221 for (int i = 0; i < 2; ++i) {
222 for (int j = 0; j < 2; ++j) {
223 g[i][j] = new TGraphErrors(6);
224 g[i][j]->SetName(Form("sigma%s%s%d", dir[i], extension, j));
225 g[i][j]->SetTitle(Form("#sigma%s per station;station ID;#sigma%s (cm)", dir[i], dir[i]));
226 g[i][j]->SetMarkerStyle(kFullDotLarge);
227 g[i][j]->SetMarkerColor(color[j]);
228 g[i][j]->SetLineColor(color[j]);
229 }
230 }
231
232 int nPadsx = (histos1.size() + 1) / 2;
233 if (!c1) {
234 c1 = new TCanvas(Form("residual%sFit", extension), Form("residual%sFit", extension), 10, 10, nPadsx * 300, 600);
235 }
236 c1->Divide(nPadsx, 2);
237 int i(0);
238 double ymax[2] = {0., 0.};
239 double ymin[2] = {std::numeric_limits<double>::max(), std::numeric_limits<double>::max()};
240 for (auto h : histos1) {
241 c1->cd((i % 2) * nPadsx + i / 2 + 1);
242 gPad->SetLogy();
243 auto h1 = static_cast<TH1*>(h->Clone());
244 h1->SetLineColor(color[0]);
245 h1->Draw();
246 auto res1 = GetSigma(h1, color[0]);
247 g[i % 2][0]->SetPoint(i / 2, i * 1. / 2 + 1., res1.first);
248 g[i % 2][0]->SetPointError(i / 2, 0., res1.second);
249 ymin[i % 2] = std::min(ymin[i % 2], res1.first - res1.second - 0.001);
250 ymax[i % 2] = std::max(ymax[i % 2], res1.first + res1.second + 0.001);
251 auto h2 = static_cast<TH1*>(histos2[i]->Clone());
252 h2->SetLineColor(color[1]);
253 h2->Draw("sames");
254 auto res2 = GetSigma(h2, color[1]);
255 g[i % 2][1]->SetPoint(i / 2, i * 1. / 2 + 1., res2.first);
256 g[i % 2][1]->SetPointError(i / 2, 0., res2.second);
257 ymin[i % 2] = std::min(ymin[i % 2], res2.first - res2.second - 0.001);
258 ymax[i % 2] = std::max(ymax[i % 2], res2.first + res2.second + 0.001);
259 printf("%s: %f ± %f cm --> %f ± %f cm\n", h->GetName(), res1.first, res1.second, res2.first, res2.second);
260 ++i;
261 }
262
263 if (!c2) {
264 c2 = new TCanvas(Form("sigma%s", extension), Form("sigma%s", extension), 10, 10, 600, 300);
265 }
266 c2->Divide(2, 1);
267 c2->cd(1);
268 g[0][0]->Draw("ap");
269 g[0][0]->GetYaxis()->SetRangeUser(ymin[0], ymax[0]);
270 g[0][1]->Draw("p");
271 c2->cd(2);
272 g[1][0]->Draw("ap");
273 g[1][0]->GetYaxis()->SetRangeUser(ymin[1], ymax[1]);
274 g[1][1]->Draw("p");
275
276 // add a legend
277 TLegend* lHist = new TLegend(0.2, 0.65, 0.4, 0.8);
278 lHist->SetFillStyle(0);
279 lHist->SetBorderSize(0);
280 lHist->AddEntry(histos1[0], "file 1", "l");
281 lHist->AddEntry(histos2[0], "file 2", "l");
282 c1->cd(1);
283 lHist->Draw("same");
284}
285
286void drawPlainHistosAtVertex(const std::array<std::vector<TH1*>, 2>& histos, TCanvas* c)
287{
288 if (!c) {
289 c = autoCanvas("histos", "histos", histos[0]);
290 }
291
292 for (int i = 0; i < (int)histos[0].size(); ++i) {
293 c->cd(i + 1);
294 gPad->SetLogy();
295 histos[0][i]->SetStats(false);
296 histos[0][i]->SetLineColor(4);
297 histos[0][i]->Draw();
298 histos[1][i]->SetLineColor(2);
299 histos[1][i]->Draw("same");
300 }
301
302 // add a legend
303 TLegend* lHist = new TLegend(0.5, 0.65, 0.9, 0.8);
304 lHist->SetFillStyle(0);
305 lHist->SetBorderSize(0);
306 lHist->AddEntry(histos[0][0], Form("%g tracks in file 1", histos[0][0]->GetEntries()), "l");
307 lHist->AddEntry(histos[1][0], Form("%g tracks in file 2", histos[1][0]->GetEntries()), "l");
308 c->cd(1);
309 lHist->Draw("same");
310}
311
312void drawDiffHistosAtVertex(const std::array<std::vector<TH1*>, 2>& histos, TCanvas* c)
313{
314 if (!c) {
315 c = autoCanvas("differences", "histos2 - histos1", histos[0]);
316 }
317
318 // draw differences
319 for (int i = 0; i < (int)histos[0].size(); ++i) {
320 c->cd(i + 1);
321 TH1F* hDiff = static_cast<TH1F*>(histos[1][i]->Clone());
322 hDiff->Add(histos[0][i], -1.);
323 hDiff->SetStats(false);
324 hDiff->SetLineColor(2);
325 hDiff->Draw();
326 }
327}
328
329void drawClusterTrackResidualsRatio(const std::vector<TH1*>& histos1,
330 const std::vector<TH1*>& histos2,
331 const char* extension,
332 TCanvas* c)
333{
335
336 int nPadsx = (histos1.size() + 1) / 2;
337 if (!c) {
338 c = new TCanvas(Form("ratio%s", extension), Form("ratio%s", extension), 10, 10, nPadsx * 300, 600);
339 }
340 c->Divide(nPadsx, 2);
341 int i(0);
342 for (const auto& h : histos2) {
343 c->cd((i % 2) * nPadsx + i / 2 + 1);
344 TH1* hRat = new TH1F(*static_cast<TH1F*>(h));
345 hRat->Rebin(4);
346 auto h1 = static_cast<TH1F*>(histos1[i]->Clone());
347 h1->Rebin(4);
348 hRat->Divide(h1);
349 delete h1;
350 hRat->SetStats(false);
351 hRat->SetLineColor(2);
352 hRat->Draw();
353 hRat->GetXaxis()->SetRangeUser(-0.5, 0.5);
354 ++i;
355 }
356}
357
358void drawRatioHistosAtVertex(const std::array<std::vector<TH1*>, 2>& histos, TCanvas* c)
359{
360 // draw ratios
361 if (!c) {
362 c = autoCanvas("ratios", "histos2 / histos1", histos[0]);
363 }
364
365 for (int i = 0; i < (int)histos[0].size(); ++i) {
366 c->cd(i + 1);
367 TH1F* hRat = static_cast<TH1F*>(histos[1][i]->Clone());
368 hRat->Divide(histos[0][i]);
369 hRat->SetStats(false);
370 hRat->SetLineColor(2);
371 hRat->Draw();
372 }
373}
374
375void drawHistosAtVertex(const std::array<std::vector<TH1*>, 2>& histos,
376 TCanvas* c)
377{
379
380 drawPlainHistosAtVertex(histos, c);
381 drawDiffHistosAtVertex(histos, c);
382 drawRatioHistosAtVertex(histos, c);
383}
384
385void drawComparisonsAtVertex(const std::array<std::vector<TH1*>, 5> histos, TCanvas* c)
386{
388
389 if (!c) {
390 c = autoCanvas("comparisons", "comparisons", histos[0]);
391 }
392 for (int i = 0; i < (int)histos[0].size(); ++i) {
393 c->cd(i + 1);
394 gPad->SetLogy();
395 histos[0][i]->SetStats(false);
396 histos[0][i]->SetLineColor(1);
397 histos[0][i]->SetMinimum(0.5);
398 histos[0][i]->Draw();
399 histos[1][i]->SetLineColor(4);
400 histos[1][i]->Draw("same");
401 histos[2][i]->SetLineColor(877);
402 histos[2][i]->Draw("same");
403 histos[3][i]->SetLineColor(3);
404 histos[3][i]->Draw("same");
405 histos[4][i]->SetLineColor(2);
406 histos[4][i]->Draw("same");
407 }
408
409 // add a legend
410 TLegend* lHist = new TLegend(0.5, 0.5, 0.9, 0.8);
411 lHist->SetFillStyle(0);
412 lHist->SetBorderSize(0);
413 lHist->AddEntry(histos[0][0], Form("%g tracks identical", histos[0][0]->GetEntries()), "l");
414 lHist->AddEntry(histos[1][0], Form("%g tracks similar (1)", histos[1][0]->GetEntries()), "l");
415 lHist->AddEntry(histos[2][0], Form("%g tracks similar (2)", histos[2][0]->GetEntries()), "l");
416 lHist->AddEntry(histos[3][0], Form("%g tracks additional", histos[3][0]->GetEntries()), "l");
417 lHist->AddEntry(histos[4][0], Form("%g tracks missing", histos[4][0]->GetEntries()), "l");
418 c->cd(1);
419 lHist->Draw("same");
420}
421
422void drawAll(const char* filename)
423{
424 TFile* f = TFile::Open(filename);
425
426 f->ls();
427
428 std::vector<TH1*>* trackResidualsAtFirstCluster = reinterpret_cast<std::vector<TH1*>*>(f->GetObjectUnchecked("trackResidualsAtFirstCluster"));
429 if (trackResidualsAtFirstCluster) {
430 drawTrackResiduals(*trackResidualsAtFirstCluster);
431 } else {
432 std::cerr << "could not read trackResidualsAtFirstCluster vector of histogram from file\n";
433 }
434
435 std::array<std::vector<TH1*>, 5>* clusterResiduals = reinterpret_cast<std::array<std::vector<TH1*>, 5>*>(f->GetObjectUnchecked("clusterResiduals"));
436 drawClusterResiduals(*clusterResiduals);
437
438 std::array<std::vector<TH1*>, 2>* histosAtVertex = reinterpret_cast<std::array<std::vector<TH1*>, 2>*>(f->GetObjectUnchecked("histosAtVertex"));
439 drawHistosAtVertex(*histosAtVertex);
440
441 std::array<std::vector<TH1*>, 5>* comparisonsAtVertex = reinterpret_cast<std::array<std::vector<TH1*>, 5>*>(f->GetObjectUnchecked("comparisonsAtVertex"));
442 drawComparisonsAtVertex(*comparisonsAtVertex);
443}
444} // namespace o2::mch::eval
uint64_t exp(uint64_t base, uint8_t exp) noexcept
int32_t i
bool const GPUTPCGMMerger::trackCluster * c1
bool const GPUTPCGMMerger::trackCluster const clcomparestruct * c2
uint32_t j
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
Class for time synchronization of RawReader instances.
GLsizeiptr size
Definition glcorearb.h:659
GLuint color
Definition glcorearb.h:1272
GLuint const GLchar * name
Definition glcorearb.h:781
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean g
Definition glcorearb.h:1233
void drawAll(const char *filename)
Definition Draw.cxx:422
void drawPlainHistosAtVertex(const std::array< std::vector< TH1 * >, 2 > &histos, TCanvas *c=nullptr)
Definition Draw.cxx:286
void drawClusterTrackResidualsSigma(const std::vector< TH1 * > &histos1, const std::vector< TH1 * > &histos2, const char *extension, TCanvas *c1=nullptr, TCanvas *c2=nullptr)
Definition Draw.cxx:211
void drawClusterClusterResiduals(const std::vector< TH1 * > &histos, const char *extension, TCanvas *c=nullptr)
Definition Draw.cxx:159
void drawClusterTrackResidualsRatio(const std::vector< TH1 * > &histos1, const std::vector< TH1 * > &histos2, const char *extension, TCanvas *c=nullptr)
Definition Draw.cxx:329
auto padGridSize(const std::vector< TH1 * > &histos)
Definition Draw.cxx:95
void drawRatioHistosAtVertex(const std::array< std::vector< TH1 * >, 2 > &histos, TCanvas *c=nullptr)
Definition Draw.cxx:358
void drawDiffHistosAtVertex(const std::array< std::vector< TH1 * >, 2 > &histos, TCanvas *c=nullptr)
Definition Draw.cxx:312
void drawTrackResiduals(std::vector< TH1 * > &histos, TCanvas *c=nullptr)
Definition Draw.cxx:125
TCanvas * autoCanvas(const char *title, const char *name, const std::vector< TH1 * > &histos, int *nPadsx=nullptr, int *nPadsy=nullptr)
Definition Draw.cxx:109
void drawClusterTrackResiduals(const std::vector< TH1 * > &histos1, const std::vector< TH1 * > &histos2, const char *extension, TCanvas *c=nullptr)
Definition Draw.cxx:179
void drawClusterResiduals(const std::array< std::vector< TH1 * >, 5 > &histos, TCanvas *c=nullptr)
Definition Draw.cxx:148
void drawComparisonsAtVertex(const std::array< std::vector< TH1 * >, 5 > histos, TCanvas *c=nullptr)
Definition Draw.cxx:385
void drawHistosAtVertex(const std::array< std::vector< TH1 * >, 2 > &histos, TCanvas *c=nullptr)
Definition Draw.cxx:375
std::string filename()