CbmRoot
Loading...
Searching...
No Matches
CbmCaOutputQa.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko [committer] */
4
9
10#include "CbmCaOutputQa.h"
11
12#include "CbmCaMCModule.h"
14#include "CbmKfTarget.h"
15#include "FairRootManager.h"
16#include "Logger.h"
17#include "TAttLine.h"
18#include "THStack.h"
19#include "TMarker.h"
20#include "TPad.h"
21#include "TText.h"
22
23#include <thread>
24
30
31// ---------------------------------------------------------------------------------------------------------------------
32//
33OutputQa::OutputQa(int verbose, bool isMCUsed, ECbmRecoMode recoMode)
34 : CbmQaTask("CbmCaOutputQa", verbose, isMCUsed, recoMode)
35 , fDebugger("CaOutputQaDebug.root")
36{
37 // Create TS reader
38 fpTSReader = std::make_unique<TimeSliceReader>();
39
40 // Turn on default track classes
47
60
73
74 //AddTrackType(ETrackType::kAllE);
75 //AddTrackType(ETrackType::kAllMU);
76 //AddTrackType(ETrackType::kAllPI);
77 //AddTrackType(ETrackType::kAllK);
78 //AddTrackType(ETrackType::kAllPPBAR);
79
80 // Init track type histograms drawing attributes
82}
83
84// ---------------------------------------------------------------------------------------------------------------------
85//
87{
88 // Create summary table
89 if (IsMCUsed()) {
90 fpMCModule->Finish();
91
92 // TODO: Add cuts on entries from fmSummaryTableEntries
93 std::vector<ETrackType> vTypesToPlot;
94 int nRows = std::count_if(fmSummaryTableEntries.begin(), fmSummaryTableEntries.end(),
95 [&](const auto& f) { return fvbTrackTypeOn[f] && fvpTrackHistograms[f]->IsMCUsed(); })
96 + 1;
97
98 CbmQaTable* aTable = MakeQaObject<CbmQaTable>("summary_table", "Tracking summary table", nRows + 1, 9);
99 int iRow = 0;
100 std::vector<std::string> colNames = {"Efficiency", "Killed", "Length", "Fakes", "Clones",
101 "Reco/Evt", "MC/Evt", "Nst(hit)", "Nst(point)"};
102 aTable->SetNamesOfCols(colNames);
103 aTable->SetColWidth(14);
104 double nEvents = static_cast<double>(GetEventNumber());
105 LOG(info) << "Number of events: " << GetEventNumber();
106 for (auto trType : fmSummaryTableEntries) {
107 if (!fvbTrackTypeOn[trType] || !fvpTrackHistograms[trType]->IsMCUsed()) {
108 continue;
109 }
110 aTable->SetRowName(iRow, fvpTrackHistograms[trType]->GetTitle());
111 aTable->SetCell(iRow, 0, fvpTrackHistograms[trType]->GetIntegratedEff());
112 aTable->SetCell(iRow, 1, fvpTrackHistograms[trType]->GetKilledRate());
113 aTable->SetCell(iRow, 2, fvpTrackHistograms[trType]->GetAverageRecoLength());
114 aTable->SetCell(iRow, 3, fvpTrackHistograms[trType]->GetAverageFakeLength());
115 aTable->SetCell(iRow, 4, fvpTrackHistograms[trType]->GetClonesRate());
116 aTable->SetCell(iRow, 5, fvpTrackHistograms[trType]->GetNofRecoTracksMatched() / nEvents);
117 aTable->SetCell(iRow, 6, fvpTrackHistograms[trType]->GetNofMCTracks() / nEvents);
118 aTable->SetCell(iRow, 7, fvpTrackHistograms[trType]->GetAverageNofStationsWithHit());
119 aTable->SetCell(iRow, 8, fvpTrackHistograms[trType]->GetAverageNofStationsWithPoint());
120 ++iRow;
121 }
122 double nGhosts = 0.;
124 nGhosts = fvpTrackHistograms[ETrackType::kGhost]->fph_reco_p->GetEntries();
125 aTable->SetRowName(iRow, "N ghosts");
126 aTable->SetCell(iRow, 0, nGhosts);
127 aTable->SetRowName(iRow + 1, "Ghost rate");
128 aTable->SetCell(iRow + 1, 0, nGhosts / fMonitor.GetCounterValue(EMonitorKey::kTrack));
129 }
130 LOG(info) << '\n' << aTable->ToString(3);
131 }
132
133 LOG(info) << '\n' << fMonitor.ToString();
134}
135
136// ---------------------------------------------------------------------------------------------------------------------
137//
139{
140 constexpr double kZmin = 0.;
141 constexpr double kZmax = 300.;
142 constexpr double kXmin = -100.;
143 constexpr double kXmax = +100.;
144 constexpr double kYmin = -100.;
145 constexpr double kYmax = +100.;
146 constexpr std::array<Color_t, 11> kColorMC = {205, 209, 213, 217, 225, 208, 213, 216, 219, 224, 227};
147 constexpr std::array<Color_t, 3> kColorGhost = {201, 202, 203};
148 constexpr int kCanvX = 1920;
149 constexpr int kCanvY = 1080;
150 constexpr double kLMargin = 0.05; // Left margin
151 constexpr double kVEMargin = 0.15; // Vertical margin (top + bottom)
152 constexpr double kRMarginDispl = 0.4;
153 constexpr double kVIMargin = 0.0001;
154 constexpr Marker_t kMarkerPointWHit = 25;
155 constexpr Marker_t kMarkerPointWOHit = 5;
156 constexpr Marker_t kMarkerHitWPoint = 24;
157 constexpr Marker_t kMarkerHitWOPoint = 28;
158 constexpr double kFontSize = 0.035;
159 constexpr Width_t kLineWidth = 1;
160 constexpr Style_t kLineMCTrackReconstructed = 9;
161 constexpr Style_t kLineMCTrackNotReconstructed = 10;
162 constexpr Style_t kLineRecoTrackGhost = 2;
163 constexpr Style_t kLineRecoTrackNotGhost = 1;
164
165 int iEvent = GetEventNumber();
166 auto* pCanv = MakeQaObject<CbmQaCanvas>(Form("events/event_%d", iEvent), Form("event_%d", iEvent), kCanvX, kCanvY);
167 pCanv->Divide(1, 2, kVIMargin, kVIMargin);
168 pCanv->cd(1);
169 gPad->SetMargin(kLMargin, kRMarginDispl, kVIMargin, kVEMargin);
170 gPad->SetGrid();
171 auto* pHistX = new TH2F(Form("hFrameX_%d", iEvent), ";z [cm];x [cm]", 2, kZmin, kZmax, 2, kXmin, kXmax);
172 pHistX->GetYaxis()->SetTitleOffset(0.6);
173 pHistX->GetXaxis()->SetLabelSize(kFontSize);
174 pHistX->GetYaxis()->SetLabelSize(kFontSize);
175 pHistX->GetXaxis()->SetTitleSize(kFontSize);
176 pHistX->GetYaxis()->SetTitleSize(kFontSize);
177 pHistX->SetStats(false);
178 pHistX->Draw();
179 pCanv->cd(2);
180 gPad->SetMargin(kLMargin, kRMarginDispl, kVEMargin, kVIMargin);
181 gPad->SetGrid();
182 auto* pHistY = new TH2F(Form("hFrameY_%d", iEvent), ";z [cm];y [cm]", 2, kZmin, kZmax, 2, kYmin, kYmax);
183 pHistY->GetYaxis()->SetTitleOffset(0.6);
184 pHistY->GetXaxis()->SetLabelSize(kFontSize);
185 pHistY->GetYaxis()->SetLabelSize(kFontSize);
186 pHistY->GetXaxis()->SetTitleSize(kFontSize);
187 pHistY->GetYaxis()->SetTitleSize(kFontSize);
188 pHistY->SetStats(false);
189 pHistY->Draw();
190
191 pCanv->cd(1);
192
193 auto* pHeader = new TLegend(kLMargin, 1 - kVEMargin + 0.01, 0.99, 0.99);
194 pHeader->SetNColumns(6);
195 pHeader->SetTextSize(kFontSize);
196 pHeader->SetMargin(0.1);
197 pHeader->AddEntry(static_cast<TObject*>(nullptr), Form("event #%d", iEvent), "");
198 pHeader->AddEntry(new TMarker(0, 0, kMarkerPointWHit), "point w/ hit", "p");
199 pHeader->AddEntry(new TMarker(0, 0, kMarkerPointWOHit), "point w/o hit", "p");
200 pHeader->AddEntry(new TMarker(0, 0, kMarkerHitWPoint), "hit w/ point", "p");
201 pHeader->AddEntry(new TMarker(0, 0, kMarkerHitWOPoint), "hit w/o point", "p");
202 pHeader->Draw("same");
203
204 auto* pLegendReco = new TLegend(1 - kRMarginDispl, kVIMargin, 0.99, 1 - kVEMargin, "Reco tracks");
205 pLegendReco->SetMargin(0.1);
206 pLegendReco->SetTextSize(kFontSize);
207 //pLegendReco->SetHeader("Reco Tracks", "C");
208 pCanv->cd(2);
209 auto* pLegendMC = new TLegend(1 - kRMarginDispl, kVEMargin, 0.99, 1 - kVIMargin, "MC tracks");
210 pLegendMC->SetMargin(0.1);
211 pLegendMC->SetTextSize(kFontSize);
212 //pLegendMC->SetHeader("MC Tracks", "C");
213
214 int iColorRec = 0;
215 int iColorGhost = 0;
216
217 // Draw MC tracks
218 std::map<int, Color_t> mMCtrkColors; // Trk ID vs. color
219 if (IsMCUsed()) {
220 // Draw MC tracks
221 int nMCTracks = fMCData.GetNofTracks();
222 for (int iTmc = 0; iTmc < nMCTracks; ++iTmc) {
223 const auto& trk = fMCData.GetTrack(iTmc);
224 int nPoints = trk.GetNofPoints();
225 if (nPoints == 0) {
226 continue;
227 }
228 std::vector<double> trkPointX(nPoints);
229 std::vector<double> trkPointY(nPoints);
230 std::vector<double> trkPointZ(nPoints);
231 for (int iPLoc = 0; iPLoc < nPoints; ++iPLoc) {
232 const auto& point = fMCData.GetPoint(trk.GetPointIndexes()[iPLoc]);
233 trkPointX[iPLoc] = point.GetX();
234 trkPointY[iPLoc] = point.GetY();
235 trkPointZ[iPLoc] = point.GetZ();
236 }
237 Color_t currColor = 1;
238 Style_t currStyle = trk.IsReconstructed() ? kLineMCTrackReconstructed : kLineMCTrackNotReconstructed;
239 currColor = kColorMC[iColorRec];
240 iColorRec = (iColorRec + 1) % static_cast<int>(kColorMC.size());
241 mMCtrkColors[trk.GetId()] = currColor;
242 {
243 pCanv->cd(1);
244 auto* gr = new TGraph(nPoints, trkPointZ.data(), trkPointX.data());
245 gr->SetMarkerStyle(1);
246 gr->SetMarkerColor(currColor);
247 gr->SetLineColor(currColor);
248 gr->SetLineStyle(currStyle);
249 gr->SetLineWidth(kLineWidth);
250 gr->Draw("LSAME");
251
252 std::stringstream msg;
253 msg << "ID=" << trk.GetId() << ", ";
254 msg << "PDG=" << trk.GetPdgCode() << ", ";
255 msg << "p=" << trk.GetP() << " GeV/c, ";
256 msg << "rec-able=" << trk.IsReconstructable() << ", ";
257 msg << "rec-ed=" << trk.IsReconstructed() << ", ";
258 if (trk.GetNofRecoTracks() > 0) {
259 msg << "reco_IDs=(";
260 for (int iTr : trk.GetRecoTrackIndexes()) {
261 msg << iTr << ' ';
262 }
263 msg << "), ";
264 }
265 if (trk.GetNofTouchTracks() > 0) {
266 msg << "touch_IDs=(";
267 for (int iTr : trk.GetTouchTrackIndexes()) {
268 msg << iTr << ' ';
269 }
270 msg << "), ";
271 }
272 pLegendMC->AddEntry(gr, msg.str().c_str(), "l");
273 }
274 {
275 pCanv->cd(2);
276 auto* gr = new TGraph(nPoints, trkPointZ.data(), trkPointY.data());
277 gr->SetMarkerStyle(1);
278 gr->SetMarkerColor(currColor);
279 gr->SetLineColor(currColor);
280 gr->SetLineStyle(currStyle);
281 gr->SetLineWidth(kLineWidth);
282 gr->Draw("LSAME");
283 }
284 }
285
286 // Draw MC points
287 int nPoints = fMCData.GetNofPoints();
288 for (int iP = 0; iP < nPoints; ++iP) {
289 const auto& point = fMCData.GetPoint(iP);
290 bool bHasHit = point.GetHitIndexes().size() > 0;
291 Marker_t style = bHasHit ? kMarkerPointWHit : kMarkerPointWOHit;
292 Color_t color = mMCtrkColors.at(point.GetTrackId());
293 {
294 pCanv->cd(1);
295 auto* marker = new TMarker(point.GetZ(), point.GetX(), style);
296 marker->SetMarkerColor(color);
297 marker->Draw("same");
298
299 auto* pText = new TText(point.GetZ() + 2., point.GetX() + 2., Form("%d", point.GetActiveStationId()));
300 pText->SetTextColor(color);
301 pText->SetTextSize(kFontSize);
302 pText->Draw("same");
303 }
304 {
305 pCanv->cd(2);
306 auto* marker = new TMarker(point.GetZ(), point.GetY(), style);
307 marker->SetMarkerColor(color);
308 marker->Draw("same");
309
310 auto* pText = new TText(point.GetZ() + 2., point.GetY() + 2., Form("%d", point.GetActiveStationId()));
311 pText->SetTextColor(color);
312 pText->SetTextSize(kFontSize);
313 pText->Draw("same");
314 }
315 }
316
317 // Draw reconstructed tracks
318 int nRecoTracks = fvRecoTracks.size();
319 std::vector<char> vbHitUsed(fvHits.size());
320 std::vector<Color_t> vRecoTrkColors(fvHits.size()); // Reco hit ID vs. color
321 if (nRecoTracks > 0) {
322 for (int iTr = 0; iTr < nRecoTracks; ++iTr) {
323 const auto& trk = fvRecoTracks[iTr];
324 Color_t currColor = 1;
325 Style_t currStyle = trk.IsGhost() ? kLineRecoTrackGhost : kLineRecoTrackNotGhost;
326 if (trk.IsGhost()) {
327 currColor = kColorGhost[iColorGhost];
328 iColorGhost = (iColorGhost + 1) % static_cast<int>(kColorGhost.size());
329 }
330 else {
331 int iTmc = trk.GetMatchedMCTrackIndex();
332 currColor = iTmc > -1 ? mMCtrkColors[iTmc] : 1;
333 }
334
335 int nHits = trk.GetNofHits();
336 std::vector<double> trkHitX(nHits);
337 std::vector<double> trkHitY(nHits);
338 std::vector<double> trkHitZ(nHits);
339 for (int iHLoc = 0; iHLoc < nHits; ++iHLoc) {
340 int iH = trk.GetHitIndexes()[iHLoc];
341 const auto& hit = fvHits[iH];
342 vbHitUsed[iH] = true;
343 trkHitX[iHLoc] = hit.GetX();
344 trkHitY[iHLoc] = hit.GetY();
345 trkHitZ[iHLoc] = hit.GetZ();
346 vRecoTrkColors[iH] = currColor;
347 }
348
349 {
350 pCanv->cd(1);
351 auto* gr = new TGraph(nHits, trkHitZ.data(), trkHitX.data());
352 gr->SetMarkerStyle(1);
353 gr->SetMarkerColor(currColor);
354 gr->SetLineColor(currColor);
355 gr->SetLineStyle(currStyle);
356 gr->SetLineWidth(kLineWidth + 2);
357 gr->Draw("LSAME");
358 }
359 {
360 pCanv->cd(2);
361 auto* gr = new TGraph(nHits, trkHitZ.data(), trkHitY.data());
362 gr->SetMarkerStyle(1);
363 gr->SetMarkerColor(currColor);
364 gr->SetLineColor(currColor);
365 gr->SetLineStyle(currStyle);
366 gr->SetLineWidth(kLineWidth + 2);
367 gr->Draw("LSAME");
368 std::stringstream msg;
369 msg << "ID=" << trk.index << ", ";
370 msg << "MC_IDs=(";
371 for (int iTmc : trk.GetMCTrackIndexes()) {
372 msg << iTmc << ' ';
373 }
374 msg << "), ";
375 msg << "purity=" << trk.GetMaxPurity();
376 pLegendReco->AddEntry(gr, msg.str().c_str(), "l");
377 }
378 }
379 }
380 // Draw hits
381 int nHits = fvHits.size();
382 if (nHits > 0) {
383 for (int iH = 0; iH < nHits; ++iH) {
384 const auto& hit = fvHits[iH];
385 bool bFake = hit.GetBestMcPointId() == -1;
386 bool bUsed = vbHitUsed[iH];
387
388 Marker_t style = bFake ? kMarkerHitWOPoint : kMarkerHitWPoint;
389 Color_t color = bUsed ? vRecoTrkColors[iH] : 1;
390 {
391 pCanv->cd(1);
392 auto* marker = new TMarker(hit.GetZ(), hit.GetX(), style);
393 marker->SetMarkerColor(color);
394 marker->Draw("same");
395 }
396 {
397 pCanv->cd(2);
398 auto* marker = new TMarker(hit.GetZ(), hit.GetY(), style);
399 marker->SetMarkerColor(color);
400 marker->Draw("same");
401 }
402 }
403 }
404 }
405 pCanv->cd(1);
406 pLegendReco->Draw();
407 pCanv->cd(2);
408 pLegendMC->Draw();
409}
410
411// ---------------------------------------------------------------------------------------------------------------------
412//
414{
415 fMonitor.IncrementCounter(EMonitorKey::kEvent);
416
417 // Read reconstructed input
418 fpTSReader->ReadEvent(this->GetCurrentEvent());
419 int nHits = fvHits.size();
420 int nRecoTracks = fvRecoTracks.size();
421
422 fMonitor.IncrementCounter(EMonitorKey::kTrack, nRecoTracks);
423 fMonitor.IncrementCounter(EMonitorKey::kHit, nHits);
424
425 // Match tracks and points
426 // Read MC tracks and points
427 int nMCTracks = 0;
428 int nMCPoints = 0;
429 if (IsMCUsed()) {
430 fpMCModule->InitEvent(this->GetCurrentEvent());
431 nMCPoints = fMCData.GetNofPoints();
432 nMCTracks = fMCData.GetNofTracks();
433 fpMCModule->MatchHits();
434 fpMCModule->MatchTracks();
435 fMonitor.IncrementCounter(EMonitorKey::kMcPoint, nMCPoints);
436 fMonitor.IncrementCounter(EMonitorKey::kMcTrack, nMCTracks);
437 // TODO: enable for real data, select interesting events
438 if (fbDrawEvents && nMCPoints > std::max(0, fEvtDisplayMinNofPoints)) {
439 DrawEvent();
440 }
441 }
442 LOG_IF(info, fVerbose > 3) << ": Data sample consists of " << nHits << " hits, " << nRecoTracks << " reco tracks, "
443 << nMCTracks << " MC tracks, " << nMCPoints << " MC points";
444 LOG_IF(info, fVerbose > 3) << "Using " << fNthreads
445 << " threads for track propagation, max extrapolation step: " << fMaxExtrapolationStep
446 << " cm";
447
448 // ************************************************************************
449 // ** Fill distributions for reconstructed tracks (including ghost ones) **
450 // ************************************************************************
451
452 // Estimates DCA rt origin using STS hits
453 auto EstimateDcaRtOriginReco = [&](const CbmL1Track& trk) -> double {
454 const auto* pTarget = cbm::kf::Target::Instance();
455 std::vector<const cbm::algo::ca::McHitInfo*> vpStsHits;
456 for (auto iHit : trk.GetHitIndexes()) {
457 const auto& hit = fvHits[iHit];
458 if (hit.GetDetectorType() == static_cast<int>(ca::EDetectorID::kSts)) {
459 vpStsHits.push_back(&hit);
460 }
461 }
462 std::sort(vpStsHits.begin(), vpStsHits.end(), [](const auto* l, const auto* r) { return l->GetZ() < r->GetZ(); });
463 if (vpStsHits.size() < 2) {
464 return std::numeric_limits<double>::quiet_NaN();
465 }
466
467 const auto* pHitFst = vpStsHits[0];
468 const auto* pHitSnd = vpStsHits[1];
469 double factor{(pHitFst->GetZ() - pTarget->GetZ()) / (pHitSnd->GetZ() - pHitFst->GetZ())};
470 double x{pHitFst->GetX() - pTarget->GetX() - factor * (pHitSnd->GetX() - pHitFst->GetX())};
471 double y{pHitFst->GetY() - pTarget->GetY() - factor * (pHitSnd->GetY() - pHitFst->GetY())};
472 return std::sqrt(x * x + y * y);
473 };
474
475
476 std::vector<TrackTypeQa::FitQaPointSet> allFitPoints(nRecoTracks + 1); // +1 for the case of no reco tracks
477
478 { // Create fit points in parallel
479 if (fNthreads < 1) {
480 fNthreads = 1;
481 }
482
483 auto fitPointsThread = [&](int iThread) {
484 for (int iTrkReco = iThread; iTrkReco < nRecoTracks; iTrkReco += fNthreads) {
485 allFitPoints[iTrkReco] = CreateFitQaPointSet(iTrkReco);
486 }
487 };
488
489 std::vector<std::thread> threads(fNthreads);
490 for (int i = 0; i < fNthreads; i++) {
491 threads[i] = std::thread(fitPointsThread, i);
492 }
493 for (auto& th : threads) {
494 th.join();
495 }
496 }
497
498 for (int iTrkReco = 0; iTrkReco < nRecoTracks; iTrkReco++) {
499
500 const auto& recoTrk = fvRecoTracks[iTrkReco];
501
502 // Reject tracks, which do not contain hits (??????????????)
503 if (recoTrk.GetNofHits() < 1) {
504 continue;
505 }
506 std::vector<ETrackType> vTrackTypes;
507 vTrackTypes.reserve(ETrackType::END);
508
509 vTrackTypes.push_back(ETrackType::kAll);
510
512 std::array<int, static_cast<int>(ca::EDetectorID::END)> nHitsDet = {0}; //< Number of hits per detector
513 for (auto iHit : recoTrk.GetHitIndexes()) {
514 const auto& hit = fvHits[iHit];
515 ++nHitsDet[hit.GetDetectorType()];
516 }
517 int nStsHits = nHitsDet[static_cast<int>(ca::EDetectorID::kSts)];
518 int nTofHits = nHitsDet[static_cast<int>(ca::EDetectorID::kTof)];
519 if (nStsHits > 1 && nTofHits > 0) {
520 vTrackTypes.push_back(ETrackType::kAll2STS1TOF);
521 double dcaRtOrigin = EstimateDcaRtOriginReco(recoTrk);
522 if (dcaRtOrigin < 0.5) { // primary
523 vTrackTypes.push_back(ETrackType::kPrim2STS1TOF);
524 }
525 else { // secondary
526 vTrackTypes.push_back(ETrackType::kSec2STS1TOF);
527 }
528 }
529 }
530
531 if (IsMCUsed()) {
532 // NOTE: The ghost status of track is now defined by its purity, thus it can still contain MC information
533 if (recoTrk.IsGhost()) {
534 vTrackTypes.push_back(ETrackType::kGhost);
535 }
536
537 int iTrkMC = recoTrk.GetMatchedMCTrackIndex();
538 if (iTrkMC > -1) {
539 const auto& mcTrk = fMCData.GetTrack(iTrkMC);
540 int pdg = mcTrk.GetPdgCode();
541 bool isPrimary = mcTrk.IsPrimary();
542
543 // Check that the MC track has hits in the tracker
544 if (mcTrk.GetNofHits() == 0) {
545 LOG(error) << "Track #" << iTrkMC << " (ID=" << mcTrk.GetId()
546 << ") has no hits in tracker, but is referenced by "
547 << "reco track #" << iTrkReco << " (ID=" << recoTrk.index << ").";
548 }
549
550 if (isPrimary) {
551 vTrackTypes.push_back(ETrackType::kPrim);
552 bool bFast = mcTrk.GetP() > CbmL1Constants::MinFastMom;
553 bool bLong = mcTrk.GetTotNofStationsWithHit() == fpParameters->GetNstationsActive();
554 if (bFast) {
555 vTrackTypes.push_back(ETrackType::kPrimFast);
556 }
557 if (bLong) {
558 vTrackTypes.push_back(ETrackType::kPrimLong);
559 }
560 if (bLong && bFast) {
561 vTrackTypes.push_back(ETrackType::kPrimLongFast);
562 }
563 }
564 else {
565 vTrackTypes.push_back(ETrackType::kSec);
566 if (mcTrk.GetP() > CbmL1Constants::MinFastMom) {
567 vTrackTypes.push_back(ETrackType::kSecFast);
568 }
569 }
570
571 // Track distributions for different particle species
572 switch (std::abs(pdg)) {
573 case 211: // pion
574 vTrackTypes.push_back(ETrackType::kAllPI);
575 if (isPrimary) {
576 vTrackTypes.push_back(ETrackType::kPrimPI);
577 vTrackTypes.push_back((pdg > 0) ? ETrackType::kPrimPIP : ETrackType::kPrimPIM);
578 }
579 else {
580 vTrackTypes.push_back(ETrackType::kSecPI);
581 vTrackTypes.push_back((pdg > 0) ? ETrackType::kSecPIP : ETrackType::kSecPIM);
582 }
583 break;
584 case 2212: // proton
585 vTrackTypes.push_back(ETrackType::kAllPPBAR);
586 if (isPrimary) {
587 vTrackTypes.push_back(ETrackType::kPrimPPBAR);
588 vTrackTypes.push_back((pdg > 0) ? ETrackType::kPrimP : ETrackType::kPrimPBAR);
589 }
590 else {
591 vTrackTypes.push_back(ETrackType::kSecPPBAR);
592 vTrackTypes.push_back((pdg > 0) ? ETrackType::kSecP : ETrackType::kSecPBAR);
593 }
594 break;
595 case 321: // kaon
596 vTrackTypes.push_back(ETrackType::kAllK);
597 if (isPrimary) {
598 vTrackTypes.push_back(ETrackType::kPrimK);
599 vTrackTypes.push_back((pdg > 0) ? ETrackType::kPrimKP : ETrackType::kPrimKM);
600 }
601 else {
602 vTrackTypes.push_back(ETrackType::kSecK);
603 vTrackTypes.push_back((pdg > 0) ? ETrackType::kSecKP : ETrackType::kSecKM);
604 }
605 break;
606 case 11: // electron
607 vTrackTypes.push_back(ETrackType::kAllE);
608 if (isPrimary) {
609 vTrackTypes.push_back(ETrackType::kPrimE);
610 vTrackTypes.push_back((pdg < 0) ? ETrackType::kPrimEP : ETrackType::kPrimEM);
611 }
612 else {
613 vTrackTypes.push_back(ETrackType::kSecE);
614 vTrackTypes.push_back((pdg < 0) ? ETrackType::kSecEP : ETrackType::kSecEM);
615 }
616 break;
617 case 13: // muon
618 vTrackTypes.push_back(ETrackType::kAllMU);
619 if (isPrimary) {
620 vTrackTypes.push_back(ETrackType::kPrimMU);
621 vTrackTypes.push_back((pdg > 0) ? ETrackType::kPrimMUP : ETrackType::kPrimMUM);
622 }
623 else {
624 vTrackTypes.push_back(ETrackType::kSecMU);
625 vTrackTypes.push_back((pdg > 0) ? ETrackType::kSecMUP : ETrackType::kSecMUM);
626 }
627 break;
628 } // switch abs(pdg): end
629 } // if iTrkMC > -1: end
630 } // if IsMCUsed(): end
631
632 for (auto trType : vTrackTypes) { // Fill track type histograms
633 if (fvbTrackTypeOn[trType]) {
634 fvpTrackHistograms[trType]->FillRecoTrack(iTrkReco, allFitPoints[iTrkReco]);
635 }
636 }
637 } // loop over recoTrk: end
638
639
640 // *************************************
641 // ** Fill distributions of MC-tracks **
642 // *************************************
643 if (IsMCUsed()) {
644 // Estimates DCA rt origin using STS hits
645 auto EstimateDcaRtOriginMc = [&](const McTrack& trk) -> double {
646 const auto* pTarget = cbm::kf::Target::Instance();
647 std::vector<const cbm::algo::ca::McHitInfo*> vpStsHits;
648 for (auto iHit : trk.GetHitIndexes()) {
649 const auto& hit = fvHits[iHit];
650 if (hit.GetDetectorType() == static_cast<int>(ca::EDetectorID::kSts)) {
651 vpStsHits.push_back(&hit);
652 }
653 }
654 std::sort(vpStsHits.begin(), vpStsHits.end(), [](const auto* l, const auto* r) { return l->GetZ() < r->GetZ(); });
655 if (vpStsHits.size() < 2) {
656 return std::numeric_limits<double>::quiet_NaN();
657 }
658
659 const auto* pHitFst = vpStsHits[0];
660 const auto* pHitSnd = vpStsHits[1];
661 double factor{(pHitFst->GetZ() - pTarget->GetZ()) / (pHitSnd->GetZ() - pHitFst->GetZ())};
662 double x{pHitFst->GetX() - pTarget->GetX() - factor * (pHitSnd->GetX() - pHitFst->GetX())};
663 double y{pHitFst->GetY() - pTarget->GetY() - factor * (pHitSnd->GetY() - pHitFst->GetY())};
664 return std::sqrt(x * x + y * y);
665 };
666
667 for (int iTrkMC = 0; iTrkMC < fMCData.GetNofTracks(); ++iTrkMC) {
668 const auto& mcTrk = fMCData.GetTrack(iTrkMC);
669
670 // ----- CUTS ON MC TRACKS
671 // Cut tracks, which did not leave hits in tracker
672 if (mcTrk.GetNofHits() == 0) {
673 continue;
674 }
675
676 // Cut tracks, which cannot be reconstructed
677 if (!mcTrk.IsReconstructable()) {
678 continue;
679 }
680 int pdg = mcTrk.GetPdgCode();
681 bool isPrimary = mcTrk.IsPrimary();
682
683 // Fill different track categories
685
687 std::array<int, static_cast<int>(ca::EDetectorID::END)> nHitsDet = {0}; //< Number of hits per detector
688 for (auto iHit : mcTrk.GetHitIndexes()) {
689 const auto& hit = fvHits[iHit];
690 ++nHitsDet[hit.GetDetectorType()];
691 }
692 int nStsHits = nHitsDet[static_cast<int>(ca::EDetectorID::kSts)];
693 int nTofHits = nHitsDet[static_cast<int>(ca::EDetectorID::kTof)];
694 if (nStsHits > 1 && nTofHits > 0) {
696 double dcaRtOrigin = EstimateDcaRtOriginMc(mcTrk);
697 if (dcaRtOrigin < 0.5) { // primary
699 }
700 else { // secondary
702 }
703 }
704 }
705
706 if (isPrimary) {
708 bool bFast = mcTrk.GetP() > CbmL1Constants::MinFastMom;
709 bool bLong = mcTrk.GetTotNofStationsWithHit() == fpParameters->GetNstationsActive();
710 if (bFast) {
712 }
713 if (bLong) {
715 }
716 if (bLong && bFast) {
718 }
719 }
720 else {
722 if (mcTrk.GetP() > CbmL1Constants::MinFastMom) {
724 }
725 }
726
727 // Track distributions for different particle species
728 switch (std::abs(pdg)) {
729 case 211: // pion
731 if (isPrimary) {
734 }
735 else {
738 }
739 break;
740 case 2212: // proton
742 if (isPrimary) {
745 }
746 else {
749 }
750 break;
751 case 321: // kaon
753 if (isPrimary) {
756 }
757 else {
760 }
761 break;
762 case 11: // electron
764 if (isPrimary) {
767 }
768 else {
771 }
772 break;
773 case 13: // muon
775 if (isPrimary) {
778 }
779 else {
782 }
783 break;
784 } // switch abs(pdg): end
785 } // iTrkMC
786 } // IsMCUsed()
787}
788
789// ---------------------------------------------------------------------------------------------------------------------
790//
792{
794 std::vector<ETrackType> vCmpTypesGeneral = {kAll, kPrim, kSec};
795 std::vector<ETrackType> vCmpTypesPrim = {kPrim, kPrimE, kPrimMU, kPrimPI, kPrimK, kPrimPPBAR};
796 std::vector<ETrackType> vCmpTypesSec = {kSec, kSecE, kSecMU, kSecPI, kSecK, kSecPPBAR};
797 std::vector<ETrackType> vCmpTypesPions = {kAllPI, kPrimPIP, kPrimPIM, kSecPIP, kSecPIM};
798 std::vector<ETrackType> vCmpTypesKaons = {kAllK, kPrimKP, kPrimKM, kSecKP, kSecKM};
799 std::vector<ETrackType> vCmpTypesProtons = {kAllPPBAR, kPrimP, kPrimPBAR, kSecP, kSecPBAR};
800
802 auto DrawTrackDistributions = [&](TCanvas* pCanv, std::function<TH1F*(ETrackType)> Hist) {
803 pCanv->Divide(3, 2);
804 pCanv->cd(1);
805 gPad->SetLogy();
806 DrawSetOf<TH1F>(vCmpTypesGeneral, Hist);
807 pCanv->cd(2);
808 gPad->SetLogy();
809 DrawSetOf<TH1F>(vCmpTypesPrim, Hist);
810 pCanv->cd(3);
811 gPad->SetLogy();
812 DrawSetOf<TH1F>(vCmpTypesSec, Hist);
813 pCanv->cd(4);
814 gPad->SetLogy();
815 DrawSetOf<TH1F>(vCmpTypesPions, Hist);
816 pCanv->cd(5);
817 gPad->SetLogy();
818 DrawSetOf<TH1F>(vCmpTypesKaons, Hist);
819 pCanv->cd(6);
820 gPad->SetLogy();
821 DrawSetOf<TH1F>(vCmpTypesProtons, Hist);
822 };
823
825 auto DrawTrackEfficiens = [&](TCanvas* pCanv, std::function<TProfile*(ETrackType)> Prof) {
826 pCanv->Divide(3, 1);
827 pCanv->cd(1);
828 DrawSetOf<TProfile>(vCmpTypesGeneral, Prof);
829 pCanv->cd(2);
830 DrawSetOf<TProfile>(vCmpTypesPrim, Prof);
831 pCanv->cd(3);
832 DrawSetOf<TProfile>(vCmpTypesSec, Prof);
833 };
834
835
836 if (IsMCUsed()) {
837 // ** Reconstructed track distributions **
838 // Reconstructed pseudorapidity
839 auto* pc_reco_eta =
840 MakeQaObject<TCanvas>("reco_eta", "Reconstructed track pseudorapidity", kCXSIZEPX * 3, kCYSIZEPX * 2);
841 DrawTrackDistributions(pc_reco_eta, [&](ETrackType t) -> TH1F* { return fvpTrackHistograms[t]->fph_reco_eta; });
842
843 // MC pseudorapidity
844 auto* pc_reco_etaMC =
845 MakeQaObject<TCanvas>("reco_etaMC", "Reconstructed track MC pseudorapidity", kCXSIZEPX * 3, kCYSIZEPX * 2);
846 DrawTrackDistributions(pc_reco_etaMC, [&](ETrackType t) -> TH1F* { return fvpTrackHistograms[t]->fph_reco_etaMC; });
847
848 // MC momentum
849 auto* pc_reco_pMC =
850 MakeQaObject<TCanvas>("reco_pMC", "Reconstructed track MC momentum", kCXSIZEPX * 3, kCYSIZEPX * 2);
851 DrawTrackDistributions(pc_reco_pMC, [&](ETrackType t) -> TH1F* { return fvpTrackHistograms[t]->fph_reco_pMC; });
852
853 // MC rapidity
854 auto* pc_reco_yMC =
855 MakeQaObject<TCanvas>("reco_yMC", "Reconstructed track MC rapidity", kCXSIZEPX * 3, kCYSIZEPX * 2);
856 DrawTrackDistributions(pc_reco_yMC, [&](ETrackType t) -> TH1F* { return fvpTrackHistograms[t]->fph_reco_yMC; });
857
858 // ** MC track distributions **
859
860 // MC momentum
861 auto* pc_mc_pMC =
862 MakeQaObject<TCanvas>("mc_pMC", "MC reconstructable track MC momentum", kCXSIZEPX * 3, kCYSIZEPX * 2);
863 DrawTrackDistributions(pc_mc_pMC, [&](ETrackType t) -> TH1F* { return fvpTrackHistograms[t]->fph_mc_pMC; });
864
865 // MC rapidity
866 auto* pc_mc_yMC =
867 MakeQaObject<TCanvas>("mc_yMC", "MC reconstructable track MC rapidity", kCXSIZEPX * 3, kCYSIZEPX * 2);
868 DrawTrackDistributions(pc_mc_yMC, [&](ETrackType t) -> TH1F* { return fvpTrackHistograms[t]->fph_mc_yMC; });
869
870 // MC rapidity vs. MC momentum
871 // auto* pc_mc_pMC_yMC =
872 MakeQaObject<TCanvas>("mc_ptMC_yMC", "MC track MC transverse mom. vs. rapidity ", kCXSIZEPX * 3, kCYSIZEPX * 2);
873 DrawSetOf<TH2F>(vCmpTypesGeneral, [&](ETrackType t) -> TH2F* { return fvpTrackHistograms[t]->fph_reco_ptMC_yMC; });
874
875 // ** Efficiencies **
876
877 // MC momentum
878 auto* pc_eff_pMC = MakeQaObject<TCanvas>("eff_pMC", "Tracking Eff. vs. MC momentum", kCXSIZEPX * 3, kCYSIZEPX);
879 DrawTrackEfficiens(pc_eff_pMC, [&](ETrackType t) -> TProfile* { return fvpTrackHistograms[t]->fph_eff_pMC; });
880
881 auto* pc_eff_yMC = MakeQaObject<TCanvas>("eff_yMC", "Tracking Eff. vs. MC rapidity", kCXSIZEPX * 3, kCYSIZEPX);
882 DrawTrackEfficiens(pc_eff_yMC, [&](ETrackType t) -> TProfile* { return fvpTrackHistograms[t]->fph_eff_yMC; });
883
884 auto* pc_eff_thetaMC =
885 MakeQaObject<TCanvas>("eff_thetaMC", "Tracking Eff. vs. MC polar angle", kCXSIZEPX * 3, kCYSIZEPX);
886 DrawTrackEfficiens(pc_eff_thetaMC,
887 [&](ETrackType t) -> TProfile* { return fvpTrackHistograms[t]->fph_eff_thetaMC; });
888
889 auto* pc_eff_phiMC =
890 MakeQaObject<TCanvas>("eff_phiMC", "Tracking Eff. vs. MC azimuthal angle", kCXSIZEPX * 3, kCYSIZEPX);
891 DrawTrackEfficiens(pc_eff_phiMC, [&](ETrackType t) -> TProfile* { return fvpTrackHistograms[t]->fph_eff_phiMC; });
892
893 auto* pc_eff_etaMC =
894 MakeQaObject<TCanvas>("eff_etaMC", "Tracking Eff. vs. MC pseudorapidity", kCXSIZEPX * 3, kCYSIZEPX);
895 DrawTrackEfficiens(pc_eff_etaMC, [&](ETrackType t) -> TProfile* { return fvpTrackHistograms[t]->fph_eff_etaMC; });
896
897
898 // ** Pulls and residuals **
899 // NOTE: stored in a subdirectory for a given track type and point type
900 for (int iType = 0; iType < ETrackType::END; ++iType) {
901 if (fvbTrackTypeOn[iType] && fvpTrackHistograms[iType]->IsMCUsed()) {
902 fvpTrackHistograms[iType]->fpFitQaFirstHit->CreateResidualPlot();
903 fvpTrackHistograms[iType]->fpFitQaFirstHit->CreatePullPlot();
904 fvpTrackHistograms[iType]->fpFitQaLastHit->CreateResidualPlot();
905 fvpTrackHistograms[iType]->fpFitQaLastHit->CreatePullPlot();
906 }
907 }
908 }
909 fDebugger.Write();
910}
911
912// ---------------------------------------------------------------------------------------------------------------------
913//
915try {
917 assert(fpParameters != nullptr); // Hint: Add the cbm::ca::ParametersHandler::Instance() as a task in the FairRunAna
918
919 if (fNthreads < 1) { // check if the number of threads is set
920
921 const char* env = std::getenv("OMP_NUM_THREADS");
922 if (env) {
923 fNthreads = TString(env).Atoi();
924 LOG(info) << "CaOutputQA: found environment variable OMP_NUM_THREADS = \"" << env
925 << "\", read as integer: " << fNthreads;
926 }
927
928 // ensure that at least one thread is set
929
930 if (fNthreads < 1) {
931 fNthreads = 1;
932 }
933
934 // fNthreads = 1; // enforce n threads to one
935 }
936
937 // Turn off detectors that are not used in the reconstruction setup
938
939 fbUseMvd = fbUseMvd && (fpParameters->GetNstationsActive(ca::EDetectorID::kMvd) > 0);
940 fbUseSts = fbUseSts && (fpParameters->GetNstationsActive(ca::EDetectorID::kSts) > 0);
941 fbUseMuch = fbUseMuch && (fpParameters->GetNstationsActive(ca::EDetectorID::kMuch) > 0);
942 fbUseTrd = fbUseTrd && (fpParameters->GetNstationsActive(ca::EDetectorID::kTrd) > 0);
943 fbUseTof = fbUseTof && (fpParameters->GetNstationsActive(ca::EDetectorID::kTof) > 0);
944
945 // Turn off detectors, which hits are not presented in input tree
946
947 auto* fairManager = FairRootManager::Instance();
948 fbUseMvd = fbUseMvd && fairManager->GetObject("MvdHit");
949 fbUseSts = fbUseSts && fairManager->GetObject("StsHit");
950 fbUseMuch = fbUseMuch && fairManager->GetObject("MuchPixelHit");
951 fbUseTrd = fbUseTrd && fairManager->GetObject("TrdHit");
952 fbUseTof = fbUseTof && fairManager->GetObject("TofHit");
953
954
955 LOG(info) << fName << ": Detector subsystems used:";
956 LOG(info) << "\tMVD: " << (fbUseMvd ? "ON" : "OFF");
957 LOG(info) << "\tSTS: " << (fbUseSts ? "ON" : "OFF");
958 LOG(info) << "\tMuCh: " << (fbUseMuch ? "ON" : "OFF");
959 LOG(info) << "\tTRD: " << (fbUseTrd ? "ON" : "OFF");
960 LOG(info) << "\tTOF: " << (fbUseTof ? "ON" : "OFF");
961
962 LOG(info) << fName << ": Initializing data branches";
963
964 // Initialize IO data manager
965 if (!fpDataManager.get()) {
966 fpDataManager = std::make_shared<ca::DataManager>();
967 }
968
969 // Initialize time slice reader instance
970 fpTSReader->SetTrackingMode(fTrackingMode);
976
977 fpTSReader->RegisterParameters(fpParameters);
978 fpTSReader->RegisterTracksContainer(fvRecoTracks);
979 fpTSReader->RegisterQaHitContainer(fvHits);
980 fpTSReader->RegisterHitIndexContainer(fvHitIds);
981 fpTSReader->SetSortQaHits(true);
982 if (!fpTSReader->InitRun()) {
983 throw std::runtime_error("Initialization of the CbmCaTimesliceReader object failed");
984 }
985
986 // Initialize MC module
987 if (IsMCUsed()) {
988 fpMCModule = std::make_shared<MCModule>(fVerbose, fPerformanceMode);
994 if (fairManager->GetObject("TrdPoint")) { // TRD points are used for the fit quality check
995 fpMCModule->SetDetector(ca::EDetectorID::kTrd, true);
996 }
997
998 fpMCModule->RegisterMcData(fMCData);
999 fpMCModule->RegisterRecoTrackContainer(fvRecoTracks);
1000 fpMCModule->RegisterHitIndexContainer(fvHitIds);
1001 fpMCModule->RegisterQaHitContainer(fvHits);
1002 fpMCModule->RegisterParameters(fpParameters);
1003 fpMCModule->RegisterFirstHitIndexes(fpTSReader->GetHitFirstIndexDet());
1004 if (!fpMCModule->InitRun()) {
1005 throw std::runtime_error("Initialization of the CbmCaMCModule object failed");
1006 }
1007 }
1008
1009 // Initialize monitor
1010 fMonitor.SetCounterName(EMonitorKey::kEvent, "N events");
1011 fMonitor.SetCounterName(EMonitorKey::kTrack, "N reco tracks");
1012 fMonitor.SetCounterName(EMonitorKey::kHit, "N hits");
1013 fMonitor.SetCounterName(EMonitorKey::kMcTrack, "N MC tracks");
1014 fMonitor.SetCounterName(EMonitorKey::kMcPoint, "N MC points");
1016
1017 fDebugger.AddNtuple("clone", "it:ic:ih:p:x:y:z:t");
1018 fDebugger.AddNtuple("mcMissedHits", "it:sta:p:eta:y:pt:theta:phi:tx:ty:missed");
1019
1020 // ----- Histograms initialization
1021 //
1022 auto RegisterTrackQa = [&](const char* typeName, const char* title, ETrackType type, bool bSuppressMC = false) {
1023 if (!fvbTrackTypeOn[type]) {
1024 return;
1025 }
1026 bool bUseMC = IsMCUsed() && !bSuppressMC;
1027 fvsTrackTypeName[type] = typeName;
1028 fvpTrackHistograms[type] = std::make_unique<TrackTypeQa>(typeName, fsPrefix.Data(), bUseMC, fpvObjList);
1029 fvpTrackHistograms[type]->SetRootFolderName(fsRootFolderName + "/" + typeName);
1030 fvpTrackHistograms[type]->SetTitle(title);
1031 fvpTrackHistograms[type]->RegisterParameters(fpParameters);
1032 fvpTrackHistograms[type]->RegisterRecoHits(fvHits);
1033 fvpTrackHistograms[type]->RegisterRecoTracks(fvRecoTracks);
1034 fvpTrackHistograms[type]->RegisterMCData(fMCData);
1035 fvpTrackHistograms[type]->SetDrawAtt(fvTrackDrawAtts[type].fColor, fvTrackDrawAtts[type].fMarker);
1036 fvpTrackHistograms[type]->Init();
1037 };
1038
1039 //for (int i = 0; i < ETrackType::END; ++i) {
1040 //LOG(info) << i << ' ' << fvpTrackHistograms[i].get() << ' ' << fvbTrackTypeOn[i];
1041 //}
1042
1043 // TODO: Replace these parameters into the AddTrackType method!!!
1044 RegisterTrackQa("all", "all", ETrackType::kAll);
1045
1047 RegisterTrackQa("all_2STS1TOF", "all w/ min. 2STS, 1TOF", ETrackType::kAll2STS1TOF);
1048 RegisterTrackQa("prim_2STS1TOF", "prim w/ min. 2STS, 1TOF", ETrackType::kPrim2STS1TOF);
1049 RegisterTrackQa("sec_2STS1TOF", "sec w/ min. 2STS, 1TOF", ETrackType::kSec2STS1TOF);
1050 }
1051 if (IsMCUsed()) {
1052 RegisterTrackQa("prim_long_fast", "primary long fast", ETrackType::kPrimLongFast);
1053 RegisterTrackQa("prim_long", "primary long", ETrackType::kPrimLong);
1054 RegisterTrackQa("ghost", "ghost", ETrackType::kGhost, true);
1055 RegisterTrackQa("prim", "primary", ETrackType::kPrim);
1056 RegisterTrackQa("prim_fast", "primary fast", ETrackType::kPrimFast);
1058 RegisterTrackQa("sec", "secondary", ETrackType::kSec);
1059 RegisterTrackQa("sec_fast", "secondary fast", ETrackType::kSecFast);
1060 RegisterTrackQa("all_pi", "all #pi^{#pm}", ETrackType::kAllPI);
1061 RegisterTrackQa("prim_pi", "primary #pi^{#pm}", ETrackType::kPrimPI);
1062 RegisterTrackQa("prim_pip", "primary #pi^{#plus}", ETrackType::kPrimPIP);
1063 RegisterTrackQa("prim_pim", "primary #pi^{#minus}", ETrackType::kPrimPIM);
1064 RegisterTrackQa("sec_pi", "secondary #pi^{#pm}", ETrackType::kSecPI);
1065 RegisterTrackQa("sec_pip", "secondary #pi^{#plus}", ETrackType::kSecPIP);
1066 RegisterTrackQa("sec_pim", "secondary #pi^{#minus}", ETrackType::kSecPIM);
1067 RegisterTrackQa("all_e", "all e^{#pm}", ETrackType::kAllE);
1068 RegisterTrackQa("prim_e", "primary e^{#pm}", ETrackType::kPrimE);
1069 RegisterTrackQa("prim_ep", "primary e^{#plus}", ETrackType::kPrimEP);
1070 RegisterTrackQa("prim_em", "primary e^{#minus}", ETrackType::kPrimEM);
1071 RegisterTrackQa("sec_e", "secondary e^{#pm}", ETrackType::kSecE);
1072 RegisterTrackQa("sec_ep", "secondary e^{#plus}", ETrackType::kSecEP);
1073 RegisterTrackQa("sec_em", "secondary e^{#minus}", ETrackType::kSecEM);
1074 RegisterTrackQa("all_mu", "all #mu^{#pm}", ETrackType::kAllMU);
1075 RegisterTrackQa("prim_mu", "primary #mu^{#pm}", ETrackType::kPrimMU);
1076 RegisterTrackQa("prim_mup", "primary #mu^{#plus}", ETrackType::kPrimMUP);
1077 RegisterTrackQa("prim_mum", "primary #mu^{#minus}", ETrackType::kPrimMUM);
1078 RegisterTrackQa("sec_mu", "secondary #mu^{#pm}", ETrackType::kSecMU);
1079 RegisterTrackQa("sec_mup", "secondary #mu^{#plus}", ETrackType::kSecMUP);
1080 RegisterTrackQa("sec_mum", "secondary #mu^{#minus}", ETrackType::kSecMUM);
1081 RegisterTrackQa("all_k", "all K^{#pm}", ETrackType::kAllK);
1082 RegisterTrackQa("prim_k", "primary K^{#pm}", ETrackType::kPrimK);
1083 RegisterTrackQa("prim_kp", "primary K^{#plus}", ETrackType::kPrimKP);
1084 RegisterTrackQa("prim_km", "primary K^{#minus}", ETrackType::kPrimKM);
1085 RegisterTrackQa("sec_k", "secondary K^{#pm}", ETrackType::kSecK);
1086 RegisterTrackQa("sec_kp", "secondary K^{#plus}", ETrackType::kSecKP);
1087 RegisterTrackQa("sec_km", "secondary K^{#minus}", ETrackType::kSecKM);
1088 RegisterTrackQa("all_ppbar", "all p/#bar{p}", ETrackType::kAllPPBAR);
1089 RegisterTrackQa("prim_ppbar", "primary p/#bar{p}", ETrackType::kPrimPPBAR);
1090 RegisterTrackQa("prim_p", "primary p", ETrackType::kPrimP);
1091 RegisterTrackQa("prim_pbar", "primary #bar{p}", ETrackType::kPrimPBAR);
1092 RegisterTrackQa("sec_ppbar", "secondary p/#bar{p}", ETrackType::kSecPPBAR);
1093 RegisterTrackQa("sec_p", "secondary p", ETrackType::kSecP);
1094 RegisterTrackQa("sec_pbar", "secondary #bar{p}", ETrackType::kSecPBAR);
1095 }
1096
1097 // Init default track types for the summary table
1098 if (!fmSummaryTableEntries.size()) {
1099 // clang-format off
1107 };
1108 // clang-format on
1109 }
1110
1111 // Track fitter
1112 fTrackFitter.Init();
1113 if (fMaxExtrapolationStep > 0.) { // enforce minimum step size
1114 fTrackFitter.SetMaxExtrapolationStep(fMaxExtrapolationStep); // [cm]
1115 }
1116
1117 return kSUCCESS;
1118}
1119catch (const std::exception& err) {
1120 LOG(error) << fName << ": Initialization failed. Reason: " << err.what();
1121 return kFATAL;
1122}
1123
1124
1125// ---------------------------------------------------------------------------------------------------------------------
1126//
1128{
1130 fvTrackDrawAtts[ETrackType::kGhost] = {kGray, 20};
1131 fvTrackDrawAtts[ETrackType::kPrim] = {kGray + 3, 21};
1132 fvTrackDrawAtts[ETrackType::kSec] = {kGray + 2, 25};
1133
1134 fvTrackDrawAtts[ETrackType::kAllPI] = {kRed - 4, 20};
1135 fvTrackDrawAtts[ETrackType::kPrimPI] = {kRed - 2, 21};
1136 fvTrackDrawAtts[ETrackType::kPrimPIP] = {kRed - 1, 22};
1137 fvTrackDrawAtts[ETrackType::kPrimPIM] = {kRed - 3, 23};
1138 fvTrackDrawAtts[ETrackType::kSecPI] = {kRed - 8, 25};
1139 fvTrackDrawAtts[ETrackType::kSecPIP] = {kRed - 6, 26};
1140 fvTrackDrawAtts[ETrackType::kSecPIM] = {kRed - 10, 32};
1141
1142 fvTrackDrawAtts[ETrackType::kAllK] = {kBlue - 4, 20};
1143 fvTrackDrawAtts[ETrackType::kPrimK] = {kBlue - 2, 21};
1144 fvTrackDrawAtts[ETrackType::kPrimKP] = {kBlue - 1, 22};
1145 fvTrackDrawAtts[ETrackType::kPrimKM] = {kBlue - 3, 23};
1146 fvTrackDrawAtts[ETrackType::kSecK] = {kBlue - 8, 25};
1147 fvTrackDrawAtts[ETrackType::kSecKP] = {kBlue - 6, 26};
1148 fvTrackDrawAtts[ETrackType::kSecKM] = {kBlue - 10, 32};
1149
1150 fvTrackDrawAtts[ETrackType::kAllPPBAR] = {kGreen - 4, 20};
1151 fvTrackDrawAtts[ETrackType::kPrimPPBAR] = {kGreen - 2, 21};
1152 fvTrackDrawAtts[ETrackType::kPrimP] = {kGreen - 1, 22};
1153 fvTrackDrawAtts[ETrackType::kPrimPBAR] = {kGreen - 3, 23};
1154 fvTrackDrawAtts[ETrackType::kSecPPBAR] = {kGreen - 8, 25};
1155 fvTrackDrawAtts[ETrackType::kSecP] = {kGreen - 6, 26};
1156 fvTrackDrawAtts[ETrackType::kSecPBAR] = {kGreen - 10, 32};
1157
1158 fvTrackDrawAtts[ETrackType::kAllE] = {kCyan - 4, 20};
1159 fvTrackDrawAtts[ETrackType::kPrimE] = {kCyan - 2, 21};
1160 fvTrackDrawAtts[ETrackType::kPrimEP] = {kCyan - 1, 22};
1161 fvTrackDrawAtts[ETrackType::kPrimEM] = {kCyan - 3, 23};
1162 fvTrackDrawAtts[ETrackType::kSecE] = {kCyan - 8, 25};
1163 fvTrackDrawAtts[ETrackType::kSecEP] = {kCyan - 6, 26};
1164 fvTrackDrawAtts[ETrackType::kSecEM] = {kCyan - 10, 32};
1165
1166 fvTrackDrawAtts[ETrackType::kAllMU] = {kMagenta - 4, 20};
1167 fvTrackDrawAtts[ETrackType::kPrimMU] = {kMagenta - 2, 21};
1168 fvTrackDrawAtts[ETrackType::kPrimMUP] = {kMagenta - 1, 22};
1169 fvTrackDrawAtts[ETrackType::kPrimMUM] = {kMagenta - 3, 23};
1170 fvTrackDrawAtts[ETrackType::kSecMU] = {kMagenta - 8, 25};
1171 fvTrackDrawAtts[ETrackType::kSecMUP] = {kMagenta - 6, 26};
1172 fvTrackDrawAtts[ETrackType::kSecMUM] = {kMagenta - 10, 32};
1173}
1174
1175
1176// ---------------------------------------------------------------------------------------------------------------------
1177//
1179{
1181
1182 const auto& recoTrack = fvRecoTracks[iTrkReco];
1183 const auto& rSetup = fpParameters->GetSetup();
1184 const auto& rActSetup = rSetup.GetActiveSetup();
1185
1186 int iTrkMC = recoTrack.GetMatchedMCTrackIndex();
1187
1188 if (!IsMCUsed() || iTrkMC < 0) {
1189 return ret;
1190 }
1191
1192 // TODO: fill mass hypothesis into CbmL1Track ?
1193
1194 const auto& mcTrack = fMCData.GetTrack(iTrkMC);
1195
1196 // *****************************
1197 // ** Track fit parameters QA **
1198 // *****************************
1199
1200 auto threadFitter = fTrackFitter;
1201 threadFitter.SetMassHypothesis(mcTrack.GetMass());
1202
1203 int nTimeMeasurements = 0;
1204 for (int iH : recoTrack.GetHitIndexes()) {
1205 int iSt = fvHits[iH].GetStationId();
1206 if (rActSetup.GetActiveLayer(iSt).IsTimeMeasured()) {
1207 ++nTimeMeasurements;
1208 }
1209 }
1210 ret.isTimeFitted = (nTimeMeasurements > 1);
1211
1212 // ** First hit **
1213 bool isFirstHitOk = false;
1214 {
1215 ret.firstHit.isFilled = false;
1216 int iH = recoTrack.GetFirstHitIndex();
1217 int iP = fvHits[iH].GetBestMcPointId();
1218 if (iP > -1) {
1219 isFirstHitOk = true;
1220 ret.firstHit.mcPoint = fMCData.GetPoint(iP);
1221 ret.firstHit.trackParam = recoTrack;
1222 ret.firstHit.isFilled = threadFitter.PropagateToZ(ret.firstHit.trackParam, ret.firstHit.mcPoint.GetZ());
1223 }
1224 }
1225
1226 // ** Last hit **
1227 bool isLastHitOk = false;
1228 {
1229 ret.lastHit.isFilled = false;
1230 int iH = recoTrack.GetLastHitIndex();
1231 int iP = fvHits[iH].GetBestMcPointId();
1232 if (iP > -1) {
1233 isLastHitOk = true;
1234 ret.lastHit.mcPoint = fMCData.GetPoint(iP);
1235 ret.lastHit.trackParam = recoTrack.TLast;
1236 ret.lastHit.isFilled = threadFitter.PropagateToZ(ret.lastHit.trackParam, ret.lastHit.mcPoint.GetZ());
1237 }
1238 }
1239
1240
1241 // ** Extrapolation from the first hit to the production vertex of the particle **
1242 {
1243 ret.vertex.mcPoint = mcTrack.GetVertexPoint();
1244 ret.vertex.trackParam = recoTrack;
1245 ret.vertex.isFilled = threadFitter.PropagateToZ(ret.vertex.trackParam, ret.vertex.mcPoint.GetZ());
1246 }
1247
1248
1249 // ** Extrapolation from the last STS station to TRD **
1250 bool isTrdPointOk = false;
1251 {
1252 ret.trd.isFilled = false;
1253 int iStLstActive = fvHits[recoTrack.GetLastHitIndex()].GetStationId();
1254 auto [detId, iStLstGeoLocal] = rSetup.ActToLocStationId(iStLstActive);
1255 if (detId == ca::EDetectorID::kSts
1256 // FIXME: Should not it be the last active station in STS (in case, the last geo station is disabled)?
1257 && iStLstGeoLocal == rSetup.GetNofGeoStations(ca::EDetectorID::kSts) - 1) {
1258 for (int ip = 0; ip < mcTrack.GetNofPoints(); ip++) {
1259 int id = mcTrack.GetPointIndexes()[ip];
1260 const auto& mcPoint = fMCData.GetPoint(id);
1261 if (mcPoint.GetDetectorId() == ca::EDetectorID::kTrd && mcPoint.GetLocalStationId() == 0) {
1262 isTrdPointOk = true;
1263 ret.trd.mcPoint = mcPoint;
1264 ret.trd.trackParam = recoTrack.TLast;
1265 ret.trd.isFilled = threadFitter.PropagateToZ(ret.trd.trackParam, ret.trd.mcPoint.GetZ());
1266 break;
1267 }
1268 }
1269 }
1270 }
1271
1272
1273 static std::mutex mymutex;
1274
1275 if (isFirstHitOk && !ret.firstHit.isFilled) {
1276 mymutex.lock();
1277 LOG(warning) << "TrackTypeQa: "
1278 << "Propagation to the first hit failed for track with ID = " << iTrkReco
1279 << ", MC track ID = " << iTrkMC << ".";
1280 mymutex.unlock();
1281 }
1282 if (isLastHitOk && !ret.lastHit.isFilled) {
1283 mymutex.lock();
1284 LOG(warning) << "TrackTypeQa: "
1285 << "Propagation to the last hit failed for track with ID = " << iTrkReco
1286 << ", MC track ID = " << iTrkMC << ".";
1287 mymutex.unlock();
1288 }
1289 if (!ret.vertex.isFilled) {
1290 mymutex.lock();
1291 LOG(warning) << "TrackTypeQa: "
1292 << "Propagation to the production vertex failed for track with ID = " << iTrkReco
1293 << ", MC track ID = " << iTrkMC << ".";
1294 mymutex.unlock();
1295 }
1296 if (isTrdPointOk && !ret.trd.isFilled) {
1297 mymutex.lock();
1298 LOG(warning) << "TrackTypeQa: "
1299 << "Propagation to the TRD failed for track with ID = " << iTrkReco << ", MC track ID = " << iTrkMC
1300 << ".";
1301 mymutex.unlock();
1302 }
1303 return ret;
1304}
CA Tracking performance interface for CBM (header)
Tracking output QA-task (header)
Handles an instance of the CA-parameters as a shared pointer (header)
ECbmRecoMode
Reconstruct the full time slice or event-by-event.
Definition CbmDefs.h:202
Char_t * gr
Int_t nTofHits
Int_t nStsHits
Int_t nMCTracks
Target property initialization and access in CBM (source)
@ kMCBM
Global tracking in mCBM (STS, MuCh, TRD, TOF), results stored to GlobalTrack branch.
T * MakeQaObject(TString sName, TString sTitle, Args... args)
Definition CbmQaIO.h:260
TString fsPrefix
Unique prefix for all writeable root.
Definition CbmQaIO.h:158
std::shared_ptr< ObjList_t > fpvObjList
List of registered ROOT objects.
Definition CbmQaIO.h:161
TString fsRootFolderName
Name of root folder.
Definition CbmQaIO.h:156
TODO: SZh, 30.01.2023: Override THistPainter::PaintText() to add zeroes in tables.
Definition CbmQaTable.h:24
void SetNamesOfCols(const std::vector< std::string > &names)
Sets the names of table columns.
void SetCell(Int_t iRow, Int_t iCol, Double_t content, Double_t error=0.)
void SetRowName(Int_t iRow, const char *name)
Set name of a row.
void SetColWidth(Int_t width)
Definition CbmQaTable.h:74
std::string ToString(int prec, bool useErr=false) const
CbmEvent * GetCurrentEvent()
Gets pointer to current event.
Definition CbmQaTask.h:216
CbmQaTask(const char *name, int verbose, bool isMCUsed, ECbmRecoMode recoMode=ECbmRecoMode::Timeslice)
Constructor from parameters.
Definition CbmQaTask.cxx:32
int GetEventNumber() const
Get current event number.
Definition CbmQaTask.h:183
bool IsMCUsed() const
Returns flag, whether MC information is used or not in the task.
Definition CbmQaTask.h:126
OutputQa(int verbose, bool isMCUsed, ECbmRecoMode recoMode=ECbmRecoMode::EventByEvent)
Constructor from parameters.
double GetZ() const
Gets z coordinate at reference z of station [cm].
Definition CaMcPoint.h:249
A container for all external parameters of the CA tracking algorithm.
Class CbmCaPerformance is an interface to communicate between.
QA-task for CA tracking output results.
void ExecQa() override
Fills histograms from time slice or event.
static constexpr int kCYSIZEPX
Canvas size along y-axis [px].
void DrawSetOf(const std::vector< ETrackType > &vTypes, std::function< TObj *(ETrackType)> GetObj)
Utility function to draw a generic comparison of histograms from different track types.
double fMaxExtrapolationStep
Maximum extrapolation step [cm], set when it is > 0.
TTypeArr_t< bool > fvbTrackTypeOn
Usage flag for different track types.
std::unique_ptr< TimeSliceReader > fpTSReader
Reader of the time slice.
bool fbUseTrd
is TRD used
ECbmCaTrackingMode fTrackingMode
Tracking mode.
TTypeArr_t< std::string > fvsTrackTypeName
Array of track type unique names.
ca::McData fMCData
Input MC data (points and tracks)
void AddTrackType(ETrackType type, bool flag=true)
Adds track type.
bool fbUseMvd
is MVD used
ca::Vector< cbm::algo::ca::McHitInfo > fvHits
void CreateSummary() override
Creates summary cavases, tables etc.
bool fbUseMuch
is MuCh used
InitStatus InitQa() override
Initialises the QA-task.
int fPerformanceMode
Performance mode.
void InitDrawingAttributes()
Defines drawing attributes for histograms of different track types.
bool fbUseTof
is TOF used
std::set< ETrackType > fmSummaryTableEntries
Which track types should be listed in the summary table.
cbm::ca::tools::Debugger fDebugger
debugger
ca::Monitor< EMonitorKey > fMonitor
TTypeArr_t< DrawAtt > fvTrackDrawAtts
Drawing attributes for track types.
cbm::ca::TrackTypeQa::FitQaPointSet CreateFitQaPointSet(int iTrkReco) const
void FillMCTrack(ETrackType type, int iTrkMC)
Fills MC track by its index.
int fEvtDisplayMinNofPoints
minimum number of MC points in the event display
void DrawEvent()
Draws event.
TTypeArr_t< std::unique_ptr< TrackTypeQa > > fvpTrackHistograms
Histogrammers for different track types.
std::shared_ptr< const ca::Parameters< double > > fpParameters
Tracking parameters object.
static constexpr int kCXSIZEPX
Canvas size along x-axis [px].
std::shared_ptr< MCModule > fpMCModule
MC module.
CbmKfTrackFitter fTrackFitter
Track fitter.
std::shared_ptr< ca::DataManager > fpDataManager
Data manager.
ca::Vector< CbmL1HitId > fvHitIds
bool fbDrawEvents
flag to draw events with the event display
void Check() override
Method to check, if the QA results are acceptable.
ca::Vector< CbmL1Track > fvRecoTracks
bool fbUseSts
is STS used
static ParametersHandler & Instance()
Instance.
ParametersPtr_t Get() const
Accessor to the parameters shared pointer.
static Target * Instance()
Instance access.
const double MinFastMom
ETrackType
Enumeration fors track category.
@ kPrimPIP
primary pi+
@ kSecMUP
secondary mu+
@ kSecMUM
secondary mu-
@ kAllE
all e-/e+
@ kGhost
ghost tracks (no MC is used)
@ kPrim
primary
@ kAll2STS1TOF
tracks, which have at least two STS hits and one TOF hit
@ kPrimLongFast
primary long tracks (all stations in set)
@ kPrimEP
primary e+
@ kSecFast
secondary fast
@ kPrimP
primary p
@ kPrimKM
primary K-
@ kPrimPBAR
primary p-bar
@ kSecK
secondary K+/K-
@ kSecPIP
secondary pi+
@ kPrimMUM
primary mu-
@ kSecE
secondary e-/e+
@ kPrimPI
primary pi+/pi-
@ kPrimPIM
primary pi-
@ kSecEM
secondary e-
@ kAllPI
all pi+/pi-
@ kPrimK
primary K+/K-
@ kSec
secondary
@ kPrimMU
primary mu+/mu-
@ kPrimPPBAR
primary p/p-bar
@ kPrim2STS1TOF
primary tracks, which have at least two STS hits and one TOF hit
@ kSecPI
secondary pi+/pi-
@ kPrimE
primary e-/e+
@ kSecP
secondary p
@ kAll
all tracks
@ kAllPPBAR
all p/p-bar
@ kSecPPBAR
secondary p/p-bar
@ kPrimFast
primary fast
@ kPrimEM
primary e-
@ kSecKM
secondary K-
@ kAllK
all K+/K-
@ kSecEP
secondary e+
@ kAllMU
all mu+/mu-
@ kPrimMUP
primary mu+
@ kSecKP
secondary K+
@ kSecMU
secondary mu+/mu-
@ kPrimLong
long primary
@ kPrimKP
primary K+
@ kSecPBAR
secondary p-bar
@ kSec2STS1TOF
secondary tracks, which have at least two STS hits and one TOF hit
@ kSecPIM
secondary pi-
FitQaPoint firstHit
First hit point.
bool isTimeFitted
Flag: true - time is fitted, false - time is not fitted.
FitQaPoint lastHit
Last hit point.
cbm::algo::kf::TrackParamD trackParam