CbmRoot
Loading...
Searching...
No Matches
CaQa.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko [committer] */
4
9
10#include "CaQa.h"
11
12#include "CaDefs.h"
13#include "CaInputData.h"
14#include "CaParameters.h"
15#include "CaTrack.h"
17
18#include <algorithm>
19#include <fstream>
20#include <limits>
21
22#include <fmt/format.h>
23
27
28// ---------------------------------------------------------------------------------------------------------------------
29//
30bool Qa::CheckInit() const
31{
32 bool res = true;
33 if (!fpParameters) {
34 L_(error) << "cbm::algo::ca::OutputQa::Build(): parameters object is undefined";
35 res = false;
36 }
37 if (!fpInputData) {
38 L_(error) << "cbm::algo::ca::OutputQa::Build(): input data object is undefined";
39 res = false;
40 }
41 if (!fpvTracks) {
42 L_(error) << "cbm::algo::ca::OutputQa::Build(): track vector is undefined";
43 res = false;
44 }
45 if (!fpvRecoHits) {
46 L_(error) << "cbm::algo::ca::OutputQa::Build(): used hit index vector is undefined";
47 res = false;
48 }
49 return res;
50}
51
52// ---------------------------------------------------------------------------------------------------------------------
53//
55{
62 using fmt::format;
63
64 if (!IsActive()) {
65 return;
66 }
67
68 const auto& rSetup = fpParameters->GetSetup(); // TODO: active -> geo
69 const auto& rActSetup = rSetup.GetActiveSetup();
70
71 // ********************
72 // ** Hit distributions
73 int nSt = rSetup.GetNofActStations(); // Number of active tracking stations
74 {
75 // Occupancy distributions
76 fvphHitOccupXY.resize(nSt);
77 fvphHitOccupZX.resize(nSt);
78 if (kDebug) {
79 fvphHitOccupZY.resize(nSt);
80 fvphHitUsageXY.resize(nSt);
81 }
82
83 // Station sizes in transverse plane
84 std::vector<double> vMinX(nSt);
85 std::vector<double> vMaxX(nSt);
86 std::vector<double> vMinY(nSt);
87 std::vector<double> vMaxY(nSt);
88
89 int nBinsXY = 200;
90 int nBinsZ = 400;
91
92 for (int iSt = 0; iSt < nSt; ++iSt) {
93 const auto& station = rActSetup.GetActiveLayer(iSt);
94 vMaxX[iSt] = station.GetXmax()[0];
95 vMinX[iSt] = station.GetXmin()[0];
96 vMaxY[iSt] = station.GetYmax()[0];
97 vMinY[iSt] = station.GetYmin()[0];
98 double dy = (vMaxY[iSt] - vMinY[iSt]) * kXYZMargin;
99 double dx = (vMaxX[iSt] - vMinX[iSt]) * kXYZMargin;
100 vMaxX[iSt] += dx;
101 vMinX[iSt] -= dx;
102 vMaxY[iSt] += dy;
103 vMinY[iSt] -= dy;
104 }
105 // Station max
106 double xMinA = *std::min_element(vMinX.begin(), vMinX.end());
107 double xMaxA = *std::max_element(vMaxX.begin(), vMaxX.end());
108 double yMinA = *std::min_element(vMinY.begin(), vMinY.end());
109 double yMaxA = *std::max_element(vMaxY.begin(), vMaxY.end());
110 double zMinA = rActSetup.GetActiveLayers().front().GetZref()[0];
111 double zMaxA = rActSetup.GetActiveLayers().back().GetZref()[0];
112 {
113 double dz = (zMaxA - zMinA) * kXYZMargin;
114 zMinA -= dz;
115 zMaxA += dz;
116 }
117 for (int iSt = 0; iSt < nSt; ++iSt) {
118 auto [detID, iStLoc] = rSetup.ActToLocStationId(iSt);
119 for (auto hitSet : kHitSets) {
120 auto setNm = EHitSet::Input == hitSet ? "input" : "used";
121 auto setTl = EHitSet::Input == hitSet ? "Input" : "Used";
122 {
123 auto name = format("hit_{}_occup_xy_sta_{}", setNm, iSt);
124 auto titl = format("{} hit occupancy in XY plane for station {} ({}{});x [cm];y [cm]", setTl, iSt,
125 kDetName[detID], iStLoc);
126 fvphHitOccupXY[iSt][hitSet] =
127 MakeObj<H2D>(name, titl, nBinsXY, vMinX[iSt], vMaxX[iSt], nBinsXY, vMinY[iSt], vMaxY[iSt]);
128 }
129 {
130 auto name = format("hit_{}_occup_zx_sta_{}", setNm, iSt);
131 auto titl = format("{} hit occupancy in ZX plane for station {} ({}{});z [cm];x [cm]", setTl, iSt,
132 kDetName[detID], iStLoc);
133 fvphHitOccupZX[iSt][hitSet] = MakeObj<H2D>(name, titl, nBinsZ, zMinA, zMaxA, nBinsXY, xMinA, xMaxA);
134 }
135 if (kDebug) {
136 auto name = format("hit_{}_occup_zy_sta_{}", setNm, iSt);
137 auto titl = format("{} hit occupancy in ZY plane for station {} ({}{});z [cm];y [cm]", setTl, iSt,
138 kDetName[detID], iStLoc);
139 fvphHitOccupZY[iSt][hitSet] = MakeObj<H2D>(name, titl, nBinsZ, zMinA, zMaxA, nBinsXY, yMinA, yMaxA);
140 }
141 }
142 if (kDebug) {
143 auto name = format("hit_usage_xy_sta_{}", iSt);
144 auto titl = format("Hit usage in XY plane for station {} ({}{});x [cm];y [cm]", iSt, kDetName[detID], iStLoc);
145 fvphHitUsageXY[iSt] =
146 MakeObj<Prof2D>(name, titl, nBinsXY, vMinX[iSt], vMaxX[iSt], nBinsXY, vMinY[iSt], vMaxY[iSt], 0., 1.);
147 }
148 }
149 if (kDebug) {
150 for (auto hitSet : kHitSets) {
151 constexpr int NBins = 1000000;
152 auto setNm = EHitSet::Input == hitSet ? "input" : "used";
153 auto setTl = EHitSet::Input == hitSet ? "Input" : "Used";
154 {
155 auto name = format("hit_{}_front_key_index", setNm);
156 auto titl = format("{} hit front key index;ID_{{key}}/N_{{keys}};Count", setTl);
157 fvphHitFrontKeyIndex[hitSet] = MakeObj<H1D>(name, titl, NBins, 0., 1.);
158 }
159 {
160 auto name = format("hit_{}_back_key_index", setNm);
161 auto titl = format("{} hit back key index;ID_{{key}}/N_{{keys}};Count", setTl);
162 fvphHitBackKeyIndex[hitSet] = MakeObj<H1D>(name, titl, NBins, 0., 1.);
163 }
164 }
165 }
166
167 // Hit time distributions
168 if (kDebug) {
169 fvphHitTime.resize(nSt + 1); // [nSt] - total over stations
170 for (int iSt = 0; iSt < nSt + 1; ++iSt) {
171 auto staNm = iSt == nSt ? "" : format("_sta_{}", iSt);
172 auto staTl = iSt == nSt ? "" : format(" in station {}", iSt);
173 for (auto hitSet : kHitSets) {
174 auto setNm = EHitSet::Input == hitSet ? "input" : "used";
175 auto setTl = EHitSet::Input == hitSet ? "Input" : "Used";
176 auto name = format("hit_{}_rel_time{}", setNm, staNm);
177 auto titl = format("{} hit relative time{}; #delta t_{{hit}};Count", setTl, staTl);
178 fvphHitTime[iSt][hitSet] = MakeObj<H1D>(name, titl, 10000, -0.1, 1.1);
179 }
180 }
181 }
182 }
183
184 // **********************
185 // ** Track distributions
186 std::vector<std::string> vsPointName = {"first", "last"};
187 for (int i = 0; i < knTrkParPoints; ++i) {
188 if (!kDebug && i > 0) {
189 continue;
190 }
191 {
192 auto sName = format("{}_track_{}_theta", GetTaskName(), vsPointName[i]);
193 auto sTitl = format("#theta at {} hit; #theta", vsPointName[i]);
194 fvphTrkTheta[i] = MakeObj<H1D>(sName, sTitl, 62, 0., 90.);
195 }
196 {
197 auto sName = format("{}_track_{}_phi", GetTaskName(), vsPointName[i]);
198 auto sTitl = format("#phi at {} hit; #phi", vsPointName[i]);
199 fvphTrkPhi[i] = MakeObj<H1D>(sName, sTitl, 62, -180., 180.);
200 }
201 {
202 auto sName = format("{}_track_{}_thata_phi", GetTaskName(), vsPointName[i]);
203 auto sTitl = format("#theta vs #phi at {} hit; #phi; #theta", vsPointName[i]);
204 fvphTrkPhiTheta[i] = MakeObj<H2D>(sName, sTitl, 62, -180., 180., 62, 0., 90.);
205 }
206 {
207 auto sName = format("{}_track_{}_chi2_ndf", GetTaskName(), vsPointName[i]);
208 auto sTitl = format("#chi^{{2}}/NDF at {} hit; #chi^{{2}}/NDF", vsPointName[i]);
209 fvphTrkChi2Ndf[i] = MakeObj<H1D>(sName, sTitl, 100, 0., 20.);
210 }
211 }
212 {
213 int nBins = knStaMax;
214 double xMin = -0.5;
215 double xMax = double(knStaMax) - 0.5;
216 {
217 auto sName = format("{}_track_fst_lst_sta", GetTaskName());
218 auto sTitl = "First vs. last station index;ID^{last}_{station};ID^{first}_{station}";
219 fphTrkFstLstSta = MakeObj<H2D>(sName, sTitl, nBins, xMin, xMax, nBins, xMin, xMax);
220 }
221 {
222 auto sName = format("{}_track_origin", GetTaskName());
223 auto sTitl = "Track origin;x [cm];y [cm]";
225 }
226 fphTrkNofHits = MakeObj<H1D>("n_hits", "Number of hits;N_{hit}", nBins, xMin, xMax);
227 }
228
229 // ---- Init canvases
230 {
231 // Input hits canvas
232 {
233 for (auto hitSet : kHitSets) {
234 auto setNm = EHitSet::Input == hitSet ? "input" : "used";
235 auto setTl = EHitSet::Input == hitSet ? "Input" : "Used";
236 { // XY
237 auto name = format("{}_ca_hit_{}_occupancy_xy", GetTaskName(), setNm);
238 auto titl = format("{} hit occupancy in different stations in XY plane", setNm);
239 auto canv = CanvasConfig(name, titl);
240 for (int iSt = 0; iSt < nSt; ++iSt) {
241 auto pad = PadConfig(false, false, false, false, true);
242 pad.RegisterHistogram(fvphHitOccupXY[iSt][hitSet], "colz");
243 canv.AddPadConfig(pad);
244 }
245 AddCanvasConfig(canv);
246 }
247 { // ZX and ZY
248 auto name = format("{}_ca_hit_{}_occupancy_zx_zy", GetTaskName(), setNm);
249 auto titl = format("{} hit occupancy in different stations in ZX and ZY planes", setTl);
250 auto canv = CanvasConfig(name, titl);
251 { // ZX
252 auto pad = PadConfig();
253 for (int iSt = 0; iSt < nSt; ++iSt) {
254 pad.RegisterHistogram(fvphHitOccupZX[iSt][hitSet], (iSt == 0 ? "colz" : "cols same"));
255 }
256 canv.AddPadConfig(pad);
257 }
258 if (kDebug) { // ZY
259 auto pad = PadConfig();
260 for (int iSt = 0; iSt < nSt; ++iSt) {
261 pad.RegisterHistogram(fvphHitOccupZY[iSt][hitSet], (iSt == 0 ? "colz" : "cols same"));
262 }
263 canv.AddPadConfig(pad);
264 }
265 AddCanvasConfig(canv);
266 }
267 }
268 if (kDebug) {
269 auto name = format("{}_ca_hit_usage_xy", GetTaskName());
270 auto titl = format("Hit usage in different stations in XY plane");
271 auto canv = CanvasConfig(name, titl);
272 for (int iSt = 0; iSt < nSt; ++iSt) {
273 auto pad = PadConfig();
274 pad.RegisterHistogram(fvphHitUsageXY[iSt], "colz");
275 canv.AddPadConfig(pad);
276 }
277 AddCanvasConfig(canv);
278 }
279 }
280
281 // Tracks canvas
282 {
283 auto canv = CanvasConfig(format("{}_ca_tracks", GetTaskName()), "Tracking output QA");
284 {
285 auto pad = PadConfig(true, true, false, false, true);
286 pad.RegisterHistogram(fvphTrkPhiTheta[0], "colz");
287 canv.AddPadConfig(pad);
288 }
289 {
290 auto pad = PadConfig(true, true, false, false, false);
291 pad.RegisterHistogram(fvphTrkChi2Ndf[0], "hist");
292 canv.AddPadConfig(pad);
293 }
294 {
295 auto pad = PadConfig(true, true, false, true, false);
296 pad.RegisterHistogram(fphTrkNofHits, "hist");
297 canv.AddPadConfig(pad);
298 }
299 {
300 auto pad = PadConfig(true, true, false, false, true);
301 pad.RegisterHistogram(fphTrkFstLstSta, "colz");
302 canv.AddPadConfig(pad);
303 }
304 {
305 auto pad = PadConfig(true, true, false, false, false);
306 pad.RegisterHistogram(fphTrkOriginXY, "colz");
307 canv.AddPadConfig(pad);
308 }
309 AddCanvasConfig(canv);
310 }
311 }
312}
313
314// ---------------------------------------------------------------------------------------------------------------------
315//
317{
318 if (!IsActive()) {
319 return;
320 }
321
322 if (!CheckInit()) {
323 L_(fatal) << "ca::Qa: instance is not initialized";
324 assert(false);
325 }
326
327 int nHitsInput = fpInputData->GetNhits();
328 // Map: if hit used in tracking
329 std::vector<unsigned char> vbHitUsed(nHitsInput, false);
330 for (int iH : (*fpvRecoHits)) {
331 vbHitUsed[iH] = true;
332 }
333
334 // Calculate max and min hit time
335 if constexpr (kDebug) {
336 const auto& hits = fpInputData->GetHits();
337 auto [minTimeIt, maxTimeIt] =
338 std::minmax_element(hits.cbegin(), hits.cend(), [](const auto& h1, const auto& h2) { return h1.T() < h2.T(); });
339 fMinHitTime = minTimeIt->T();
340 fMaxHitTime = maxTimeIt->T();
341 }
342
343 // Fill input hit histograms
344 {
345 for (int iH = 0; iH < nHitsInput; ++iH) {
346 const auto& hit = fpInputData->GetHit(iH);
348 if (vbHitUsed[iH]) {
350 }
351 if constexpr (kDebug) {
352 int iSt = hit.Station();
353 double x = hit.X();
354 double y = hit.Y();
355 fvphHitUsageXY[iSt]->Fill(x, y, static_cast<double>(vbHitUsed[iH]));
356 }
357 }
358 }
359
360 // Fill track histograms
361 {
362 int trkFirstHit = 0; // Index of hit in fpvRecoHits
363 for (auto trkIt = fpvTracks->begin(); trkIt != fpvTracks->end(); ++trkIt) {
364 auto& track = *trkIt;
365 int nHits = track.fNofHits;
366 // Indices of hits in fpInputData->GetHits()
367 int iFstHit = (*fpvRecoHits)[trkFirstHit];
368 int iLstHit = (*fpvRecoHits)[trkFirstHit + nHits - 1];
369
370 // Distributions in different track points
371 for (int ip = 0; ip < knTrkParPoints; ++ip) {
372 if (!kDebug && ip > 0) {
373 continue;
374 }
375 //int iHit = (ip == 0 ? iFstHit : iLstHit);
376 //const auto& hit = fpInputData->GetHit(iHit);
377 const auto& trkPar = (ip == 0 ? track.fParFirst : track.fParLast);
378 fvphTrkTheta[ip]->Fill(trkPar.GetTheta() * 180. / Pi);
379 fvphTrkPhi[ip]->Fill(trkPar.GetPhi() * 180. / Pi);
380 fvphTrkPhiTheta[ip]->Fill(trkPar.GetPhi() * 180. / Pi, trkPar.GetTheta() * 180. / Pi);
381 fvphTrkChi2Ndf[ip]->Fill(trkPar.GetChiSq() / trkPar.GetNdf());
382 }
383 // Other distributions
384 fphTrkFstLstSta->Fill(fpInputData->GetHit(iLstHit).Station(), fpInputData->GetHit(iFstHit).Station());
385 fphTrkNofHits->Fill(nHits);
386 fphTrkOriginXY->Fill(track.fParPV.X(), track.fParPV.Y());
387 trkFirstHit += nHits;
388 }
389 }
390}
391
392// ---------------------------------------------------------------------------------------------------------------------
393//
395{
396 int nSt = fpParameters->GetNstationsActive();
397 int iSt = hit.Station();
398 double x = hit.X();
399 double y = hit.Y();
400 double z = hit.Z();
401 fvphHitOccupXY[iSt][hitSet]->Fill(x, y);
402 fvphHitOccupZX[iSt][hitSet]->Fill(z, x);
403 if constexpr (kDebug) {
404 fvphHitOccupZY[iSt][hitSet]->Fill(z, y);
405 auto nKeys = static_cast<double>(fpInputData->GetNhitKeys());
406 fvphHitFrontKeyIndex[hitSet]->Fill(hit.FrontKey() / nKeys);
407 fvphHitBackKeyIndex[hitSet]->Fill(hit.BackKey() / nKeys);
408 double relTime = (hit.T() - fMinHitTime) / (fMaxHitTime - fMinHitTime);
409 fvphHitTime[iSt][hitSet]->Fill(relTime);
410 fvphHitTime[nSt][hitSet]->Fill(relTime);
411 }
412}
#define L_(level)
Compile-time constants definition for the CA tracking algorithm.
Structure for input data to the L1 tracking algorithm (declaration)
constexpr double Pi
Value of PI, used in ROOT TMath.
Definition CaDefs.h:103
A QA module for CA tracking (header)
source file for the ca::Track class
static vector< vector< QAHit > > hits
Definitions for tracking in the online reconstruction.
A pad configuration for the histogram server.
Definition PadConfig.h:26
ca::Hit class describes a generic hit for the CA tracker
Definition CaHit.h:32
fscal Z() const
Get the Z coordinate.
Definition CaHit.h:108
HitKeyIndex_t BackKey() const
Get the back key index.
Definition CaHit.h:99
fscal Y() const
Get the Y coordinate.
Definition CaHit.h:105
HitKeyIndex_t FrontKey() const
Get the front key index.
Definition CaHit.h:96
fscal T() const
Get the time.
Definition CaHit.h:111
fscal X() const
Get the X coordinate.
Definition CaHit.h:102
int Station() const
Get the station index.
Definition CaHit.h:138
void Exec()
QA execution function.
Definition CaQa.cxx:316
bool CheckInit() const
Check initialization.
Definition CaQa.cxx:30
std::vector< HitSetArray_t< qa::H1D * > > fvphHitTime
Time distribution of hits.
Definition CaQa.h:143
OccupHistContainer_t fvphHitOccupXY
hist: Hit occupancy in different stations in XY plane
Definition CaQa.h:134
static constexpr double kOriginL
Track X(Y) at origin: lower bound [cm].
Definition CaQa.h:121
const Vector< Track > * fpvTracks
Pointer to tracks vector.
Definition CaQa.h:129
static constexpr int knStaMax
Max number of stations (histogram binning)
Definition CaQa.h:118
std::array< qa::H1D *, knTrkParPoints > fvphTrkPhi
hist: phi at first/last hit
Definition CaQa.h:147
void Init()
Initializes the QA.
Definition CaQa.cxx:54
void FillHitDistributionsForHitSet(EHitSet hitSet, const ca::Hit &hit)
Fills hit distributions.
Definition CaQa.cxx:394
static constexpr HitSetArray_t< EHitSet > kHitSets
Array of EHitSet entries for iteration.
Definition CaQa.h:54
HitSetArray_t< qa::H1D * > fvphHitBackKeyIndex
Indices of back hit keys.
Definition CaQa.h:141
std::vector< qa::Prof2D * > fvphHitUsageXY
prof: Hit usage in different stations in XY plane
Definition CaQa.h:138
static constexpr double kXYZMargin
Margin for occupancy distributions in XY plane.
Definition CaQa.h:115
double fMinHitTime
Definition CaQa.h:124
HitSetArray_t< qa::H1D * > fvphHitFrontKeyIndex
Indices of front hit keys.
Definition CaQa.h:140
static constexpr int knTrkParPoints
Number of track points to build par distributions.
Definition CaQa.h:117
const Vector< HitIndex_t > * fpvRecoHits
Pointer to reco hit indices.
Definition CaQa.h:130
qa::H2D * fphTrkOriginXY
hist: origin of tracks in x-y plane [cm]
Definition CaQa.h:151
qa::H1D * fphTrkNofHits
hist: number of hits in track
Definition CaQa.h:153
OccupHistContainer_t fvphHitOccupZX
hist: Hit occupancy in different stations in ZX plane
Definition CaQa.h:135
qa::H2D * fphTrkFstLstSta
hist: fst vs lst station index
Definition CaQa.h:152
double fMaxHitTime
Definition CaQa.h:125
const InputData * fpInputData
Pointer to input data.
Definition CaQa.h:128
static constexpr double kOriginU
Track X(Y) at origin: upper bound [cm].
Definition CaQa.h:122
static constexpr bool kDebug
Additional histograms.
Definition CaQa.h:119
OccupHistContainer_t fvphHitOccupZY
hist: Hit occupancy in different stations in ZY plane
Definition CaQa.h:136
std::array< qa::H1D *, knTrkParPoints > fvphTrkChi2Ndf
hist: chi2/NDF at first/last hit
Definition CaQa.h:148
std::array< qa::H2D *, knTrkParPoints > fvphTrkPhiTheta
hist: theta vs. phi at first/last hit
Definition CaQa.h:149
std::array< qa::H1D *, knTrkParPoints > fvphTrkTheta
hist: theta at first/last hit
Definition CaQa.h:146
static constexpr int kOriginB
Track X(Y) at origin: n bins.
Definition CaQa.h:120
const Parameters< fvec > * fpParameters
Pointer to tracking parameters.
Definition CaQa.h:127
EHitSet
Hit set entries.
Definition CaQa.h:43
@ Used
Hits used in tracks.
Definition CaQa.h:45
@ Input
Input hits.
Definition CaQa.h:44
A canvas configuration for the histogram server.
Class to handle QA-objects in the online reconstruction.
Definition QaData.h:27
1D-histogram
Definition Histogram.h:442
2D-histogram
Definition Histogram.h:511
A pad configuration for the histogram server.
Definition PadConfig.h:26
const std::string & GetTaskName()
Gets name of the task.
void AddCanvasConfig(const CanvasConfig &canvas)
Adds a canvas configuration.
bool IsActive() const
Checks, if the task is active.
Obj * MakeObj(Args... args)
Creates a QA-object and returns the pointer to it.
constexpr double Pi
Value of PI, used in ROOT TMath.
Definition CaDefs.h:103
constexpr DetIdArray_t< const char * > kDetName
Detector subsystem names.