CbmRoot
Loading...
Searching...
No Matches
CbmCaInputQaBase.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko [committer] */
4
9
10#include "CbmCaInputQaBase.h"
11
12#include "CaDefs.h"
13#include "CbmAddress.h"
14#include "CbmDigiManager.h"
15#include "CbmL1DetectorID.h"
16#include "CbmMCDataArray.h"
17#include "CbmMCEventList.h"
18#include "CbmMCTrack.h"
19#include "CbmMatch.h"
20#include "CbmMuchPixelHit.h"
21#include "CbmMuchPoint.h"
22#include "CbmMvdDigi.h"
23#include "CbmMvdHit.h"
24#include "CbmMvdPoint.h"
25#include "CbmQaTable.h"
26#include "CbmQaUtil.h"
27#include "CbmStsCluster.h"
28#include "CbmStsHit.h"
29#include "CbmStsPoint.h"
30#include "CbmTimeSlice.h"
31#include "CbmTofAddress.h"
32#include "CbmTofHit.h"
33#include "CbmTofPoint.h"
34#include "CbmTrdHit.h"
35#include "CbmTrdPoint.h"
36#include "FairMCPoint.h"
37#include "FairRootManager.h"
38#include "Logger.h"
39#include "TBox.h"
40#include "TCanvas.h"
41#include "TClonesArray.h"
42#include "TEllipse.h"
43#include "TF1.h"
44#include "TFormula.h"
45#include "TGraphAsymmErrors.h"
46#include "TH1F.h"
47#include "TH2F.h"
48#include "TMath.h"
49#include "TProfile.h"
50#include "TProfile2D.h"
51#include "TStyle.h"
52
53#include <algorithm>
54#include <bitset>
55#include <fstream>
56#include <iomanip>
57#include <numeric>
58#include <tuple>
59
60using namespace cbm::algo::ca::constants;
61
62namespace
63{
64 namespace ca = cbm::algo::ca;
65}
66
67// ---------------------------------------------------------------------------------------------------------------------
68//
69template<ca::EDetectorID DetID>
70CbmCaInputQaBase<DetID>::CbmCaInputQaBase(const char* name, int verbose, bool isMCUsed)
71 : CbmQaTask(name, verbose, isMCUsed)
72{
74}
75
76// ---------------------------------------------------------------------------------------------------------------------
77//
78template<ca::EDetectorID DetID>
80{
81 LOG(info) << "\n\n ** Checking the " << fName << " **\n\n";
82
83 int nSt = fpDetInterface->GetNofTrackingStations();
84
85 // **************************************************************
86 // ** Basic checks, available both for real and simulated data **
87 // **************************************************************
88
89 // Fill efficiency distributions
90
91 if (IsMCUsed()) {
92 for (int iSt = 0; iSt < nSt; ++iSt) {
93 TProfile2D* effxy = fvpe_reco_eff_vs_xy[iSt];
94 for (int i = 1; i < effxy->GetNbinsX() - 1; i++) {
95 for (int j = 1; j < effxy->GetNbinsY() - 1; j++) {
96 int bin = effxy->GetBin(i, j);
97 if (effxy->GetBinEntries(bin) >= 1) {
98 fvph_reco_eff[iSt]->Fill(effxy->GetBinContent(bin));
99 fvph_reco_eff[nSt]->Fill(effxy->GetBinContent(bin));
100 }
101 }
102 }
103 }
104 }
105
106 // ----- Checks for mismatches in the ordering of the stations
107 //
108 {
109 bool res = true;
110
111 std::vector<double> vStationPos(nSt, 0.);
112 for (int iSt = 0; iSt < nSt; ++iSt) {
113 vStationPos[iSt] = fpDetInterface->GetFullVolume(iSt).GetCenterZ();
115
116 if (!std::is_sorted(vStationPos.cbegin(), vStationPos.cend(), [](int l, int r) { return l <= r; })) {
117 if (fVerbose > 0) {
118 LOG(error) << fName << ": stations are ordered improperly along the beam axis:";
119 for (auto z : vStationPos) {
120 LOG(error) << "\t- " << z;
121 }
122 }
123 res = false;
124 }
125 StoreCheckResult("station_position_ordering", res);
126 }
127 // ----- Checks for mismatch between station and hit z positions
128 // The purpose of this block is to be ensured, that hits belong to the correct tracking station. For each tracking
129 // station a unified position z-coordinate is defined, which generally differs from the corresponding positions of
130 // reconstructed hits. This is due to non-regular position along the beam axis for each detector sensor. Thus, the
131 // positions of the hits along z-axis are distributed relatively to the position of the station in some range.
132 // If hits goes out this range, it can signal about a mismatch between hits and geometry. For limits of the range
133 // one should select large enough values to cover the difference described above and in the same time small enough
134 // to avoid overlaps with the neighboring stations.
135 // For each station, a distribution of z_{hit} - z_{st} is integrated over the defined range and scaled by the
136 // total number of entries to the distribution. If this value is smaller then unity, then some of the hits belong to
137 // another station.
138 //
139 {
140 bool res = true;
141 std::stringstream msgs;
142 msgs.precision(3);
143 for (int iSt = 0; iSt < nSt; ++iSt) {
144 int nHits = fvph_hit_station_delta_z[iSt]->GetEntries();
145 if (!nHits) {
146 LOG_IF(error, fVerbose > 0) << fName << ": station " << iSt << " does not have hits";
147 res = false;
148 continue;
149 }
150 int iBinMin = fvph_hit_station_delta_z[iSt]->FindBin(-fConfig.fMaxDiffZStHit);
151 int iBinMax = fvph_hit_station_delta_z[iSt]->FindBin(+fConfig.fMaxDiffZStHit);
152
153 auto nHitsWithin = fvph_hit_station_delta_z[iSt]->Integral(iBinMin, iBinMax);
154 if (nHitsWithin < nHits) {
155 if (!msgs.str().empty()) {
156 msgs << ", ";
157 }
158 msgs << (static_cast<double>((nHits - nHitsWithin) * 100) / nHits) << "% (st. " << iSt << ")";
159 res = false;
160 }
161 }
162 std::string msg = msgs.str().empty() ? "" : Form("Out of range z = +-%.2f cm: ", fConfig.fMaxDiffZStHit);
163 if (!msg.empty()) {
164 msg += msgs.str();
165 }
166 StoreCheckResult("station_position_hit_delta_z", res, msg);
167 }
168
169 // *******************************************************
170 // ** Additional checks, if MC information is available **
171 // *******************************************************
172
173 if (IsMCUsed()) {
174 // ----- Check efficiencies
175 // Error is raised, if any station has integrated efficiency lower then a selected threshold.
176 // Integrated efficiency is estimated with fitting the efficiency curve for hit distances (r) with a uniform
177 // distribution in the range from kEffRangeMin to kEffRangeMax, where the efficiency is assigned to be constant
178 //
179 // Fit efficiency curves
180 {
181 LOG(info) << "-- Hit efficiency integrated over hit distance from station center";
182
183 auto* pEffTable = MakeQaObject<CbmQaTable>("vs Station/eff_table", "Efficiency table", nSt, 1);
184 pEffTable->SetNamesOfCols({"Efficiency"});
185 pEffTable->SetColWidth(20);
186
187 for (int iSt = 0; iSt < nSt; ++iSt) {
188 auto eff = fvph_reco_eff[iSt]->GetMean(); // FIXME (GetMean(>>>2<<<))
189 pEffTable->SetRowName(iSt, Form("station %d", iSt));
190 pEffTable->SetCell(iSt, 0, eff);
191 bool res = CheckRange("Hit finder efficiency in station " + std::to_string(iSt), eff, fConfig.fEffThrsh, 1.000);
192 std::string msg = (res ? "" : Form("efficiency = %f lower then threshold = %f", eff, fConfig.fEffThrsh));
193 StoreCheckResult(Form("hit_efficiency_station_%d", iSt), res, msg);
194 }
195 LOG(info) << '\n' << pEffTable->ToString(3);
196 }
197
198 // ----- Checks for residuals
199 // Check hits for potential biases from central values
200 {
201 auto* pResidualsTable =
202 MakeQaObject<CbmQaTable>("vs Station/residuals_mean", "Residual mean values in different stations", nSt, 3);
203 pResidualsTable->SetNamesOfCols({"Residual(x) [cm]", "Residual(y) [cm]", "Residual(t) [ns]"});
204 pResidualsTable->SetColWidth(20);
205
206 // Fit residuals
207 for (int iSt = 0; iSt <= nSt; ++iSt) {
208
209 cbm::qa::util::SetLargeStats(fvph_res_x[iSt]);
210 cbm::qa::util::SetLargeStats(fvph_res_y[iSt]);
211 cbm::qa::util::SetLargeStats(fvph_res_t[iSt]);
212
213 pResidualsTable->SetRowName(iSt, Form("station %d", iSt));
214 pResidualsTable->SetCell(iSt, 0, fvph_res_x[iSt]->GetStdDev());
215 pResidualsTable->SetCell(iSt, 1, fvph_res_y[iSt]->GetStdDev());
216 pResidualsTable->SetCell(iSt, 2, fvph_res_t[iSt]->GetStdDev());
217 }
218 LOG(info) << '\n' << pResidualsTable->ToString(8);
219 }
220 // ----- Checks for pulls
221 //
222 // For the hit pull is defined as a ration of the difference between hit and MC-point position or time component
223 // values and an error of the hit position (or time) component, calculated in the same z-positions. In ideal case,
224 // when the resolutions are well determined for detecting stations, the pull distributions should have a RMS equal
225 // to unity. Here we allow a RMS of the pull distributions to be varied in a predefined range. If the RMS runs out
226 // this range, QA task fails.
227 {
228 std::vector<CbmQaTable*> vpPullTables = {
229 // {x, y, t}
230 MakeQaObject<CbmQaTable>("vs Station/pulls_x", "x-coordinate pull quantities in diff. stations", nSt, 2),
231 MakeQaObject<CbmQaTable>("vs Station/pulls_y", "y-coordinate pull quantities in diff. stations", nSt, 2),
232 MakeQaObject<CbmQaTable>("vs Station/pulls_t", "Time pull quantities in diff. stations", nSt, 2)};
233
234 for (auto* pullTable : vpPullTables) {
235 pullTable->SetNamesOfCols({"mean", "std.dev."});
236 pullTable->SetColWidth(20);
237 }
238
239 // NOTE: The table format is assumed: mean | 3.5 * mean err. | sigm | 3.5 * sigm err. |
240 auto DefinePullTableRow = [&](const TH1* h, CbmQaTable* table, int iSt) {
241 table->SetCell(iSt, 0, h->GetMean(), 3.5 * h->GetMeanError());
242 table->SetCell(iSt, 1, h->GetStdDev(), 3.5 * h->GetStdDevError());
243 };
244
245 for (int iSt = 0; iSt < nSt + 1; ++iSt) {
246 // Fit pull distributions for nicer representation. Fit results are not used in further checks.
247 cbm::qa::util::SetLargeStats(fvph_pull_x[iSt]);
248 cbm::qa::util::SetLargeStats(fvph_pull_y[iSt]);
249 cbm::qa::util::SetLargeStats(fvph_pull_t[iSt]);
250
251 for (auto* pullTable : vpPullTables) {
252 pullTable->SetRowName(iSt, (iSt == nSt ? "all stations" : Form("station %u", iSt)));
253 }
254 // Check the pull quality
255 {
256 auto [msg, status] = CheckRangePull(fvph_pull_x[iSt]);
257 StoreCheckResult(Form("pull_x_station_%d", iSt), status, msg);
258 DefinePullTableRow(fvph_pull_x[iSt], vpPullTables[0], iSt);
259 }
260 {
261 auto [msg, status] = CheckRangePull(fvph_pull_y[iSt]);
262 StoreCheckResult(Form("pull_y_station_%d", iSt), status, msg);
263 DefinePullTableRow(fvph_pull_y[iSt], vpPullTables[1], iSt);
264 }
265 {
266 auto [msg, status] = CheckRangePull(fvph_pull_t[iSt]);
267 StoreCheckResult(Form("pull_t_station_%d", iSt), status, msg);
268 DefinePullTableRow(fvph_pull_t[iSt], vpPullTables[2], iSt);
269 }
270 }
271
272 for (auto* pullTable : vpPullTables) {
273 LOG(info) << '\n' << pullTable->ToString(3, true);
274 }
275 }
276 } // McUsed
277
278 // Print out monitor
279 LOG(info) << fMonitor.ToString();
280}
281
282// ---------------------------------------------------------------------------------------------------------------------
283//
284template<ca::EDetectorID DetID>
285std::pair<std::string, bool> CbmCaInputQaBase<DetID>::CheckRangePull(TH1* h) const
286{
287 constexpr double factor = 3.5;
288 // Function to check overflow and underflow
289 constexpr auto Check = [&](double val, double err, double min, double max) -> std::pair<std::string, bool> {
290 std::stringstream msg;
291 bool res;
292 if (val + factor * err < min) {
293 msg << "underflow: " << val << " < " << min << " - " << factor << " x " << err;
294 res = false;
295 }
296 if (val - factor * err > max) {
297 msg << "overflow: " << val << " > " << max << " + " << factor << " x " << err;
298 res = false;
299 }
300 return std::make_pair(msg.str(), res);
301 };
302
303 std::pair<std::string, bool> ret = {"", true};
304 if (h->GetEntries() >= 10) {
305 // Mean check
306 {
307 auto [msg, res] = Check(h->GetMean(), h->GetMeanError(), -fConfig.fPullMeanThrsh, +fConfig.fPullMeanThrsh);
308 if (!msg.empty()) {
309 ret.first += "mean ";
310 ret.first += msg;
311 ret.second = res;
312 }
313 }
314 // Sigma check
315 {
316 auto [msg, res] =
317 Check(h->GetStdDev(), h->GetStdDevError(), 1. - fConfig.fPullWidthThrsh, 1. + fConfig.fPullWidthThrsh);
318 if (!msg.empty()) {
319 if (!ret.first.empty()) {
320 ret.first += "; ";
321 }
322 ret.first += "std.dev. ";
323 ret.first += msg;
324 ret.second = res;
325 }
326 }
327 }
328 return ret;
329}
330
331
332// ---------------------------------------------------------------------------------------------------------------------
333//
334template<ca::EDetectorID DetID>
336{
337 // Vectors with pointers to histograms
338 fvph_hit_xy.clear();
339 fvph_hit_zx.clear();
340 fvph_hit_zy.clear();
341
343
344 fvph_hit_dx.clear();
345 fvph_hit_dy.clear();
346 fvph_hit_du.clear();
347 fvph_hit_dv.clear();
348 fvph_hit_kuv.clear();
349 fvph_hit_dt.clear();
350
351 fvph_n_points_per_hit.clear();
352
353 fvph_point_xy.clear();
354 fvph_point_zx.clear();
355 fvph_point_zy.clear();
356
358
359 fvph_res_x.clear();
360 fvph_res_y.clear();
361 fvph_res_u.clear();
362 fvph_res_v.clear();
363 fvph_res_t.clear();
364
365 fvph_pull_x.clear();
366 fvph_pull_y.clear();
367 fvph_pull_u.clear();
368 fvph_pull_v.clear();
369 fvph_pull_t.clear();
370
371 fvph_res_x_vs_x.clear();
372 fvph_res_y_vs_y.clear();
373 fvph_res_u_vs_u.clear();
374 fvph_res_v_vs_v.clear();
375 fvph_res_t_vs_t.clear();
376
377 fvph_pull_x_vs_x.clear();
378 fvph_pull_y_vs_y.clear();
379 fvph_pull_u_vs_u.clear();
380 fvph_pull_v_vs_v.clear();
381 fvph_pull_t_vs_t.clear();
382
383 fvpe_reco_eff_vs_xy.clear();
384 fvph_reco_eff.clear();
385}
386
387// ---------------------------------------------------------------------------------------------------------------------
388//
389template<ca::EDetectorID DetID>
391{
392 const int nSt = fpDetInterface->GetNofTrackingStations();
393 const int nHits = fpHits->GetEntriesFast();
394 const int nMCevents = (IsMCUsed()) ? fpMCEventList->GetNofEvents() : -1;
395
396 // TODO: SZh 06.09.2023: Probably, this approach can fail, if there are several input files are used. Thus I propose
397 // to use unordered_map with a CbmLink key type.
398 std::vector<std::vector<std::vector<int>>>
399 vNofHitsPerMcTrack; // Number of hits per MC track per station in different MC events
400
401 if (IsMCUsed()) {
402 vNofHitsPerMcTrack.resize(nMCevents);
403 for (int iE = 0; iE < nMCevents; ++iE) {
404 int iFile = fpMCEventList->GetFileIdByIndex(iE);
405 int iEvent = fpMCEventList->GetEventIdByIndex(iE);
406 int nMcTracks = fpMCTracks->Size(iFile, iEvent);
407 vNofHitsPerMcTrack[iE].resize(nSt);
408 for (int iSt = 0; iSt < nSt; iSt++) {
409 vNofHitsPerMcTrack[iE][iSt].resize(nMcTracks, 0);
410 }
411 }
412 }
413
414 for (int iH = 0; iH < nHits; ++iH) {
415 fHitQaData.Reset();
416 fHitQaData.SetHitIndex(iH);
417
418 const auto* pHit = dynamic_cast<const CbmPixelHit*>(fpHits->At(iH));
419 if (!pHit) {
420 LOG(error) << fName << ": hit with iH = " << iH << " is not an CbmStsHit (dynamic cast failed)";
421 continue;
422 }
423
424 if constexpr (ca::EDetectorID::kTof == DetID) {
425 auto address = pHit->GetAddress();
426 if (5 == CbmTofAddress::GetSmType(address)) {
427 continue;
428 } // Skip Bmon hits
429 }
430
431 fMonitor.IncrementCounter(EMonitorKey::kHit);
432 fMonitor.IncrementCounter(EMonitorKey::kHitAccepted);
433
434 // *************************
435 // ** Reconstructed hit QA
436
437 // Hit station geometry info
438 int iSt = fpDetInterface->GetTrackingStationId(pHit->GetAddress());
439 if (iSt < 0) {
440 continue;
441 }
442
443 if (iSt >= nSt) {
444 LOG(error) << fName << ": index of station (" << iSt << ") is out of range for hit with id = " << iH;
445 continue;
446 }
447
448 //auto [stPhiU, stPhiV] = fpDetInterface->GetStereoAnglesSensor(pHit->GetAddress());
449
450 //fHitQaData.SetPhiU(stPhiU);
451 //fHitQaData.SetPhiV(stPhiV);
452 fHitQaData.SetHitX(pHit->GetX());
453 fHitQaData.SetHitY(pHit->GetY());
454 fHitQaData.SetHitZ(pHit->GetZ());
455 fHitQaData.SetHitTime(pHit->GetTime());
456
457 fHitQaData.SetHitDx(pHit->GetDx());
458 fHitQaData.SetHitDy(pHit->GetDy());
459 fHitQaData.SetHitDxy(pHit->GetDxy());
460 fHitQaData.SetHitTimeError(pHit->GetTimeError());
461 fHitQaData.SetStationID(iSt);
462
463 // Per station distributions
464 fvph_hit_xy[iSt]->Fill(fHitQaData.GetHitX(), fHitQaData.GetHitY());
465 fvph_hit_zx[iSt]->Fill(fHitQaData.GetHitZ(), fHitQaData.GetHitX());
466 fvph_hit_zy[iSt]->Fill(fHitQaData.GetHitZ(), fHitQaData.GetHitY());
467
468 const auto& actVol = fpDetInterface->GetActiveVolume(iSt);
469 fvph_hit_station_delta_z[iSt]->Fill(fHitQaData.GetHitZ() - actVol.GetCenterZ());
470
471 //fvph_hit_dx[iSt]->Fill(fHitQaData.GetHitDx());
472 //fvph_hit_dy[iSt]->Fill(fHitQaData.GetHitDy());
473 //fvph_hit_du[iSt]->Fill(fHitQaData.GetHitDu());
474 //fvph_hit_dv[iSt]->Fill(fHitQaData.GetHitDv());
475 fvph_hit_kuv[iSt]->Fill(fHitQaData.GetHitRuv());
476 fvph_hit_dt[iSt]->Fill(fHitQaData.GetHitTimeError());
477
478 // Sum over station distributions
479 fvph_hit_xy[nSt]->Fill(fHitQaData.GetHitX(), fHitQaData.GetHitY());
480 fvph_hit_zx[nSt]->Fill(fHitQaData.GetHitZ(), fHitQaData.GetHitX());
481 fvph_hit_zy[nSt]->Fill(fHitQaData.GetHitZ(), fHitQaData.GetHitY());
482
483 fvph_hit_station_delta_z[nSt]->Fill(fHitQaData.GetHitZ() - actVol.GetCenterZ());
484
485 //fvph_hit_dx[nSt]->Fill(fHitQaData.GetHitDx());
486 //fvph_hit_dy[nSt]->Fill(fHitQaData.GetHitDy());
487 //fvph_hit_du[nSt]->Fill(fHitQaData.GetHitDu());
488 //fvph_hit_dv[nSt]->Fill(fHitQaData.GetHitDv());
489 fvph_hit_kuv[nSt]->Fill(fHitQaData.GetHitRuv());
490 fvph_hit_dt[nSt]->Fill(fHitQaData.GetHitTimeError());
491
492 // **********************
493 // ** MC information QA
494
495 if (IsMCUsed()) {
496 const auto* pHitMatch = dynamic_cast<CbmMatch*>(fpHitMatches->At(iH));
497 assert(pHitMatch);
498
499 // Evaluate number of hits per one MC point
500 int nMCpoints = 0; // Number of MC points for this hit
501 for (int iLink = 0; iLink < pHitMatch->GetNofLinks(); ++iLink) {
502 const auto& link = pHitMatch->GetLink(iLink);
503
504 int iP = link.GetIndex(); // Index of MC point
505
506 // Skip noisy links
507 if (iP < 0) {
508 continue;
509 }
510
511 ++nMCpoints;
512
513 int iE = fpMCEventList->GetEventIndex(link);
514 // TODO: debug
515 //if (iE < 0) continue;
516
517 if (iE < 0 || iE >= nMCevents) {
518 LOG(error) << fName << ": id of MC event is out of range (hit id = " << iH << ", link id = " << iLink
519 << ", event id = " << iE << ", mc point ID = " << iP << ')';
520 continue;
521 }
522
523 // matched point
524 const auto* pMCPoint = dynamic_cast<const Point_t*>(fpMCPoints->Get(link));
525 if (!pMCPoint) {
526 LOG(error) << fName << ": MC point object does not exist for hit " << iH;
527 continue;
528 }
529
530 int iTr = pMCPoint->GetTrackID();
531
532 if (iTr >= static_cast<int>(vNofHitsPerMcTrack[iE][iSt].size())) {
533 LOG(error) << fName << ": index of MC track is out of range (hit id = " << iH << ", link id = " << iLink
534 << ", event id = " << iE << ", track id = " << iTr << ')';
535 continue;
536 }
537
538 vNofHitsPerMcTrack[iE][iSt][iTr]++;
539 }
540
541 fvph_n_points_per_hit[iSt]->Fill(nMCpoints);
542 fvph_n_points_per_hit[nSt]->Fill(nMCpoints);
543
544 //
545 // Fill the following histograms exclusively for isolated hits with a one-to-one correspondence to the mc track
546 // The mc track must satisfy the cuts
547 //
548
549 if (pHitMatch->GetNofLinks() != 1) {
550 continue;
551 }
552
553 // The best link to in the match (probably, the cut on nMCpoints is meaningless)
554 assert(pHitMatch->GetNofLinks() > 0); // Should be always true due to the cut above
555 const auto& bestPointLink = pHitMatch->GetMatchedLink();
556
557 // Skip noisy links
558 if (bestPointLink.GetIndex() < 0) {
559 continue;
560 }
561
562 // Point matched by the best link
563 const auto* pMCPoint = dynamic_cast<const Point_t*>(fpMCPoints->Get(bestPointLink));
564 fHitQaData.SetPointID(bestPointLink.GetIndex(), bestPointLink.GetEntry(), bestPointLink.GetFile());
565 if (!pMCPoint) {
566 LOG(error) << fName << ": MC point object does not exist for hit " << iH;
567 continue;
568 }
569
570
573 //if constexpr (DetID == ca::EDetectorID::kMvd) {
574 // const auto* pMvdHit = static_cast<const CbmMvdHit*>(pHit);
575 // LOG(info) << "===== iHit=" << iH << "\n\thit address: 0b" << std::bitset<32>(pHit->GetAddress())
576 // << "\n\tpoint address: 0b" << std::bitset<32>(pMCPoint->GetDetectorID())
577 // << "\n\tzHit=" << pMvdHit->GetZ() << " cm, zPoint=" << pMCPoint->GetZ();
578 //}
579 //else {
580 // LOG(info) << "===== iHit=" << iH
581 // << "\n\thit address: 0b" << std::bitset<32>(pHit->GetAddress())
582 // << "\n\tpoint address: 0b" << std::bitset<32>(pMCPoint->GetDetectorID())
583 // << "\n\tzHit=" << pHit->GetZ() << " cm, zPoint=" << pMCPoint->GetZ();
584 //}
585 // DEBUG: END
586
587
588 // MC track for this point
589 CbmLink bestTrackLink = bestPointLink;
590 bestTrackLink.SetIndex(pMCPoint->GetTrackID());
591 const auto* pMCTrack = dynamic_cast<const CbmMCTrack*>(fpMCTracks->Get(bestTrackLink));
592 if (!pMCTrack) {
593 LOG(error) << fName << ": MC track object does not exist for hit " << iH << " and link: ";
594 continue;
595 }
596
597 double t0MC = fpMCEventList->GetEventTime(bestPointLink);
598 if (t0MC < 0) {
599 LOG(error) << fName << ": MC time zero is lower then 0 ns: " << t0MC;
600 continue;
601 }
602
603 // cut on the mc track quality
604 if (!IsTrackSelected(pMCTrack, pMCPoint)) {
605 continue;
606 }
607
608 { // skip the case when the mc point participates to several hits
609 int iE = fpMCEventList->GetEventIndex(bestTrackLink);
610 if (vNofHitsPerMcTrack[iE][iSt][pMCPoint->GetTrackID()] != 1) {
611 continue;
612 }
613 }
614
615 // ----- MC point properties
616 //
617 double mass = pMCTrack->GetMass();
618 //double charge = pMCTrack->GetCharge();
619 //double pdg = pMCTrack->GetPdgCode();
620
621 // Entrance position and time
622 // NOTE: SZh 04.09.2023: Methods GetX(), GetY(), GetZ() for MVD, STS, MUCH, TRD and TOF always return
623 // positions of track at entrance to the active volume.
624 double xMC = pMCPoint->FairMCPoint::GetX();
625 double yMC = pMCPoint->FairMCPoint::GetY();
626 double zMC = pMCPoint->FairMCPoint::GetZ();
627 double tMC = pMCPoint->GetTime() + t0MC;
628
629 // MC point entrance momenta
630 // NOTE: SZh 04.09.2023: Methods GetPx(), GetPy(), GetPz() for MVD, STS, MUCH, TRD and TOF always return
631 // the momentum components of track at entrance to the active volume.
632 double pxMC = pMCPoint->GetPx();
633 double pyMC = pMCPoint->GetPy();
634 double pzMC = pMCPoint->GetPz();
635 double pMC = sqrt(pxMC * pxMC + pyMC * pyMC + pzMC * pzMC);
636
637 // MC point exit momenta
638 // double pxMCo = pMCPoint->GetPxOut();
639 // double pyMCo = pMCPoint->GetPyOut();
640 // double pzMCo = pMCPoint->GetPzOut();
641 // double pMCo = sqrt(pxMCo * pxMCo + pyMCo * pyMCo + pzMCo * pzMCo);
642
643 // Position and time shifted to z-coordinate of the hit
644 // TODO: SZh 04.09.2023: Probably, the approximation
645 double shiftZ = fHitQaData.GetHitZ() - zMC; // Difference between hit and point z positions
646 double xMCs = xMC + shiftZ * pxMC / pzMC;
647 double yMCs = yMC + shiftZ * pyMC / pzMC;
648 double tMCs = tMC + shiftZ / (pzMC * phys::SpeedOfLight) * sqrt(mass * mass + pMC * pMC);
649
650 fHitQaData.SetPointTime(tMCs);
651 fHitQaData.SetPointX(xMCs);
652 fHitQaData.SetPointY(yMCs);
653 fHitQaData.SetPointZ(fHitQaData.GetHitZ());
654
655 double zRes = kNAN;
656 if constexpr (ca::EDetectorID::kTof == DetID) {
657 zRes = fHitQaData.GetHitZ() - pMCPoint->GetZ();
658 }
659 else {
660 zRes = fHitQaData.GetHitZ() - 0.5 * (pMCPoint->GetZ() + pMCPoint->GetZOut());
661 }
662 fvph_point_hit_delta_z[iSt]->Fill(zRes);
663
664 double xRes = fHitQaData.GetResidualX();
665 double yRes = fHitQaData.GetResidualY();
666 double uRes = fHitQaData.GetResidualU();
667 double vRes = fHitQaData.GetResidualV();
668 double tRes = fHitQaData.GetResidualTime();
669
670 double xPull = fHitQaData.GetPullX();
671 double yPull = fHitQaData.GetPullY();
672 double uPull = fHitQaData.GetPullU();
673 double vPull = fHitQaData.GetPullV();
674 double tPull = fHitQaData.GetPullTime();
675
676 fvph_res_x[iSt]->Fill(xRes);
677 fvph_res_y[iSt]->Fill(yRes);
678 fvph_res_u[iSt]->Fill(uRes);
679 fvph_res_v[iSt]->Fill(vRes);
680 fvph_res_t[iSt]->Fill(tRes);
681
682 fvph_pull_x[iSt]->Fill(xPull);
683 fvph_pull_y[iSt]->Fill(yPull);
684 fvph_pull_u[iSt]->Fill(uPull);
685 fvph_pull_v[iSt]->Fill(vPull);
686 fvph_pull_t[iSt]->Fill(tPull);
687
688 fvph_res_x_vs_x[iSt]->Fill(fHitQaData.GetPointX(), xRes);
689 fvph_res_y_vs_y[iSt]->Fill(fHitQaData.GetPointY(), yRes);
690 fvph_res_u_vs_u[iSt]->Fill(fHitQaData.GetPointU(), uRes);
691 fvph_res_v_vs_v[iSt]->Fill(fHitQaData.GetPointV(), vRes);
692 fvph_res_t_vs_t[iSt]->Fill(fHitQaData.GetPointTime(), tRes);
693
694 fvph_pull_x_vs_x[iSt]->Fill(fHitQaData.GetPointX(), xPull);
695 fvph_pull_y_vs_y[iSt]->Fill(fHitQaData.GetPointY(), yPull);
696 fvph_pull_u_vs_u[iSt]->Fill(fHitQaData.GetPointU(), uPull);
697 fvph_pull_v_vs_v[iSt]->Fill(fHitQaData.GetPointV(), vPull);
698 fvph_pull_t_vs_t[iSt]->Fill(fHitQaData.GetPointTime(), tPull);
699
700 // fill summary histos
701
702 fvph_point_hit_delta_z[nSt]->Fill(zRes);
703
704 fvph_res_x[nSt]->Fill(xRes);
705 fvph_res_y[nSt]->Fill(yRes);
706 fvph_res_u[nSt]->Fill(uRes);
707 fvph_res_v[nSt]->Fill(vRes);
708 fvph_res_t[nSt]->Fill(tRes);
709
710 fvph_pull_x[nSt]->Fill(xPull);
711 fvph_pull_y[nSt]->Fill(yPull);
712 fvph_pull_u[nSt]->Fill(uPull);
713 fvph_pull_v[nSt]->Fill(vPull);
714 fvph_pull_t[nSt]->Fill(tPull);
715
716 fvph_res_x_vs_x[nSt]->Fill(fHitQaData.GetPointX(), xRes);
717 fvph_res_y_vs_y[nSt]->Fill(fHitQaData.GetPointY(), yRes);
718 fvph_res_u_vs_u[nSt]->Fill(fHitQaData.GetPointU(), uRes);
719 fvph_res_v_vs_v[nSt]->Fill(fHitQaData.GetPointV(), vRes);
720 fvph_res_t_vs_t[nSt]->Fill(fHitQaData.GetPointTime(), tRes);
721
722 fvph_pull_x_vs_x[nSt]->Fill(fHitQaData.GetPointX(), xPull);
723 fvph_pull_y_vs_y[nSt]->Fill(fHitQaData.GetPointY(), yPull);
724 fvph_pull_u_vs_u[nSt]->Fill(fHitQaData.GetPointU(), uPull);
725 fvph_pull_v_vs_v[nSt]->Fill(fHitQaData.GetPointV(), vPull);
726 fvph_pull_t_vs_t[nSt]->Fill(fHitQaData.GetPointTime(), tPull);
727 }
729 } // loop over hits: end
730
731 // Fill hit reconstruction efficiencies
732 if (IsMCUsed()) {
733 for (int iE = 0; iE < nMCevents; ++iE) {
734 int iFile = fpMCEventList->GetFileIdByIndex(iE);
735 int iEvent = fpMCEventList->GetEventIdByIndex(iE);
736 int nPoints = fpMCPoints->Size(iFile, iEvent);
737 int nTracks = fpMCTracks->Size(iFile, iEvent);
738
739 // If efficiency for the track at the station is already evaluated
740 std::vector<std::vector<bool>> vIsTrackProcessed(nSt);
741 for (int iSt = 0; iSt < nSt; iSt++) {
742 vIsTrackProcessed[iSt].resize(nTracks, 0);
743 }
744
745 for (int iP = 0; iP < nPoints; ++iP) {
746 fHitQaData.Reset();
747 fHitQaData.SetPointID(iP, iEvent, iFile);
748 fMonitor.IncrementCounter(EMonitorKey::kMcPoint);
749
750 const auto* pMCPoint = dynamic_cast<const Point_t*>(fpMCPoints->Get(iFile, iEvent, iP));
751 if (!pMCPoint) {
752 LOG(error) << fName << ": MC point does not exist for iFile = " << iFile << ", iEvent = " << iEvent
753 << ", iP = " << iP;
754 continue;
755 }
756
757 int address = pMCPoint->GetDetectorID();
758 int iSt = fpDetInterface->GetTrackingStationId(pMCPoint->GetDetectorID());
759 if (iSt < 0) {
760 continue; // NOTE: legit, such sensors must be ignored in tracking
761 }
762
763 if (iSt >= nSt) {
764 LOG(error) << fName << ": MC point for FEI = " << iFile << ", " << iEvent << ", " << iP << " and address "
765 << address << " has wrong station index: iSt = " << iSt;
767 continue;
768 }
769
770 // NOTE: SZh 04.09.2023: Methods GetX(), GetY(), GetZ() for MVD, STS, MUCH, TRD and TOF always return
771 // positions of track at entrance to the active volume.
772 fHitQaData.SetPointX(pMCPoint->FairMCPoint::GetX());
773 fHitQaData.SetPointY(pMCPoint->FairMCPoint::GetY());
774 fHitQaData.SetPointZ(pMCPoint->FairMCPoint::GetZ());
775
776 fvph_point_xy[iSt]->Fill(fHitQaData.GetPointX(), fHitQaData.GetPointY());
777 fvph_point_zx[iSt]->Fill(fHitQaData.GetPointZ(), fHitQaData.GetPointX());
778 fvph_point_zy[iSt]->Fill(fHitQaData.GetPointZ(), fHitQaData.GetPointY());
779
780 fvph_point_xy[nSt]->Fill(fHitQaData.GetPointX(), fHitQaData.GetPointY());
781 fvph_point_zx[nSt]->Fill(fHitQaData.GetPointZ(), fHitQaData.GetPointX());
782 fvph_point_zy[nSt]->Fill(fHitQaData.GetPointZ(), fHitQaData.GetPointY());
783
784 int iTr = pMCPoint->GetTrackID();
785
786 if (iTr >= nTracks) {
787 LOG(error) << fName << ": index of MC track is out of range (point id = " << iP << ", event id = " << iE
788 << ", track id = " << iTr << ')';
789 continue;
790 }
791 const auto* pMCTrack = dynamic_cast<const CbmMCTrack*>(fpMCTracks->Get(iFile, iEvent, iTr));
792
793 fHitQaData.SetIfTrackHasHits(vNofHitsPerMcTrack[iE][iSt][iTr] > 0);
794 fHitQaData.SetIfTrackSelected(IsTrackSelected(pMCTrack, pMCPoint));
795
796 if (!pMCTrack) {
797 LOG(error) << fName << ": null MC track pointer for file id = " << iFile << ", event id = " << iEvent
798 << ", track id = " << iTr;
799 continue;
800 }
801
802 // check efficiency only once per mc track per station
803 if (vIsTrackProcessed[iSt][iTr]) {
804 continue;
805 }
806
807 vIsTrackProcessed[iSt][iTr] = true;
808
809 // cut on the mc track quality
810 if (!fHitQaData.GetIfTrackSelected()) {
811 continue;
812 }
813
814 // Conditions under which point is accounted as reconstructed: point
815 bool ifTrackHasHits = fHitQaData.GetIfTrackHasHits();
816
817 fvpe_reco_eff_vs_xy[iSt]->Fill(fHitQaData.GetPointX(), fHitQaData.GetPointY(), ifTrackHasHits);
818 fvpe_reco_eff_vs_xy[nSt]->Fill(fHitQaData.GetPointX(), fHitQaData.GetPointY(), ifTrackHasHits);
819 } // loop over MC-points: end
820 } // loop over MC-events: end
821 } // MC is used: end
822}
823
824// ---------------------------------------------------------------------------------------------------------------------
825//
826template<ca::EDetectorID DetID>
828{
829 // ----- Specific configuration initialization
831
832
833
834 // FairRootManager
835 auto* pFairRootManager = FairRootManager::Instance();
836 LOG_IF(fatal, !pFairRootManager) << "\033[1;31m" << fName << ": FairRootManager instance is a null pointer\033[0m";
837
838 // Detector interface
839 const auto* pRecoSetupManager = cbm::RecoSetupManager::Instance();
840 LOG_IF(fatal, !pRecoSetupManager->IsInitialized())
841 << "\033[1;31m" << fName << ": RecoSetupManager instance is not initialized\033[0m";
842
843 fpDetInterface = pRecoSetupManager->GetSetup().Get<ToCbmModuleId(DetID)>();
844 LOG_IF(fatal, !fpDetInterface) << "\033[1;31m" << fName << ": reco setup unit for detId=" << static_cast<int>(DetID)
845 << " was not created\033[0m";
846
847 LOG_IF(fatal, !fpDetInterface) << "\033[1;31m" << fName << ": tracking detector interface is undefined\033[0m";
848
849 // ----- Digi manager
851 fDigiManager->Init();
852
853 // ----- Reconstructed data-branches initialization
854
855 // Hits container
856 if constexpr (DetID == EDetectorID::kTof) {
857 fpHits = dynamic_cast<TClonesArray*>(pFairRootManager->GetObject("TofCalHit"));
858 if (!fpHits) {
859 fpHits = dynamic_cast<TClonesArray*>(pFairRootManager->GetObject("TofHit"));
860 }
861 }
862 else {
863 fpHits = dynamic_cast<TClonesArray*>(pFairRootManager->GetObject(cbm::ca::kDetHitBrName[DetID]));
864 }
865
866 LOG_IF(fatal, !fpHits) << "\033[1;31m" << fName << ": container of reconstructed hits is not found\033[0m";
867
868 // ----- MC-information branches initialization
869 if (IsMCUsed()) {
870 // MC manager
871 fpMCDataManager = dynamic_cast<CbmMCDataManager*>(pFairRootManager->GetObject("MCDataManager"));
872 LOG_IF(fatal, !fpMCDataManager) << "\033[1;31m" << fName << ": MC data manager branch is not found\033[0m";
873
874 // MC event list
875 fpMCEventList = dynamic_cast<CbmMCEventList*>(pFairRootManager->GetObject("MCEventList."));
876 LOG_IF(fatal, !fpMCEventList) << "\033[1;31m" << fName << ": MC event list branch is not found\033[0m";
877
878 // MC tracks
879 fpMCTracks = fpMCDataManager->InitBranch("MCTrack");
880 LOG_IF(fatal, !fpMCTracks) << "\033[1;31m" << fName << ": MC track branch is not found\033[0m";
881
882 // MC points
884 LOG_IF(fatal, !fpMCTracks) << "\033[1;31m" << fName << ": MC point branch is not found\033[0m";
885
886 // Hit matches
887 const char* hitMatchName = Form("%sMatch", cbm::ca::kDetHitBrName[DetID]);
888 fpHitMatches = dynamic_cast<TClonesArray*>(pFairRootManager->GetObject(hitMatchName));
889 LOG_IF(fatal, !fpHitMatches) << "\033[1;31m]" << fName << ": hit match branch is not found\033[0m";
890 }
891
892 // get hit distribution ranges from the geometry
893 int nSt = fpDetInterface->GetNofTrackingStations();
894
895 frXmin.resize(nSt + 1, 0.);
896 frXmax.resize(nSt + 1, 0.);
897
898 frYmin.resize(nSt + 1, 0.);
899 frYmax.resize(nSt + 1, 0.);
900
901 frZmin.resize(nSt + 1, 0.);
902 frZmax.resize(nSt + 1, 0.);
903
904 for (int i = nSt; i >= 0; --i) {
905 { // read the ranges for station i
906 int j = (i == nSt ? 0 : i);
907 const auto& vol = fpDetInterface->GetFullVolume(j);
908 frXmin[i] = vol.GetMaxX();
909 frXmax[i] = vol.GetMinX();
910
911 frYmin[i] = vol.GetMinY();
912 frYmax[i] = vol.GetMaxY();
913
914 frZmin[i] = vol.GetMinZ();
915 frZmax[i] = vol.GetMaxZ();
916 }
917
918 // update overall ranges
919
920 frXmin[nSt] = std::min(frXmin[nSt], frXmin[i]);
921 frXmax[nSt] = std::max(frXmax[nSt], frXmax[i]);
922
923 frYmin[nSt] = std::min(frYmin[nSt], frYmin[i]);
924 frYmax[nSt] = std::max(frYmax[nSt], frYmax[i]);
925
926 frZmin[nSt] = std::min(frZmin[nSt], frZmin[i]);
927 frZmax[nSt] = std::max(frZmax[nSt], frZmax[i]);
928 }
929
930 // add 5% margins for a better view
931
932 for (int i = 0; i <= nSt; ++i) {
933 double dx = 0.05 * fabs(frXmax[i] - frXmin[i]);
934 frXmin[i] -= dx;
935 frXmax[i] += dx;
936
937 double dy = 0.05 * fabs(frYmax[i] - frYmin[i]);
938 frYmin[i] -= dy;
939 frYmax[i] += dy;
940
941 if constexpr (ca::EDetectorID::kMuch == DetID) {
942 frZmin[i] -= 40;
943 frZmax[i] += 40;
944 }
945 else {
946 double dz = 0.05 * fabs(frZmax[i] - frZmin[i]);
947 frZmin[i] -= dz;
948 frZmax[i] += dz;
949 }
950 }
951
952 // ----- Monitor initialization
953 //
954 fMonitor.SetName(Form("Monitor for %s", fName.Data()));
955 fMonitor.SetCounterName(EMonitorKey::kEvent, "N events");
956 fMonitor.SetCounterName(EMonitorKey::kHit, "N hits total");
957 fMonitor.SetCounterName(EMonitorKey::kHitAccepted, "N hits accepted");
958 fMonitor.SetCounterName(EMonitorKey::kMcPoint, "N MC points total");
959 fMonitor.SetCounterName(EMonitorKey::kMcPointWrongStation, "N MC points total");
960 fMonitor.SetRatioKeys({EMonitorKey::kEvent});
961
962
963 // ----- Histograms initialization
964 //
965 //SetStoringMode(EStoringMode::kSAMEDIR);
966 MakeQaDirectory("Summary");
967 MakeQaDirectory("Summary/vs Station");
968 if constexpr (ca::EDetectorID::kSts == DetID) {
969 MakeQaDirectory("Summary/vs N digi");
970 }
971 MakeQaDirectory("All stations");
972
973 fvph_hit_xy.resize(nSt + 1, nullptr);
974 fvph_hit_zy.resize(nSt + 1, nullptr);
975 fvph_hit_zx.resize(nSt + 1, nullptr);
976
977 fvph_hit_station_delta_z.resize(nSt + 1, nullptr);
978
979 fvph_hit_dx.resize(nSt + 1, nullptr);
980 fvph_hit_dy.resize(nSt + 1, nullptr);
981 fvph_hit_dt.resize(nSt + 1, nullptr);
982 fvph_hit_dv.resize(nSt + 1, nullptr);
983 fvph_hit_kuv.resize(nSt + 1, nullptr);
984 fvph_hit_du.resize(nSt + 1, nullptr);
985
986 std::string detName{DetName.begin(), DetName.end()};
987
988 for (int iSt = 0; iSt <= nSt; ++iSt) {
989 TString sF = ""; // Subfolder
990 sF += (iSt == nSt) ? "All stations/" : Form("Station %d/", iSt);
991 TString nsuff = (iSt == nSt) ? "" : Form("_st%d", iSt); // Histogram name suffix
992 TString tsuff = (iSt == nSt) ? "" : Form(" in %s station %d", detName.c_str(), iSt); // Histogram title suffix
993 TString sN = "";
994 TString sT = "";
995
996 // place directories in a prefered order
997 MakeQaDirectory(sF + "occup/");
998 if (IsMCUsed()) {
999 MakeQaDirectory(sF + "res/");
1000 MakeQaDirectory(sF + "pull/");
1001 MakeQaDirectory(sF + "eff/");
1002 }
1003 MakeQaDirectory(sF + "err/");
1004
1005 int nBinsZ = (iSt < nSt) ? fNbins : fNbinsZ;
1006
1007 // Hit occupancy
1008 sN = (TString) "hit_xy" + nsuff;
1009 sT = (TString) "Hit occupancy in xy-Plane" + tsuff + ";x_{hit} [cm];y_{hit} [cm]";
1010 fvph_hit_xy[iSt] =
1011 MakeQaObject<TH2F>(sF + "occup/" + sN, sT, fNbins, frXmin[iSt], frXmax[iSt], fNbins, frYmin[iSt], frYmax[iSt]);
1012
1013 sN = (TString) "hit_zx" + nsuff;
1014 sT = (TString) "Hit occupancy in xz-Plane" + tsuff + ";z_{hit} [cm];x_{hit} [cm]";
1015 fvph_hit_zx[iSt] =
1016 MakeQaObject<TH2F>(sF + "occup/" + sN, sT, nBinsZ, frZmin[iSt], frZmax[iSt], fNbins, frXmin[iSt], frXmax[iSt]);
1017
1018 sN = (TString) "hit_zy" + nsuff;
1019 sT = (TString) "Hit occupancy in yz-plane" + tsuff + ";z_{hit} [cm];y_{hit} [cm]";
1020 fvph_hit_zy[iSt] =
1021 MakeQaObject<TH2F>(sF + "occup/" + sN, sT, nBinsZ, frZmin[iSt], frZmax[iSt], fNbins, frYmin[iSt], frYmax[iSt]);
1022
1023 // Hit errors
1024 sN = (TString) "hit_dx" + nsuff;
1025 sT = (TString) "Hit position error along x-axis" + tsuff + ";dx_{hit} [cm]";
1026 fvph_hit_dx[iSt] = MakeQaObject<TH1F>(sF + "err/" + sN, sT, fNbins, fRHitDx[0], fRHitDx[1]);
1027
1028 sN = (TString) "hit_dy" + nsuff;
1029 sT = (TString) "Hit position error along y-axis" + tsuff + ";dy_{hit} [cm]";
1030 fvph_hit_dy[iSt] = MakeQaObject<TH1F>(sF + "err/" + sN, sT, fNbins, fRHitDy[0], fRHitDy[1]);
1031
1032 sN = (TString) "hit_du" + nsuff;
1033 sT = (TString) "Hit position error along the major detector coordinate U" + tsuff + ";du_{hit} [cm]";
1034 fvph_hit_du[iSt] = MakeQaObject<TH1F>(sF + "err/" + sN, sT, fNbins, fRHitDu[0], fRHitDu[1]);
1035
1036 sN = (TString) "hit_dv" + nsuff;
1037 sT = (TString) "Hit position error along the minor detector coordinate V" + tsuff + ";dv_{hit} [cm]";
1038 fvph_hit_dv[iSt] = MakeQaObject<TH1F>(sF + "err/" + sN, sT, fNbins, fRHitDv[0], fRHitDv[1]);
1039
1040 sN = (TString) "hit_kuv" + nsuff;
1041 sT = (TString) "Hit error correlation between the major (U) and the minor detector coordinate Vs" + tsuff
1042 + ";kuv_{hit} [unitless]";
1043 fvph_hit_kuv[iSt] = MakeQaObject<TH1F>(sF + "err/" + sN, sT, fNbins / 2 * 2 + 1, -1.1, 1.1);
1044
1045 sN = (TString) "hit_dt" + nsuff;
1046 sT = (TString) "Hit time error" + tsuff + ";dt_{hit} [ns]";
1047 fvph_hit_dt[iSt] = MakeQaObject<TH1F>(sF + "err/" + sN, sT, fNbins, fRHitDt[0], fRHitDt[1]);
1048
1049 sN = (TString) "hit_station_delta_z" + nsuff;
1050 sT = (TString) "Different between hit and station z-positions" + tsuff + ";z_{hit} - z_{st} [cm]";
1051 fvph_hit_station_delta_z[iSt] = MakeQaObject<TH1F>(sF + sN, sT, fNbins, -5., 5.);
1052
1053 } // loop over station index: end
1054
1055 // ----- Initialize histograms, which are use MC-information
1056 if (IsMCUsed()) {
1057 // Resize histogram vectors
1058 fvph_n_points_per_hit.resize(nSt + 1, nullptr);
1059 fvph_point_xy.resize(nSt + 1, nullptr);
1060 fvph_point_zx.resize(nSt + 1, nullptr);
1061 fvph_point_zy.resize(nSt + 1, nullptr);
1062 fvph_point_hit_delta_z.resize(nSt + 1, nullptr);
1063 fvph_res_x.resize(nSt + 1, nullptr);
1064 fvph_res_y.resize(nSt + 1, nullptr);
1065 fvph_res_u.resize(nSt + 1, nullptr);
1066 fvph_res_v.resize(nSt + 1, nullptr);
1067 fvph_res_t.resize(nSt + 1, nullptr);
1068 fvph_pull_x.resize(nSt + 1, nullptr);
1069 fvph_pull_y.resize(nSt + 1, nullptr);
1070 fvph_pull_u.resize(nSt + 1, nullptr);
1071 fvph_pull_v.resize(nSt + 1, nullptr);
1072 fvph_pull_t.resize(nSt + 1, nullptr);
1073 fvph_res_x_vs_x.resize(nSt + 1, nullptr);
1074 fvph_res_y_vs_y.resize(nSt + 1, nullptr);
1075 fvph_res_u_vs_u.resize(nSt + 1, nullptr);
1076 fvph_res_v_vs_v.resize(nSt + 1, nullptr);
1077 fvph_res_t_vs_t.resize(nSt + 1, nullptr);
1078 fvph_pull_x_vs_x.resize(nSt + 1, nullptr);
1079 fvph_pull_y_vs_y.resize(nSt + 1, nullptr);
1080 fvph_pull_u_vs_u.resize(nSt + 1, nullptr);
1081 fvph_pull_v_vs_v.resize(nSt + 1, nullptr);
1082 fvph_pull_t_vs_t.resize(nSt + 1, nullptr);
1083 fvpe_reco_eff_vs_xy.resize(nSt + 1, nullptr);
1084 fvph_reco_eff.resize(nSt + 1, nullptr);
1085
1086 for (int iSt = 0; iSt <= nSt; ++iSt) {
1087 TString sF = ""; // Subfolder
1088 sF += (iSt == nSt) ? "All stations/" : Form("Station %d/", iSt);
1089 TString nsuff = (iSt == nSt) ? "" : Form("_st%d", iSt); // Histogram name suffix
1090 TString tsuff = (iSt == nSt) ? "" : Form(" in %s station %d", detName.c_str(), iSt); // Histogram title suffix
1091 TString sN = "";
1092 TString sT = "";
1093
1094 sN = (TString) "n_points_per_hit" + nsuff;
1095 sT = (TString) "Number of points per hit" + tsuff + ";N_{point}/hit";
1096 fvph_n_points_per_hit[iSt] = MakeQaObject<TH1F>(sF + sN, sT, 10, -0.5, 9.5);
1097
1098 // Point occupancy
1099 sN = (TString) "point_xy" + nsuff;
1100 sT = (TString) "Point occupancy in XY plane" + tsuff + ";x_{MC} [cm];y_{MC} [cm]";
1101 fvph_point_xy[iSt] =
1102 MakeQaObject<TH2F>(sF + "occup/" + sN, sT, fNbins, frXmin[iSt], frXmax[iSt], fNbins, frYmin[iSt], frYmax[iSt]);
1103
1104 sN = (TString) "point_zx" + nsuff;
1105 sT = (TString) "Point Occupancy in XZ plane" + tsuff + ";z_{MC} [cm];x_{MC} [cm]";
1106 fvph_point_zx[iSt] =
1107 MakeQaObject<TH2F>(sF + "occup/" + sN, sT, fNbinsZ, frZmin[iSt], frZmax[iSt], fNbins, frXmin[iSt], frXmax[iSt]);
1108
1109 sN = (TString) "point_zy" + nsuff;
1110 sT = (TString) "Point Occupancy in YZ Plane" + tsuff + ";z_{MC} [cm];y_{MC} [cm]";
1111 fvph_point_zy[iSt] =
1112 MakeQaObject<TH2F>(sF + "occup/" + sN, sT, fNbinsZ, frZmin[iSt], frZmax[iSt], fNbins, frYmin[iSt], frYmax[iSt]);
1113
1114 // Difference between MC input z and hit z coordinates
1115 sN = (TString) "point_hit_delta_z" + nsuff;
1116 sT = (TString) "Distance between " + detName + " point and hit along z axis" + tsuff + ";z_{reco} - z_{MC} [cm]";
1118
1119 sN = (TString) "res_x" + nsuff;
1120 sT = (TString) "Residuals for X" + tsuff + ";x_{reco} - x_{MC} [cm]";
1121 fvph_res_x[iSt] = MakeQaObject<TH1F>(sF + "res/" + sN, sT, fNbins, fRResX[0], fRResX[1]);
1122
1123 sN = (TString) "res_y" + nsuff;
1124 sT = (TString) "Residuals for Y" + tsuff + ";y_{reco} - y_{MC} [cm]";
1125 fvph_res_y[iSt] = MakeQaObject<TH1F>(sF + "res/" + sN, sT, fNbins, fRResY[0], fRResY[1]);
1126
1127 sN = (TString) "res_u" + nsuff;
1128 sT = (TString) "Residuals for the major detector coordinate U" + tsuff + ";u_{reco} - u_{MC} [cm]";
1129 fvph_res_u[iSt] = MakeQaObject<TH1F>(sF + "res/" + sN, sT, fNbins, fRResU[0], fRResU[1]);
1130
1131 sN = (TString) "res_v" + nsuff;
1132 sT = (TString) "Residuals for the minor detector coordinate V" + tsuff + ";v_{reco} - v_{MC} [cm]";
1133 fvph_res_v[iSt] = MakeQaObject<TH1F>(sF + "res/" + sN, sT, fNbins, fRResV[0], fRResV[1]);
1134
1135 sN = (TString) "res_t" + nsuff;
1136 sT = (TString) "Residuals for Time" + tsuff + ";t_{reco} - t_{MC} [ns]";
1137 fvph_res_t[iSt] = MakeQaObject<TH1F>(sF + "res/" + sN, sT, fNbins, fRResT[0], fRResT[1]);
1138
1139 sN = (TString) "pull_x" + nsuff;
1140 sT = (TString) "Pulls for X" + tsuff + ";(x_{reco} - x_{MC}) / #sigma_{x}^{reco}";
1141 fvph_pull_x[iSt] = MakeQaObject<TH1F>(sF + "pull/" + sN, sT, kNbinsPull, kRPull[0], kRPull[1]);
1142
1143 sN = (TString) "pull_y" + nsuff;
1144 sT = (TString) "Pulls for Y" + tsuff + ";(y_{reco} - y_{MC}) / #sigma_{y}^{reco}";
1145 fvph_pull_y[iSt] = MakeQaObject<TH1F>(sF + "pull/" + sN, sT, kNbinsPull, kRPull[0], kRPull[1]);
1146
1147 sN = (TString) "pull_u" + nsuff;
1148 sT = (TString) "Pulls for the major detector coordinate U" + tsuff + ";(u_{reco} - u_{MC}) / #sigma_{u}^{reco}";
1149 fvph_pull_u[iSt] = MakeQaObject<TH1F>(sF + "pull/" + sN, sT, kNbinsPull, kRPull[0], kRPull[1]);
1150
1151 sN = (TString) "pull_v" + nsuff;
1152 sT = (TString) "Pulls for the minor detector coordinate V" + tsuff + ";(v_{reco} - v_{MC}) / #sigma_{v}^{reco}";
1153 fvph_pull_v[iSt] = MakeQaObject<TH1F>(sF + "pull/" + sN, sT, kNbinsPull, kRPull[0], kRPull[1]);
1154
1155 sN = (TString) "pull_t" + nsuff;
1156 sT = (TString) "Pulls for Time" + tsuff + ";(t_{reco} - t_{MC}) / #sigma_{t}^{reco}";
1157 fvph_pull_t[iSt] = MakeQaObject<TH1F>(sF + "pull/" + sN, sT, kNbinsPull, kRPull[0], kRPull[1]);
1158
1159 sN = (TString) "res_x_vs_x" + nsuff;
1160 sT = (TString) "Residuals for X" + tsuff + ";x_{MC} [cm];x_{reco} - x_{MC} [cm]";
1161 fvph_res_x_vs_x[iSt] =
1162 MakeQaObject<TH2F>(sF + "res/" + sN, sT, fNbins, frXmin[iSt], frXmax[iSt], fNbins, fRResX[0], fRResX[1]);
1163
1164 sN = (TString) "res_y_vs_y" + nsuff;
1165 sT = (TString) "Residuals for Y" + tsuff + ";y_{MC} [cm];y_{reco} - y_{MC} [cm]";
1166 fvph_res_y_vs_y[iSt] =
1167 MakeQaObject<TH2F>(sF + "res/" + sN, sT, fNbins, frYmin[iSt], frYmax[iSt], fNbins, fRResY[0], fRResY[1]);
1168
1169 sN = (TString) "res_u_vs_u" + nsuff;
1170 sT = (TString) "Residuals for the major detector coordinate U" + tsuff + ";u_{MC} [cm];u_{reco} - u_{MC} [cm]";
1171 fvph_res_u_vs_u[iSt] =
1172 MakeQaObject<TH2F>(sF + "res/" + sN, sT, fNbins, frXmin[iSt], frXmax[iSt], fNbins, fRResU[0], fRResU[1]);
1173
1174 sN = (TString) "res_v_vs_v" + nsuff;
1175 sT = (TString) "Residuals for the minor detector coordinate V" + tsuff + ";v_{MC} [cm];v_{reco} - v_{MC} [cm]";
1176 fvph_res_v_vs_v[iSt] =
1177 MakeQaObject<TH2F>(sF + "res/" + sN, sT, fNbins, frXmin[iSt], frXmax[iSt], fNbins, fRResV[0], fRResV[1]);
1178
1179 sN = (TString) "res_t_vs_t" + nsuff;
1180 sT = (TString) "Residuals for Time" + tsuff + ";t_{MC} [ns];t_{reco} - t_{MC} [ns]";
1181 fvph_res_t_vs_t[iSt] = MakeQaObject<TH2F>(sF + "res/" + sN, sT, fNbins, 0, 0, fNbins, fRResT[0], fRResT[1]);
1182
1183 sN = (TString) "pull_x_vs_x" + nsuff;
1184 sT = (TString) "Pulls for X" + tsuff + ";x_{MC} [cm];(x_{reco} - x_{MC}) / #sigma_{x}^{reco}";
1185 fvph_pull_x_vs_x[iSt] =
1186 MakeQaObject<TH2F>(sF + "pull/" + sN, sT, fNbins, frXmin[iSt], frXmax[iSt], kNbinsPull, kRPull[0], kRPull[1]);
1187
1188 sN = (TString) "pull_y_vs_y" + nsuff;
1189 sT = (TString) "Pulls for Y" + tsuff + ";y_{MC} [cm];(y_{reco} - y_{MC}) / #sigma_{y}^{reco}";
1190 fvph_pull_y_vs_y[iSt] =
1191 MakeQaObject<TH2F>(sF + "pull/" + sN, sT, fNbins, frYmin[iSt], frYmax[iSt], kNbinsPull, kRPull[0], kRPull[1]);
1192
1193 sN = (TString) "pull_u_vs_u" + nsuff;
1194 sT = (TString) "Pulls for the major detector coordinate U" + tsuff
1195 + ";u_{MC} [cm];(u_{reco} - u_{MC}) / #sigma_{u}^{reco}";
1196 fvph_pull_u_vs_u[iSt] =
1197 MakeQaObject<TH2F>(sF + "pull/" + sN, sT, fNbins, frXmin[iSt], frXmax[iSt], kNbinsPull, kRPull[0], kRPull[1]);
1198
1199 sN = (TString) "pull_v_vs_v" + nsuff;
1200 sT = (TString) "Pulls for the minor detector coordinate V" + tsuff
1201 + ";v_{MC} [cm];(v_{reco} - v_{MC}) / #sigma_{v}^{reco}";
1202 fvph_pull_v_vs_v[iSt] =
1203 MakeQaObject<TH2F>(sF + "pull/" + sN, sT, fNbins, frXmin[iSt], frXmax[iSt], kNbinsPull, kRPull[0], kRPull[1]);
1204
1205 sN = (TString) "pull_t_vs_t" + nsuff;
1206 sT = (TString) "Pulls for Time" + tsuff + ";t_{MC} [ns];(t_{reco} - t_{MC}) / #sigma_{t}^{reco}";
1207 fvph_pull_t_vs_t[iSt] = MakeQaObject<TH2F>(sF + "pull/" + sN, sT, fNbins, 0, 0, fNbins, kRPull[0], kRPull[1]);
1208
1209 sN = (TString) "reco_eff_vs_xy" + nsuff;
1210 sT = (TString) "Hit rec. efficiency in XY" + tsuff + ";x_{MC} [cm];y_{MC} [cm];#epsilon";
1211 fvpe_reco_eff_vs_xy[iSt] = MakeQaObject<TProfile2D>(sF + "eff/" + sN, sT, fNbins, frXmin[iSt], frXmax[iSt],
1212 fNbins, frYmin[iSt], frYmax[iSt]);
1213
1214 sN = (TString) "reco_eff" + nsuff;
1215 sT = (TString) "Hit rec. efficiency in XY bins" + tsuff + ";eff";
1216 fvph_reco_eff[iSt] = MakeQaObject<TH1F>(sF + "eff/" + sN, sT, 130, -0.005, 1.30 - 0.005);
1217 } // stations
1218 }
1219 return kSUCCESS;
1220}
1221
1222// ---------------------------------------------------------------------------------------------------------------------
1223//
1224template<ca::EDetectorID DetID>
1226{
1228 gStyle->SetOptFit(1);
1229 int nSt = fpDetInterface->GetNofTrackingStations();
1230
1231 // ********************
1232 // ** Drawing options
1233
1234 // Contours
1235 constexpr auto contColor = kOrange + 7;
1236 constexpr auto contWidth = 2; // Line width
1237 constexpr auto contStyle = 2; // Line style
1238 constexpr auto contFill = 0; // Fill style
1239
1240 // **********************
1241 // ** summary for all stations
1242
1243 {
1244 auto* canv = MakeQaObject<TCanvas>("occ_hit", "Hit Occupancy", 1600, 800);
1245 canv->Divide(1, 3);
1246 canv->cd(1);
1247 fvph_hit_xy[nSt]->DrawCopy("colz", "");
1248 canv->cd(2);
1249 fvph_hit_zx[nSt]->DrawCopy("colz", "");
1250 canv->cd(3);
1251 fvph_hit_zy[nSt]->DrawCopy("colz", "");
1252 }
1253
1254 if (IsMCUsed()) {
1255 auto* canv = MakeQaObject<TCanvas>("occ_point", "Point Occupancy", 1600, 800);
1256 canv->Divide(1, 3);
1257 canv->cd(1);
1258 fvph_point_xy[nSt]->DrawCopy("colz", "");
1259 canv->cd(2);
1260 fvph_point_zx[nSt]->DrawCopy("colz", "");
1261 canv->cd(3);
1262 fvph_point_zy[nSt]->DrawCopy("colz", "");
1263 }
1264
1265 if (IsMCUsed()) {
1266 auto* canv = MakeQaObject<TCanvas>("residual", "Hit Residuals", 1600, 800);
1267 canv->Divide(1, 5);
1268 canv->cd(1);
1269 fvph_res_x[nSt]->DrawCopy("colz", "");
1270 canv->cd(2);
1271 fvph_res_y[nSt]->DrawCopy("colz", "");
1272 canv->cd(3);
1273 fvph_res_t[nSt]->DrawCopy("colz", "");
1274 canv->cd(4);
1275 fvph_res_u[nSt]->DrawCopy("colz", "");
1276 canv->cd(5);
1277 fvph_res_v[nSt]->DrawCopy("colz", "");
1278 }
1279
1280 if (IsMCUsed()) {
1281 auto* canv = MakeQaObject<TCanvas>("pull", "Hit Pulls", 1600, 800);
1282 canv->Divide(1, 5);
1283 canv->cd(1);
1284 fvph_pull_x[nSt]->DrawCopy("colz", "");
1285 canv->cd(2);
1286 fvph_pull_y[nSt]->DrawCopy("colz", "");
1287 canv->cd(3);
1288 fvph_pull_t[nSt]->DrawCopy("colz", "");
1289 canv->cd(4);
1290 fvph_pull_u[nSt]->DrawCopy("colz", "");
1291 canv->cd(5);
1292 fvph_pull_v[nSt]->DrawCopy("colz", "");
1293 }
1294
1295 if (IsMCUsed()) {
1296 auto* canv = MakeQaObject<TCanvas>("eff", "Hit Reconstruction Efficiency", 1600, 800);
1297 canv->Divide(1, 2);
1298 canv->cd(1);
1299 fvpe_reco_eff_vs_xy[nSt]->DrawCopy("colz", "");
1300 canv->cd(2);
1301 fvph_reco_eff[nSt]->DrawCopy("colz", "");
1302 }
1303
1304 {
1305 auto* canv = MakeQaObject<TCanvas>("err", "Hit Errors", 1600, 800);
1306 canv->Divide(2, 3);
1307 canv->cd(1);
1308 fvph_hit_dx[nSt]->DrawCopy();
1309 canv->cd(2);
1310 fvph_hit_dy[nSt]->DrawCopy();
1311 canv->cd(3);
1312 fvph_hit_dt[nSt]->DrawCopy();
1313 canv->cd(4);
1314 fvph_hit_du[nSt]->DrawCopy();
1315 canv->cd(5);
1316 fvph_hit_dv[nSt]->DrawCopy();
1317 canv->cd(6);
1318 fvph_hit_kuv[nSt]->DrawCopy();
1319 }
1320
1321 // TODO: Split the histograms for MC and real data
1322 if (IsMCUsed()) {
1323 auto* canv = MakeQaObject<TCanvas>("other", "Other histograms", 1600, 800);
1324 canv->Divide(1, 3);
1325 canv->cd(1);
1326 fvph_n_points_per_hit[nSt]->DrawCopy("colz", "");
1327 canv->cd(2);
1328 fvph_hit_station_delta_z[nSt]->DrawCopy("colz", "");
1329 canv->cd(3);
1330 fvph_point_hit_delta_z[nSt]->DrawCopy("colz", "");
1331 }
1332
1333
1334 // *********************************
1335 // ** Hit occupancies
1336
1337 { // ** Occupancy in XY plane
1338 auto* canv = MakeQaObject<TCanvas>("vs Station/hit_xy", "", 1600, 800);
1339 canv->DivideSquare(nSt);
1340 for (int iSt = 0; iSt < nSt; ++iSt) {
1341 canv->cd(iSt + 1);
1342 fvph_hit_xy[iSt]->DrawCopy("colz", "");
1343
1344 // Square boarders of the active area of the station
1345 const auto& actVol{fpDetInterface->GetActiveVolume(iSt)};
1346 double stXmin = actVol.GetMinX();
1347 double stXmax = actVol.GetMaxX();
1348 double stYmin = actVol.GetMinY();
1349 double stYmax = actVol.GetMaxY();
1350
1351 auto* pBox = new TBox(stXmin, stYmin, stXmax, stYmax);
1352 pBox->SetLineWidth(contWidth);
1353 pBox->SetLineStyle(contStyle);
1354 pBox->SetLineColor(contColor);
1355 pBox->SetFillStyle(contFill);
1356 pBox->Draw("SAME");
1357 }
1358 }
1359
1360 { // ** Occupancy in XZ plane
1361 auto* canv = MakeQaObject<TCanvas>("vs Station/hit_zx", "", 1600, 800);
1362 canv->cd();
1363 fvph_hit_zx[nSt]->DrawCopy("colz", "");
1364 for (int iSt = 0; iSt < nSt; ++iSt) {
1365 // Station positions in detector IFS
1366 const auto& actVol{fpDetInterface->GetActiveVolume(iSt)};
1367 double stZmin = actVol.GetMinZ();
1368 double stZmax = actVol.GetMaxZ();
1369 double stHmin = actVol.GetMinX();
1370 double stHmax = actVol.GetMaxX();
1371
1372 auto* pBox = new TBox(stZmin, stHmin, stZmax, stHmax);
1373 pBox->SetLineWidth(contWidth);
1374 pBox->SetLineStyle(contStyle);
1375 pBox->SetLineColor(contColor);
1376 pBox->SetFillStyle(contFill);
1377 pBox->Draw("SAME");
1378 }
1379 }
1380
1381 { // ** Occupancy in YZ plane
1382 auto* canv = MakeQaObject<TCanvas>("vs Station/hit_zy", "", 1600, 800);
1383 canv->cd();
1384 fvph_hit_zy[nSt]->DrawCopy("colz", "");
1385 for (int iSt = 0; iSt < nSt; ++iSt) {
1386 // Station positions in detector IFS
1387 const auto& actVol{fpDetInterface->GetActiveVolume(iSt)};
1388 double stZmin = actVol.GetMinZ();
1389 double stZmax = actVol.GetMaxZ();
1390 double stHmin = actVol.GetMinY();
1391 double stHmax = actVol.GetMaxY();
1392
1393 auto* pBox = new TBox(stZmin, stHmin, stZmax, stHmax);
1394 pBox->SetLineWidth(contWidth);
1395 pBox->SetLineStyle(contStyle);
1396 pBox->SetLineColor(contColor);
1397 pBox->SetFillStyle(contFill);
1398 pBox->Draw("SAME");
1399 }
1400 }
1401
1402 // ************
1403 // ************
1404
1405 if (IsMCUsed()) {
1406
1407 // **********************
1408 // ** Point occupancies
1409
1410 { // ** Occupancy in XY plane
1411 auto* canv = MakeQaObject<TCanvas>("vs Station/point_xy", "", 1600, 800);
1412 canv->DivideSquare(nSt);
1413 for (int iSt = 0; iSt < nSt; ++iSt) {
1414 canv->cd(iSt + 1);
1415 fvph_point_xy[iSt]->DrawCopy("colz", "");
1416
1417 // Square boarders of the active area of the station
1418 const auto& actVol{fpDetInterface->GetActiveVolume(iSt)};
1419 double stXmin = actVol.GetMinX();
1420 double stXmax = actVol.GetMaxX();
1421 double stYmin = actVol.GetMinY();
1422 double stYmax = actVol.GetMaxY();
1423
1424 auto* pBox = new TBox(stXmin, stYmin, stXmax, stYmax);
1425 pBox->SetLineWidth(contWidth);
1426 pBox->SetLineStyle(contStyle);
1427 pBox->SetLineColor(contColor);
1428 pBox->SetFillStyle(contFill);
1429 pBox->Draw("SAME");
1430 }
1431 }
1432
1433 { // ** Occupancy in XZ plane
1434 auto* canv = MakeQaObject<TCanvas>("vs Station/point_zx", "", 1600, 800);
1435 canv->cd();
1436 fvph_point_zx[nSt]->DrawCopy("colz", "");
1437 for (int iSt = 0; iSt < nSt; ++iSt) {
1438 // Station positions in detector IFS
1439 const auto& actVol{fpDetInterface->GetActiveVolume(iSt)};
1440 double stZmin = actVol.GetMinZ();
1441 double stZmax = actVol.GetMaxZ();
1442 double stHmin = actVol.GetMinX();
1443 double stHmax = actVol.GetMaxX();
1444
1445 auto* pBox = new TBox(stZmin, stHmin, stZmax, stHmax);
1446 pBox->SetLineWidth(contWidth);
1447 pBox->SetLineStyle(contStyle);
1448 pBox->SetLineColor(contColor);
1449 pBox->SetFillStyle(contFill);
1450 pBox->Draw("SAME");
1451 }
1452 }
1453
1454 { // ** Occupancy in YZ plane
1455 auto* canv = MakeQaObject<TCanvas>("vs Station/point_zy", "", 1600, 800);
1456 canv->cd();
1457 fvph_point_zy[nSt]->DrawCopy("colz", "");
1458 for (int iSt = 0; iSt < nSt; ++iSt) {
1459 // Station positions in detector IFS
1460 const auto& actVol{fpDetInterface->GetActiveVolume(iSt)};
1461 double stZmin = actVol.GetMinZ();
1462 double stZmax = actVol.GetMaxZ();
1463 double stHmin = actVol.GetMinY();
1464 double stHmax = actVol.GetMaxY();
1465
1466 auto* pBox = new TBox(stZmin, stHmin, stZmax, stHmax);
1467 pBox->SetLineWidth(contWidth);
1468 pBox->SetLineStyle(contStyle);
1469 pBox->SetLineColor(contColor);
1470 pBox->SetFillStyle(contFill);
1471 pBox->Draw("SAME");
1472 }
1473 }
1474
1475 // **************
1476 // ** Residuals
1477
1478 { // x-coordinate
1479 auto* canv = MakeQaObject<TCanvas>("vs Station/res_x", "Residuals for x coordinate", 1600, 800);
1480 canv->DivideSquare(nSt);
1481 for (int iSt = 0; iSt < nSt; ++iSt) {
1482 canv->cd(iSt + 1);
1483 fvph_res_x[iSt]->DrawCopy("", "");
1484 }
1485 }
1486
1487 { // y-coordinate
1488 auto* canv = MakeQaObject<TCanvas>("vs Station/res_y", "Residuals for y coordinate", 1600, 800);
1489 canv->DivideSquare(nSt);
1490 for (int iSt = 0; iSt < nSt; ++iSt) {
1491 canv->cd(iSt + 1);
1492 fvph_res_y[iSt]->DrawCopy("", "");
1493 }
1494 }
1495
1496 { // u-coordinate
1497 auto* canv = MakeQaObject<TCanvas>("vs Station/res_u", "Residuals for u coordinate", 1600, 800);
1498 canv->DivideSquare(nSt);
1499 for (int iSt = 0; iSt < nSt; ++iSt) {
1500 canv->cd(iSt + 1);
1501 fvph_res_u[iSt]->DrawCopy("", "");
1502 }
1503 }
1504
1505 { // v-coordinate
1506 auto* canv = MakeQaObject<TCanvas>("vs Station/res_v", "Residuals for v coordinate", 1600, 800);
1507 canv->DivideSquare(nSt);
1508 for (int iSt = 0; iSt < nSt; ++iSt) {
1509 canv->cd(iSt + 1);
1510 fvph_res_v[iSt]->DrawCopy("", "");
1511 }
1512 }
1513
1514 { // t-coordinate
1515 auto* canv = MakeQaObject<TCanvas>("vs Station/res_t", "Residuals for time", 1600, 800);
1516 canv->DivideSquare(nSt);
1517 for (int iSt = 0; iSt < nSt; ++iSt) {
1518 canv->cd(iSt + 1);
1519 fvph_res_t[iSt]->DrawCopy("", "");
1520 }
1521 }
1522
1523
1524 // **********
1525 // ** Pulls
1526
1527 { // x-coordinate
1528 auto* canv = MakeQaObject<TCanvas>("vs Station/pull_x", "Pulls for x coordinate", 1600, 800);
1529 canv->DivideSquare(nSt);
1530 for (int iSt = 0; iSt < nSt; ++iSt) {
1531 canv->cd(iSt + 1);
1532 fvph_pull_x[iSt]->DrawCopy("", "");
1533 }
1534 }
1535
1536 { // y-coordinate
1537 auto* canv = MakeQaObject<TCanvas>("vs Station/pull_y", "Pulls for y coordinate", 1600, 800);
1538 canv->DivideSquare(nSt);
1539 for (int iSt = 0; iSt < nSt; ++iSt) {
1540 canv->cd(iSt + 1);
1541 fvph_pull_y[iSt]->DrawCopy("", "");
1542 }
1543 }
1544
1545 { // u-coordinate
1546 auto* canv = MakeQaObject<TCanvas>("vs Station/pull_u", "Pulls for u coordinate", 1600, 800);
1547 canv->DivideSquare(nSt);
1548 for (int iSt = 0; iSt < nSt; ++iSt) {
1549 canv->cd(iSt + 1);
1550 fvph_pull_u[iSt]->DrawCopy("", "");
1551 }
1552 }
1553
1554 { // v-coordinate
1555 auto* canv = MakeQaObject<TCanvas>("vs Station/pull_v", "Pulls for v coordinate", 1600, 800);
1556 canv->DivideSquare(nSt);
1557 for (int iSt = 0; iSt < nSt; ++iSt) {
1558 canv->cd(iSt + 1);
1559 fvph_pull_v[iSt]->DrawCopy("", "");
1560 }
1561 }
1562
1563 { // t-coordinate
1564 auto* canv = MakeQaObject<TCanvas>("vs Station/pull_t", "Pulls for time", 1600, 800);
1565 canv->DivideSquare(nSt);
1566 for (int iSt = 0; iSt < nSt; ++iSt) {
1567 canv->cd(iSt + 1);
1568 fvph_pull_t[iSt]->DrawCopy("", "");
1569 }
1570 }
1571
1572 // ************************************
1573 // ** Hit reconstruction efficiencies
1574
1575 {
1576 auto* canv = MakeQaObject<TCanvas>("vs Station/reco_eff", "Hit efficiencies in xy bins", 1600, 800);
1577 canv->DivideSquare(nSt);
1578 for (int iSt = 0; iSt < nSt; ++iSt) {
1579 canv->cd(iSt + 1);
1580 //fvph_reco_eff[iSt]->SetMarkerStyle(20);
1581 fvph_reco_eff[iSt]->DrawCopy();
1582 }
1583 }
1584
1585 {
1586 auto* canv = MakeQaObject<TCanvas>("vs Station/reco_eff_vs_xy", "Hit efficiencies wrt x and y", 1600, 800);
1587 canv->DivideSquare(nSt);
1588 for (int iSt = 0; iSt < nSt; ++iSt) {
1589 canv->cd(iSt + 1);
1590 fvpe_reco_eff_vs_xy[iSt]->DrawCopy("colz", "");
1591 }
1592 }
1593 }
1594}
1595
1596// ---------------------------------------------------------------------------------------------------------------------
1597//
1598template<ca::EDetectorID DetID>
1600{
1601 assert(point);
1602
1603 if (fConfig.fMcTrackCuts.fbPrimary && track->GetMotherId() >= 0) {
1604 return false;
1605 }
1606
1607 double px = std::numeric_limits<double>::signaling_NaN();
1608 double py = std::numeric_limits<double>::signaling_NaN();
1609 double pz = std::numeric_limits<double>::signaling_NaN();
1610 if constexpr (ca::EDetectorID::kTof == DetID) {
1611 px = point->GetPx();
1612 py = point->GetPy();
1613 pz = point->GetPz();
1614 }
1615 else {
1616 px = point->GetPxOut();
1617 py = point->GetPyOut();
1618 pz = point->GetPzOut();
1619 }
1620 double p = sqrt(px * px + py * py + pz * pz);
1621
1622 if (pz <= 0.) {
1623 return false;
1624 }
1625
1626 if (p < fConfig.fMcTrackCuts.fMinMom) {
1627 return false;
1628 }
1629
1630 if (TMath::ATan2(sqrt(px * px + py * py), pz) * TMath::RadToDeg() > fConfig.fMcTrackCuts.fMaxTheta) {
1631 return false;
1632 }
1633
1634 return true;
1635}
1636
Compile-time constants definition for the CA tracking algorithm.
Class providing basic functionality for CA input QA-tasks.
Implementation of L1DetectorID enum class for CBM.
Class for pixel hits in MUCH detector.
Definition of CbmQaTable class.
Useful utilities for CBM QA tasks.
Data class for STS clusters.
Data class for a reconstructed hit in the STS.
Class for hits in TRD detector.
friend fvec sqrt(const fvec &a)
friend fscal max(fscal x, fscal y)
friend fscal min(fscal x, fscal y)
Generates beam ions for transport simulation.
A QA-task class, which provides assurance of MuCh hits and geometry.
std::vector< TH1F * > fvph_point_hit_delta_z
difference between z of hit and MC point in different stations
std::array< double, 2 > fRangeDzHitPoint
Range for z-pos difference of the hit and point [cm].
cbm::ca::HitQaData fHitQaData
Current hit QA data object.
std::vector< TH1F * > fvph_hit_du
std::vector< TH2F * > fvph_res_v_vs_v
residual for v coordinate in different stations
static constexpr auto DetName
std::vector< double > frYmin
Range for hit y coordinate [cm].
TClonesArray * fpHits
Array of hits.
std::vector< TH2F * > fvph_res_u_vs_u
residual for u coordinate in different stations
std::vector< TH1F * > fvph_res_u
residual for u coordinate in different stations
std::vector< double > frXmax
Range for hit x coordinate [cm].
std::vector< TH1F * > fvph_pull_t
pull for t coordinate in different stations
void CreateSummary() override
Creates summary cavases, tables etc.
std::vector< TH1F * > fvph_n_points_per_hit
number of points per one hit in different stations
std::vector< TH2F * > fvph_hit_xy
hit y vs x in different stations
std::vector< double > frZmin
Range for hit z coordinate [cm].
std::vector< TH2F * > fvph_res_t_vs_t
residual for t coordinate in different stations
std::vector< TH1F * > fvph_hit_dt
std::vector< TH1F * > fvph_pull_y
pull for y coordinate in different stations
void ExecQa() override
Fills histograms per event or time-slice.
std::vector< TH1F * > fvph_res_x
residual for x coordinate in different stations
std::vector< double > frXmin
Range for hit x coordinate [cm].
std::pair< std::string, bool > CheckRangePull(TH1 *h) const
Checks ranges for mean and standard deviation.
std::vector< TH2F * > fvph_point_xy
point y vs x in different stations
std::vector< TH1F * > fvph_pull_v
pull for v coordinate in different stations
std::vector< TProfile2D * > fvpe_reco_eff_vs_xy
Efficiency of hit reconstruction vs. x and y coordinates of MC.
static constexpr int kNbinsPull
cbm::ca::PointTypes_t::at< DetID > Point_t
Point type for a given detector ID.
std::vector< TH2F * > fvph_hit_zx
hit x vs z in different stations
CbmDigiManager * fDigiManager
Interface to digi branches.
std::array< double, 2 > fRHitDt
Range for hit time error [ns].
std::vector< TH2F * > fvph_point_zy
point y vs z in different stations
std::array< double, 2 > fRHitDv
Range for hit v coordinate error [cm].
std::vector< double > frYmax
Range for hit y coordinate [cm].
CbmMCDataArray * fpMCPoints
Array of MC points.
std::vector< TH1F * > fvph_pull_u
pull for u coordinate in different stations
std::array< double, 2 > fRHitDy
Range for hit y coordinate error [cm].
CbmMCDataArray * fpMCTracks
Array of MC tracks.
std::vector< TH2F * > fvph_point_zx
point x vs z in different stations
std::vector< TH1F * > fvph_hit_dx
void Check() override
Method to check, if the QA results are acceptable.
cbm::algo::ca::Monitor< EMonitorKey > fMonitor
Monitor for the input QA.
std::vector< TH1F * > fvph_res_y
residual for y coordinate in different stations
int fNbins
General number of bins.
TClonesArray * fpHitMatches
Array of hit matches.
std::array< double, 2 > fRResU
Range for residual of u coordinate [cm].
CbmMCDataManager * fpMCDataManager
MC data manager.
std::vector< TH2F * > fvph_pull_y_vs_y
pull for y coordinate in different stations
CbmMCEventList * fpMCEventList
MC event list.
std::vector< TH1F * > fvph_res_v
residual for v coordinate in different stations
std::vector< double > frZmax
Range for hit z coordinate [cm].
std::vector< TH1F * > fvph_res_t
residual for t coordinate in different stations
static constexpr double kRPull[2]
Range for pull histograms coordinate.
std::vector< TH1F * > fvph_reco_eff
Distribution of hit reconstruction efficiency in bins of fvpe_reco_eff_vs_xy.
CbmCaInputQaBase(const char *name, int verbose, bool isMCUsed)
Constructor from parameters.
std::vector< TH2F * > fvph_pull_v_vs_v
pull for v coordinate in different stations
int fNbinsZ
Number of bins for z axis in overall views.
std::vector< TH2F * > fvph_res_y_vs_y
residual for y coordinate in different stations
std::array< double, 2 > fRResY
Range for residual of y coordinate [cm].
std::vector< TH2F * > fvph_res_x_vs_x
residual for x coordinate in different stations
static constexpr double kNAN
std::array< double, 2 > fRHitDu
Range for hit u coordinate error [cm].
Config fConfig
Task specific configuration parameters.
std::array< double, 2 > fRResT
Range for residual of time [ns].
std::vector< TH2F * > fvph_hit_zy
hit y vs z in different stations
bool IsTrackSelected(const CbmMCTrack *track, const Point_t *point) const
checks if the track at mc point passes the track selection cuts
InitStatus InitQa() override
Initializes QA task.
std::vector< TH2F * > fvph_pull_u_vs_u
pull for u coordinate in different stations
std::vector< TH1F * > fvph_hit_kuv
std::vector< TH2F * > fvph_pull_x_vs_x
pull for x coordinate in different stations
std::vector< TH2F * > fvph_pull_t_vs_t
pull for t coordinate in different stations
std::vector< TH1F * > fvph_hit_dv
std::array< double, 2 > fRHitDx
Range for hit x coordinate error [cm].
std::vector< TH1F * > fvph_pull_x
pull for x coordinate in different stations
const cbm::algo::RecoSetupUnit_t< ToCbmModuleId(DetID)> * fpDetInterface
Instance of detector interface.
virtual void FillHistogramsPerHit()
Fills histograms per hit.
std::vector< TH1F * > fvph_hit_dy
std::array< double, 2 > fRResX
Range for residual of x coordinate [cm].
std::array< double, 2 > fRResV
Range for residual of v coordinate [cm].
void DeInit() override
De-initializes histograms.
static CbmDigiManager * Instance()
Static instance.
Task class creating and managing CbmMCDataArray objects.
Container class for MC events with number, file and start time.
int32_t GetMotherId() const
Definition CbmMCTrack.h:68
T * MakeQaObject(TString sName, TString sTitle, Args... args)
Definition CbmQaIO.h:260
void MakeQaDirectory(TString sName)
Definition CbmQaIO.cxx:132
std::optional< Config > ReadSpecificConfig() const
Reads the specific configuration structure from the YAML node.
Definition CbmQaIO.h:126
void SetStoringMode(EStoringMode mode)
Set storing mode.
Definition CbmQaIO.h:111
@ kSUBDIR
Objects of different type will be stored in different subdirectories like histograms/ canvases/.
Definition CbmQaIO.h:50
TODO: SZh, 30.01.2023: Override THistPainter::PaintText() to add zeroes in tables.
Definition CbmQaTable.h:24
CbmQaTask(const char *name, int verbose, bool isMCUsed, ECbmRecoMode recoMode=ECbmRecoMode::Timeslice)
Constructor from parameters.
Definition CbmQaTask.cxx:32
bool IsMCUsed() const
Returns flag, whether MC information is used or not in the task.
Definition CbmQaTask.h:126
Data class with information on a STS local track.
static int32_t GetSmType(uint32_t address)
static RecoSetupManager * Instance()
Instance access.
constexpr fscal SpeedOfLight
Speed of light [cm/ns].
Definition CaDefs.h:95
TODO: SZh 8.11.2022: add selection of parameterisation.
Definition CaBranch.h:14
constexpr ECbmModuleId ToCbmModuleId(EDetectorID detID)
Conversion map from EDetectorID to ECbmModuleId.
Definition CbmDefs.h:228
constexpr DetIdArr_t< const char * > kDetPointBrName
Name of point branches for each detector.
constexpr DetIdArr_t< const char * > kDetHitBrName
Name of hit branches for each detector.
void SetLargeStats(TH1 *pHist)
Set large stat. window.
Specific configuration for the CA input QA task.