Project
Loading...
Searching...
No Matches
Painter.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 <string>
13#include <algorithm>
14#include <fmt/core.h>
15#include <fmt/format.h>
16#include <cmath>
17
18#include "TAxis.h"
19#include "TMultiGraph.h"
20#include "TGraphErrors.h"
21#include "TTree.h"
22#include "TH1.h"
23#include "TH2.h"
24#include "TH3.h"
25#include "TH2Poly.h"
26#include "TProfile2D.h"
27#include "TCanvas.h"
28#include "TLine.h"
29#include "TLatex.h"
30#include "TStyle.h"
31#include "TPaveText.h"
32#include "TPaletteAxis.h"
33#include "TObjArray.h"
34#include "TMath.h"
35
38#include "DataFormatsTPC/Defs.h"
39#include "TPCBase/ROC.h"
40#include "TPCBase/Sector.h"
41#include "TPCBase/Mapper.h"
42#include "TPCBase/CalDet.h"
43#include "TPCBase/CalArray.h"
46#include "TPCBase/Utils.h"
48
49// for conversion CalDet to TH3
50#include <deque>
51#include <boost/geometry.hpp>
52#include <boost/geometry/geometries/point_xy.hpp>
53#include <boost/geometry/geometries/polygon.hpp>
54#include <string_view>
55#include "MathUtils/Utils.h"
56
57using namespace o2::tpc;
58
59std::array<int, 6> painter::colors = {EColor::kBlack, EColor::kRed + 1, EColor::kOrange + 2, EColor::kGreen + 2, EColor::kBlue + 1, EColor::kMagenta + 1};
60std::array<int, 10> painter::markers = {20, 21, 33, 34, 47, 24, 25, 27, 28, 46};
61
62std::vector<painter::PadCoordinates> painter::getPadCoordinatesSector()
63{
64 std::vector<painter::PadCoordinates> padCoords;
65
66 const auto& regInf = Mapper::instance().getMapPadRegionInfo();
67
68 for (const auto& padReg : regInf) {
69 const auto npr = padReg.getNumberOfPadRows();
70 const auto ro = padReg.getRowOffset();
71 const auto xm = padReg.getXhelper();
72 const auto ph = padReg.getPadHeight();
73 const auto pw = padReg.getPadWidth();
74 const auto yro = padReg.getRadiusFirstRow();
75 const auto ks = ph / pw * std::tan(1.74532925199432948e-01);
76
77 for (int irow = 0; irow < npr; ++irow) {
78 const auto npads = std::floor(ks * (irow + ro) + xm);
79 for (int ipad = -npads; ipad < npads; ++ipad) {
80 const auto xPadBottomRight = yro + ph * irow;
81 const auto xPadTopRight = yro + ph * (irow + 1);
82 const auto ri = xPadBottomRight;
83 const auto yPadBottomRight = pw * ipad * xPadBottomRight / (ri + ph / 2);
84 const auto yPadTopRight = pw * ipad * xPadTopRight / (ri + ph / 2);
85 const auto yPadBottomLeft = pw * (ipad + 1) * xPadBottomRight / (ri + ph / 2);
86 const auto yPadTopLeft = pw * (ipad + 1) * xPadTopRight / (ri + ph / 2);
87 auto& padCoord = padCoords.emplace_back();
88 padCoord.xVals = {xPadBottomRight, xPadTopRight, xPadTopRight, xPadBottomRight};
89 padCoord.yVals = {yPadBottomRight, yPadTopRight, yPadTopLeft, yPadBottomLeft};
90 }
91 }
92 }
93
94 return padCoords;
95}
96
97std::vector<painter::PadCoordinates> painter::getStackCoordinatesSector()
98{
99 std::vector<painter::PadCoordinates> padCoords;
100 const auto& regInf = Mapper::instance().getMapPadRegionInfo();
101
102 std::vector<GEMstack> stacks;
103 stacks.reserve(CRU::CRUperSector);
104 for (int cru = 0; cru < CRU::CRUperSector; ++cru) {
105 stacks.emplace_back(CRU(cru).gemStack());
106 }
107
108 for (int stack = 0; stack < GEMSTACKSPERSECTOR; ++stack) {
109 auto& padCoord = padCoords.emplace_back();
110 padCoord.xVals.resize(0);
111 padCoord.yVals.resize(0);
112
113 const GEMstack currentStack = static_cast<GEMstack>(stack);
114 const auto first = std::find(stacks.cbegin(), stacks.cend(), currentStack);
115 const auto last = std::find(stacks.crbegin(), stacks.crend(), currentStack);
116 const int firstRegion = std::distance(stacks.cbegin(), first);
117 const int lastRegion = (stacks.size() - std::distance(stacks.crbegin(), last) - 1);
118
119 for (int region = firstRegion; region <= lastRegion; ++region) {
120 const auto& padReg = regInf[region];
121 const auto npr = padReg.getNumberOfPadRows();
122 const auto ro = padReg.getRowOffset();
123 const auto xm = padReg.getXhelper();
124 const auto ph = padReg.getPadHeight();
125 const auto pw = padReg.getPadWidth();
126 const auto yro = padReg.getRadiusFirstRow();
127 const auto ks = ph / pw * std::tan(1.74532925199432948e-01);
128
129 for (int irow = 0; irow < npr; ++irow) {
130 const auto npads = std::floor(ks * (irow + ro) + xm);
131 const int ipad = -npads;
132 const auto xPadBottomRight = yro + ph * irow;
133 const auto xPadTopRight = yro + ph * (irow + 1);
134 const auto ri = xPadBottomRight;
135 const auto yPadBottomRight = pw * ipad * xPadBottomRight / (ri + ph / 2);
136 const auto yPadTopRight = pw * ipad * xPadTopRight / (ri + ph / 2);
137 const auto yPadBottomLeft = pw * (ipad + 1) * xPadBottomRight / (ri + ph / 2);
138 const auto yPadTopLeft = pw * (ipad + 1) * xPadTopRight / (ri + ph / 2);
139 padCoord.xVals.emplace_back(xPadBottomRight);
140 padCoord.yVals.emplace_back(yPadBottomRight);
141 padCoord.xVals.emplace_back(xPadTopRight);
142 padCoord.yVals.emplace_back(yPadTopRight);
143 }
144 }
145 // mirror coordinates
146 for (int i = padCoord.xVals.size() - 1; i >= 0; i--) {
147 padCoord.xVals.emplace_back(padCoord.xVals[i]);
148 padCoord.yVals.emplace_back(std::abs(padCoord.yVals[i]));
149 }
150 }
151 return padCoords;
152}
153
154std::vector<painter::PadCoordinates> painter::getFECCoordinatesSector()
155{
156 std::vector<painter::PadCoordinates> padCoords;
157 const Mapper& mapper = Mapper::instance();
158 const auto& regInf = mapper.getMapPadRegionInfo();
159
160 for (int stack = 0; stack < 5; ++stack) {
161 const int regionStart = 2 * stack;
162 const int regionEnd = regionStart + 2;
163
164 struct fecInf {
165 void addPad(int pad, int row) { pad_map[row].emplace_back(pad); }
166 const std::vector<int>& getPads(const int row) { return pad_map[row]; }
167 std::unordered_map<int, std::vector<int>> pad_map;
168 };
169
170 std::unordered_map<size_t, std::array<fecInf, 2>> fecs;
171 for (int region = regionStart; region < regionEnd; ++region) {
172 for (unsigned int lrow = 0; lrow < Mapper::ROWSPERREGION[region]; ++lrow) {
173 for (unsigned int pad = 0; pad < Mapper::PADSPERROW[region][lrow]; ++pad) {
174 const FECInfo& fec = mapper.fecInfo(Mapper::getGlobalPadNumber(lrow, pad, region));
175 const size_t fecIndex = fec.getIndex();
176 fecs[fecIndex][region - regionStart].addPad(pad, lrow);
177 }
178 }
179 }
180
181 for (auto& fec : fecs) {
182 auto& padCoord = padCoords.emplace_back();
183 padCoord.xVals.resize(0);
184 padCoord.yVals.resize(0);
185 for (int j = 0; j < 2; ++j) {
186 for (int regionTmp = regionStart; regionTmp < regionEnd; ++regionTmp) {
187 const int region = (j == 0) ? regionTmp : (regionStart + regionEnd - regionTmp - 1);
188 const auto& padReg = regInf[region];
189 const auto npr = padReg.getNumberOfPadRows();
190 const auto ro = padReg.getRowOffset();
191 const auto xm = padReg.getXhelper();
192 const auto ph = padReg.getPadHeight();
193 const auto pw = padReg.getPadWidth();
194 const auto yro = padReg.getRadiusFirstRow();
195 const auto ks = ph / pw * std::tan(1.74532925199432948e-01);
196
197 for (int irowTmp = 0; irowTmp < npr; ++irowTmp) {
198 const int irow = (j == 0) ? irowTmp : (npr - irowTmp - 1);
199 const auto npads = std::floor(ks * (irow + ro) + xm);
200 const std::vector<int>& padsFEC = fec.second[region - regionStart].getPads(irow);
201 const int padOff = (j == 0) ? padsFEC.front() : (padsFEC.back() + 1);
202 const int ipad = -npads + padOff;
203 const auto xPadBottomRight = yro + ph * irow;
204 const auto xPadTopRight = yro + ph * (irow + 1);
205 const auto ri = xPadBottomRight;
206 const auto yPadBottomRight = pw * ipad * xPadBottomRight / (ri + ph / 2);
207 const auto yPadTopRight = pw * ipad * xPadTopRight / (ri + ph / 2);
208 const auto yPadBottomLeft = pw * (ipad + 1) * xPadBottomRight / (ri + ph / 2);
209 const auto yPadTopLeft = pw * (ipad + 1) * xPadTopRight / (ri + ph / 2);
210 if (j == 0) {
211 padCoord.xVals.emplace_back(xPadBottomRight);
212 padCoord.yVals.emplace_back(yPadBottomRight);
213 padCoord.xVals.emplace_back(xPadTopRight);
214 padCoord.yVals.emplace_back(yPadTopRight);
215 } else {
216 padCoord.yVals.emplace_back(yPadTopRight);
217 padCoord.xVals.emplace_back(xPadTopRight);
218 padCoord.yVals.emplace_back(yPadBottomRight);
219 padCoord.xVals.emplace_back(xPadBottomRight);
220 }
221 }
222 }
223 }
224 }
225 }
226 return padCoords;
227}
228
229std::vector<painter::PadCoordinates> painter::getSCDY2XCoordinatesSector(std::string binningStr)
230{
231 const float deadZone = 1.5;
232 const float secPhi = 20.0 * TMath::DegToRad();
233 std::vector<painter::PadCoordinates> padCoords;
234 const Mapper& mapper = Mapper::instance();
235 const auto nPadRows = Mapper::PADROWS;
236 std::vector<float> maxY2X(nPadRows);
237 auto binCenters = o2::RangeTokenizer::tokenize<float>(binningStr);
238 size_t nY2XBins = 20;
239 std::vector<float> halfBinWidth;
240
241 auto setUniformBinning = [&binCenters, &halfBinWidth](int nY2XBins) {
242 binCenters.resize(nY2XBins);
243 halfBinWidth.resize(nY2XBins);
244 for (int i = 0; i < nY2XBins; ++i) {
245 const auto binWidth = 2.f / nY2XBins;
246 halfBinWidth[i] = binWidth / 2.f;
247 binCenters[i] = -1.f + (i + 0.5f) * binWidth;
248 }
249 };
250
251 if (binCenters.size() == 0) {
252 LOGP(info, "Empty binning provided, will use default uniform y/x binning with {} bins", nY2XBins);
253 setUniformBinning(nY2XBins);
254 } else if (binCenters.size() == 1) {
255 nY2XBins = static_cast<int>(binCenters.at(0));
256 LOGP(info, "Setting uniform binning for y/x with {} bins", nY2XBins);
257 setUniformBinning(nY2XBins);
258 } else {
259 nY2XBins = binCenters.size() - 1;
260 if (std::abs(binCenters[0] + 1.f) > 1e-6 || std::abs(binCenters[nY2XBins] - 1.f) > 1e-6) {
261 LOG(error) << "Provided binning for y/x not in range -1 to 1: " << binCenters[0] << " - " << binCenters[nY2XBins] << ". Using default uniform binning with " << nY2XBins << " bins";
262 setUniformBinning(nY2XBins);
263 } else {
264 LOGP(info, "Setting custom binning for y/x with {} bins", nY2XBins);
265 halfBinWidth.reserve(nY2XBins);
266 halfBinWidth.clear();
267 for (int i = 0; i < nY2XBins; ++i) {
268 halfBinWidth.push_back(.5f * (binCenters[i + 1] - binCenters[i]));
269 binCenters[i] = .5f * (binCenters[i] + binCenters[i + 1]);
270 }
271 binCenters.resize(nY2XBins);
272 }
273 }
274
275 for (int irow = 0; irow < nPadRows; ++irow) {
276 const auto x = mapper.getPadCentre(PadPos(irow, 0)).X();
277 maxY2X[irow] = std::tan(.5f * secPhi) - deadZone / x;
278 const auto region = Mapper::REGION[irow];
279 const auto ph = mapper.getPadRegionInfo(region).getPadHeight();
280 const auto xPadBottom = x - ph / 2;
281 const auto xPadTop = x + ph / 2;
282 for (int iy2x = 0; iy2x < nY2XBins; ++iy2x) {
283 auto& padCoord = padCoords.emplace_back();
284 float yPadRight = 0;
285 if (iy2x == 0) {
286 yPadRight = maxY2X[irow] * (binCenters[iy2x] - halfBinWidth[iy2x]);
287 } else {
288 yPadRight = maxY2X[irow] * (binCenters[iy2x - 1] + halfBinWidth[iy2x - 1]);
289 }
290 const auto yPadLeft = maxY2X[irow] * (binCenters[iy2x] + halfBinWidth[iy2x]);
291 padCoord.xVals = {xPadBottom, xPadTop, xPadTop, xPadBottom};
292 padCoord.yVals = {yPadRight * xPadBottom, yPadRight * xPadTop, yPadLeft * xPadTop, yPadLeft * xPadBottom};
293 }
294 }
295
296 return padCoords;
297}
298
299std::vector<o2::tpc::painter::PadCoordinates> painter::getCoordinates(const Type type, std::string binningStr)
300{
301 if (type == Type::Pad) {
303 } else if (type == Type::Stack) {
305 } else if (type == Type::FEC) {
307 } else if (type == Type::SCD) {
308 return painter::getSCDY2XCoordinatesSector(binningStr);
309 } else {
310 LOGP(warning, "Wrong Type provided!");
311 return std::vector<o2::tpc::painter::PadCoordinates>();
312 }
313}
314
315std::vector<double> painter::getRowBinningCM(uint32_t roc)
316{
317 const Mapper& mapper = Mapper::instance();
318
319 int firstRegion = 0, lastRegion = 10;
320 if (roc < 36) {
321 firstRegion = 0;
322 lastRegion = 4;
323 } else if (roc < 72) {
324 firstRegion = 4;
325 lastRegion = 10;
326 }
327
328 std::vector<double> binning;
329
330 float lastPadHeight = mapper.getPadRegionInfo(firstRegion).getPadHeight();
331 float localX = mapper.getPadRegionInfo(firstRegion).getRadiusFirstRow();
332 binning.emplace_back(localX - 3);
333 binning.emplace_back(localX);
334 for (int iregion = firstRegion; iregion < lastRegion; ++iregion) {
335 const auto& regionInfo = mapper.getPadRegionInfo(iregion);
336 const auto padHeight = regionInfo.getPadHeight();
337
338 if (std::abs(padHeight - lastPadHeight) > 1e-5) {
339 lastPadHeight = padHeight;
340 localX = regionInfo.getRadiusFirstRow();
341 binning.emplace_back(localX);
342 }
343
344 for (int irow = 0; irow < regionInfo.getNumberOfPadRows(); ++irow) {
345 localX += lastPadHeight;
346 binning.emplace_back(localX);
347 }
348 }
349 binning.emplace_back(localX + 3);
350
351 return binning;
352}
353
354std::string painter::getROCTitle(const int rocNumber)
355{
356 const std::string_view type = (rocNumber < 36) ? "IROC" : "OROC";
357 const std::string_view side = ((rocNumber % 36) < 18) ? "A" : "C";
358 return fmt::format("{} {}{:02}", type, side, rocNumber % 18);
359}
360
361template <class T>
362TCanvas* painter::draw(const CalDet<T>& calDet, int nbins1D, float xMin1D, float xMax1D, TCanvas* outputCanvas)
363{
364 using DetType = CalDet<T>;
365 using CalType = CalArray<T>;
366
367 const Mapper& mapper = Mapper::instance();
368
369 const bool draw1D = nbins1D > 0;
370
371 // ===| name and title |======================================================
372 std::string title = calDet.getName();
373 std::string name = calDet.getName();
374 std::replace(name.begin(), name.end(), ' ', '_');
375 std::replace(title.begin(), title.end(), '_', ' ');
376
377 // ===| define histograms |===================================================
378 // TODO: auto scaling of ranges based on mean and variance?
379 // for the moment use roots auto scaling
380
381 // set buffer size such that autoscaling uses the full range. This is about 2MB per histogram!
382 const int bufferSize = TH1::GetDefaultBufferSize();
383 TH1::SetDefaultBufferSize(Sector::MAXSECTOR * mapper.getPadsInSector());
384
385 auto hAside1D = draw1D ? new TH1F(fmt::format("h_Aside_1D_{}", name).data(), fmt::format("{0} (A-Side);{0}", title).data(),
386 nbins1D, xMin1D, xMax1D)
387 : nullptr; // TODO: modify ranges
388
389 auto hCside1D = draw1D ? new TH1F(fmt::format("h_Cside_1D_{}", name).data(), fmt::format("{0} (C-Side);{0}", title).data(),
390 nbins1D, xMin1D, xMax1D)
391 : nullptr; // TODO: modify ranges
392
393 auto hAside2D = new TH2F(fmt::format("h_Aside_2D_{}", name).data(), fmt::format("{0} (A-Side);#it{{x}} (cm);#it{{y}} (cm);{0}", title).data(),
394 330, -270, 270, 330, -270, 270);
395
396 auto hCside2D = new TH2F(fmt::format("h_Cside_2D_{}", name).data(), fmt::format("{0} (C-Side);#it{{x}} (cm);#it{{y}} (cm);{0}", title).data(),
397 330, -270, 270, 330, -270, 270);
398
399 for (ROC roc; !roc.looped(); ++roc) {
400
401 auto hist2D = hAside2D;
402 auto hist1D = hAside1D;
403 if (roc.side() == Side::C) {
404 hist2D = hCside2D;
405 hist1D = hCside1D;
406 }
407
408 const int nrows = mapper.getNumberOfRowsROC(roc);
409 for (int irow = 0; irow < nrows; ++irow) {
410 const int npads = mapper.getNumberOfPadsInRowROC(roc, irow);
411 for (int ipad = 0; ipad < npads; ++ipad) {
412 const auto val = calDet.getValue(roc, irow, ipad);
413 const GlobalPosition2D pos = mapper.getPadCentre(PadROCPos(roc, irow, ipad));
414 const int bin = hist2D->FindBin(pos.X(), pos.Y());
415 if (!hist2D->GetBinContent(bin)) {
416 hist2D->SetBinContent(bin, double(val));
417 }
418 if (draw1D) {
419 hist1D->Fill(double(val));
420 }
421 }
422 }
423 }
424
425 if (xMax1D > xMin1D) {
426 hAside2D->SetMinimum(xMin1D);
427 hAside2D->SetMaximum(xMax1D);
428 hCside2D->SetMinimum(xMin1D);
429 hCside2D->SetMaximum(xMax1D);
430 }
431
432 // ===| Draw histograms |=====================================================
433 gStyle->SetOptStat("mr");
434 auto c = outputCanvas;
435 if (!c) {
436 c = new TCanvas(fmt::format("c_{}", name).data(), title.data(), 1000, draw1D ? 1000 : 500);
437 }
438 gStyle->SetStatX(1. - gPad->GetRightMargin());
439 gStyle->SetStatY(1. - gPad->GetTopMargin());
440
441 c->Clear();
442 c->Divide(2, draw1D ? 2 : 1);
443
444 c->cd(1);
445 hAside2D->Draw("colz");
446 hAside2D->SetStats(0);
447 hAside2D->SetTitleOffset(1.05, "XY");
448 hAside2D->SetTitleSize(0.05, "XY");
449 adjustPalette(hAside2D, 0.92);
451
452 c->cd(2);
453 hCside2D->Draw("colz");
454 hCside2D->SetStats(0);
455 hCside2D->SetTitleOffset(1.05, "XY");
456 hCside2D->SetTitleSize(0.05, "XY");
457 adjustPalette(hCside2D, 0.92);
459
460 if (draw1D) {
461 c->cd(3);
462 hAside1D->Draw();
463
464 c->cd(4);
465 hCside1D->Draw();
466
467 // associate histograms to canvas
468 hAside1D->SetBit(TObject::kCanDelete);
469 hCside1D->SetBit(TObject::kCanDelete);
470 }
471
472 // reset the buffer size
473 TH1::SetDefaultBufferSize(bufferSize);
474
475 // associate histograms to canvas
476 hAside2D->SetBit(TObject::kCanDelete);
477 hCside2D->SetBit(TObject::kCanDelete);
478
479 return c;
480}
481
482//______________________________________________________________________________
483template <class T>
484TCanvas* painter::draw(const CalArray<T>& calArray)
485{
486 auto hist = getHistogram2D(calArray);
487 std::string name = hist->GetName();
488 name[0] = 'c';
489 auto c = new TCanvas(fmt::format("c_{}", name).data(), hist->GetTitle());
490
491 hist->Draw("colz");
492
493 // associate histograms to canvas
494 hist->SetBit(TObject::kCanDelete);
495
496 return c;
497}
498
499//______________________________________________________________________________
500template <class T>
501void painter::fillHistogram2D(TH2& h2D, const CalDet<T>& calDet, Side side)
502{
503 const Mapper& mapper = Mapper::instance();
504
505 for (ROC roc; !roc.looped(); ++roc) {
506 if (roc.side() != side) {
507 continue;
508 }
509
510 const int nrows = mapper.getNumberOfRowsROC(roc);
511 for (int irow = 0; irow < nrows; ++irow) {
512 const int npads = mapper.getNumberOfPadsInRowROC(roc, irow);
513 for (int ipad = 0; ipad < npads; ++ipad) {
514 const auto val = calDet.getValue(roc, irow, ipad);
515 const GlobalPosition2D pos = mapper.getPadCentre(PadROCPos(roc, irow, ipad));
516 const int bin = h2D.FindBin(pos.X(), pos.Y());
517 if (!h2D.GetBinContent(bin)) {
518 h2D.SetBinContent(bin, double(val));
519 }
520 }
521 }
522 }
523}
524
525//______________________________________________________________________________
526template <class T>
527void painter::fillHistogram2D(TH2& h2D, const CalArray<T>& calArray)
528{
529 const Mapper& mapper = Mapper::instance();
530
531 const size_t position = calArray.getPadSubsetNumber();
532 const PadSubset padSubset = calArray.getPadSubset();
533 const int nrows = mapper.getNumberOfPadRows(padSubset, position);
534
535 // ===| fill hist |===========================================================
536 for (int irow = 0; irow < nrows; ++irow) {
537 const int padsInRow = mapper.getNumberOfPadsInRow(padSubset, position, irow);
538 for (int ipad = 0; ipad < padsInRow; ++ipad) {
539 const GlobalPadNumber pad = mapper.getPadNumber(padSubset, position, irow, ipad);
540 const auto val = calArray.getValue(pad);
541 const int cpad = ipad - padsInRow / 2;
542 h2D.Fill(irow, cpad, double(val));
543 }
544 }
545}
546
547//______________________________________________________________________________
548template <class T>
549TH2* painter::getHistogram2D(const CalDet<T>& calDet, Side side)
550{
551 std::string title = calDet.getName();
552 std::string name = calDet.getName();
553 std::replace(name.begin(), name.end(), ' ', '_');
554 std::replace(title.begin(), title.end(), '_', ' ');
555 const char side_name = (side == Side::A) ? 'A' : 'C';
556
557 auto h2D = new TH2F(fmt::format("h_{}side_2D_{}", side_name, name).data(),
558 fmt::format("{} ({}-Side);x (cm);y (cm)", title, side_name).data(),
559 300, -300, 300, 300, -300, 300);
560
561 fillHistogram2D(*h2D, calDet, side);
562
563 return h2D;
564}
565
566//______________________________________________________________________________
567template <class T>
568TH2* painter::getHistogram2D(const CalArray<T>& calArray)
569{
570 const Mapper& mapper = Mapper::instance();
571
572 const size_t position = calArray.getPadSubsetNumber();
573 const PadSubset padSubset = calArray.getPadSubset();
574
575 // ===| maximum number of rows and pads |=====================================
576 const int nrows = mapper.getNumberOfPadRows(padSubset, position);
577 const int npads = mapper.getNumberOfPadsInRow(padSubset, position, nrows - 1) + 6;
578
579 // ===| create histogram |====================================================
580 std::string title = calArray.getName();
581 std::string name = calArray.getName();
582 std::replace(title.begin(), title.end(), '_', ' ');
583 std::replace(name.begin(), name.end(), ' ', '_');
584
585 if (padSubset == PadSubset::ROC) {
586 title += fmt::format(" ({})", getROCTitle(position));
587 }
588
589 auto hist = new TH2F(fmt::format("h_{}", name).data(),
590 fmt::format("{};pad row;pad", title).data(),
591 nrows, 0., nrows,
592 npads, -npads / 2., npads / 2.);
593
594 fillHistogram2D(*hist, calArray);
595
596 return hist;
597}
598
599template <typename T>
600std::enable_if_t<std::is_signed<T>::value, bool> hasData(const CalArray<T>& cal)
601{
602 return std::abs(cal.getSum()) > T{0};
603}
604
605template <typename T>
606std::enable_if_t<std::is_unsigned<T>::value, bool> hasData(const CalArray<T>& cal)
607{
608 return cal.getSum() > T{0};
609}
610
611template <typename T>
612std::enable_if_t<std::is_enum<T>::value, bool> hasData(const CalArray<T>& cal)
613{
614 for (const auto v : cal.getData()) {
615 if (int(v) > 0) {
616 return true;
617 }
618 }
619 return false;
620}
621
622template <class T>
623std::vector<TCanvas*> painter::makeSummaryCanvases(const CalDet<T>& calDet, int nbins1D, float xMin1D, float xMax1D, bool onlyFilled, std::vector<TCanvas*>* outputCanvases)
624{
625
626 std::vector<TCanvas*> vecCanvases;
627
628 auto nROCs = calDet.getData().size();
629
630 if (onlyFilled) {
631 nROCs = 0;
632 for (size_t iroc = 0; iroc < calDet.getData().size(); ++iroc) {
633 const auto& roc = calDet.getCalArray(iroc);
634
635 if (hasData(roc)) {
636 ++nROCs;
637 }
638 }
639
640 if (!nROCs) {
641 return vecCanvases;
642 }
643 }
644
645 // ===| set up canvases |===
646 TCanvas* cSides = nullptr;
647 TCanvas* cROCs1D = nullptr;
648 TCanvas* cROCs2D = nullptr;
649 const std::string_view calName = calDet.getName();
650
651 if (outputCanvases) {
652 if (outputCanvases->size() < 3) {
653 LOGP(error, "At least 3 canvases are needed to fill the output, only {} given", outputCanvases->size());
654 return vecCanvases;
655 }
656
657 cSides = outputCanvases->at(0);
658 cROCs1D = outputCanvases->at(1);
659 cROCs2D = outputCanvases->at(2);
660 cSides->Clear();
661 cROCs1D->Clear();
662 cROCs2D->Clear();
663 } else {
664
665 cROCs1D = new TCanvas(fmt::format("c_ROCs_{}_1D", calName).data(), fmt::format("{} values for each ROC", calName).data(), 1400, 1000);
666 cROCs2D = new TCanvas(fmt::format("c_ROCs_{}_2D", calName).data(), fmt::format("{} values for each ROC", calName).data(), 1400, 1000);
667 }
668 cSides = draw(calDet, nbins1D, xMin1D, xMax1D, cSides);
669 cROCs1D->DivideSquare(nROCs);
670 cROCs2D->DivideSquare(nROCs);
671
672 vecCanvases.emplace_back(cSides);
673 vecCanvases.emplace_back(cROCs1D);
674 vecCanvases.emplace_back(cROCs2D);
675
676 // ===| produce plots for each ROC |===
677 size_t pad = 1;
678 for (size_t iroc = 0; iroc < calDet.getData().size(); ++iroc) {
679 const auto& roc = calDet.getCalArray(iroc);
680
681 if (onlyFilled && !hasData(roc)) {
682 continue;
683 }
684
685 // ===| 1D histogram |===
686 auto h1D = new TH1F(fmt::format("h1_{}_{:02d}", calName, iroc).data(), fmt::format("{} distribution ROC {:02d} ({});ADC value", calName, iroc, getROCTitle(iroc)).data(), nbins1D, xMin1D, xMax1D);
687 for (const auto& val : roc.getData()) {
688 h1D->Fill(double(val));
689 }
690
691 // ===| 2D histogram |===
692 auto h2D = painter::getHistogram2D(roc);
693 h2D->SetStats(0);
694 if (xMax1D > xMin1D) {
695 h2D->SetMinimum(xMin1D);
696 h2D->SetMaximum(xMax1D);
697 }
698 h2D->SetUniqueID(iroc);
699
700 cROCs1D->cd(pad);
701 h1D->Draw();
702
703 cROCs2D->cd(pad);
704 h2D->Draw("colz");
705
706 ++pad;
707
708 // associate histograms to canvas
709 h1D->SetBit(TObject::kCanDelete);
710 h2D->SetBit(TObject::kCanDelete);
711 }
712
713 return vecCanvases;
714}
715
716std::vector<TCanvas*> o2::tpc::painter::makeSummaryCanvases(TTree& tree, const std::string_view draw, std::string_view cut, int nbins1D, float xMin1D, float xMax1D)
717{
718 const Mapper& mapper = Mapper::instance();
719
720 std::vector<TCanvas*> vecCanvases;
721
722 // ===| name and title |======================================================
723 std::string title = draw.data();
724 std::string name = title;
725 std::replace(name.begin(), name.end(), ' ', '_');
726 std::replace(name.begin(), name.end(), '/', '_');
727 const std::string_view calName = name;
728
729 // ===| Per ROC histograms |===
730 if (nbins1D > 0) {
731 const size_t nROCs = 72;
732 auto cROCs1D = new TCanvas(fmt::format("c_ROCs_{}_1D", calName).data(), fmt::format("{} values for each ROC", calName).data(), 1400, 1000);
733 auto cROCs2D = new TCanvas(fmt::format("c_ROCs_{}_2D", calName).data(), fmt::format("{} values for each ROC", calName).data(), 1400, 1000);
734
735 cROCs1D->DivideSquare(nROCs);
736 cROCs2D->DivideSquare(nROCs);
737
738 vecCanvases.emplace_back(cROCs1D);
739 vecCanvases.emplace_back(cROCs2D);
740
741 // ===| produce plots for each ROC |===
742 size_t pad = 1;
743 for (size_t iroc = 0; iroc < nROCs; ++iroc) {
744
745 // ===| 1D histogram |===
746 auto h1D = new TH1F(fmt::format("h1_{}_{:02d}", calName, iroc).data(), fmt::format("{} distribution ROC {:02d} ({});{}", calName, iroc, getROCTitle(iroc), draw).data(), nbins1D, xMin1D, xMax1D);
747 tree.Draw(fmt::format("{} >> {}", draw, h1D->GetName()).data(), fmt::format("(roc == {}) && ({})", iroc, cut).data(), "goff");
748
749 // ===| 2D histogram |===
750 const int nrows = mapper.getNumberOfPadRows(PadSubset::ROC, iroc);
751 const int npads = mapper.getNumberOfPadsInRow(PadSubset::ROC, iroc, nrows - 1) + 6;
752
753 // ===| create histogram |====================================================
754
755 const std::string rocTitle = title + fmt::format(" ({})", getROCTitle(iroc));
756
757 auto h2D = new TProfile2D(fmt::format("h_{}_ROC{}", name, iroc).data(),
758 fmt::format("{};pad row;pad;{}", rocTitle, draw).data(),
759 nrows, 0., nrows,
760 npads, -npads / 2., npads / 2.);
761 tree.Draw(fmt::format("{} : cpad : row >> {}", draw, h2D->GetName()).data(), fmt::format("(roc == {}) && ({})", iroc, cut).data(), "profcolzgoff");
762
763 h2D->SetStats(0);
764 if (xMax1D > xMin1D) {
765 h2D->SetMinimum(xMin1D);
766 h2D->SetMaximum(xMax1D);
767 }
768 h2D->SetUniqueID(iroc);
769
770 cROCs1D->cd(pad);
771 h1D->Draw();
772
773 cROCs2D->cd(pad);
774 h2D->Draw("colz");
775
776 ++pad;
777
778 // associate histograms to canvas
779 h1D->SetBit(TObject::kCanDelete);
780 h2D->SetBit(TObject::kCanDelete);
781 }
782 }
783
784 // ===| Side histograms |=====================================================
785
786 // ---| define histograms |---------------------------------------------------
787 // TODO: auto scaling of ranges based on mean and variance?
788 // for the moment use roots auto scaling
789
790 // set buffer size such that autoscaling uses the full range. This is about 2MB per histogram!
791 const int bufferSize = TH1::GetDefaultBufferSize();
792 TH1::SetDefaultBufferSize(Sector::MAXSECTOR * mapper.getPadsInSector());
793
794 auto hAside1D = new TH1F(fmt::format("h_Aside_1D_{}", name).data(), fmt::format("{0} (A-Side);{0}", title).data(),
795 std::abs(nbins1D), xMin1D, xMax1D); // TODO: modify ranges
796
797 auto hCside1D = new TH1F(fmt::format("h_Cside_1D_{}", name).data(), fmt::format("{0} (C-Side);{0}", title).data(),
798 std::abs(nbins1D), xMin1D, xMax1D); // TODO: modify ranges
799
800 auto hAside2D = new TProfile2D(fmt::format("h_Aside_2D_{}", name).data(), fmt::format("{} (A-Side);#it{{x}} (cm);#it{{y}} (cm);{}", title, draw).data(),
801 330, -270, 270, 330, -270, 270);
802
803 auto hCside2D = new TProfile2D(fmt::format("h_Cside_2D_{}", name).data(), fmt::format("{} (C-Side);#it{{x}} (cm);#it{{y}} (cm);{}", title, draw).data(),
804 330, -270, 270, 330, -270, 270);
805
806 tree.Draw(fmt::format("{} >> {}", draw, hAside1D->GetName()).data(), fmt::format("(A_Side) && ({})", cut).data(), "goff");
807 tree.Draw(fmt::format("{} >> {}", draw, hCside1D->GetName()).data(), fmt::format("(C_Side) && ({})", cut).data(), "goff");
808 tree.Draw(fmt::format("{} : gy : gx >> {}", draw, hAside2D->GetName()).data(), fmt::format("(A_Side) && ({})", cut).data(), "profcolzgoff");
809 tree.Draw(fmt::format("{} : gy : gx >> {}", draw, hCside2D->GetName()).data(), fmt::format("(C_Side) && ({})", cut).data(), "profcolzgoff");
810
811 if (xMax1D > xMin1D) {
812 hAside2D->SetMinimum(xMin1D);
813 hAside2D->SetMaximum(xMax1D);
814 hCside2D->SetMinimum(xMin1D);
815 hCside2D->SetMaximum(xMax1D);
816 }
817
818 // ===| Draw histograms |=====================================================
819 gStyle->SetOptStat("mr");
820 auto cSides = new TCanvas(fmt::format("c_{}", name).data(), title.data(), 1000, 1000);
821 vecCanvases.emplace_back(cSides);
822
823 gStyle->SetStatX(1. - gPad->GetRightMargin());
824 gStyle->SetStatY(1. - gPad->GetTopMargin());
825
826 cSides->Clear();
827 cSides->Divide(2, 2);
828
829 cSides->cd(1);
830 hAside2D->Draw("colz");
831 hAside2D->SetStats(0);
832 hAside2D->SetTitleOffset(1.05, "XY");
833 hAside2D->SetTitleSize(0.05, "XY");
834 adjustPalette(hAside2D, 0.92);
835 drawSectorsXY(Side::A);
836
837 cSides->cd(2);
838 hCside2D->Draw("colz");
839 hCside2D->SetStats(0);
840 hCside2D->SetTitleOffset(1.05, "XY");
841 hCside2D->SetTitleSize(0.05, "XY");
842 adjustPalette(hCside2D, 0.92);
843 drawSectorsXY(Side::C);
844
845 cSides->cd(3);
846 hAside1D->Draw();
847
848 cSides->cd(4);
849 hCside1D->Draw();
850
851 // reset the buffer size
852 TH1::SetDefaultBufferSize(bufferSize);
853
854 // associate histograms to canvas
855 hAside1D->SetBit(TObject::kCanDelete);
856 hCside1D->SetBit(TObject::kCanDelete);
857 hAside2D->SetBit(TObject::kCanDelete);
858 hCside2D->SetBit(TObject::kCanDelete);
859
860 return vecCanvases;
861}
862
863//______________________________________________________________________________
864std::vector<TCanvas*> painter::makeSummaryCanvases(const std::string_view fileName, const std::string_view calPadNames, int nbins1D, float xMin1D, float xMax1D, bool onlyFilled)
865{
866 using namespace o2::tpc;
867
868 const auto calPads = utils::readCalPads(fileName, calPadNames);
869
870 std::vector<TCanvas*> vecCanvases;
871
872 for (const auto calPad : calPads) {
873 auto canvases = makeSummaryCanvases(*calPad, nbins1D, xMin1D, xMax1D, onlyFilled);
874 for (auto c : canvases) {
875 vecCanvases.emplace_back(c);
876 }
877 }
878
879 return vecCanvases;
880}
881
882//______________________________________________________________________________
883TH2Poly* painter::makeSectorHist(const std::string_view name, const std::string_view title, const float xMin, const float xMax, const float yMin, const float yMax, const Type type, std::string binningStr)
884{
885 auto poly = new TH2Poly(name.data(), title.data(), xMin, xMax, yMin, yMax);
886
887 auto coords = painter::getCoordinates(type, binningStr);
888 for (const auto& coord : coords) {
889 poly->AddBin(coord.xVals.size(), coord.xVals.data(), coord.yVals.data());
890 }
891
892 return poly;
893}
894
895//______________________________________________________________________________
896TH2Poly* painter::makeSideHist(Side side, const Type type, std::string binningStr)
897{
898 const auto s = (side == Side::A) ? "A" : "C";
899 auto poly = new TH2Poly(fmt::format("hSide_{}", s).data(), fmt::format("{}-Side;#it{{x}} (cm);#it{{y}} (cm)", s).data(), -270., 270., -270., 270.);
900
901 auto coords = painter::getCoordinates(type, binningStr);
902 for (int isec = 0; isec < 18; ++isec) {
903 const float angDeg = 10.f + isec * 20;
904 for (auto coord : coords) {
905 coord.rotate(angDeg);
906 poly->AddBin(coord.xVals.size(), coord.xVals.data(), coord.yVals.data());
907 }
908 }
909
910 return poly;
911}
912
913//______________________________________________________________________________
914template <class T>
915void painter::fillPoly2D(TH2Poly& h2D, const CalDet<T>& calDet, Side side)
916{
917 const Mapper& mapper = Mapper::instance();
918
919 int bin = 1;
920 for (const auto& calROC : calDet.getData()) {
921 ROC roc(calROC.getPadSubsetNumber());
922 if (roc.side() != side) {
923 continue;
924 }
925
926 const int nrows = mapper.getNumberOfRowsROC(roc);
927 for (int irow = 0; irow < nrows; ++irow) {
928 const int padMax = mapper.getNumberOfPadsInRowROC(roc, irow) - 1;
929 for (int ipad = 0; ipad <= padMax; ++ipad) {
930 const auto pos = mapper.getPadCentre(PadROCPos(calROC.getPadSubsetNumber(), irow, ipad));
931 const auto val = calDet.getValue(roc, irow, ipad);
932 h2D.Fill(pos.X(), pos.Y(), val);
933 }
934 }
935 }
936}
937
938//______________________________________________________________________________
939void painter::drawSectorsXY(Side side, int sectorLineColor, int sectorTextColor)
940{
941 TLine l;
942 l.SetLineColor(std::abs(sectorLineColor));
943
944 TLatex latSide;
945 latSide.SetTextColor(sectorTextColor);
946 latSide.SetTextAlign(22);
947 latSide.SetTextSize(0.08);
948 if (sectorTextColor >= 0) {
949 latSide.DrawLatex(0, 0, (side == Side::C) ? "C" : "A");
950 }
951
952 TLatex lat;
953 lat.SetTextAlign(22);
954 lat.SetTextSize(0.03);
955 lat.SetTextColor(std::abs(sectorLineColor));
956
957 constexpr float phiWidth = float(SECPHIWIDTH);
958 const float rFactor = std::cos(phiWidth / 2.);
959 const float rLow = 83.65 / rFactor;
960 const float rIROCup = 133.3 / rFactor;
961 const float rOROClow = 133.5 / rFactor;
962 const float rOROC12 = 169.75 / rFactor;
963 const float rOROC23 = 207.85 / rFactor;
964 const float rOut = 247.7 / rFactor;
965 const float rText = rLow * rFactor * 3. / 4.;
966
967 for (Int_t isector = 0; isector < 18; ++isector) {
968 const float sinR = std::sin(phiWidth * isector);
969 const float cosR = std::cos(phiWidth * isector);
970
971 const float sinL = std::sin(phiWidth * ((isector + 1) % 18));
972 const float cosL = std::cos(phiWidth * ((isector + 1) % 18));
973
974 const float sinText = std::sin(phiWidth * (isector + 0.5));
975 const float cosText = std::cos(phiWidth * (isector + 0.5));
976
977 const float xR1 = rLow * cosR;
978 const float yR1 = rLow * sinR;
979 const float xR2 = rOut * cosR;
980 const float yR2 = rOut * sinR;
981
982 const float xL1 = rLow * cosL;
983 const float yL1 = rLow * sinL;
984 const float xL2 = rOut * cosL;
985 const float yL2 = rOut * sinL;
986
987 const float xOROCmup1 = rOROClow * cosR;
988 const float yOROCmup1 = rOROClow * sinR;
989 const float xOROCmup2 = rOROClow * cosL;
990 const float yOROCmup2 = rOROClow * sinL;
991
992 const float xIROCmup1 = rIROCup * cosR;
993 const float yIROCmup1 = rIROCup * sinR;
994 const float xIROCmup2 = rIROCup * cosL;
995 const float yIROCmup2 = rIROCup * sinL;
996
997 const float xO121 = rOROC12 * cosR;
998 const float yO121 = rOROC12 * sinR;
999 const float xO122 = rOROC12 * cosL;
1000 const float yO122 = rOROC12 * sinL;
1001
1002 const float xO231 = rOROC23 * cosR;
1003 const float yO231 = rOROC23 * sinR;
1004 const float xO232 = rOROC23 * cosL;
1005 const float yO232 = rOROC23 * sinL;
1006
1007 const float xText = rText * cosText;
1008 const float yText = rText * sinText;
1009
1010 // left side line
1011 l.DrawLine(xR1, yR1, xR2, yR2);
1012
1013 // IROC inner line
1014 l.DrawLine(xR1, yR1, xL1, yL1);
1015
1016 // IROC end line
1017 l.DrawLine(xIROCmup1, yIROCmup1, xIROCmup2, yIROCmup2);
1018
1019 // OROC start line
1020 l.DrawLine(xOROCmup1, yOROCmup1, xOROCmup2, yOROCmup2);
1021
1022 // OROC1 - OROC2 line
1023 l.DrawLine(xO121, yO121, xO122, yO122);
1024
1025 // OROC2 - OROC3 line
1026 l.DrawLine(xO231, yO231, xO232, yO232);
1027
1028 // IROC inner line
1029 l.DrawLine(xR2, yR2, xL2, yL2);
1030
1031 // sector numbers
1032 if (sectorLineColor >= 0) {
1033 lat.DrawLatex(xText, yText, fmt::format("{}", isector).data());
1034 }
1035 }
1036}
1037
1038void painter::drawSectorLocalPadNumberPoly(short padTextColor, float lineScalePS)
1039{
1040 const Mapper& mapper = Mapper::instance();
1041 const auto coords = getPadCoordinatesSector();
1042 TLatex lat;
1043 lat.SetTextAlign(12);
1044 lat.SetTextSize(0.002f);
1045 lat.SetTextColor(padTextColor);
1046 gStyle->SetLineScalePS(lineScalePS);
1047
1048 for (unsigned int iregion = 0; iregion < Mapper::NREGIONS; ++iregion) {
1049 const auto padInf = mapper.getPadRegionInfo(iregion);
1050 for (unsigned int irow = 0; irow < Mapper::ROWSPERREGION[iregion]; ++irow) {
1051 for (unsigned int ipad = 0; ipad < Mapper::PADSPERROW[iregion][irow]; ++ipad) {
1052 const GlobalPadNumber padNum = o2::tpc::Mapper::getGlobalPadNumber(irow, ipad, iregion);
1053 const auto coordinate = coords[padNum];
1054 const float yPos = (coordinate.yVals[0] + coordinate.yVals[2]) / 2;
1055 const float xPos = (coordinate.xVals[0] + coordinate.xVals[2]) / 2;
1056 lat.DrawLatex(xPos, yPos, Form("%i", ipad));
1057 }
1058 }
1059 }
1060}
1061
1062void painter::drawSectorInformationPoly(short regionLineColor, short rowTextColor)
1063{
1064 const Mapper& mapper = Mapper::instance();
1065
1066 TLatex lat;
1067 lat.SetTextColor(rowTextColor);
1068 lat.SetTextSize(0.02f);
1069 lat.SetTextAlign(12);
1070
1071 TLine line;
1072 line.SetLineColor(regionLineColor);
1073
1074 std::vector<float> radii(Mapper::NREGIONS + 1);
1075 radii.back() = 247;
1076 for (unsigned int ireg = 0; ireg < Mapper::NREGIONS; ++ireg) {
1077 const auto reg = mapper.getPadRegionInfo(ireg);
1078 const float rad = reg.getRadiusFirstRow();
1079 radii[ireg] = rad;
1080 line.DrawLine(rad, -43, rad, 43);
1081 }
1082
1083 // draw top region information
1084 for (unsigned int ireg = 0; ireg < Mapper::NREGIONS; ++ireg) {
1085 lat.DrawLatex((radii[ireg] + radii[ireg + 1]) / 2, 45, Form("%i", ireg));
1086 }
1087
1088 lat.SetTextSize(0.002f);
1089 lat.SetTextAlign(13);
1090 // draw local and global rows
1091 const std::array<float, Mapper::NREGIONS> posRow{16.2f, 18.2f, 20.2f, 22.3f, 26.f, 29.f, 33.f, 35.f, 39.f, 42.5f};
1092 int globalRow = 0;
1093 for (unsigned int ireg = 0; ireg < Mapper::NREGIONS; ++ireg) {
1094 const auto reg = mapper.getPadRegionInfo(ireg);
1095 const float nRows = reg.getNumberOfPadRows();
1096 for (int i = 0; i < nRows; ++i) {
1097 const float padHeight = reg.getPadHeight();
1098 const float radiusFirstRow = reg.getRadiusFirstRow();
1099 const float xPos = radiusFirstRow + (i + 0.5f) * padHeight;
1100 const float yPos = posRow[ireg];
1101 // row in region
1102 lat.DrawLatex(xPos, yPos, Form("%i", i));
1103 lat.DrawLatex(xPos, -yPos, Form("%i", i));
1104 // row in sector
1105 const float offs = 0.5f;
1106 lat.DrawLatex(xPos, yPos + offs, Form("%i", globalRow));
1107 lat.DrawLatex(xPos, -yPos - offs, Form("%i", globalRow++));
1108 }
1109 }
1110}
1111
1112template <typename DataT>
1113TH3F painter::convertCalDetToTH3(const std::vector<CalDet<DataT>>& calDet, const bool norm, const int nRBins, const float rMin, const float rMax, const int nPhiBins, const float zMax)
1114{
1115 const int nZBins = calDet.size();
1116 TH3F histConvSum("hisCalDet", "hisCalDet", nPhiBins, 0, o2::constants::math::TwoPI, nRBins, rMin, rMax, 2 * nZBins, -zMax, zMax); // final converted histogram
1117 TH3F histConvWeight("histConvWeight", "histConvWeight", nPhiBins, 0, o2::constants::math::TwoPI, nRBins, rMin, rMax, 2 * nZBins, -zMax, zMax);
1118
1119 typedef boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<float>> polygon;
1120 const auto coords = o2::tpc::painter::getPadCoordinatesSector(); // coordinates of the pads in one sector
1121
1122 // create polygons per pad of the input histogram
1123 std::vector<polygon> geoBin;
1124 const int nGeoBins = nPhiBins * nRBins;
1125 geoBin.reserve(nGeoBins);
1126 for (int iphi = 1; iphi <= nPhiBins; ++iphi) {
1127 const double phiLow = histConvSum.GetXaxis()->GetBinLowEdge(iphi);
1128 const double phiUp = histConvSum.GetXaxis()->GetBinUpEdge(iphi);
1129 for (int ir = 1; ir <= nRBins; ++ir) {
1130 const double rLow = histConvSum.GetYaxis()->GetBinLowEdge(ir);
1131 const double rUp = histConvSum.GetYaxis()->GetBinUpEdge(ir);
1132 const double xPos1 = rLow * std::cos(phiLow);
1133 const double yPos1 = rLow * std::sin(phiLow);
1134 const double xPos2 = rLow * std::cos(phiUp);
1135 const double yPos2 = rLow * std::sin(phiUp);
1136 const double xPos4 = rUp * std::cos(phiLow);
1137 const double yPos4 = rUp * std::sin(phiLow);
1138 const double xPos3 = rUp * std::cos(phiUp);
1139 const double yPos3 = rUp * std::sin(phiUp);
1140 // round the values due to problems in intersection in boost with polygons close to each other
1141 boost::geometry::read_wkt(Form("POLYGON((%.4f %.4f, %.4f %.4f, %.4f %.4f, %.4f %.4f, %.4f %.4f))", xPos1, yPos1, xPos2, yPos2, xPos3, yPos3, xPos4, yPos4, xPos1, yPos1), geoBin.emplace_back());
1142 boost::geometry::correct(geoBin.back());
1143 }
1144 }
1145
1146 for (unsigned int sector = 0; sector < Mapper::NSECTORS / 2; ++sector) {
1147 for (unsigned int region = 0; region < Mapper::NREGIONS; ++region) {
1148 const unsigned int rowsRegion = o2::tpc::Mapper::ROWSPERREGION[region];
1149 for (unsigned int iRow = 0; iRow < rowsRegion; ++iRow) {
1150 const unsigned int padsInRow = o2::tpc::Mapper::PADSPERROW[region][iRow] - 1;
1151 for (unsigned int iPad = 0; iPad <= padsInRow; ++iPad) {
1152 const GlobalPadNumber padNum = Mapper::getGlobalPadNumber(iRow, iPad, region);
1153
1154 const float angDeg = 10.f + sector * 20;
1155 auto coordinate = coords[padNum];
1156 coordinate.rotate(angDeg);
1157
1158 const std::array<double, 2> radiusPadCoord{
1159 std::sqrt(coordinate.xVals[0] * coordinate.xVals[0] + coordinate.yVals[0] * coordinate.yVals[0]),
1160 std::sqrt(coordinate.xVals[2] * coordinate.xVals[2] + coordinate.yVals[2] * coordinate.yVals[2]),
1161 };
1162
1163 std::array<float, 4> phiPadCoord{
1164 static_cast<float>(std::atan2(coordinate.yVals[0], coordinate.xVals[0])),
1165 static_cast<float>(std::atan2(coordinate.yVals[1], coordinate.xVals[1])),
1166 static_cast<float>(std::atan2(coordinate.yVals[2], coordinate.xVals[2])),
1167 static_cast<float>(std::atan2(coordinate.yVals[3], coordinate.xVals[3]))};
1168
1169 for (auto& phi : phiPadCoord) {
1171 }
1172
1173 // bins of the histogram of the edges of the pad
1174 const int binRBottomStart = std::clamp(histConvSum.GetYaxis()->FindBin(radiusPadCoord[0]) - 1, 1, nRBins);
1175 const int binRTopEnd = std::clamp(histConvSum.GetYaxis()->FindBin(radiusPadCoord[1]) + 1, 1, nRBins);
1176 int binPhiStart = std::min(histConvSum.GetXaxis()->FindBin(phiPadCoord[0]), histConvSum.GetXaxis()->FindBin(phiPadCoord[1]));
1177 int binPhiEnd = std::max(histConvSum.GetXaxis()->FindBin(phiPadCoord[2]), histConvSum.GetXaxis()->FindBin(phiPadCoord[3]));
1178
1179 // define boost geoemtry object
1180 polygon geoPad;
1181 boost::geometry::read_wkt(Form("POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))", coordinate.xVals[0], coordinate.yVals[0], coordinate.xVals[1], coordinate.yVals[1], coordinate.xVals[2], coordinate.yVals[2], coordinate.xVals[3], coordinate.yVals[3], coordinate.xVals[0], coordinate.yVals[0]), geoPad);
1182 boost::geometry::correct(geoPad);
1183
1184 for (int binR = binRBottomStart; binR <= binRTopEnd; ++binR) {
1185 for (int binPhi = binPhiStart; binPhi <= binPhiEnd; ++binPhi) {
1186 const int ind = (binPhi - 1) * nRBins + binR - 1;
1187
1188 std::deque<polygon> output;
1189 boost::geometry::intersection(geoPad, geoBin[ind], output);
1190 if (output.empty()) {
1191 continue;
1192 }
1193 const double area = boost::geometry::area(output.front());
1194 const double fac = area * Mapper::INVPADAREA[region];
1195
1196 for (int iSide = 0; iSide < 2; ++iSide) {
1197 const Side side = iSide == 0 ? Side::C : Side::A;
1198 const unsigned int iCRU = side == Side::A ? (sector * Mapper::NREGIONS + region) : ((sector + Mapper::NSECTORS / 2) * Mapper::NREGIONS + region);
1199 const CRU cru(iCRU);
1200
1201 for (int iz = 0; iz < nZBins; ++iz) {
1202 const auto val = calDet[iz].getValue(cru, iRow, (side == Side::A) ? iPad : padsInRow - iPad);
1203 const int zBin = side == Side::A ? (nZBins + iz + 1) : (nZBins - iz);
1204 const auto globBin = histConvSum.GetBin(binPhi, binR, zBin);
1205 histConvSum.AddBinContent(globBin, val * fac);
1206 if (norm) {
1207 histConvWeight.AddBinContent(globBin, fac);
1208 }
1209 }
1210 }
1211 }
1212 }
1213 }
1214 }
1215 }
1216 }
1217
1218 if (norm) {
1219 histConvSum.Divide(&histConvWeight);
1220 }
1221
1222 return histConvSum;
1223}
1224
1225std::vector<TCanvas*> painter::makeSummaryCanvases(const LtrCalibData& ltr, std::vector<TCanvas*>* outputCanvases)
1226{
1227 std::vector<TCanvas*> vecCanvases;
1228
1229 // ===| set up canvases |===
1230 TCanvas* cLtrCoverage = nullptr;
1231 TCanvas* cLtrdEdx = nullptr;
1232 TCanvas* cCalibValues = nullptr;
1233
1234 const auto size = 1400;
1235 if (outputCanvases) {
1236 if (outputCanvases->size() < 3) {
1237 LOGP(error, "At least 3 canvases are needed to fill the output, only {} given", outputCanvases->size());
1238 return vecCanvases;
1239 }
1240
1241 cLtrCoverage = outputCanvases->at(0);
1242 cCalibValues = outputCanvases->at(1);
1243 cLtrdEdx = outputCanvases->at(2);
1244 cLtrCoverage->Clear();
1245 cCalibValues->Clear();
1246 cLtrdEdx->Clear();
1247 cLtrCoverage->SetCanvasSize(size, 2. * size * 7 / 24 * 1.1);
1248 cCalibValues->SetCanvasSize(size, 2. * size * 7 / 24 * 1.1);
1249 cLtrdEdx->SetCanvasSize(size, 2. * size * 7 / 24 * 1.1);
1250 } else {
1251 cLtrCoverage = new TCanvas("cLtrCoverage", "laser track coverage", size, 2. * size * 7 / 24 * 1.1);
1252 cLtrdEdx = new TCanvas("cLtrdEdx", "laser track average dEdx", size, 2. * size * 7 / 24 * 1.1);
1253 cCalibValues = new TCanvas("cCalibValues", "calibration values", size, 2. * size * 7 / 24 * 1.1);
1254
1255 // TODO: add cCalibValues
1256 }
1257
1258 auto getLtrStatHist = [](Side side, std::string_view type = "Coverage") -> TH2F* {
1259 auto sideName = (side == Side::A) ? "A" : "C";
1260 auto hltr = new TH2F(fmt::format("hltr{}_{}", type, sideName).data(), ";Bundle ID;Track in bundle", 24, 0, 24, 7, 0, 7);
1261 hltr->SetBit(TObject::kCanDelete);
1262 hltr->SetStats(0);
1263 hltr->GetXaxis()->SetNdivisions(406, false);
1264 hltr->GetYaxis()->SetNdivisions(107, false);
1265 hltr->SetLabelSize(0.05, "XY");
1266 hltr->SetTitleSize(0.06, "X");
1267 hltr->SetTitleSize(0.07, "Y");
1268 hltr->SetTitleOffset(0.8, "X");
1269 hltr->SetTitleOffset(0.4, "Y");
1270 return hltr;
1271 };
1272
1273 auto drawNames = [](Side side) {
1274 const std::array<const std::string_view, 6> namesA{"A01/02", "A04/05", "A07/08", "A10/11", "A13/14", "A16/17"};
1275 const std::array<const std::string_view, 6> namesC{"C00/01", "C03/04", "C06/07", "C09/10", "C12/13", "C15/16"};
1276 const auto& names = (side == Side::A) ? namesA : namesC;
1277
1278 TLatex lat;
1279 lat.SetTextAlign(22);
1280 lat.SetTextSize(0.06);
1281
1282 TLine line;
1283 for (int i = 0; i < 6; ++i) {
1284 lat.DrawLatex(2.f + i * 4.f, 7.5, names[i].data());
1285 if (i < 5) {
1286 line.DrawLine(4.f + i * 4.f, 0, 4.f + i * 4.f, 8);
1287 }
1288 }
1289 };
1290
1291 auto hltrCoverageA = getLtrStatHist(Side::A);
1292 auto hltrCoverageC = getLtrStatHist(Side::C);
1293
1294 auto hltrdEdxA = getLtrStatHist(Side::A, "dEdx");
1295 auto hltrdEdxC = getLtrStatHist(Side::C, "dEdx");
1296
1297 float dEdxSumA = 0.f;
1298 float dEdxSumC = 0.f;
1299 int nTrackA = 0;
1300 int nTrackC = 0;
1301
1302 for (size_t itrack = 0; itrack < ltr.matchedLtrIDs.size(); ++itrack) {
1303 const auto id = ltr.matchedLtrIDs.at(itrack);
1304 const auto dEdx = ltr.dEdx.at(itrack);
1305 const auto trackID = id % LaserTrack::TracksPerBundle;
1307 const auto sideA = id < (LaserTrack::NumberOfTracks / 2);
1308
1309 auto hltrCoverage = (sideA) ? hltrCoverageA : hltrCoverageC;
1310 auto hltrdEdx = (sideA) ? hltrdEdxA : hltrdEdxC;
1311
1312 hltrCoverage->Fill(bundleID, trackID);
1313 hltrdEdx->Fill(bundleID, trackID, dEdx);
1314
1315 if (sideA) {
1316 dEdxSumA += dEdx;
1317 ++nTrackA;
1318 } else {
1319 dEdxSumC += dEdx;
1320 ++nTrackC;
1321 }
1322 }
1323 // hltrCoverage->Scale(1.f/float(ltr->processedTFs));
1324
1325 if (nTrackA > 1) {
1326 dEdxSumA /= nTrackA;
1327 }
1328
1329 if (nTrackC > 1) {
1330 dEdxSumC /= nTrackC;
1331 }
1332
1333 // ===| coverage canvases |===
1334 cLtrCoverage->Divide(1, 2);
1335
1336 // A-Side
1337 cLtrCoverage->cd(1);
1338 gPad->SetGridx(1);
1339 gPad->SetGridy(1);
1340 gPad->SetRightMargin(0.01);
1341 hltrCoverageA->Draw("col text");
1342 drawNames(Side::A);
1343
1344 // C-Side
1345 cLtrCoverage->cd(2);
1346 gPad->SetGridx(1);
1347 gPad->SetGridy(1);
1348 gPad->SetRightMargin(0.01);
1349 hltrCoverageC->Draw("col text");
1350 drawNames(Side::C);
1351
1352 // ===| dEdx canvases |===
1353 cLtrdEdx->Divide(1, 2);
1354
1355 // A-Side
1356 cLtrdEdx->cd(1);
1357 gPad->SetGridx(1);
1358 gPad->SetGridy(1);
1359 gPad->SetRightMargin(0.01);
1360 hltrdEdxA->Divide(hltrCoverageA);
1361 hltrdEdxA->Draw("col text");
1362 drawNames(Side::A);
1363
1364 // C-Side
1365 cLtrdEdx->cd(2);
1366 gPad->SetGridx(1);
1367 gPad->SetGridy(1);
1368 gPad->SetRightMargin(0.01);
1369 hltrdEdxC->Divide(hltrCoverageC);
1370 hltrdEdxC->Draw("col text");
1371 drawNames(Side::C);
1372
1373 // ===| calibration value canvas |===
1374 // TODO: Implement
1375 auto calibValMsg = new TPaveText(0.1, 0.1, 0.9, 0.9, "NDC");
1376 calibValMsg->SetFillColor(0);
1377 calibValMsg->SetBorderSize(0);
1378 calibValMsg->AddText(fmt::format("processedTFs: {}", ltr.processedTFs).data());
1379 calibValMsg->AddText(fmt::format("dvCorrectionA: {}", ltr.dvCorrectionA).data());
1380 calibValMsg->AddText(fmt::format("dvCorrectionC: {}", ltr.dvCorrectionC).data());
1381 calibValMsg->AddText(fmt::format("dvCorrection: {}", ltr.getDriftVCorrection()).data());
1382 calibValMsg->AddText(fmt::format("dvAbsolute: {}", ltr.refVDrift / ltr.getDriftVCorrection()).data());
1383 calibValMsg->AddText(fmt::format("dvOffsetA: {}", ltr.dvOffsetA).data());
1384 calibValMsg->AddText(fmt::format("dvOffsetC: {}", ltr.dvOffsetC).data());
1385 calibValMsg->AddText(fmt::format("t0A: {}", ltr.getT0A()).data());
1386 calibValMsg->AddText(fmt::format("t0C: {}", ltr.getT0C()).data());
1387 calibValMsg->AddText(fmt::format("nTracksA: {}", ltr.nTracksA).data());
1388 calibValMsg->AddText(fmt::format("nTracksC: {}", ltr.nTracksC).data());
1389 calibValMsg->AddText(fmt::format("#LTdEdx A#GT: {}", dEdxSumA).data());
1390 calibValMsg->AddText(fmt::format("#LTdEdx C#GT: {}", dEdxSumC).data());
1391
1392 cCalibValues->cd();
1393 calibValMsg->Draw();
1394
1395 vecCanvases.emplace_back(cLtrCoverage);
1396 vecCanvases.emplace_back(cCalibValues);
1397 vecCanvases.emplace_back(cLtrdEdx);
1398 return vecCanvases;
1399}
1400
1401TCanvas* painter::makeJunkDetectionCanvas(const TObjArray* data, TCanvas* outputCanvas)
1402{
1403 auto c = outputCanvas;
1404 if (!c) {
1405 c = new TCanvas("junk_detection", "Junk Detection", 1000, 1000);
1406 }
1407
1408 c->Clear();
1409
1410 auto strA = (TH2F*)data->At(4);
1411 auto strB = (TH2F*)data->At(5);
1412
1413 double statsA[7];
1414 double statsB[7];
1415
1416 strA->GetStats(statsA);
1417 strB->GetStats(statsB);
1418
1419 auto junkDetectionMsg = new TPaveText(0.1, 0.1, 0.9, 0.9, "NDC");
1420 junkDetectionMsg->SetFillColor(0);
1421 junkDetectionMsg->SetBorderSize(0);
1422 junkDetectionMsg->AddText("Removal Strategy A");
1423 junkDetectionMsg->AddText(fmt::format("Number of Clusters before Removal: {}", statsA[2]).data());
1424 junkDetectionMsg->AddText(fmt::format("Removed Fraction: {:.2f}%", statsA[4]).data());
1425 junkDetectionMsg->AddLine(.0, .5, 1., .5);
1426 junkDetectionMsg->AddText("Removal Strategy B");
1427 junkDetectionMsg->AddText(fmt::format("Number of Clusters before Removal: {}", statsB[2]).data());
1428 junkDetectionMsg->AddText(fmt::format("Removed Fraction: {:.2f}%", statsB[4]).data());
1429
1430 c->cd();
1431 junkDetectionMsg->Draw();
1432
1433 return c;
1434}
1435
1436void painter::adjustPalette(TH1* h, float x2ndc, float tickLength)
1437{
1438 gPad->Modified();
1439 gPad->Update();
1440 auto palette = (TPaletteAxis*)h->GetListOfFunctions()->FindObject("palette");
1441 if (!palette) {
1442 return;
1443 }
1444 palette->SetX2NDC(x2ndc);
1445 auto ax = h->GetZaxis();
1446 ax->SetTickLength(tickLength);
1447}
1448
1449TMultiGraph* painter::makeMultiGraph(TTree& tree, std::string_view varX, std::string_view varsY, std::string_view errVarsY, std::string_view cut, bool makeSparse)
1450{
1451 bool hasErrors = errVarsY.size() > 0 && (std::count(varsY.begin(), varsY.end(), ':') == std::count(errVarsY.begin(), errVarsY.end(), ':'));
1452
1453 tree.Draw(fmt::format("{} : {} {} {}", varX, varsY, hasErrors ? " : " : "", hasErrors ? errVarsY : "").data(), cut.data(), "goff");
1454 const auto nRows = tree.GetSelectedRows();
1455
1456 // get sort index
1457 std::vector<size_t> idx(tree.GetSelectedRows());
1458 std::iota(idx.begin(), idx.end(), static_cast<size_t>(0));
1459 std::sort(idx.begin(), idx.end(), [&tree](auto a, auto b) { return tree.GetVal(0)[a] < tree.GetVal(0)[b]; });
1460
1461 auto mgr = new TMultiGraph();
1462 const auto params = o2::utils::Str::tokenize(varsY.data(), ':');
1463
1464 for (size_t ivarY = 0; ivarY < params.size(); ++ivarY) {
1465 auto gr = new TGraphErrors(nRows);
1466 gr->SetMarkerSize(1);
1467 gr->SetMarkerStyle(markers[ivarY % markers.size()]);
1468 gr->SetMarkerColor(colors[ivarY % colors.size()]);
1469 gr->SetLineColor(colors[ivarY % colors.size()]);
1470 gr->SetNameTitle(params[ivarY].data(), params[ivarY].data());
1471 for (Long64_t iEntry = 0; iEntry < nRows; ++iEntry) {
1472 if (makeSparse) {
1473 gr->SetPoint(iEntry, iEntry + 0.5, tree.GetVal(ivarY + 1)[idx[iEntry]]);
1474 } else {
1475 gr->SetPoint(iEntry, tree.GetVal(0)[idx[iEntry]], tree.GetVal(ivarY + 1)[idx[iEntry]]);
1476 }
1477 if (hasErrors) {
1478 gr->SetPointError(iEntry, 0, tree.GetVal(ivarY + 1 + params.size())[idx[iEntry]]);
1479 }
1480 }
1481
1482 mgr->Add(gr, "lp");
1483 }
1484
1485 if (makeSparse) {
1486 auto xax = mgr->GetXaxis();
1487 xax->Set(nRows, 0., static_cast<Double_t>(nRows));
1488 for (Long64_t iEntry = 0; iEntry < nRows; ++iEntry) {
1489 xax->SetBinLabel(iEntry + 1, fmt::format("{}", tree.GetVal(0)[idx[iEntry]]).data());
1490 }
1491 xax->LabelsOption("v");
1492 }
1493
1494 return mgr;
1495}
1496
1497// ===| explicit instantiations |===============================================
1498// this is required to force the compiler to create instances with the types
1499// we usually would like to deal with
1500template TCanvas* painter::draw<float>(const CalDet<float>& calDet, int, float, float, TCanvas*);
1501template std::vector<TCanvas*> painter::makeSummaryCanvases<float>(const CalDet<float>& calDet, int, float, float, bool, std::vector<TCanvas*>*);
1502template TCanvas* painter::draw<float>(const CalArray<float>& calArray);
1503template void painter::fillHistogram2D<float>(TH2& h2D, const CalDet<float>& calDet, Side side);
1504template void painter::fillPoly2D<float>(TH2Poly& h2D, const CalDet<float>& calDet, Side side);
1505template void painter::fillHistogram2D<float>(TH2& h2D, const CalArray<float>& calArray);
1506template TH2* painter::getHistogram2D<float>(const CalDet<float>& calDet, Side side);
1507template TH2* painter::getHistogram2D<float>(const CalArray<float>& calArray);
1508
1509template TCanvas* painter::draw<double>(const CalDet<double>& calDet, int, float, float, TCanvas*);
1510template std::vector<TCanvas*> painter::makeSummaryCanvases<double>(const CalDet<double>& calDet, int, float, float, bool, std::vector<TCanvas*>*);
1511template TCanvas* painter::draw<double>(const CalArray<double>& calArray);
1512template TH2* painter::getHistogram2D<double>(const CalDet<double>& calDet, Side side);
1513template TH2* painter::getHistogram2D<double>(const CalArray<double>& calArray);
1514
1515template TCanvas* painter::draw<int>(const CalDet<int>& calDet, int, float, float, TCanvas*);
1516template std::vector<TCanvas*> painter::makeSummaryCanvases<int>(const CalDet<int>& calDet, int, float, float, bool, std::vector<TCanvas*>*);
1517template TCanvas* painter::draw<int>(const CalArray<int>& calArray);
1518template TH2* painter::getHistogram2D<int>(const CalDet<int>& calDet, Side side);
1519template TH2* painter::getHistogram2D<int>(const CalArray<int>& calArray);
1520
1521template TCanvas* painter::draw<short>(const CalDet<short>& calDet, int, float, float, TCanvas*);
1522template std::vector<TCanvas*> painter::makeSummaryCanvases<short>(const CalDet<short>& calDet, int, float, float, bool, std::vector<TCanvas*>*);
1523template TCanvas* painter::draw<short>(const CalArray<short>& calArray);
1524template TH2* painter::getHistogram2D<short>(const CalDet<short>& calDet, Side side);
1525template TH2* painter::getHistogram2D<short>(const CalArray<short>& calArray);
1526
1527template TCanvas* painter::draw<PadFlags>(const CalDet<PadFlags>& calDet, int, float, float, TCanvas*);
1528template std::vector<TCanvas*> painter::makeSummaryCanvases<PadFlags>(const CalDet<PadFlags>& calDet, int, float, float, bool, std::vector<TCanvas*>*);
1529template TCanvas* painter::draw<PadFlags>(const CalArray<PadFlags>& calArray);
1530template TH2* painter::getHistogram2D<PadFlags>(const CalDet<PadFlags>& calDet, Side side);
1531template TH2* painter::getHistogram2D<PadFlags>(const CalArray<PadFlags>& calArray);
1532
1533template TCanvas* painter::draw<bool>(const CalDet<bool>& calDet, int, float, float, TCanvas*);
1534template std::vector<TCanvas*> painter::makeSummaryCanvases<bool>(const CalDet<bool>& calDet, int, float, float, bool, std::vector<TCanvas*>*);
1535template TCanvas* painter::draw<bool>(const CalArray<bool>& calArray);
1536template TH2* painter::getHistogram2D<bool>(const CalDet<bool>& calDet, Side side);
1537template TH2* painter::getHistogram2D<bool>(const CalArray<bool>& calArray);
1538
1539template TH3F painter::convertCalDetToTH3<float>(const std::vector<CalDet<float>>&, const bool, const int, const float, const float, const int, const float);
General auxilliary methods.
int32_t i
float float float & zMax
float & yMax
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
std::enable_if_t< std::is_signed< T >::value, bool > hasData(const CalArray< T > &cal)
Definition Painter.cxx:600
Helper function to tokenize sequences and ranges of integral numbers.
uint16_t pos
Definition RawData.h:3
uint32_t roc
Definition RawData.h:3
uint32_t j
Definition RawData.h:0
uint32_t side
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
uint32_t stack
Definition RawData.h:1
const auto & getData()
Class for time synchronization of RawReader instances.
@ CRUperSector
Definition CRU.h:30
const U getSum() const
calculate the sum of all elements
Definition CalArray.h:118
const std::string & getName() const
Definition CalArray.h:111
PadSubset getPadSubset() const
Definition CalArray.h:94
const std::vector< T > & getData() const
Definition CalArray.h:113
int getPadSubsetNumber() const
Definition CalArray.h:98
const T getValue(const size_t channel) const
Definition CalArray.h:101
const CalType & getCalArray(size_t position) const
Definition CalDet.h:69
const T getValue(const int sec, const int globalPadInSector) const
Definition CalDet.h:160
const std::vector< CalType > & getData() const
Definition CalDet.h:64
const std::string & getName() const
Definition CalDet.h:91
unsigned char getIndex() const
Definition FECInfo.h:41
static constexpr int RodsPerSide
Number of laser rods per side.
Definition LaserTrack.h:30
static constexpr int BundlesPerRod
number of micro-mirror bundle per laser rod
Definition LaserTrack.h:31
static constexpr int NumberOfTracks
Total number of laser tracks.
Definition LaserTrack.h:29
static constexpr int TracksPerBundle
number of micro-mirrors per bundle
Definition LaserTrack.h:32
const std::array< PadRegionInfo, 10 > & getMapPadRegionInfo() const
Definition Mapper.h:386
static GlobalPadNumber getGlobalPadNumber(const unsigned int lrow, const unsigned int pad, const unsigned int region)
Definition Mapper.h:64
static const std::vector< unsigned int > PADSPERROW[NREGIONS]
number of pads per row in region
Definition Mapper.h:567
const FECInfo & fecInfo(GlobalPadNumber padNumber) const
Definition Mapper.h:52
int getNumberOfRowsROC(ROC roc) const
Definition Mapper.h:305
int getNumberOfPadsInRow(PadSubset padSubset, int position, int row) const
Definition Mapper.h:354
int getNumberOfPadsInRowROC(int roc, int row) const
Definition Mapper.h:342
static constexpr float INVPADAREA[NREGIONS]
inverse size of the pad area padwidth*padLength
Definition Mapper.h:536
static Mapper & instance(const std::string mappingDir="")
Definition Mapper.h:44
GlobalPadNumber getPadNumber(const PadSubset padSubset, const size_t padSubsetNumber, const int row, const int pad) const
Definition Mapper.h:134
static constexpr unsigned int ROWSPERREGION[NREGIONS]
number of pad rows for region
Definition Mapper.h:532
static constexpr unsigned int NSECTORS
total number of sectors in the TPC
Definition Mapper.h:526
const PadRegionInfo & getPadRegionInfo(const unsigned char region) const
Definition Mapper.h:385
static constexpr unsigned int NREGIONS
total number of regions in one sector
Definition Mapper.h:527
static constexpr unsigned short getPadsInSector()
Definition Mapper.h:414
int getNumberOfPadRows(PadSubset padSubset, int position) const
Definition Mapper.h:321
static constexpr unsigned int PADROWS
total number of pad rows
Definition Mapper.h:528
GlobalPosition2D getPadCentre(const PadSecPos &padSec) const
Definition Mapper.h:163
static constexpr unsigned REGION[PADROWS]
region for global pad row
Definition Mapper.h:537
Pad and row inside a ROC.
Definition PadROCPos.h:37
float getRadiusFirstRow() const
float getPadHeight() const
bool looped() const
if increment operator went above MaxROC
Definition ROC.h:108
static constexpr int MAXSECTOR
Definition Sector.h:44
GLint GLenum GLint x
Definition glcorearb.h:403
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
GLenum coord
Definition glcorearb.h:4109
GLsizei const GLubyte GLsizei GLenum const void * coords
Definition glcorearb.h:5468
GLuint const GLchar * name
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLenum const GLfloat * params
Definition glcorearb.h:272
GLboolean * data
Definition glcorearb.h:298
GLuint GLfloat * val
Definition glcorearb.h:1582
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
constexpr float TwoPI
int32_t const char int32_t line
void bringTo02PiGen(float &phi)
Definition Utils.h:80
std::vector< CalPad * > readCalPads(const std::string_view fileName, const std::vector< std::string > &calPadNames)
Definition Utils.cxx:190
Global TPC definitions and constants.
Definition SimTraits.h:168
GEMstack
TPC GEM stack types.
Definition Defs.h:53
constexpr double SECPHIWIDTH
Definition Defs.h:45
PadSubset
Definition of the different pad subsets.
Definition Defs.h:63
@ ROC
ROCs (up to 72)
Side
TPC readout sidE.
Definition Defs.h:35
@ A
Definition Defs.h:35
@ C
Definition Defs.h:36
constexpr unsigned short GEMSTACKSPERSECTOR
Definition Defs.h:57
const int iz
Definition TrackUtils.h:69
constexpr std::array< double, nLayers > radii
Definition Specs.h:53
constexpr std::array< int, nLayers > nRows
Definition Specs.h:57
float getDriftVCorrection() const
float dvCorrectionA
drift velocity correction factor A-Side (inverse multiplicative)
float dvOffsetC
drift velocity trigger offset C-Side
float dvOffsetA
drift velocity trigger offset A-Side
float dvCorrectionC
drift velocity correction factor C-Side (inverse multiplicative)
std::vector< uint16_t > matchedLtrIDs
matched laser track IDs
std::vector< float > dEdx
dE/dx of each track
size_t processedTFs
number of processed TFs with laser track candidates
uint16_t nTracksC
number of tracks used for C-Side fit
uint16_t nTracksA
number of tracks used for A-Side fit
float refVDrift
reference vdrift for which factor was extracted
static TH2Poly * makeSectorHist(const std::string_view name="hSector", const std::string_view title="Sector;local #it{x} (cm);local #it{y} (cm)", const float xMin=83.65f, const float xMax=247.7f, const float yMin=-43.7f, const float yMax=43.7f, const Type type=Type::Pad, std::string binningStr="")
static std::vector< double > getRowBinningCM(uint32_t roc=72)
static std::array< int, 6 > colors
Definition Painter.h:60
static TH2Poly * makeSideHist(Side side, const Type type=Type::Pad, std::string binningStr="")
static std::vector< painter::PadCoordinates > getSCDY2XCoordinatesSector(std::string binningStr)
static TH3F convertCalDetToTH3(const std::vector< CalDet< DataT > > &calDet, const bool norm=true, const int nRBins=150, const float rMin=83.5, const float rMax=254.5, const int nPhiBins=720, const float zMax=1)
static std::vector< PadCoordinates > getStackCoordinatesSector()
create a vector of stack corner coordinate for one full sector
static std::array< int, 10 > markers
Definition Painter.h:61
static void fillHistogram2D(TH2 &h2D, const CalDet< T > &calDet, Side side)
static TMultiGraph * makeMultiGraph(TTree &tree, std::string_view varX, std::string_view varsY, std::string_view errVarsY="", std::string_view cut="", bool makeSparse=true)
static std::vector< o2::tpc::painter::PadCoordinates > getCoordinates(const Type type, std::string binningStr="")
static std::string getROCTitle(const int rocNumber)
ROC title from ROC number.
static std::vector< PadCoordinates > getFECCoordinatesSector()
create a vector of FEC corner coordinates for one full sector
static void drawSectorLocalPadNumberPoly(short padTextColor=kBlack, float lineScalePS=1)
static void adjustPalette(TH1 *h, float x2ndc, float tickLength=0.015)
static void fillPoly2D(TH2Poly &h2D, const CalDet< T > &calDet, Side side)
@ FEC
drawing of FECs
@ Stack
drawing stacks
@ SCD
drawing of FECs
static TH2 * getHistogram2D(const CalDet< T > &calDet, Side side)
static void drawSectorInformationPoly(short regionLineColor=kRed, short rowTextColor=kRed)
static void drawSectorsXY(Side side, int sectorLineColor=920, int sectorTextColor=1)
draw sector boundaris, side name and sector numbers
static std::vector< PadCoordinates > getPadCoordinatesSector()
create a vector of pad corner coordinate for one full sector
static TCanvas * makeJunkDetectionCanvas(const TObjArray *data, TCanvas *outputCanvas=nullptr)
make a canvas for junk detection data
static TCanvas * draw(const CalDet< T > &calDet, int nbins1D=300, float xMin1D=0, float xMax1D=0, TCanvas *outputCanvas=nullptr)
static std::vector< TCanvas * > makeSummaryCanvases(const CalDet< T > &calDet, int nbins1D=300, float xMin1D=0, float xMax1D=0, bool onlyFilled=true, std::vector< TCanvas * > *outputCanvases=nullptr)
static std::vector< std::string > tokenize(const std::string &src, char delim, bool trimToken=true, bool skipEmpty=true)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))
std::vector< int > row