CbmRoot
Loading...
Searching...
No Matches
CbmTrdCalibTracker.cxx
Go to the documentation of this file.
1/* Copyright (C) 2022 Horia Hulubei National Institute of Physics and Nuclear Engineering, Bucharest
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Alexandru Bercuci[committer]*/
4
8
10
11#include "CbmDefs.h"
12#include "CbmDigiManager.h"
13#include "CbmLink.h"
14#include "CbmMCDataArray.h"
15#include "CbmMCDataManager.h"
16#include "CbmMCEventList.h"
17#include "CbmMCTrack.h"
18#include "CbmMatch.h"
19#include "CbmQaCanvas.h"
20//#include "CbmSetup.h"
21#include "CbmQaUtil.h"
22#include "CbmTimeSlice.h"
23#include "CbmTrdCluster.h"
24#include "CbmTrdDigi.h"
25#include "CbmTrdHit.h"
26#include "CbmTrdHitMC.h"
27#include "CbmTrdParModDigi.h" // for CbmTrdModule
28#include "CbmTrdParModGeo.h"
29#include "CbmTrdParSetDigi.h" // for CbmTrdParSetDigi
30#include "CbmTrdParSetGeo.h"
31#include "CbmTrdPoint.h"
32
33#include <FairRootManager.h>
34#include <FairRunAna.h>
35#include <FairRuntimeDb.h>
36#include <FairSink.h>
37#include <FairTask.h>
38#include <Logger.h>
39
40#include <TClonesArray.h>
41#include <TDatabasePDG.h>
42#include <TGenericClassInfo.h>
43#include <TGeoManager.h>
44#include <TGeoNode.h>
45#include <TMathBase.h>
46#include <TObjArray.h>
47#include <TParameter.h>
48#include <TParticlePDG.h>
49#include <TString.h>
50#include <TStyle.h>
51
52#include <algorithm>
53#include <iostream>
54#include <map>
55#include <vector>
56
57#include <stdio.h>
58
60
61// -------------------------------------------------------------------------
62
63CbmTrdCalibTracker::CbmTrdCalibTracker(const char* name, Int_t verbose) : FairTask(name, verbose)
64{
65 // Constructor
66
67 // Create a list of histogramms
68
69 fHistList.clear();
70 fHistList.reserve(20);
71 fHistList.push_back(&fh1DresidualU);
72 fHistList.push_back(&fh1DresidualV);
73 fHistList.push_back(&fh1DresidualT);
74 fHistList.push_back(&fh2DresidualX);
75 fHistList.push_back(&fh2DresidualY);
76 fHistList.push_back(&fh2DresidualT);
77 fHistList.push_back(&fh1DpullU);
78 fHistList.push_back(&fh1DpullV);
79 fHistList.push_back(&fh1DpullT);
80 fHistList.push_back(&fh2DpullX);
81 fHistList.push_back(&fh2DpullY);
82 fHistList.push_back(&fh2DpullT);
83
84 // Keep the ownership on the histograms to avoid double deletion
85 for (unsigned int i = 0; i < fHistList.size(); i++) {
86 fHistList[i]->SetDirectory(0);
87 }
88}
89
90// -------------------------------------------------------------------------
95
96
97// -------------------------------------------------------------------------
99{
100 fIsTrdInSetup = 0;
101 fIsMcPresent = false;
103
104 fTimeSlice = nullptr;
105 fDigiManager = nullptr;
106
107 fMcManager = nullptr;
108 fMcTracks = nullptr;
109 fMcPoints = nullptr;
110
111 fClusters = nullptr;
112 fHits = nullptr;
113 fHitMatches = nullptr;
114
115 fOutFolder.Clear();
116
117 fHistFolder = nullptr;
118
119 fNevents.SetVal(0);
120
121 fhPointsPerHit.clear();
122 fhHitsPerPoint.clear();
123
124 if (fHitsMc) {
125 fHitsMc->Clear("C");
126 fHitsMc->Delete();
127 delete fHitsMc;
128 }
129}
130// -------------------------------------------------------------------------
131
133{
134 fTrdDigiPar = nullptr;
135 fTrdGeoPar = nullptr;
136
137 // Get run and runtime database
138 FairRunAna* ana = FairRunAna::Instance();
139 if (!ana) {
140 LOG(fatal) << "No FairRunAna instance";
141 }
142
143 FairRuntimeDb* rtdb = ana->GetRuntimeDb();
144 if (!rtdb) {
145 LOG(fatal) << "No FairRuntimeDb instance";
146 }
147
148 fTrdDigiPar = dynamic_cast<CbmTrdParSetDigi*>(rtdb->getContainer("CbmTrdParSetDigi"));
149 fTrdGeoPar = dynamic_cast<CbmTrdParSetGeo*>(rtdb->getContainer("CbmTrdParSetGeo"));
150}
151
152// -------------------------------------------------------------------------
154{
155 // Initialize and check the setup
156
157 DeInit();
158
159 // Check if TRD is present in the CBM setup
160 // A straightforward way to do so is CbmSetup::Instance()->IsActive(ECbmModuleId::kTrd),
161 // but unfortunatelly CbmSetup class is unaccesible.
162 // ( CbmSimSteer library requires libfreetype that has linking problems on MacOsX )
163 // Therefore let's simply check if any TRD material is present in the geometry.
164 //
165 fIsTrdInSetup = 0;
166 {
167 TObjArray* topNodes = gGeoManager->GetTopNode()->GetNodes();
168 for (Int_t iTopNode = 0; iTopNode < topNodes->GetEntriesFast(); iTopNode++) {
169 TGeoNode* topNode = static_cast<TGeoNode*>(topNodes->At(iTopNode));
170 if (TString(topNode->GetName()).Contains("trd")) {
171 fIsTrdInSetup = 1;
172 break;
173 }
174 }
175 }
176
177 if (!fIsTrdInSetup) {
178 LOG(info) << "TRD is not in the setup, do nothing";
179 return kSUCCESS;
180 }
181
182 // check parameter containers
183
184 if (!fTrdDigiPar) {
185 LOG(error) << "No CbmTrdParSetDigi container in FairRuntimeDb";
186 return kERROR;
187 }
188
189 if (!fTrdGeoPar) {
190 LOG(error) << "No CbmTrdParSetGeo container in FairRuntimeDb";
191 return kERROR;
192 }
193
194 FairRootManager* manager = FairRootManager::Instance();
197
198 fTimeSlice = dynamic_cast<CbmTimeSlice*>(manager->GetObject("TimeSlice."));
199 if (!fTimeSlice) {
200 LOG(error) << "No time slice found";
201 return kERROR;
202 }
203
204 fHits = dynamic_cast<TClonesArray*>(manager->GetObject("TrdHit"));
205
206 if (!fHits) {
207 LOG(error) << "No TRD hit array found";
208 return kERROR;
209 }
210
211 fClusters = dynamic_cast<TClonesArray*>(manager->GetObject("TrdCluster"));
212
213 if (!fClusters) {
214 LOG(error) << "No TRD cluster array found";
215 return kERROR;
216 }
217
218 fMcManager = dynamic_cast<CbmMCDataManager*>(manager->GetObject("MCDataManager"));
219
220 fIsMcPresent = (fMcManager != nullptr);
221
222 if (fIsMcPresent) {
223
224 fMcEventList = dynamic_cast<CbmMCEventList*>(manager->GetObject("MCEventList."));
225 fMcTracks = fMcManager->InitBranch("MCTrack");
226 fMcPoints = fMcManager->InitBranch("TrdPoint");
227 fHitMatches = dynamic_cast<TClonesArray*>(manager->GetObject("TrdHitMatch"));
228
229 // we assume that when TRD is in the setup and the MC manager is present,
230 // the TRD MC data must be present too
231
232 if (!fMcEventList) {
233 LOG(error) << ": No MCEventList data!";
234 return kERROR;
235 }
236
237 if (!fMcTracks) {
238 LOG(error) << "No MC tracks found";
239 return kERROR;
240 }
241
242 if (!fMcPoints) {
243 LOG(error) << "No MC points found";
244 return kERROR;
245 }
246
247 if (!fHitMatches) {
248 LOG(error) << "No TRD hit matches found";
249 return kERROR;
250 }
251
253 LOG(error) << "No TRD digi matches found";
254 return kERROR;
255 }
256 }
257
258 // count TRD stations
259 // TODO: put the code below to some TRD geometry interface
260
262 {
263 Int_t layerCounter = 0;
264 TObjArray* topNodes = gGeoManager->GetTopNode()->GetNodes();
265 for (Int_t iTopNode = 0; iTopNode < topNodes->GetEntriesFast(); iTopNode++) {
266 TGeoNode* topNode = static_cast<TGeoNode*>(topNodes->At(iTopNode));
267 if (TString(topNode->GetName()).Contains("trd")) {
268 TObjArray* layers = topNode->GetNodes();
269 for (Int_t iLayer = 0; iLayer < layers->GetEntriesFast(); iLayer++) {
270 TGeoNode* layer = static_cast<TGeoNode*>(layers->At(iLayer));
271 if (TString(layer->GetName()).Contains("layer")) {
272 layerCounter++;
273 }
274 }
275 }
276 }
277 fNtrackingStations = layerCounter;
278 }
279
280 LOG(debug) << "Init(): fNtrackingStations = " << fNtrackingStations;
281
282 if (fNtrackingStations <= 0) {
283 LOG(error) << "can not count TRD tracking stations";
284 return kERROR;
285 }
286
287 // init output tree
288 fHitsMc = new TClonesArray("CbmTrdHitMC", 100);
289 manager->Register("TrdHitMC", "TRD", fHitsMc, IsOutputBranchPersistent("TrdHitMC"));
290
291 // initialise histograms
292 fOutFolder.SetOwner(false);
293 fHistFolder = fOutFolder.AddFolder("rawHist", "Raw Histograms");
294 gStyle->SetOptStat(0);
295
296 fNevents.SetVal(0);
297 fHistFolder->Add(&fNevents);
298
299 for (unsigned int i = 0; i < fHistList.size(); i++) {
300 fHistList[i]->Reset();
301 fHistFolder->Add(fHistList[i]);
302 }
303
304 fhPointsPerHit.clear();
305 fhHitsPerPoint.clear();
306 fhEfficiencyR.clear();
307 fhEfficiencyXY.clear();
308
313
314 for (Int_t i = 0; i < fNtrackingStations; i++) {
315 fhPointsPerHit.emplace_back(Form("hMcPointsPerHit%i", i),
316 Form("MC Points per Hit: Station %i;N mc points / hit", i), 10, -0.5, 9.5);
317 fhPointsPerHit[i].SetDirectory(0);
318 fhPointsPerHit[i].SetLineWidth(2);
319 fhPointsPerHit[i].SetOptStat(110);
320 fHistFolder->Add(&fhPointsPerHit[i]);
321 }
322
323 for (Int_t i = 0; i < fNtrackingStations; i++) {
324 fhHitsPerPoint.emplace_back(Form("hHitsPerMcPoint%i", i),
325 Form("Hits per MC Point: Station %i; N hits / mc point", i), 10, -0.5, 9.5);
326 fhHitsPerPoint[i].SetDirectory(0);
327 fhHitsPerPoint[i].SetLineWidth(2);
328 fhHitsPerPoint[i].SetOptStat(110);
329 fHistFolder->Add(&fhHitsPerPoint[i]);
330 }
331
332 for (Int_t i = 0; i < fNtrackingStations; i++) {
333
334 double dx = 350;
335 double dy = 350;
336 double dr = sqrt(dx * dx + dy * dy);
337
338 fhEfficiencyR.emplace_back(Form("hEfficiencyR%i", i), Form("Efficiency R: Station %i;R [cm]", i), 100, 0, dr);
339 fhEfficiencyR[i].SetDirectory(0);
340 fhEfficiencyR[i].SetOptStat(1110);
341 fHistFolder->Add(&fhEfficiencyR[i]);
342
343 fhEfficiencyXY.emplace_back(Form("hEfficiencyXY%i", i), Form("Efficiency XY: Station %i;X [cm];Y [cm]", i), 50, -dx,
344 dx, 50, -dy, dy);
345 fhEfficiencyXY[i].SetDirectory(0);
346 fhEfficiencyXY[i].SetOptStat(10);
347 fhEfficiencyXY[i].GetYaxis()->SetTitleOffset(1.4);
348 fHistFolder->Add(&fhEfficiencyXY[i]);
349 }
350
351 fCanvResidual.Clear();
353
354 fCanvPull.Clear();
356
357 fCanvEfficiencyR.Clear();
359
360 fCanvEfficiencyXY.Clear();
362
363 fCanvPointsPerHit.Clear();
365
366 fCanvHitsPerPoint.Clear();
368
370 fOutFolder.Add(&fCanvPull);
375
376 // analyse the geometry setup
377 return GeometryQa();
378}
379
380
381// -------------------------------------------------------------------------
383{
384 if (!fIsTrdInSetup) {
385 return;
386 }
387
388 // update number of processed events
389 fNevents.SetVal(fNevents.GetVal() + 1);
390 LOG(debug) << "Event: " << fNevents.GetVal();
391 ResolutionQa();
392}
393
394
395// -------------------------------------------------------------------------
397{
398 FairSink* sink = FairRootManager::Instance()->GetSink();
399 if (sink) {
400 sink->WriteObject(&GetQa(), nullptr);
401 }
402}
403
404
405// -------------------------------------------------------------------------
407{
408 // check geometry of the TRD modules
409
410 double lastZ = -1;
411
412 // load alignment matrices
414 for (int iStation = 0; iStation < fNtrackingStations; iStation++) {
415
416 int ModuleId = fTrdDigiPar->GetModuleId(iStation);
417
418 const CbmTrdParModGeo* pGeo = dynamic_cast<const CbmTrdParModGeo*>(fTrdGeoPar->GetModulePar(ModuleId));
419 if (!pGeo) {
420 LOG(fatal) << " No Geo params for station " << iStation << " module " << ModuleId << " found ";
421 return kERROR;
422 }
423
424 double staZ = pGeo->GetZ();
425
426 // check that the stations are properly ordered in Z
427 if ((iStation > 0) && (staZ <= lastZ)) {
428 LOG(error) << "TRD trackig stations are not properly ordered in Z";
429 return kERROR;
430 }
431 lastZ = staZ;
432
433 //TODO: what are these 3 and 6 here in L1 code? Why are they hardcoed?
434 // if (num == 0 || num == 2 || num == 4) geo.push_back(3);
435 // if (num == 1 || num == 3) geo.push_back(6);
436 }
437
438 return kSUCCESS;
439}
440
441// -------------------------------------------------------------------------
443{
445
446 if (!fIsMcPresent) return;
447
448 Int_t nHits = fHits->GetEntriesFast();
449 Int_t nClusters = fClusters->GetEntriesFast();
451
452 int nMcEvents = fMcEventList->GetNofEvents();
453 int imc(0); // index of hit->MC QA objects
454 fHitsMc->Delete();
455
456 // Vector of integers parallel to mc points
457 std::vector<std::vector<int>> pointNhits;
458 pointNhits.resize(nMcEvents);
459 for (int iE = 0; iE < nMcEvents; iE++) {
460 int fileId = fMcEventList->GetFileIdByIndex(iE);
461 int eventId = fMcEventList->GetEventIdByIndex(iE);
462 int nPoints = fMcPoints->Size(fileId, eventId);
463 pointNhits[iE].resize(nPoints, 0);
464 }
465
466 for (Int_t iHit = 0; iHit < nHits; iHit++) {
467
468 const CbmTrdHit* hit = dynamic_cast<const CbmTrdHit*>(fHits->At(iHit));
469 if (!hit) {
470 LOG(error) << "TRD hit N " << iHit << " doesn't exist";
471 return;
472 }
473
474 if ((int) hit->GetClassType() > 1) {
475 // class type 0: trd-1D
476 // class type 1: trd-2D
477 // the return type is (currently) boolean, so this error should never happen
478 LOG(error) << "Unknown detector class type " << hit->GetClassType() << " for TRD hit N " << iHit;
479 return;
480 }
481
482 const int address = hit->GetAddress();
483 int StationIndex = CbmTrdAddress::GetLayerId(address);
484
485 if (StationIndex < 0 || StationIndex >= fNtrackingStations) {
486 LOG(fatal) << "TRD hit layer id " << StationIndex << " is out of range";
487 return;
488 }
489
490 Int_t clusterId = hit->GetRefId();
491 if (clusterId < 0 || clusterId >= nClusters) {
492 LOG(error) << "TRD cluster id " << clusterId << " is out of range";
493 return;
494 }
495
496 CbmTrdCluster* cluster = dynamic_cast<CbmTrdCluster*>(fClusters->At(clusterId));
497 if (!cluster) {
498 LOG(error) << "TRD cluster N " << clusterId << " doesn't exist";
499 return;
500 }
501
502 if (cluster->GetAddress() != address) {
503 LOG(error) << "TRD hit address " << address << " differs from its cluster address " << cluster->GetAddress();
504 return;
505 }
506
507 Int_t nClusterDigis = cluster->GetNofDigis();
508
509 if (nClusterDigis <= 0) {
510 LOG(error) << "hit match for TRD cluster " << clusterId << " has no digis ";
511 return;
512 }
513
514 // construct QA object
515 CbmTrdHitMC* hmc = new ((*fHitsMc)[imc++]) CbmTrdHitMC(*hit);
516 hmc->AddCluster(cluster);
517 uint64_t tdigi = 0;
518
519 // custom finder of the digi matches
520 CbmMatch myHitMatch;
521 for (Int_t iDigi = 0; iDigi < nClusterDigis; iDigi++) {
522 Int_t digiIdx = cluster->GetDigi(iDigi);
523 if (digiIdx < 0 || digiIdx >= nDigis) {
524 LOG(fatal) << "TRD cluster: digi index " << digiIdx << " out of range ";
525 return;
526 }
527 const CbmTrdDigi* digi = CbmDigiManager::Instance()->Get<CbmTrdDigi>(digiIdx);
528 if (!digi) {
529 LOG(fatal) << "TRD digi " << iDigi << " not found";
530 return;
531 }
532
533 if (digi->GetAddressModule() != address) {
534 std::stringstream ss;
535 ss << "TRD hit address " << address << " differs from its digi address " << digi->GetAddressModule();
536 hmc->SetErrorMsg(ss.str());
537 LOG(error) << ss.str();
538 return;
539 }
540 switch (digi->GetType()) {
542 if (!tdigi) tdigi = digi->GetTimeDAQ();
543 break;
545 if (!tdigi) tdigi = digi->GetTime();
546 break;
547 default: LOG(fatal) << "TRD digi type neither SPADIC or FASP"; return;
548 }
549 hmc->AddSignal(digi, tdigi);
550
551 const CbmMatch* match = dynamic_cast<const CbmMatch*>(fDigiManager->GetMatch(ECbmModuleId::kTrd, digiIdx));
552 if (!match) {
553 LOG(fatal) << "TRD digi match " << digiIdx << " not found";
554 return;
555 }
556 myHitMatch.AddLinks(*match);
557 }
558 hmc->PurgeSignals();
559
560 if (myHitMatch.GetNofLinks() == 0) {
561 continue;
562 }
563
564 const CbmLink& bestLink = myHitMatch.GetMatchedLink();
565
566 { // check if the hit match is correct
567 CbmMatch* hitMatch = dynamic_cast<CbmMatch*>(fHitMatches->At(iHit));
568 if (hitMatch == nullptr) {
569 std::stringstream ss;
570 ss << "hit match for TRD hit " << iHit << " doesn't exist";
571 hmc->SetErrorMsg(ss.str());
572 LOG(error) << ss.str();
573 }
574 else {
575 const CbmLink& link = hitMatch->GetMatchedLink();
576 if ((link != bestLink) && (link.GetWeight() != bestLink.GetWeight())) {
577 std::stringstream ss;
578 ss << "hit match for TRD hit " << iHit << " doesn't correspond to digi matches";
579 hmc->SetErrorMsg(ss.str());
580 LOG(error) << ss.str();
581 }
582 }
583 }
584
585 // how many MC points? fill N hits per mc point
586
587 int nHitPoints = 0;
588 for (int i = 0; i < myHitMatch.GetNofLinks(); i++) {
589 const CbmLink& link = myHitMatch.GetLink(i);
590 if (link.GetIndex() >= 0) { // not a noise digi
591 nHitPoints++;
592 int iE = fMcEventList->GetEventIndex(link);
593 if (iE < 0 || iE >= nMcEvents) {
594 std::stringstream ss;
595 ss << "link points to a non-existing MC event";
596 hmc->SetErrorMsg(ss.str());
597 LOG(error) << ss.str();
598 return;
599 }
600 if (link.GetIndex() >= (int) pointNhits[iE].size()) {
601 std::stringstream ss;
602 ss << "link points to a non-existing MC index";
603 hmc->SetErrorMsg(ss.str());
604 LOG(error) << ss.str();
605 return;
606 }
607 pointNhits[iE][link.GetIndex()]++;
608 }
609 }
610
611 fhPointsPerHit[StationIndex].Fill(nHitPoints);
612
613 // take corresponding MC point
614
615 // skip hits from the noise digis
616 if (bestLink.GetIndex() < 0) {
617 std::stringstream ss;
618 ss << "hit from noise [INFO]";
619 hmc->SetErrorMsg(ss.str());
620 continue;
621 }
622
623 CbmTrdPoint* p = dynamic_cast<CbmTrdPoint*>(fMcPoints->Get(bestLink));
624 if (p == nullptr) {
625 std::stringstream ss;
626 ss << "link points to a non-existing MC point";
627 hmc->SetErrorMsg(ss.str());
628 LOG(error) << ss.str();
629 return;
630 }
631
632 if (p->GetModuleAddress() != (int) CbmTrdAddress::GetModuleAddress(address)) {
633 std::stringstream ss;
634 ss << "mc point module address differs from the hit module address";
635 hmc->SetErrorMsg(ss.str());
636 LOG(error) << ss.str();
637 return;
638 }
639
640 // check that the nominal station Z is not far from the active material
641 {
642 // the cut of 1 cm is choosen arbitrary and can be changed
643
644 int ModuleId = fTrdDigiPar->GetModuleId(StationIndex);
645
646 const CbmTrdParModGeo* pGeo = dynamic_cast<const CbmTrdParModGeo*>(fTrdGeoPar->GetModulePar(ModuleId));
647 if (!pGeo) {
648 LOG(fatal) << " No Geo params for station " << StationIndex << " module " << ModuleId << " found ";
649 return;
650 }
651
652 double staZ = pGeo->GetZ(); // module->GetZ(); //+ 410;
653 if ((staZ < p->GetZIn() - 1.) || (staZ > p->GetZOut() + 1.)) {
654 std::stringstream ss;
655 ss << "TRD station " << StationIndex << ": active material Z[" << p->GetZIn() << " cm," << p->GetZOut()
656 << " cm] is too far from the nominal station Z " << staZ << " cm";
657 hmc->SetErrorMsg(ss.str());
658 LOG(error) << ss.str();
659 return;
660 }
661 // the cut of 1 cm is choosen arbitrary and can be changed
662 if (fabs(hit->GetZ() - staZ) > 1.) {
663 std::stringstream ss;
664 ss << "TRD station " << StationIndex << ": hit Z " << hit->GetZ()
665 << " cm, is too far from the nominal station Z " << staZ << " cm";
666 hmc->SetErrorMsg(ss.str());
667 LOG(error) << ss.str();
668 return;
669 }
670 }
671
672 // residual and pull
673
674 if (nHitPoints != 1) {
675 std::stringstream ss;
676 ss << "hit from mixed hit [INFO] nPoints=" << nHitPoints;
677 hmc->SetErrorMsg(ss.str());
678 continue; // only check residual for non-mixed hits
679 }
680
681 double t0 = fMcEventList->GetEventTime(bestLink);
682 if (t0 < 0) {
683 std::stringstream ss;
684 ss << "MC event time doesn't exist for a TRD link";
685 hmc->SetErrorMsg(ss.str());
686 LOG(error) << ss.str();
687 return;
688 }
689
690 double x = p->GetX(); // take the "In" point since the time is stored only for this point
691 double y = p->GetY();
692 double z = p->GetZ();
693 double t = t0 + p->GetTime();
694 double px = p->GetPx();
695 double py = p->GetPy();
696 double pz = p->GetPz();
697
698 // skip very slow particles
699 if (fabs(p->GetPzOut()) < 0.01) continue;
700
701 // transport the particle from the MC point to the hit Z
702 double dz = hit->GetZ() - z;
703 x += dz * px / pz;
704 y += dz * py / pz;
705
706 // get particle mass
707 Int_t pdg(0);
708 double mass = 0;
709 {
710 CbmLink mcTrackLink = bestLink;
711 mcTrackLink.SetIndex(p->GetTrackID());
712 CbmMCTrack* mcTrack = dynamic_cast<CbmMCTrack*>(fMcTracks->Get(mcTrackLink));
713 if (!mcTrack) {
714 std::stringstream ss;
715 ss << "MC track " << p->GetTrackID() << " doesn't exist";
716 hmc->SetErrorMsg(ss.str());
717 LOG(error) << ss.str();
718 return;
719 }
720 pdg = mcTrack->GetPdgCode();
721 if (pdg < 9999999 && ((TParticlePDG*) TDatabasePDG::Instance()->GetParticle(pdg))) {
722 mass = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
723 }
724 }
725 hmc->AddPoint(p, t0, pdg);
726 //std::cout << hmc->ToString() << "\n";
727 constexpr double speedOfLight = 29.979246; // cm/ns
728 TVector3 mom3;
729 p->Momentum(mom3);
730 t += dz / (pz * speedOfLight) * sqrt(mass * mass + mom3.Mag2());
731
732 double du = hit->GetX() - x;
733 double dv = hit->GetY() - y; //hmc->GetDy(); //hit->GetY() - y;
734 double dt = hit->GetTime() - t; // hmc->GetDt(); //hit->GetTime() - t;
735 double su = hmc->GetDx();
736 double sv = hit->GetDy();
737 double st = hit->GetTimeError();
738
739 // residuals
740 if (hit->GetClassType() == 0) {
741 if (StationIndex % 2) {
742 std::swap(du, dv);
743 std::swap(su, sv);
744 }
745 fh1DresidualU.Fill(du);
746 fh1DresidualV.Fill(dv);
747 fh1DresidualT.Fill(hit->GetTime() - t);
748 }
749 else {
750 fh2DresidualX.Fill(du);
751 fh2DresidualY.Fill(dv);
752 fh2DresidualT.Fill(hit->GetTime() - t);
753 }
754
755 // pulls
756 if ((su < 1.e-5) || (sv < 1.e-5) || (st < 1.e-5)) {
757 std::stringstream ss;
758 ss << "TRD hit errors are not properly set: errX " << hit->GetDx() << " errY " << hit->GetDy() << " errT ";
759 hmc->SetErrorMsg(ss.str());
760 LOG(error) << ss.str();
761 return;
762 }
763
764 if (hit->GetClassType() == 0) {
765 fh1DpullU.Fill(du / su);
766 fh1DpullV.Fill(dv / sv);
767 fh1DpullT.Fill(dt / st);
768 }
769 else {
770 fh2DpullX.Fill(du / su);
771 fh2DpullY.Fill(dv / sv);
772 fh2DpullT.Fill(dt / st);
773 }
774
775 } // iHit
776
777 // fill efficiency: N hits per MC point
778
779 for (int iE = 0; iE < nMcEvents; iE++) {
780 int fileId = fMcEventList->GetFileIdByIndex(iE);
781 int eventId = fMcEventList->GetEventIdByIndex(iE);
782 int nPoints = fMcPoints->Size(fileId, eventId);
783 for (int ip = 0; ip < nPoints; ip++) {
784 CbmTrdPoint* p = dynamic_cast<CbmTrdPoint*>(fMcPoints->Get(fileId, eventId, ip));
785 if (p == nullptr) {
786 LOG(error) << "MC point doesn't exist";
787 return;
788 }
789 auto address = p->GetModuleAddress();
790 int StationIndex = CbmTrdAddress::GetLayerId(address);
791 if (StationIndex < 0 || StationIndex >= fNtrackingStations) {
792 LOG(fatal) << "TRD hit layer id " << StationIndex << " for module " << address << " is out of range";
793 return;
794 }
795 fhHitsPerPoint[StationIndex].Fill(pointNhits[iE][ip]);
796 fhEfficiencyR[StationIndex].Fill(sqrt(p->GetX() * p->GetX() + p->GetY() * p->GetY()), (pointNhits[iE][ip] > 0));
797 fhEfficiencyXY[StationIndex].Fill(p->GetX(), p->GetY(), (pointNhits[iE][ip] > 0));
798 }
799 }
800}
801
802
803// -------------------------------------------------------------------------
805{
806 gStyle->SetPaperSize(20, 20);
807
808 for (Int_t i = 0; i < fNtrackingStations; i++) {
809 fCanvHitsPerPoint.cd(i + 1);
810 fhHitsPerPoint[i].DrawCopy("", "");
811 fCanvPointsPerHit.cd(i + 1);
812 fhPointsPerHit[i].DrawCopy("", "");
813
814 fCanvEfficiencyR.cd(i + 1);
815 fhEfficiencyR[i].DrawCopy("colz", "");
816
817 fCanvEfficiencyXY.cd(i + 1);
818 fhEfficiencyXY[i].DrawCopy("colz", "");
819 }
820
821 for (UInt_t i = 0; i < fHistList.size(); i++) {
823 }
824
825 for (UInt_t i = 0; i < 6; i++) {
826 fCanvResidual.cd(i + 1);
827 fHistList[i]->DrawCopy("", "");
828 fCanvPull.cd(i + 1);
829 fHistList[6 + i]->DrawCopy("", "");
830 }
831
832 return fOutFolder;
833}
@ kTrd
Transition Radiation Detector.
Definition of the CbmQaCanvas class.
Useful utilities for CBM QA tasks.
ClassImp(CbmTrdCalibTracker)
Data Container for TRD clusters.
Class for hits in TRD detector.
friend fvec sqrt(const fvec &a)
int32_t GetAddress() const
Definition CbmCluster.h:90
int32_t GetDigi(int32_t index) const
Get digi at position index.
Definition CbmCluster.h:76
int32_t GetNofDigis() const
Number of digis in cluster.
Definition CbmCluster.h:69
static Int_t GetNofDigis(ECbmModuleId systemId)
static Bool_t IsMatchPresent(ECbmModuleId systemId)
Presence of a digi match branch.
InitStatus Init()
Initialisation.
const Digi * Get(Int_t index) const
Get a digi object.
static CbmDigiManager * Instance()
Static instance.
const CbmMatch * GetMatch(ECbmModuleId systemId, UInt_t index) const
Get a match object.
double GetTimeError() const
Definition CbmHit.h:77
double GetTime() const
Definition CbmHit.h:76
int32_t GetAddress() const
Definition CbmHit.h:74
double GetZ() const
Definition CbmHit.h:71
int32_t GetRefId() const
Definition CbmHit.h:73
TObject * Get(const CbmLink *lnk)
Int_t Size(Int_t fileNumber, Int_t eventNumber)
Task class creating and managing CbmMCDataArray objects.
CbmMCDataArray * InitBranch(const char *name)
Container class for MC events with number, file and start time.
int32_t GetFileIdByIndex(uint32_t index)
File number by index @value File number for event at given index in list.
int32_t GetEventIdByIndex(uint32_t index)
Event number by index @value Event number for event at given index in list.
Int_t GetEventIndex(UInt_t event, UInt_t file)
Event index.
std::size_t GetNofEvents() const
Number of events in the list @value Number of events.
double GetEventTime(uint32_t event, uint32_t file)
Event start time.
int32_t GetPdgCode() const
Definition CbmMCTrack.h:68
void AddLinks(const CbmMatch &match)
Definition CbmMatch.cxx:39
const CbmLink & GetLink(int32_t i) const
Definition CbmMatch.h:39
int32_t GetNofLinks() const
Definition CbmMatch.h:42
const CbmLink & GetMatchedLink() const
Definition CbmMatch.h:41
double GetDy() const
Definition CbmPixelHit.h:76
double GetDx() const
Definition CbmPixelHit.h:75
double GetY() const
Definition CbmPixelHit.h:74
double GetX() const
Definition CbmPixelHit.h:73
void Divide2D(int nPads)
Divide canvas into nPads in 2D in a nice way.
Bookkeeping of time-slice content.
static uint32_t GetLayerId(uint32_t address)
Return layer ID from address.
static uint32_t GetModuleAddress(uint32_t address)
Return unique module ID from address.
std::vector< CbmQaHist< TH1D > * > fHistList
List of the above histogramms.
CbmQaHist< TH1D > fh1DpullV
CbmQaHist< TH1D > fh2DresidualY
TClonesArray * fClusters
Data.
CbmQaHist< TH1D > fh2DresidualX
CbmMCDataArray * fMcTracks
std::vector< CbmQaHist< TH1I > > fhHitsPerPoint
hits efficiency
CbmQaHist< TH1D > fh1DpullU
Histogram for PULL Distribution.
CbmTimeSlice * fTimeSlice
CbmQaHist< TH1D > fh1DresidualV
void Finish()
FairTask: Action at end of run. For this task and all of the subtasks.
CbmQaHist< TH1D > fh1DresidualU
number of processed events
TParameter< int > fNevents
subfolder for histograms
std::vector< CbmQaHist< TProfile > > fhEfficiencyR
CbmTrdCalibTracker(const char *name="TrdQaTracker", Int_t verbose=1)
Constructor.
void DeInit()
Free the memory etc.
CbmQaHist< TH1D > fh2DpullY
CbmQaCanvas fCanvResidual
Canvaces: collection of histogramms.
CbmMCDataManager * fMcManager
CbmTrdParSetDigi * fTrdDigiPar
CbmQaHist< TH1D > fh2DresidualT
CbmMCDataArray * fMcPoints
CbmDigiManager * fDigiManager
CbmQaHist< TH1D > fh2DpullT
CbmTrdParSetGeo * fTrdGeoPar
InitStatus ReInit()
FairTask: Reinitialisation.
void ResolutionQa()
Analysis of hit uncertainty (pull) distributions.
std::vector< CbmQaHist< TProfile2D > > fhEfficiencyXY
hits efficiency
void SetParContainers()
FairTask: Intialise parameter containers.
TClonesArray * fHitMatches
void Exec(Option_t *)
TTask: Process a timeslice.
InitStatus GeometryQa()
Check the geometry.
CbmQaHist< TH1D > fh2DpullX
std::vector< CbmQaHist< TH1I > > fhPointsPerHit
hits purity
TClonesArray * fHitsMc
Output.
CbmQaHist< TH1D > fh1DresidualT
TFolder * fHistFolder
output folder with histos and canvases
CbmQaHist< TH1D > fh1DpullT
~CbmTrdCalibTracker()
Destructor.
CbmMCEventList * fMcEventList
MC data.
Data Container for TRD clusters.
int32_t GetAddressModule() const
Getter module address in the experiment.
uint64_t GetTimeDAQ() const
Getter for global DAQ time [clk]. Differs for each ASIC. In FASP case DAQ time is already stored in f...
Definition CbmTrdDigi.h:158
eCbmTrdAsicType GetType() const
Channel FEE SPADIC/FASP according to CbmTrdAsicType.
Definition CbmTrdDigi.h:173
double GetTime() const
Getter for physical time [ns]. Accounts for clock representation of each ASIC. In SPADIC case physica...
Definition CbmTrdDigi.h:153
TRD hit to MC point correlation class.
Definition CbmTrdHitMC.h:28
size_t AddPoint(const CbmTrdPoint *p, double t, int id)
Add MC points to the hit. The first time this function is called is for the best matched MC point.
void SetErrorMsg(std::string msg)
Store error message.
void AddCluster(const CbmTrdCluster *c)
Copy cluster details.
size_t PurgeSignals()
Applies to TRD2D and remove 0 charges from the boundaries of the cluster.
size_t AddSignal(const CbmTrdDigi *d, uint64_t t0)
Add signal values in the increasing order of pad index.
double GetDx() const
Calculate residuals in the bending plane.
data class for a reconstructed Energy-4D measurement in the TRD
Definition CbmTrdHit.h:40
bool GetClassType() const
Definition CbmTrdHit.h:80
Definition of geometry for one TRD module.
virtual Double_t GetZ() const
bool LoadAlignVolumes()
Trigger loading alignment information for all nodes registered.
virtual Int_t GetModuleId(Int_t i) const
virtual const CbmTrdParMod * GetModulePar(Int_t detId) const
double GetPzOut() const
Definition CbmTrdPoint.h:73
double GetZIn() const
Definition CbmTrdPoint.h:67
int32_t GetModuleAddress() const
Definition CbmTrdPoint.h:78
double GetZOut() const
Definition CbmTrdPoint.h:70
std::tuple< double, double > FitKaniadakisGaussian(TH1 *pHist)
Fit a histogram with Kaniadakis Gaussian Distribution.
Definition CbmQaUtil.cxx:88