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