CbmRoot
Loading...
Searching...
No Matches
CbmRecoQaTask.cxx
Go to the documentation of this file.
1/* Copyright (C) 2024-2026 Hulubei National Institute of Physics and Nuclear Engineering - Horia Hulubei, Bucharest
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Alexandru Bercuci [committer], Omveer Singh */
4
5//CBM headers
6#include "CbmRecoQaTask.h"
7
9#include "CbmCluster.h"
10#include "CbmDefs.h"
11#include "CbmEvent.h"
12#include "CbmFsdHit.h"
13#include "CbmGlobalTrack.h"
14#include "CbmMCDataArray.h"
15#include "CbmMCDataManager.h"
16#include "CbmMvdHit.h"
17#include "CbmPsdHit.h"
18#include "CbmRichHit.h"
19#include "CbmSetup.h"
20#include "CbmStsAddress.h"
21#include "CbmStsCluster.h"
22#include "CbmStsHit.h"
23#include "CbmStsSetup.h"
24#include "CbmTimeSlice.h"
25#include "CbmTofAddress.h"
26#include "CbmTofHit.h"
27#include "CbmTrdAddress.h"
28#include "CbmTrdCluster.h"
29#include "CbmTrdHit.h"
30// FAIR headers
31#include "FairMCPoint.h"
32
33#include <FairRootManager.h>
34#include <FairSink.h>
35// ROOT headers
36#include <TClonesArray.h>
37#include <TGeoManager.h>
38#include <TGeoNode.h>
39#include <TH2D.h>
40#include <TH3D.h>
41
42#include <iterator>
43#include <regex>
44
45using namespace std;
46using namespace cbm::algo;
47std::bitset<CbmRecoQaTask::eRecoConfig::kRecoQaNConfigs> CbmRecoQaTask::fuRecoConfig = {};
48
49//_____________________________________________________________________
56
57//_____________________________________________________________________
59{
60 /* Interface to the user. Check that the det defined in the outside world
61 * fulfills the quality criteria.
62 */
63 if (GetDetector(id)) {
64 LOG(warn) << GetName() << "::AddDetector(" << id << ")."
65 << " already registered. Using "
66 << "\"CbmRecoQaTask::GetDetector(ECbmModuleId).\"";
67 return GetDetector(id);
68 }
69 switch (id) {
79 LOG(debug) << GetName() << "::AddDetector(" << id << ").";
80 fDetQa.emplace(id, id);
81 break;
82 default: LOG(warn) << GetName() << "::AddDetector : unsupported det " << id; return nullptr;
83 }
84
85 return &fDetQa[id];
86}
87
88//_____________________________________________________________________
90{
91 // translate to local parameterization
93 switch (id) {
94 case ECbmModuleId::kSts: feature = eRecoConfig::kUseSts; break;
95 case ECbmModuleId::kTrd: feature = eRecoConfig::kUseTrd; break;
96 case ECbmModuleId::kTof: feature = eRecoConfig::kUseTof; break;
97 default: break;
98 }
99 if (feature == eRecoConfig::kRecoQaNConfigs) {
100 LOG(warn) << GetName() << "::Activate : unsupported operation on det " << id;
101 return;
102 }
103 if (set) {
104 LOG(info) << GetName() << "::Activate " << id << " for track fit.";
105 fuRecoConfig.set(feature);
106 }
107 else {
108 LOG(info) << GetName() << "::Deactivate " << id << " for track fit.";
109 fuRecoConfig.reset(feature);
110 }
111}
112
113//_____________________________________________________________________
115{
116 if (fDetQa.find(id) == fDetQa.end()) return nullptr;
117 return &fDetQa[id];
118}
119
120//_____________________________________________________________________
121template<>
122std::map<ECbmModuleId, TClonesArray*> CbmRecoQaTask::MapDataList<CbmCluster>(std::string& s) const
123{
124 s = "cluster";
125 return fClusters;
126}
127template<>
128std::map<ECbmModuleId, TClonesArray*> CbmRecoQaTask::MapDataList<CbmHit>(std::string& s) const
129{
130 s = "hit";
131 return fHits;
132}
133template<>
134std::map<ECbmModuleId, TClonesArray*> CbmRecoQaTask::MapDataList<CbmTrack>(std::string& s) const
135{
136 s = "track";
137 return fTracks;
138}
139template<>
140std::map<ECbmModuleId, TClonesArray*> CbmRecoQaTask::MapDataList<CbmMatch>(std::string& s) const
141{
142 s = "match";
143 return fHitMatch;
144}
145template<class Data>
146const Data* CbmRecoQaTask::GetData(ECbmModuleId did, int id) const
147{
148 if (id < 0) {
149 LOG(warning) << GetName() << " negative data idx for " << did;
150 return nullptr;
151 }
152 std::string ss;
153 auto datas = MapDataList<Data>(ss);
154 if (datas.find(did) == datas.end()) {
155 LOG(debug1) << GetName() << " missing " << ss << "s for " << did;
156 return nullptr;
157 }
158 auto dd = (const Data*) (datas.at(did))->At(id);
159 if (!dd) {
160 LOG(debug1) << GetName() << " missing " << ss << "_" << id << " for " << did;
161 return nullptr;
162 }
163 return dd;
164}
165
166//_____________________________________________________________________
168{
169 // INIT TRACKING INTERFACE
170 fFitter.Init();
171 fFitter.SetIgnorePoorCoordinates();
172
173 // INIT DATA
174 FairRootManager* ioman = FairRootManager::Instance();
175 if (!ioman) {
176 LOG(fatal) << GetName() << "::Init :: RootManager not instantiated!";
177 return kERROR;
178 }
179 // read global tracks
180 fGTracks = static_cast<TClonesArray*>(ioman->GetObject("GlobalTrack"));
181 if (!fGTracks)
182 LOG(warn) << GetName() << "::Init: Global track array not found!";
183 else
185 // read reco events
186 fEvents = static_cast<TClonesArray*>(ioman->GetObject("CbmEvent"));
187 if (!fEvents)
188 LOG(warn) << GetName() << "::Init: No event found. Some results will be missing.";
189 else
191 // read MC particles using the MC datat manager
192 if (fuRecoConfig[kUseMC]) {
193 cbm_mc_manager = dynamic_cast<CbmMCDataManager*>(ioman->GetObject("MCDataManager"));
194 if (!cbm_mc_manager) {
195 LOG(warn) << GetName() << "::Init: MC data manager not available even though asked by user !";
196 fuRecoConfig.reset(kUseMC);
197 }
198 else {
199 fTrackMatches = static_cast<TClonesArray*>(ioman->GetObject("GlobalTrackMatch"));
200 if (!fTrackMatches) {
201 LOG(warn) << GetName() << "::Init: MC info for Global track not available !";
202 }
203 }
204 }
205 // initialize setup. For special cases use specific configurations
206 // TODO should be moved to configuration
207 switch (fSetupClass) {
208 case kMcbm22:
209 LOG(info) << GetName() << "::Init: Setup config for \"mCBM 2022\".";
210 InitMcbm22();
211 break;
212 case kMcbm24:
213 LOG(info) << GetName() << "::Init: Setup config for \"mCBM 2024\". ";
214 InitMcbm24();
215 break;
216 case kMcbm25:
217 LOG(info) << GetName() << "::Init: Setup config for \"mCBM 2025\". ";
218 InitMcbm25();
219 break;
220 case kDefault:
221 LOG(info) << GetName() << "::Init: Setup config for \"Default\". ";
222 InitDefault();
223 break;
224 }
225 // init MC points, hits and clusters for all systems registered in the setup
226 fOutFolder.Clear();
227 for (auto& detp : fDetQa) { // SYSTEM LOOP
228 auto& det = detp.second;
229 // read Hit -> MC linking
230 if (cbm_mc_manager) {
231 fPoints[det.id] = cbm_mc_manager->InitBranch(det.point.name.data());
232 if (!fPoints[det.id]) LOG(warn) << GetName() << "::Init: MC Point array for " << det.id << " not found!";
233 fHitMatch[det.id] = static_cast<TClonesArray*>(ioman->GetObject((det.hit.name + "Match").c_str()));
234
235 if (!fHitMatch[det.id]) LOG(warn) << GetName() << "::Init: Hit Match array for " << det.id << " not found!";
236 }
237 // init reco hits
238 fHits[det.id] = static_cast<TClonesArray*>(ioman->GetObject(det.hit.name.data()));
239 if (!fHits[det.id]) {
240 LOG(warn) << GetName() << "::Init: Hit array for " << cbm::util::ToString(det.id) << " not found!";
241 continue;
242 }
243 switch (det.id) {
244 case ECbmModuleId::kSts: fuRecoConfig.set(kStsHits); break;
245 case ECbmModuleId::kTrd: fuRecoConfig.set(kTrdHits); break;
246 case ECbmModuleId::kTof: fuRecoConfig.set(kTofHits); break;
249 default: break;
250 }
251
252 // init reco clusters
253 if (det.cl.id != ECbmDataType::kUnknown) {
254 fClusters[det.id] = static_cast<TClonesArray*>(ioman->GetObject(det.cl.name.data()));
255 if (!fClusters[det.id]) {
256 LOG(warn) << GetName() << "::Init: Cluster array for " << det.id << " not found!";
257 continue;
258 }
259 }
260 // init reco track segments for each detector registered in the setup
261 if (fGTracks && det.trk.id != ECbmDataType::kUnknown) {
262 fTracks[det.id] = static_cast<TClonesArray*>(ioman->GetObject(det.trk.name.data()));
263 if (!fTracks[det.id]) LOG(warn) << GetName() << "::Init: Track array for " << det.id << " not found!";
264 }
265 if (!det.Init(&fOutFolder, (bool) fuRecoConfig[kUseMC])) continue;
266 }
267
268 // INIT PROJECTION PLANES FOR TRACKS
269 TDirectoryFile* trgDir = (fuRecoConfig[kRecoEvents] || fuRecoConfig[kUseMC] || GetNviews(eViewType::kTrkProj))
270 ? (TDirectoryFile*) fOutFolder.mkdir("TRG", "Target tomography with CA")
271 : nullptr;
272 // register track projection on z planes
273 if (fPrjPlanes.size() && trgDir) {
274 fViews.emplace("prj", View("TrkProj", "", {}));
275 fViews["prj"].fType = eViewType::kTrkProj;
276 int i(0);
277 for (auto plane : fPrjPlanes) { // add projection planes according to user request
278 if (i >= kNtrkProjections) {
279 LOG(warn) << GetName() << "::Init: Only " << kNtrkProjections << " are supported. Skipping the rest.";
280 fPrjPlanes.erase(fPrjPlanes.begin() + int(kNtrkProjections), fPrjPlanes.end());
281 break;
282 }
283
285 plane.Z());
286 i++;
287 }
288 fViews["prj"].Init("");
289 fViews["prj"].Register(trgDir);
290 }
291 // register also projection plans for track filtering if they are not already defined
292 for (auto trkCut : fFilterTrk) {
293 // special cut for selection on track composition. See FilterTrack(const CbmGlobalTrack*)
294 if (trkCut.fDet != ECbmModuleId::kRef) continue;
295 // read z coordinates of projection planes
296 for (auto rcut : trkCut.GetProjCuts()) {
297 // check if projection not already on the list
298 bool projFound = false;
299 for (auto plane : fPrjPlanes)
300 if (abs(plane.Z() - rcut[0]) < 1.e-3) {
301 projFound = true;
302 break;
303 }
304 if (projFound)
305 LOG(debug1) << GetName() << "::Init: Trk projection cut @ z=" << rcut[0]
306 << " already registered as projection plane";
307 else
308 fPrjPlanes.emplace_back(0., 0., rcut[0]);
309 }
310 }
311
312 // INIT PRIMARY VERTEX QA
313 if (fuRecoConfig[kRecoEvents] && trgDir) {
314 fViews.emplace("vx", View("Vx", "", {}));
315 fViews["vx"].fType = eViewType::kPV;
323 fViews["vx"].Init("Prim");
324 fViews["vx"].Register(trgDir);
325 }
326
327 // DUMP FILTERS SETTINGS
328 for (auto evSelector : fFilterEv)
329 LOG(info) << GetName() << evSelector.ToString();
330 for (auto trkSelector : fFilterTrk)
331 LOG(info) << GetName() << trkSelector.ToString();
332 // add verbosity on active detectors
333 LOG(info) << GetName() << "::Init: Using for tracking: " << (IsActive(eRecoConfig::kUseSts) ? "STS " : "")
334 << (IsActive(eRecoConfig::kUseTrd) ? "TRD " : "") << (IsActive(eRecoConfig::kUseTof) ? "ToF " : "");
335 return kSUCCESS;
336}
337
338//_________________________________________________________________
339template<class Hit>
340bool CbmRecoQaTask::View::HasAddress(const CbmHit* h, double&, double&, double&, double&) const
341{
343 LOG(error) << "Unprocessed hit in view " << name;
344 cout << h->ToString();
345
346 return false;
347}
348
349//_________________________________________________________________
350template<ECbmModuleId d>
352{
353 return 0xab00;
354}
355template<>
357{
359
360 //auto htrd = dynamic_cast<const CbmTrdHit*>(h);
361 auto ctrd = (const CbmTrdCluster*) GetData<CbmCluster>(ECbmModuleId::kTrd, h->GetRefId());
362 if (!ctrd) return 0xab00;
363 return ctrd->GetRow();
364}
365
366//_________________________________________________________________
367template<>
369{
371 int32_t a = h->GetAddress();
375 return sel.size();
376}
377
378//_________________________________________________________________
379template<>
381{
383 int32_t a = h->GetAddress();
385 sel.emplace_back(CbmTrdAddress::GetModuleId(a));
386 return sel.size();
387}
388
389//_________________________________________________________________
390template<>
392{
394 int32_t a = h->GetAddress();
395 sel.emplace_back(CbmTofAddress::GetSmId(a));
396 sel.emplace_back(CbmTofAddress::GetSmType(a));
397 sel.emplace_back(CbmTofAddress::GetRpcId(a));
398 return sel.size();
399}
400
401//_________________________________________________________________
402template<>
404{
406 int32_t a = h->GetAddress();
407 int16_t uId = CbmRichUtil::GetDirichId(a);
408 // TODO implement at RichUtil level
409 sel.emplace_back((uId >> 8) & 0xF);
410 return sel.size();
411}
412
413//_________________________________________________________________
414template<ECbmModuleId d>
416{
418
419 // check if there is any condition defined for current detector:
420 if (!fReject.size() && !fAccept.size()) return true;
421
422 // check individually the conditions
423 std::vector<int> sel;
424 auto nsel = CbmRecoQaTask::GetHitDetectorId<d>(h, sel);
425
426 // Lambda function to filter specific location parameters
427 auto filter = [&](vector<int> def) -> size_t {
428 size_t accept(nsel);
429 // check cut in topology [unit, ladder, module]
430 for (size_t isel(0); isel < nsel; isel++) {
431 if (def[isel] < 0 || def[isel] == sel[isel])
432 accept--;
433 else
434 return accept;
435 }
436 return accept;
437 };
438 // check reject conditions
439 for (auto def : fReject) {
440 if (def.size() < nsel) {
441 LOG(error) << "TopoFilter::Accept: Det[" << d << "] unsupported definition for [reject] cut of size["
442 << def.size() << "] expect " << nsel;
443 break;
444 }
445 if (!filter(def)) return false;
446 }
447 // if not rejected check accepting conditions
448 for (auto def : fAccept) {
449 if (def.size() < nsel) {
450 LOG(error) << "TopoFilter::Accept: Det[" << d << "] unsupported definition for [accept] cut of size["
451 << def.size() << "] expect " << nsel;
452 break;
453 }
454 if (!filter(def)) return true;
455 }
456 return fAccept.size() ? false : true;
457}
458
459//_________________________________________________________________
460template<>
462 const CbmCluster*) const
463{
467 if (!fReject.size() && !fAccept.size()) return true;
468 std::vector<int> sel;
470 const CbmTrdCluster* c(nullptr);
471 if (c0) c = dynamic_cast<const CbmTrdCluster*>(c0);
472 auto htrd = dynamic_cast<const CbmTrdHit*>(h);
473
474 // Lambda function to filter specific TRD(2D) parameters
475 auto filter = [&](vector<int> def) -> size_t {
476 size_t accept(trdSz); // consider all extra cuts defined on the detector
477 // check cut in topology [layer, module]
478 size_t isel(0);
479 for (; isel < nsel; isel++) {
480 if (def[isel] < 0 || def[isel] == sel[isel])
481 accept--;
482 else
483 return accept;
484 }
485 // check cut cluster size
486 if (def[isel] < 0 || (c && c->GetSize() == def[isel]))
487 accept--;
488 else
489 return accept;
490 isel++;
491 // check hit row cross
492 auto rc = htrd->IsRowCross();
493 if (def[isel] < 0 || (rc == bool(def[isel])))
494 accept--;
495 else
496 return accept;
497 isel++;
498 // check hit maximum pairing
499 auto mx = htrd->GetMaxType();
500 if (def[isel] < 0 || (mx == bool(def[isel])))
501 accept--;
502 else
503 return accept;
504 isel++;
505 // check hit maximum symmetry. Add 1 to shift it in the range {0, 1, 2} and skip the default [-1]
506 auto symm = 0; // htrd->GetMaxSymm() + 1; TODO need update of the CbmTrdHit class
507 if (def[isel] < 0 || (symm == def[isel]))
508 accept--;
509 else
510 return accept;
511 isel++;
512 // check cut cluster row
513 if (def[isel] < 0 || (c && c->GetRow() == def[isel]))
514 accept--;
515 else
516 return accept;
517 isel++;
518
519 return accept;
520 };
521
522 // check reject conditions
523 for (auto def : fReject) {
524 if (def.size() < nsel) {
525 LOG(error) << "TopoFilter::Accept: Det[TRD] unsupported definition for [reject] cut of size[" << def.size()
526 << "] expect " << nsel;
527 break;
528 }
529 if (!filter(def)) return false;
530 }
531 for (auto def : fAccept) {
532 if (def.size() < nsel) {
533 LOG(error) << "TopoFilter::Accept: Det[TRD] unsupported definition for [accept] cut of size[" << def.size()
534 << "] expect " << nsel;
535 break;
536 }
537 if (!filter(def)) return true;
538 }
539 return fAccept.size() ? false : true;
540}
541
542//_________________________________________________________________
543// HasAddress definitions
544template<>
545bool CbmRecoQaTask::View::HasAddress<CbmStsHit>(const CbmHit* h, double& x, double& y, double& dx, double& dy) const
546{
548 std::vector<int> sel;
550 size_t isel(0);
551 for (auto ii : fSelector) {
552 if (ii != sel[isel]) break;
553 isel++;
554 }
555 if (fSetup == eSetup::kDefault && sel[0] != fSelector[0]) {
556 return false;
557 }
558 else if (fSetup != eSetup::kDefault && isel != nsel) {
559 return false;
560 }
561 else
562 LOG(debug4) << "Accept Sts hit for " << sel[0] << " " << sel[1] << " " << sel[2];
563
564 const CbmStsHit* h0 = dynamic_cast<const CbmStsHit*>(h);
565 if (!h0) {
566 LOG(error) << "Failed loading STS hit in view " << name;
567 return false;
568 }
569 x = h0->GetX();
570 dx = h0->GetDx();
571 y = h0->GetY();
572 dy = h0->GetDy();
573 return true;
574}
575
576//_________________________________________________________________
577template<>
578bool CbmRecoQaTask::View::HasAddress<CbmRichHit>(const CbmHit* h, double& x, double& y, double& dx, double& dy) const
579{
581 std::vector<int> sel;
583
584 if (fSetup != eSetup::kDefault) {
585 if (sel[0] >= fSelector[0]) return false;
586 }
587
588 const CbmRichHit* h0 = dynamic_cast<const CbmRichHit*>(h);
589 if (!h0) {
590 LOG(error) << "Failed loading RICH hit in view " << name;
591 return false;
592 }
593 x = h0->GetX();
594 dx = h0->GetDx();
595 y = h0->GetY();
596 dy = h0->GetDy();
597 return true;
598}
599
600//_________________________________________________________________
601template<>
602bool CbmRecoQaTask::View::HasAddress<CbmTrdHit>(const CbmHit* h, double& x, double& y, double& dx, double& dy) const
603{
605 std::vector<int> sel;
606 auto nsel = CbmRecoQaTask::GetHitDetectorId<ECbmModuleId::kTrd>(h, sel);
607 /*
608 if (fSetup == eSetup::kDefault) {
609 sel = {static_cast<int>(CbmTrdAddress::GetLayerId(CbmTrdAddress::GetModuleAddress(h->GetAddress()))),
610 static_cast<int>(CbmTrdAddress::GetModuleId(h->GetAddress())), -1};
611 }
612 else {
613 sel = {static_cast<int>(CbmTrdAddress::GetModuleAddress(h->GetAddress())), -1, -1};
614 }*/
615
616 size_t isel(0);
617 for (auto ii : fSelector) {
618 if (ii != sel[isel]) break;
619 isel++;
620 }
621
622 if (isel != nsel) return false;
623
624 LOG(debug4) << "Accept TRD hit for " << sel[0] << " " << sel[1] << " " << sel[2];
625
626 const CbmTrdHit* h0 = dynamic_cast<const CbmTrdHit*>(h);
627 if (!h0) {
628 LOG(error) << "Failed loading TRD hit in view " << name;
629 return false;
630 }
631 x = h0->GetX();
632 dx = h0->GetDx();
633 y = h0->GetY();
634 dy = h0->GetDy();
635 return true;
636}
637
638//_________________________________________________________________
639template<>
640bool CbmRecoQaTask::View::HasAddress<CbmTofHit>(const CbmHit* h, double& x, double& y, double& dx, double& dy) const
641{
643 std::vector<int> sel;
644 auto nsel = CbmRecoQaTask::GetHitDetectorId<ECbmModuleId::kTof>(h, sel);
645 size_t isel(0);
646 for (auto ii : fSelector) {
647 if (ii != sel[isel]) break;
648 isel++;
649 }
650 if (fSetup == eSetup::kDefault && nsel != 1) {
651 return false;
652 }
653 else if (fSetup != eSetup::kDefault && isel != nsel) {
654 return false;
655 }
656 else
657 LOG(debug4) << "Accept Tof hit for " << sel[0] << " " << sel[1] << " " << sel[2];
658
659 const CbmTofHit* h0 = dynamic_cast<const CbmTofHit*>(h);
660 if (!h0) {
661 LOG(error) << "Failed loading ToF hit in view " << name;
662 return false;
663 }
664 x = h0->GetX();
665 dx = h0->GetDx();
666 y = h0->GetY();
667 dy = h0->GetDy();
668 return true;
669}
670
671//===============================================================================
672//__________________ IMPLEMENTATIONS ____________________________________________
673template<class Hit>
674bool CbmRecoQaTask::View::Load(const CbmHit* h, const FairMCPoint* point, const CbmEvent* ev)
675{
676 double x(0), y(0), dx(0), dy(0);
677 if (!HasAddress<Hit>(h, x, y, dx, dy)) {
678 LOG(debug4) << "view " << name << " does not own hit " << h->ToString();
679 return false;
680 }
681
682 int scale(0);
683 TH2* hh(nullptr);
684 auto fillView = [&](eProjectionType proj, double xx, double yy, bool scaleY = true) {
685 auto it = fProjection.find(proj);
686 if (it != fProjection.end()) {
687 scale = std::get<0>(it->second);
688 hh = dynamic_cast<TH2*>(std::get<2>(it->second));
689 if (hh) hh->Fill(xx, scaleY ? yy * scale : yy);
690 }
691 };
692
693 if (ev) fillView(eProjectionType::kChdT, x, h->GetTime() - ev->GetStartTime());
694
695 fillView(eProjectionType::kXYh, x, y, false);
696
697 double event_time = ev ? ev->GetStartTime() : 1000;
698
699 if (point) {
700 // TODO dirty fix for MC point correction of Z coordinate. Assume straight
701 // tracks from 0,0,0 !! Works for mCBM
702 double prj = h->GetZ() / point->GetZ();
703 fillView(eProjectionType::kXYhMC, prj * point->GetX(), prj * point->GetY(), false);
704 fillView(eProjectionType::kResidualX, x, x - prj * point->GetX());
705 fillView(eProjectionType::kResidualY, y, y - prj * point->GetY());
706 fillView(eProjectionType::kResidualTX, x, h->GetTime() - event_time - point->GetTime());
707 fillView(eProjectionType::kResidualTY, y, h->GetTime() - event_time - point->GetTime());
708 fillView(eProjectionType::kPullX, x, (x - prj * point->GetX()) / dx);
709 fillView(eProjectionType::kPullY, y, (y - prj * point->GetY()) / dy);
710 }
711 fMult++; // register hit/point multiplicity
712 return true;
713}
714
715bool CbmRecoQaTask::View::Load(const Trajectory::Node* n, const FairMCPoint* point, const int dinfo)
716{
717 const kf::TrackParamD& t = n->paramUp;
718 // define aliases
719 double xhit(n->measurementXY.X()), yhit(n->measurementXY.Y()), thit(n->measurementTime.T()),
720 dx = xhit - t.X(), dy = yhit - t.Y(), dt = thit - t.Time(),
721 pullx = dx / sqrt(n->measurementXY.Dx2() + t.GetCovariance(0, 0)),
722 pully = dy / sqrt(n->measurementXY.Dy2() + t.GetCovariance(1, 1));
723 // pullt = dt / sqrt(n->fMt.Dt2() + n->fTrack.GetCovariance(5, 5));
724
725 for (auto& projection : fProjection) {
726 int scale = get<0>(projection.second);
727 auto h = get<2>(projection.second);
728 if (!h) continue;
729
730 auto hh = dynamic_cast<TH2*>(h);
731 switch (projection.first) {
732 case eProjectionType::kXYa: hh->Fill(xhit, yhit); break;
733 case eProjectionType::kXYp: hh->Fill(t.X(), t.Y()); break;
734 case eProjectionType::kXdX: hh->Fill(xhit, scale * dx); break;
735 case eProjectionType::kYdY: hh->Fill(yhit, scale * dy); break;
736 case eProjectionType::kWdT: hh->Fill(xhit, scale * dt); break;
737 case eProjectionType::kXpX: hh->Fill(xhit, pullx); break;
738 case eProjectionType::kYpY: hh->Fill(yhit, pully); break;
739 case eProjectionType::kXdXT: hh->Fill(xhit, scale * sqrt(t.GetCovariance(0, 0))); break;
740 case eProjectionType::kYdYT: hh->Fill(yhit, scale * sqrt(t.GetCovariance(1, 1))); break;
741
742 default: break;
743 }
744
745 if (point) {
746 // TODO dirty fix for MC point correction of Z coordinate. Assume straight
747 // tracks from 0,0,0 !! Works for mCBM
748 double prj = n->z / point->GetZ();
749 double dxMC = prj * point->GetX() - t.X(), dyMC = prj * point->GetY() - t.Y();
750
751 switch (projection.first) {
752 case eProjectionType::kXdXMC: hh->Fill(xhit, scale * dxMC); break;
753 case eProjectionType::kYdYMC: hh->Fill(yhit, scale * dyMC); break;
754 default: break;
755 }
756 }
757 if (dinfo != 0xab00) {
758 auto hhh = dynamic_cast<TH3*>(h);
759 switch (projection.first) {
760 case eProjectionType::kDebug0: hhh->Fill(xhit, scale * dx, double(dinfo)); break;
761 case eProjectionType::kDebug1: hhh->Fill(xhit, scale * dy, double(dinfo)); break;
762 default: break;
763 }
764 }
765 }
766 return true;
767}
768
769bool CbmRecoQaTask::View::Load(TVector3* p, TVector3* pe)
770{
771 for (auto& projection : fProjection) {
772 int scale = get<0>(projection.second);
773 TH2* hh = dynamic_cast<TH2*>(get<2>(projection.second));
774 if (!hh) continue;
775 switch (projection.first) {
777 if (int(p->Z()) == -123) hh->Fill(scale * p->X(), scale * p->Y());
778 break;
780 if (int(p->Z()) == -124) hh->Fill(p->X(), p->Y());
781 break;
783 if (int(p->Z()) == 0) hh->Fill(scale * p->X(), scale * p->Y());
784 break;
785 // fall through
787 if (int(p->Z()) == 1) hh->Fill(scale * p->X(), scale * p->Y());
788 break;
789 // fall through
791 if (int(p->Z()) == 2) hh->Fill(scale * p->X(), scale * p->Y());
792 break;
793 // fall through
795 if (int(p->Z()) == 3) hh->Fill(scale * p->X(), scale * p->Y());
796 break;
797 // fall through
799 if (int(p->Z()) == 4) hh->Fill(scale * p->X(), scale * p->Y());
800 break;
801 // fall through
803 if (int(p->Z()) == 5) hh->Fill(scale * p->X(), scale * p->Y());
804 break;
805 // fall through
807 if (pe) hh->Fill(scale * p->X(), scale * p->Y());
808 break;
810 if (pe) hh->Fill(p->Z(), scale * p->X());
811 break;
813 if (pe) hh->Fill(p->Z(), scale * p->Y());
814 break;
816 if (pe) hh->Fill(scale * p->X(), scale * pe->X());
817 break;
819 if (pe) hh->Fill(scale * p->Y(), scale * pe->Y());
820 break;
822 if (pe) hh->Fill(scale * p->Z(), scale * pe->Z());
823 break;
824 default: break;
825 }
826 }
827 return true;
828}
829
830//_____________________________________________________________________
831
832void CbmRecoQaTask::Exec(Option_t*)
833{
834 LOG(info) << GetName() << "::Exec : Evs[" << (fEvents ? fEvents->GetEntriesFast() : 0) << "] Trks["
835 << (fGTracks ? fGTracks->GetEntriesFast() : 0) << "] Hits["
836 << (fHits[ECbmModuleId::kSts] ? fHits[ECbmModuleId::kSts]->GetEntriesFast() : 0) << " "
837 << (fHits[ECbmModuleId::kTrd] ? fHits[ECbmModuleId::kTrd]->GetEntriesFast() : 0) << " "
838 << (fHits[ECbmModuleId::kTof] ? fHits[ECbmModuleId::kTof]->GetEntriesFast() : 0) << "]";
839
840 int iev = 0, itrack = 0;
841 // match to MC lambda function
842 auto matchMC = [&](const CbmHit* hit, int hid, ECbmModuleId d, const CbmEvent* ev = nullptr) -> const FairMCPoint* {
843 const FairMCPoint* mcpoint = nullptr;
844 if (fHitMatch[d] && fPoints[d]) {
845 if (d == ECbmModuleId::kRich) {
846 Int_t pointID = hit->GetRefId();
847 if (pointID >= 0) {
848 // mcpoint = dynamic_cast<FairMCPoint*>(fPoints[n.fHitSystemId]->At(pointID));
849 }
850 }
851 else {
852 auto match = dynamic_cast<const CbmMatch*>(fHitMatch[d]->At(hid));
853 if (match && match->GetNofLinks() > 0) {
854 const auto& link = match->GetMatchedLink();
855 if (ev) {
856 int file_id{0}, event_id{0};
857 if (ev && ev->GetMatch() && ev->GetMatch()->GetNofLinks() > 0) {
858 file_id = ev->GetMatch()->GetMatchedLink().GetFile();
859 event_id = ev->GetMatch()->GetMatchedLink().GetEntry();
860 }
861 else {
862 event_id = FairRootManager::Instance()->GetEntryNr();
863 }
864 if (link.GetFile() != file_id || link.GetEntry() != event_id) {
865 LOG(warn) << "match from different event";
866 }
867 }
868 mcpoint = dynamic_cast<FairMCPoint*>(fPoints[d]->Get(link));
869 }
870 }
871 }
872 return mcpoint;
873 };
874 // hit processor lambda function
875 auto processHits = [&](CbmEvent* ev) {
876 for (auto& detp : fDetQa) {
877 auto& det = detp.second;
878 // skip detectors from setup for which reco was not activated
879 switch (det.id) {
881 if (!fuRecoConfig[kStsHits]) continue;
882 break;
884 if (!fuRecoConfig[kMuchHits]) continue;
885 break;
887 if (!fuRecoConfig[kRichHits]) continue;
888 break;
891 if (!fuRecoConfig[kTrdHits]) continue;
892 break;
894 if (!fuRecoConfig[kTofHits]) continue;
895 break;
896 default: break;
897 }
898 if (!fHits[det.id]) {
899 LOG(error) << GetName() << "::Exec() : Hits for " << cbm::util::ToString(det.id) << " not available. Skip.";
900 continue;
901 }
902
903 const int nh = (ev) ? max(int(0), int(ev->GetNofData(det.hit.id))) : fHits[det.id]->GetEntriesFast();
904 for (int ih = 0; ih < nh; ++ih) {
905 const int jh = (ev) ? ev->GetIndex(det.hit.id, ih) : ih;
906 // retrieve hit
907 auto hit = dynamic_cast<const CbmHit*>(fHits[det.id]->At(jh));
908 if (!hit) {
909 LOG(warning) << GetName() << "::Exec() : Hit " << jh << " for " << det.id << " not available. Skip.";
910 continue;
911 }
912 // filter hits for analysis for which specific properties are requiered
913 if (!FilterHit(hit, det.id)) continue;
914
915 // link MC info if available
916 const FairMCPoint* mcpoint = matchMC(hit, jh, det.id, ev);
917 // upload info [hit, point, event] to the corresponding view
918 bool ret(false);
919 for (auto& view : det.fViews) {
920 switch (det.id) {
921 case ECbmModuleId::kMvd: ret = view.Load<CbmMvdHit>(hit, mcpoint, ev); break;
922 case ECbmModuleId::kSts: ret = view.Load<CbmStsHit>(hit, mcpoint, ev); break;
923 case ECbmModuleId::kMuch: ret = view.Load<CbmMuchPixelHit>(hit, mcpoint, ev); break;
924 case ECbmModuleId::kRich: ret = view.Load<CbmRichHit>(hit, mcpoint, ev); break;
926 case ECbmModuleId::kTrd2d: ret = view.Load<CbmTrdHit>(hit, mcpoint, ev); break;
927 case ECbmModuleId::kTof: ret = view.Load<CbmTofHit>(hit, mcpoint, ev); break;
928 case ECbmModuleId::kFsd: ret = view.Load<CbmFsdHit>(hit, mcpoint, ev); break;
929 case ECbmModuleId::kPsd: ret = view.Load<CbmPsdHit>(hit, mcpoint, ev); break;
930 default: LOG(fatal) << GetName() << "::Exec : unsupported det " << det.id; break;
931 }
932 if (ret) break;
933 }
934 }
935 TVector3 mult;
936 for (auto& v : det.fViews) {
937 mult.SetXYZ(nh, double(v.fMult) / nh, -124);
938 v.Load(&mult);
939 v.fMult = 0;
940 }
941 }
942 };
943
944 auto processTracks = [&](CbmEvent* ev) {
945 const int ntrk = (ev) ? ev->GetNofData(ECbmDataType::kGlobalTrack) : fGTracks->GetEntriesFast();
946 // read in the vertex and the list of tracks used for its definition
947 TVector3 pvx, evx;
948 int ntrkDet[3] = {0};
949
950 CbmVertex* vx(nullptr);
951 int nTrkVx(0);
952 if (ev && fViews.find("vx") != fViews.end()) {
953 vx = ev->GetVertex();
954 nTrkVx = vx->GetNTracks();
955 auto& v = fViews["vx"];
956 if (nTrkVx >= 2) {
957 vx->Position(pvx);
958 for (int i(0); i < 3; i++) {
959 evx[i] = vx->GetCovariance(i, i);
960 if (evx[i] > 0.) evx[i] = sqrt(evx[i]);
961 }
962 v.Load(&pvx, &evx);
963 }
964 pvx.SetXYZ(ntrk, nTrkVx, -123);
965 v.Load(&pvx);
966 }
967
968 // find the track projection view if it is registered
969 View* viewPrj = nullptr;
970 if (fViews.find("prj") != fViews.end()) {
971 viewPrj = &fViews["prj"];
972 if (viewPrj->fType != eViewType::kTrkProj) {
973 LOG(warning) << GetName() << "::Exec: view for track projection with wrong type. Skipping.";
974 viewPrj = nullptr;
975 }
976 }
977
978 for (int itrk = 0; itrk < ntrk; ++itrk) {
979 int trkIdx = ev ? ev->GetIndex(ECbmDataType::kGlobalTrack, itrk) : itrk;
980 auto track = dynamic_cast<const CbmGlobalTrack*>((*fGTracks)[trkIdx]);
981
982 // FILTER on TRACK HIT COMPOSITION/TOPOLOGY
983 if (!FilterTrack(track)) continue;
984 if (nTrkVx >= 2) {
985 if (vx->FindTrackByIndex(trkIdx)) {
986 if (track->GetStsTrackIndex() >= 0) ntrkDet[0]++;
987 if (track->GetTrdTrackIndex() >= 0) ntrkDet[1]++;
988 if (track->GetTofTrackIndex() >= 0) ntrkDet[2]++;
989 }
990 }
991
992 // CREATE THE TRAJECTORY FOR THE TRACK.
993 // When some projection views are required, create trajectory nodes for all material layers.
994 // otherwise, materials outside of the track hit area will be ignored.
995 Trajectory trkKf;
996 if (!fFitter.CreateFromGlobalTrack(trkKf, *track, (viewPrj ? true : false))) {
997 LOG(fatal) << GetName() << "::Exec: can not create the track for the fit!";
998 break;
999 }
1000
1001 // ADD REFERENCE TRAJECTORY NODES W/O MEASUREMENTS
1002 // for the track projections
1003 int nprj(0);
1004 if (viewPrj) {
1005 std::vector<Trajectory::Node> nodesPrj;
1006 for (auto plane : fPrjPlanes) {
1007 Trajectory::Node n;
1008 n.z = plane.Z();
1009 Trajectory::SetPlaneId(n, nprj++);
1010 nodesPrj.push_back(n);
1011 }
1012 trkKf.AddNodes(nodesPrj);
1013 }
1014
1015 // SWITCH OFF DETECTORS
1016 // which are skipped for tracking by user
1017 for (unsigned int i = 0; i < trkKf.GetNofNodes(); ++i) {
1018 const auto& n = trkKf.GetNode(i);
1019 // special case TRD2D. remap det id to TRD
1020 auto nodeSystemId =
1022 if (fDetQa.find(nodeSystemId) == fDetQa.end()) continue;
1023 switch (nodeSystemId) {
1024 case ECbmModuleId::kSts:
1026 trkKf.DisableMeasurementAtNode(i);
1027 }
1028 break;
1029 case ECbmModuleId::kTrd:
1031 trkKf.DisableMeasurementAtNode(i);
1032 }
1033 break;
1034 case ECbmModuleId::kTof:
1036 trkKf.DisableMeasurementAtNode(i);
1037 }
1038 break;
1039 default: break;
1040 }
1041 }
1042
1043 // FIT THE TRAJECTORY
1044 // first time
1045 if (!fFitter.FitTrajectory(trkKf)) {
1046 continue;
1047 }
1048 // second time using the previous results for the accurate linearization of equations
1049 if (!fFitter.FitTrajectory(trkKf)) {
1050 continue;
1051 }
1052
1053 // FILTER ON TRACK PROJECTION
1054 if (!FilterTrack(&trkKf)) continue;
1055 LOG(debug) << GetName() << "::Exec: Accept track for QA.";
1056
1057 // minimalistic QA tool for tracks used for target projection
1058 int nhit[(size_t) ECbmModuleId::kLastModule] = {0};
1059 for (int iNode = 0; iNode < (int) trkKf.GetNofNodes(); iNode++) {
1060 auto& n = trkKf.GetNode(iNode);
1061 int planeId = Trajectory::GetPlaneId(n);
1062
1063 if (viewPrj && planeId >= 0 && n.isFitted) { // this is a projection node
1064 TVector3 xyz(n.paramUp.X(), n.paramUp.Y(), planeId); // to communicate to the Load function
1065 viewPrj->Load(&xyz);
1066 continue;
1067 }
1068 // special case TRD2D. remap det id to TRD
1069 auto nodeSystemId =
1071 int hitIndex = Trajectory::GetHitIndex(n);
1072 // check if hit is well defined and detector is registered
1073 if (nodeSystemId == ECbmModuleId::kNotExist || fDetQa.find(nodeSystemId) == fDetQa.end()) continue;
1074 auto& det = fDetQa[nodeSystemId];
1075 // det.Print();
1076 auto view = det.FindView(n.measurementXY.X(), n.measurementXY.Y(), n.z);
1077 if (!view) {
1078 LOG(warning) << GetName() << "::Exec: " << cbm::util::ToString(det.id)
1079 << " view not defined for hit @ x=" << n.measurementXY.X() << " y=" << n.measurementXY.Y()
1080 << " z=" << n.z << ". Skipping.";
1081 LOG(debug1) << "This is symptomatic for using different alignment matrices during RECO and QA phases.";
1082 continue;
1083 }
1084 auto hit = dynamic_cast<CbmHit*>(fHits[nodeSystemId]->At(hitIndex));
1085 if (!hit) {
1086 LOG(error) << GetName() << "::Exec: " << cbm::util::ToString(det.id) << " hit @ id=" << hitIndex
1087 << " missing. Skipping.";
1088 LOG(debug1) << "The hit index present in the track but missing in the hit array.";
1089 continue;
1090 }
1091 // match to MC
1092 auto mcpoint = matchMC(hit, hitIndex, nodeSystemId);
1093 // refit the trajectory without this hit to get unbiased residual.
1094 // use a temporary copy of the trajectory to keep the best linearization in trkKf
1095 auto trkTmp = trkKf;
1096 const auto& nTmp = trkTmp.GetNode(iNode);
1097 trkTmp.DisableMeasurementAtNode(iNode); // don't use the hit measurement in the fit
1098 if (!fFitter.FitTrajectory(trkTmp) || !nTmp.isFitted) continue;
1099 // nTmp contains now the trajectory at the hit Z position, but fitted without the hit
1100 if (view->HasDebug())
1101 view->Load(&nTmp, mcpoint, GetDebugInfo<ECbmModuleId::kTrd>(hit));
1102 else
1103 view->Load(&nTmp, mcpoint);
1104 nhit[(int) nodeSystemId]++;
1105 }
1106
1107 itrack++;
1108 }
1109 };
1110
1111 if (fEvents) {
1112 for (auto evObj : *fEvents) {
1113 auto ev = dynamic_cast<CbmEvent*>(evObj);
1114 if (!FilterEvent(ev)) continue;
1115 processHits(ev);
1116 if (fGTracks) processTracks(ev);
1117 iev++;
1118 }
1119 LOG(info) << GetName() << "::Exec : Evs(%)["
1120 << (fEvents->GetEntriesFast() ? 1.e2 * iev / fEvents->GetEntriesFast() : 0) << "] Trks(%)["
1121 << (fGTracks && fGTracks->GetEntriesFast() ? 1.e2 * itrack / fGTracks->GetEntriesFast() : 0) << "]";
1122 return; // END EbyE QA
1123 }
1124 else {
1125 processHits(nullptr);
1126
1127 if (!fGTracks) {
1128 LOG(info) << GetName() << "::Exec : TS local reco only.";
1129 return; // END TS QA (no tracking)
1130 }
1131
1132 processTracks(nullptr);
1133 }
1134 LOG(info) << GetName() << "::Exec : Trks(%)["
1135 << (fGTracks && fGTracks->GetEntriesFast() ? 1.e2 * itrack / fGTracks->GetEntriesFast() : 0) << "]";
1136 return;
1137}
1138
1139//_____________________________________________________________________
1141{
1142 int n(0);
1143 for (auto v : fViews) {
1144 if (v.second.fType != type) continue;
1145 n++;
1146 }
1147 return n;
1148}
1149
1150
1151//_____________________________________________________________________
1153{
1154 FairSink* sink = FairRootManager::Instance()->GetSink();
1155 sink->WriteObject(&fOutFolder, nullptr);
1156}
1157
1158//_____________________________________________________________________
1160{
1161 // sanity checks
1162 if (ptr->GetStartTime() < 0) return false; // this is found in MC
1163
1164 for (auto evCut : fFilterEv) {
1165 if (!evCut.Accept(ptr, this)) return false;
1166 }
1167 return true;
1168}
1169
1170//_____________________________________________________________________
1172{
1173 bool ret(true);
1174 stringstream ss;
1175 for (auto tf : fFilterTrk) {
1176 if (tf.fDet != d) continue;
1177 auto filter = tf.GetHitsFilter();
1178 if (!filter) continue;
1179 const CbmCluster *cl0(nullptr), *cl1(nullptr);
1180 switch (d) {
1181 case ECbmModuleId::kSts:
1182 cl0 = (CbmCluster*) GetData<CbmCluster>(d, ((CbmStsHit*) hit)->GetFrontClusterId());
1183 cl1 = (CbmCluster*) GetData<CbmCluster>(d, ((CbmStsHit*) hit)->GetBackClusterId());
1184 ret = filter->Accept<ECbmModuleId::kSts>(hit, cl0, cl1);
1185 break;
1186 case ECbmModuleId::kTrd:
1187 cl0 = (CbmCluster*) GetData<CbmCluster>(d, hit->GetRefId());
1188 ret = filter->Accept<ECbmModuleId::kTrd>(hit, cl0);
1189 break;
1190 case ECbmModuleId::kTof: ret = filter->Accept<ECbmModuleId::kTof>(hit); break;
1191 default: break;
1192 }
1193 ss << cbm::util::ToString(d) << " topology hit :\n"
1194 << hit->ToString() << (d == ECbmModuleId::kSts ? "\n\t" : "\t") << (cl0 ? cl0->ToString() : "") << "\t"
1195 << (cl1 ? cl1->ToString() : "");
1196 if (!ret) break;
1197 }
1198 if (!ret) {
1199 LOG(debug) << "FilterHit::Reject " << cbm::util::ToString(d) << " hit.";
1200 LOG(debug1) << ss.str();
1201 }
1202 // else LOG(info) << "FilterHit::Accept " << cbm::util::ToString(d) << " hit.";
1203 return ret;
1204}
1205
1206//_____________________________________________________________________
1208{
1209 for (auto trkCut : fFilterTrk) {
1210 // special cut for selection on track projection. See FilterTrack(const cbm::algo::kf::Trajectory<>*)
1211 if (trkCut.fDet == ECbmModuleId::kRef) continue;
1212 if (!trkCut.Accept(ptr, this)) return false;
1213 }
1214 LOG(debug) << GetName() << "::FilterTrack : Accept hit cuts Sts[" << ptr->GetStsTrackIndex() << "] Trd["
1215 << ptr->GetTrdTrackIndex() << "] Tof[" << ptr->GetTofTrackIndex() << "].";
1216 return true;
1217}
1218
1219//_____________________________________________________________________
1221{
1222 bool ret = true;
1223 // check projections
1224 for (auto& n : ptr->GetNodes()) {
1225 if (Trajectory::GetPlaneId(n) < 0) continue;
1226 for (auto trkCut : fFilterTrk) {
1227 if (trkCut.fDet != ECbmModuleId::kRef) continue;
1228 for (auto rcut : trkCut.GetProjCuts()) {
1229 if (abs(rcut[0] - n.z) >= 1.e-3) continue;
1230 double r = sqrt((n.paramUp.X() - rcut[1]) * (n.paramUp.X() - rcut[1])
1231 + (n.paramUp.Y() - rcut[2]) * (n.paramUp.Y() - rcut[2]));
1232 if (r > rcut[3]) ret = false;
1233 if (!ret) {
1234 LOG(debug1) << GetName() << "::FilterTrack : Reject projection @ z[" << rcut[0] << "] r=" << r
1235 << " R=" << rcut[3];
1236 break;
1237 }
1238 }
1239 }
1240 }
1241 if (ret) LOG(debug) << GetName() << "::FilterTrack : Accept projection cuts.";
1242 return ret;
1243}
1244
1245//_____________________________________________________________________
1246TString CbmRecoQaTask::GetGeoTagForDetector(const TString& detector)
1247{
1248 gGeoManager->CdTop();
1249 TGeoNode* cave = gGeoManager->GetCurrentNode();
1250 if (!cave) {
1251 LOG(error) << "Error: Could not get the top node in the geometry manager." << std::endl;
1252 return "";
1253 }
1254
1255 for (Int_t iNode = 0; iNode < cave->GetNdaughters(); iNode++) {
1256 TString name = cave->GetDaughter(iNode)->GetVolume()->GetName();
1257 if (name.Contains(detector, TString::kIgnoreCase)) {
1258 return name.Contains("mcbm", TString::kIgnoreCase) ? TString(name(5, name.Length()))
1259 : TString(name(5, name.Length() - 5));
1260 }
1261 }
1262 return "";
1263}
1264
1265//_____________________________________________________________________
1266std::vector<TString> CbmRecoQaTask::GetPath(TGeoNode* node, TString detector, TString activeNodeName, int depth,
1267 const TString& path)
1268{
1269 std::vector<TString> nodePaths;
1270
1271 if (!node) {
1272 return nodePaths;
1273 }
1274
1275 TString nodePath = path;
1276 if (!nodePath.IsNull()) {
1277 nodePath += "/";
1278 }
1279 nodePath += node->GetName();
1280
1281 if (TString(node->GetName()).Contains(activeNodeName)) {
1282 if (nodePath.Contains(detector)) nodePaths.push_back(nodePath);
1283 }
1284
1285 // Recursively traverse the daughters
1286 Int_t numDaughters = node->GetNdaughters();
1287 for (Int_t i = 0; i < numDaughters; ++i) {
1288 TGeoNode* daughterNode = node->GetDaughter(i);
1289
1290 std::vector<TString> result = GetPath(daughterNode, detector, activeNodeName, depth + 1, nodePath);
1291 nodePaths.insert(nodePaths.end(), result.begin(), result.end());
1292 }
1293
1294 return nodePaths;
1295}
1296//_____________________________________________________________________
1298{
1299 CbmSetup* setup = CbmSetup::Instance();
1300 if (!setup) {
1301 LOG(fatal) << GetName() << "::InitMcbm22() : Missing setup definition.";
1302 return;
1303 }
1304 // fixed momentum no magentic field for mCBM
1305 fFitter.SetDefaultMomentumForMs(0.5);
1306 fFitter.SetEnforceDefaultMomentumForMs();
1307
1308 View* v = nullptr;
1309
1310 std::vector<TString> path;
1311 TGeoNode* topNode = gGeoManager->GetTopNode();
1312 if (!topNode) {
1313 LOG(error) << "Error: Top node not found.";
1314 return;
1315 }
1316
1317 auto processDetector = [&](const std::string& detector, const std::string& component) {
1318 TString geoTag = GetGeoTagForDetector(detector);
1319
1320 if (geoTag.Length() > 0) {
1321 LOG(info) << detector << ": geometry tag is " << geoTag;
1322 }
1323 else {
1324 LOG(warn) << "Warning: No geometry tag found for detector " << detector;
1325 }
1326
1327 path = GetPath(topNode, detector, component, 0);
1328 };
1329
1330 if (setup->IsActive(ECbmModuleId::kSts)) {
1331
1332 processDetector("sts", "Sensor");
1333
1334 std::regex pattern("/Station(\\d+)_(\\d+)/Ladder(\\d+)_(\\d+)/HalfLadder\\d+d_(\\d+)/"
1335 "HalfLadder\\d+d_Module(\\d+)_(\\d+)/Sensor(\\d+)_(\\d+)");
1336
1338 for (const auto& str : path) {
1339 std::string Str(str.Data());
1340 std::smatch match;
1341 if (std::regex_search(Str, match, pattern)) {
1342 int station = std::stoi(match[2]);
1343 int ladder = std::stoi(match[4]);
1344 int module = std::stoi(match[7]);
1345
1346 const char* fType = Form("U%dL%dM%d", station - 1, ladder - 1, module - 1);
1347
1348 v = sts->AddView(fType, str.Data(), {station - 1, ladder - 1, module - 1});
1349 v->SetProjection(eProjectionType::kXdX, (station == 1) ? 1 : 0.75, "mm");
1350 v->SetProjection(eProjectionType::kYdY, (station == 1) ? 4 : 3, "mm");
1351 if (fuRecoConfig[kUseMC]) {
1352 v->SetProjection(eProjectionType::kXdXMC, 1, "mm");
1353 v->SetProjection(eProjectionType::kYdYMC, 3, "mm");
1354 v->SetProjection(eProjectionType::kResidualX, 200, "um");
1355 v->SetProjection(eProjectionType::kResidualY, 500, "um");
1356 }
1357 }
1358 else {
1359 std::cout << "No match found in string: " << str << std::endl;
1360 }
1361 }
1362 }
1363
1364 if (setup->IsActive(ECbmModuleId::kTrd)) {
1365 processDetector("trd", "module");
1366
1367 // Trd2d
1369 for (const auto& str : path) {
1370 if (!str.Contains("module9")) continue;
1371 v = trd->AddView("2D", str.Data(), {5});
1372 v->SetProjection(eProjectionType::kChdT, 400, "ns");
1373 v->SetProjection(eProjectionType::kXdX, 10, "mm");
1374 v->SetProjection(eProjectionType::kYdY, 20, "mm");
1375 if (fuRecoConfig[kUseMC]) {
1376 v->SetProjection(eProjectionType::kXdXMC, 10, "mm");
1377 v->SetProjection(eProjectionType::kYdYMC, 20, "mm");
1378 v->SetProjection(eProjectionType::kResidualX, 1.5, "mm");
1379 v->SetProjection(eProjectionType::kResidualY, 5.0, "mm");
1380 }
1381 }
1382 // Trd1DxDy
1383 for (const auto& str : path) {
1384 LOG(info) << str;
1385 if (str.Contains("layer02")) {
1386 v = trd->AddView("1Dx", str.Data(), {21});
1387 v->SetProjection(eProjectionType::kChdT, 400, "ns");
1388 v->SetProjection(eProjectionType::kXdX, 1.5, "cm");
1389 if (fuRecoConfig[kUseMC]) {
1390 v->SetProjection(eProjectionType::kXdXMC, 1.5, "cm");
1391 v->SetProjection(eProjectionType::kResidualX, 1.5, "mm");
1392 }
1393 }
1394 if (str.Contains("layer03")) {
1395 v = trd->AddView("1Dy", str.Data(), {37});
1396 v->SetProjection(eProjectionType::kChdT, 400, "ns");
1397 v->SetProjection(eProjectionType::kYdY, 1.5, "cm");
1398 if (fuRecoConfig[kUseMC]) {
1399 v->SetProjection(eProjectionType::kYdYMC, 1.5, "cm");
1400 v->SetProjection(eProjectionType::kResidualY, 1.5, "mm");
1401 }
1402 }
1403 }
1404 }
1405
1406
1407 if (setup->IsActive(ECbmModuleId::kTof)) {
1408 processDetector("tof", "counter");
1409
1411 tof->hit.name = "TofHit";
1412 std::regex pattern("module_(\\d+)_(\\d+)/gas_box_(\\d+)/counter_(\\d+)");
1413
1414 for (const auto& str : path) {
1415 std::string Str(str.Data());
1416 std::smatch match;
1417 if (std::regex_search(Str, match, pattern)) {
1418 int type = std::stoi(match[1]);
1419 int smid = std::stoi(match[2]);
1420 int rpc = std::stoi(match[4]);
1421 const char* name = Form("Sm%d_%dRpc%d", type, smid, rpc);
1422 if (type == 0) {
1423 v = tof->AddView(name, str.Data(), {smid, type, rpc});
1424 v->SetProjection(eProjectionType::kChdT, 15, "ns");
1425 }
1426 else {
1427 v = tof->AddView(name, str.Data(), {smid, type, rpc});
1428 }
1429 }
1430 else {
1431 std::cout << "No match found in string: " << str << std::endl;
1432 }
1433 }
1434 }
1435 // ===============================================================================
1436 // TRG - upstream projections
1437 float angle = 25., L[] = {14.3, 0, -20, -38 /*-1*/, -50.5 /*-4.1*/};
1438 //R[]= {2.5, 3, 0.5, 0.6, 0.6}, dx[5], dz[5];
1439 for (int i(0); i < 5; i++) {
1440 fPrjPlanes.emplace_back(L[i] * TMath::Sin(angle * TMath::DegToRad()), 0.,
1441 L[i] * TMath::Cos(angle * TMath::DegToRad()));
1442 }
1443 // (cm); T_{trk} - T_{ev} (ns)", prj.first),
1444}
1445
1446//_____________________________________________________________________
1448{
1449 CbmSetup* setup = CbmSetup::Instance();
1450 if (!setup) {
1451 LOG(fatal) << GetName() << "::InitMcbm24() : Missing setup definition.";
1452 return;
1453 }
1454 // fixed momentum no magentic field for mCBM
1455 fFitter.SetDefaultMomentumForMs(1.5);
1456 fFitter.SetEnforceDefaultMomentumForMs();
1457
1458 TString dtag;
1459 View* v(nullptr);
1460 if (setup->IsActive(ECbmModuleId::kSts)) {
1461 // setup->GetGeoTag(ECbmModuleId::kSts, dtag);
1462 // LOG(debug) << GetName() << "::InitMcbm24() : found " << dtag;
1463 dtag = "v24c_mcbm";
1465 std::map<const char*, std::pair<const char*, std::vector<int>>> sensors = {
1466 {"U0L0M0", {"Station01_1/Ladder13_1/HalfLadder13u_1/HalfLadder13u_Module03_1/Sensor03_1", {0, 0, 0}}},
1467 {"U1L0M0", {"Station02_2/Ladder09_1/HalfLadder09d_2/HalfLadder09d_Module03_1/Sensor03_1", {1, 0, 0}}},
1468 {"U1L0M1", {"Station02_2/Ladder09_1/HalfLadder09d_2/HalfLadder09d_Module03_2/Sensor03_1", {1, 0, 1}}},
1469 {"U1L1M0", {"Station02_2/Ladder09_2/HalfLadder09d_2/HalfLadder09d_Module03_1/Sensor03_1", {1, 1, 0}}},
1470 {"U1L1M1", {"Station02_2/Ladder09_2/HalfLadder09d_2/HalfLadder09d_Module03_2/Sensor03_1", {1, 1, 1}}},
1471 {"U2L0M0", {"Station03_3/Ladder10_1/HalfLadder10d_2/HalfLadder10d_Module03_1/Sensor03_1", {2, 0, 0}}},
1472 {"U2L0M1", {"Station03_3/Ladder10_1/HalfLadder10d_2/HalfLadder10d_Module04_2/Sensor04_1", {2, 0, 1}}},
1473 {"U2L1M0", {"Station03_3/Ladder12_2/HalfLadder12d_2/HalfLadder12d_Module03_1/Sensor03_1", {2, 1, 0}}},
1474 {"U2L1M1", {"Station03_3/Ladder12_2/HalfLadder12d_2/HalfLadder12d_Module04_2/Sensor04_1", {2, 1, 1}}},
1475 {"U2L2M0", {"Station03_3/Ladder11_3/HalfLadder11d_2/HalfLadder11d_Module03_1/Sensor03_1", {2, 2, 0}}},
1476 {"U2L2M1", {"Station03_3/Ladder11_3/HalfLadder11d_2/HalfLadder11d_Module03_2/Sensor03_1", {2, 2, 1}}},
1477 {"U2L2M2", {"Station03_3/Ladder11_3/HalfLadder11d_2/HalfLadder11d_Module03_3/Sensor03_1", {2, 2, 2}}}};
1478 for (auto& [name, def] : sensors) {
1479 v = sts->AddView(name, Form("/cave_1/sts_%s_0/%s", dtag.Data(), def.first), def.second);
1480 v->SetProjection(eProjectionType::kXdX, 1000, "um");
1481 v->SetProjection(eProjectionType::kYdY, 1500, "um");
1482 v->SetProjection(eProjectionType::kXdXT, 500, "um");
1483 v->SetProjection(eProjectionType::kYdYT, 500, "um");
1484 }
1485 }
1486 if (setup->IsActive(ECbmModuleId::kTrd)) {
1487 // setup->GetGeoTag(ECbmModuleId::kTrd, dtag);
1488 // LOG(debug) << GetName() << "::InitMcbm24() : found " << dtag;
1489 dtag = "v24e_mcbm";
1491 // Trd2D
1492 v = trd->AddView("2D", Form("/cave_1/trd_%s_0/layer01_20101/module9_101001001/gas_0", dtag.Data()), {0, 0});
1493 v->SetProjection(eProjectionType::kChdT, 300, "ns");
1494 // Trd1Dx
1495 v = trd->AddView("1Dx", Form("/cave_1/trd_%s_0/layer02_10202/module5_101002001", dtag.Data()), {1, 0});
1496 v->SetProjection(eProjectionType::kChdT, 300, "ns");
1497 v->SetProjection(eProjectionType::kXdX, 1.5, "cm");
1498 v->SetProjection(eProjectionType::kYdY, 3.0, "cm");
1499 // Trd1Dy
1500 v = trd->AddView("1Dy", Form("/cave_1/trd_%s_0/layer03_11303/module5_101103001", dtag.Data()), {2, 0});
1501 v->SetProjection(eProjectionType::kChdT, 300, "ns");
1502 v->SetProjection(eProjectionType::kXdX, 1.5, "cm");
1503 v->SetProjection(eProjectionType::kYdY, 3.0, "cm");
1504 }
1505 if (setup->IsActive(ECbmModuleId::kTof)) {
1506 // setup->GetGeoTag(ECbmModuleId::kTof, dtag);
1507 // LOG(debug) << GetName() << "::InitMcbm24() : found " << dtag;
1508 dtag = "v24d_mcbm";
1510 vector<int> tofSelect(3);
1511 // add type 0
1512 for (int ism(0); ism < 6; ism++) {
1513 tofSelect[0] = ism;
1514 for (int irpc(0); irpc < 5; irpc++) {
1515 tofSelect[2] = irpc;
1516 v = tof->AddView(Form("Sm%dRpc%d", ism, irpc),
1517 Form("/cave_1/tof_%s_0/tof_%sStand_1/module_%d_%d/"
1518 "gas_box_0/counter_%d",
1519 dtag.Data(), dtag.Data(), tofSelect[1], tofSelect[0], tofSelect[2]),
1520 tofSelect);
1521 v->SetProjection(eProjectionType::kXdX, 3, "cm");
1522 v->SetProjection(eProjectionType::kYdY, 1, "cm");
1523 }
1524 }
1525 // add type 6 (Buch)
1526 tofSelect[0] = 0;
1527 tofSelect[1] = 6;
1528 for (int irpc(0); irpc < 2; irpc++) {
1529 tofSelect[2] = irpc;
1530 tof->AddView(Form("BuchRpc%d", irpc),
1531 Form("/cave_1/tof_%s_0/tof_%sStand_1/module_%d_%d/gas_box_0/"
1532 "counter_%d",
1533 dtag.Data(), dtag.Data(), tofSelect[1], tofSelect[0], tofSelect[2]),
1534 tofSelect);
1535 }
1536 // add type 9
1537 tofSelect[1] = 9;
1538 for (int ism(0); ism < 2; ism++) {
1539 tofSelect[0] = ism;
1540 for (int irpc(0); irpc < 2; irpc++) {
1541 tofSelect[2] = irpc;
1542 tof->AddView(Form("Test%dRpc%d", ism, irpc),
1543 Form("/cave_1/tof_%s_0/tof_%sStand_1/module_%d_%d/"
1544 "gas_box_0/counter_%d",
1545 dtag.Data(), dtag.Data(), tofSelect[1], tofSelect[0], tofSelect[2]),
1546 tofSelect);
1547 }
1548 }
1549 // add type 2
1550 tofSelect[1] = 2;
1551 for (int ism(0); ism < 2; ism++) {
1552 tofSelect[0] = ism;
1553 for (int irpc(0); irpc < 5; irpc++) {
1554 tofSelect[2] = irpc;
1555 tof->AddView(Form("Sm2%dRpc%d", ism, irpc),
1556 Form("/cave_1/tof_%s_0/tof_%sStand_1/module_%d_%d/"
1557 "gas_box_0/counter_%d",
1558 dtag.Data(), dtag.Data(), tofSelect[1], tofSelect[0], tofSelect[2]),
1559 tofSelect);
1560 }
1561 }
1562 }
1563 if (setup->IsActive(ECbmModuleId::kRich)) {
1564 // setup->GetGeoTag(ECbmModuleId::kRich, dtag);
1565 // LOG(debug) << GetName() << "::InitMcbm24() : found " << dtag;
1566 dtag = "v24a_mcbm";
1568 // Aerogel 1
1569 rich->AddView("Aerogel", Form("/cave_1/rich_%s_0/box_1/Gas_1", dtag.Data()), {4});
1570 }
1571 // ===============================================================================
1572 // TRG - upstream projections
1573 float angle = 25., L[] = {14.3, 0, -20, -38, -50.5};
1574 //R[]= {2.5, 3, 0.5, 0.6, 0.6}, dx[5], dz[5];
1575 for (int i(0); i < 5; i++) {
1576 fPrjPlanes.emplace_back(L[i] * TMath::Sin(angle * TMath::DegToRad()), 0.,
1577 L[i] * TMath::Cos(angle * TMath::DegToRad()));
1578 }
1579}
1580
1581//_____________________________________________________________________
1583{
1584 CbmSetup* setup = CbmSetup::Instance();
1585 if (!setup) {
1586 LOG(fatal) << GetName() << "::InitMcbm25() : Missing setup definition.";
1587 return;
1588 }
1589 // fixed momentum no magentic field for mCBM
1590 fFitter.SetDefaultMomentumForMs(1.5);
1591 fFitter.SetEnforceDefaultMomentumForMs();
1592
1593 TString dtag;
1594 View* v(nullptr);
1595 if (setup->IsActive(ECbmModuleId::kSts)) {
1596 // setup->GetGeoTag(ECbmModuleId::kSts, dtag);
1597 // LOG(debug) << GetName() << "::InitMcbm24() : found " << dtag;
1598 dtag = "v24c_mcbm";
1600 std::map<const char*, std::pair<const char*, std::vector<int>>> sensors = {
1601 {"U0L0M0", {"Station01_1/Ladder13_1/HalfLadder13u_1/HalfLadder13u_Module03_1/Sensor03_1", {0, 0, 0}}},
1602 {"U1L0M0", {"Station02_2/Ladder09_1/HalfLadder09d_2/HalfLadder09d_Module03_1/Sensor03_1", {1, 0, 0}}},
1603 {"U1L0M1", {"Station02_2/Ladder09_1/HalfLadder09d_2/HalfLadder09d_Module03_2/Sensor03_1", {1, 0, 1}}},
1604 {"U1L1M0", {"Station02_2/Ladder09_2/HalfLadder09d_2/HalfLadder09d_Module03_1/Sensor03_1", {1, 1, 0}}},
1605 {"U1L1M1", {"Station02_2/Ladder09_2/HalfLadder09d_2/HalfLadder09d_Module03_2/Sensor03_1", {1, 1, 1}}},
1606 {"U2L0M0", {"Station03_3/Ladder10_1/HalfLadder10d_2/HalfLadder10d_Module03_1/Sensor03_1", {2, 0, 0}}},
1607 {"U2L0M1", {"Station03_3/Ladder10_1/HalfLadder10d_2/HalfLadder10d_Module04_2/Sensor04_1", {2, 0, 1}}},
1608 {"U2L1M0", {"Station03_3/Ladder12_2/HalfLadder12d_2/HalfLadder12d_Module03_1/Sensor03_1", {2, 1, 0}}},
1609 {"U2L1M1", {"Station03_3/Ladder12_2/HalfLadder12d_2/HalfLadder12d_Module04_2/Sensor04_1", {2, 1, 1}}},
1610 {"U2L2M0", {"Station03_3/Ladder11_3/HalfLadder11d_2/HalfLadder11d_Module03_1/Sensor03_1", {2, 2, 0}}},
1611 {"U2L2M1", {"Station03_3/Ladder11_3/HalfLadder11d_2/HalfLadder11d_Module03_2/Sensor03_1", {2, 2, 1}}},
1612 {"U2L2M2", {"Station03_3/Ladder11_3/HalfLadder11d_2/HalfLadder11d_Module03_3/Sensor03_1", {2, 2, 2}}}};
1613 for (auto& [name, def] : sensors) {
1614 v = sts->AddView(name, Form("/cave_1/sts_%s_0/%s", dtag.Data(), def.first), def.second);
1615 v->SetProjection(eProjectionType::kXdX, 1000, "um");
1616 if (fuRecoConfig[kUseMC]) v->SetProjection(eProjectionType::kXdXMC, 1000, "um");
1617 v->SetProjection(eProjectionType::kYdY, 1500, "um");
1618 if (fuRecoConfig[kUseMC]) v->SetProjection(eProjectionType::kYdYMC, 1500, "um");
1619 v->SetProjection(eProjectionType::kXdXT, 500, "um");
1620 v->SetProjection(eProjectionType::kYdYT, 500, "um");
1621 if (fuRecoConfig[kUseMC]) {
1622 v->SetProjection(eProjectionType::kXdXMC, 1000, "um");
1623 v->SetProjection(eProjectionType::kYdYMC, 1500, "um");
1624 v->SetProjection(eProjectionType::kResidualX, 200, "um");
1625 v->SetProjection(eProjectionType::kResidualY, 500, "um");
1626 }
1627 }
1628 }
1629 if (setup->IsActive(ECbmModuleId::kTrd)) {
1630 // setup->GetGeoTag(ECbmModuleId::kTrd, dtag);
1631 // LOG(debug) << GetName() << "::InitMcbm24() : found " << dtag;
1632 dtag = "v24e_mcbm";
1634 std::map<const char*, std::pair<const char*, std::vector<int>>> modules = {
1635 {"2D", {"layer01_20101/module9_101001001/gas_0", {0, 0}}},
1636 {"1Dx", {"layer02_10202/module5_101002001", {1, 0}}},
1637 {"1Dy", {"layer03_11303/module5_101103001", {2, 0}}},
1638 };
1639 for (auto& [name, def] : modules) {
1640 bool debug = true;
1641 if (strcmp("2D", name) == 0) {
1642 v = trd->AddView(name, Form("/cave_1/trd_%s_0/%s", dtag.Data(), def.first), def.second, debug);
1643 v->SetProjection(eProjectionType::kXdX, 2500, "um");
1644 v->SetProjection(eProjectionType::kYdY, 15, "mm");
1645 if (debug) {
1646 v->SetProjection(eProjectionType::kDebug0, 2500, "um");
1647 v->SetProjection(eProjectionType::kDebug1, 15, "mm");
1648 }
1649 if (fuRecoConfig[kUseMC]) {
1650 v->SetProjection(eProjectionType::kXdXMC, 2500, "um");
1651 v->SetProjection(eProjectionType::kYdYMC, 3000, "um");
1652 v->SetProjection(eProjectionType::kResidualX, 1000, "um");
1653 v->SetProjection(eProjectionType::kResidualY, 15, "mm");
1654 }
1655 }
1656 else if (strcmp("1Dx", name) == 0) {
1657 v = trd->AddView(name, Form("/cave_1/trd_%s_0/%s", dtag.Data(), def.first), def.second);
1658 v->SetProjection(eProjectionType::kYdY, 5, "cm");
1659 v->SetProjection(eProjectionType::kXdX, 15, "mm");
1660 if (fuRecoConfig[kUseMC]) {
1661 v->SetProjection(eProjectionType::kXdXMC, 5, "mm");
1662 v->SetProjection(eProjectionType::kYdYMC, 15, "mm");
1663 v->SetProjection(eProjectionType::kResidualX, 3000, "um");
1664 v->SetProjection(eProjectionType::kResidualY, 15, "mm");
1665 }
1666 }
1667 else if (strcmp("1Dy", name) == 0) {
1668 v = trd->AddView(name, Form("/cave_1/trd_%s_0/%s", dtag.Data(), def.first), def.second);
1669 v->SetProjection(eProjectionType::kYdY, 10, "mm");
1670 v->SetProjection(eProjectionType::kXdX, 5, "cm");
1671 if (fuRecoConfig[kUseMC]) {
1672 v->SetProjection(eProjectionType::kXdXMC, 15, "mm");
1673 v->SetProjection(eProjectionType::kYdYMC, 5, "mm");
1674 v->SetProjection(eProjectionType::kResidualX, 15, "mm");
1675 v->SetProjection(eProjectionType::kResidualY, 3000, "um");
1676 }
1677 }
1678 v->SetProjection(eProjectionType::kChdT, 300, "ns");
1679 v->SetProjection(eProjectionType::kXdXT, 2.5, "mm");
1680 v->SetProjection(eProjectionType::kYdYT, 2.5, "mm");
1681 }
1682 }
1683 if (setup->IsActive(ECbmModuleId::kTof)) {
1684 // setup->GetGeoTag(ECbmModuleId::kTof, dtag);
1685 // LOG(debug) << GetName() << "::InitMcbm24() : found " << dtag;
1686 dtag = "v24f_mcbm";
1688 vector<int> tofSelect(3);
1689 // add type 0
1690 tofSelect[1] = 0;
1691 for (int ism(0); ism < 5; ism++) {
1692 tofSelect[0] = ism;
1693 for (int irpc(0); irpc < 5; irpc++) {
1694 tofSelect[2] = irpc;
1695 v = tof->AddView(Form("Sm%dRpc%d", ism, irpc),
1696 Form("/cave_1/tof_%s_0/tof_%sStand_1/module_%d_%d/"
1697 "gas_box_0/counter_%d",
1698 dtag.Data(), dtag.Data(), tofSelect[1], tofSelect[0], tofSelect[2]),
1699 tofSelect);
1700 v->SetProjection(eProjectionType::kXdX, 30, "mm");
1701 if (fuRecoConfig[kUseMC]) v->SetProjection(eProjectionType::kXdXMC, 30, "mm");
1702 v->SetProjection(eProjectionType::kYdY, 30, "mm");
1703 if (fuRecoConfig[kUseMC]) v->SetProjection(eProjectionType::kYdYMC, 30, "mm");
1704 }
1705 }
1706 }
1707
1708 // ===============================================================================
1709 // TRG - upstream projections
1710 float angle = 25., sina = TMath::Sin(angle * TMath::DegToRad()), cosa = TMath::Cos(angle * TMath::DegToRad());
1711 std::vector<float> L = {14.3, 0, -20, -38, -50.5};
1712 for (auto l : L)
1713 fPrjPlanes.emplace_back(l * sina, 0., l * cosa);
1714}
1715//_____________________________________________________________________
1717{
1718 LOG(info) << "Init Default ....";
1719 CbmSetup* setup = CbmSetup::Instance();
1720 if (!setup) {
1721 LOG(fatal) << GetName() << "::InitDefault() : Missing setup definition.";
1722 return;
1723 }
1724
1725 View* v = nullptr;
1726 std::vector<TString> path;
1727 TGeoNode* topNode = gGeoManager->GetTopNode();
1728 if (!topNode) {
1729 LOG(error) << "Error: Top node not found.";
1730 return;
1731 }
1732
1733 TString geoTag;
1734 auto processDetector = [&](const std::string& detector, const std::string& component) {
1735 geoTag = GetGeoTagForDetector(detector);
1736
1737 if (geoTag.Length() > 0) {
1738 LOG(info) << detector << ": geometry tag is " << geoTag;
1739 }
1740 else {
1741 LOG(warn) << "Warning: No geometry tag found for detector " << detector;
1742 }
1743 path = GetPath(topNode, detector, component, 0);
1744 };
1745
1746 if (setup->IsActive(ECbmModuleId::kSts)) {
1747 processDetector("sts", "Unit");
1748
1749 // std::regex pattern("Unit\\d{2}[LR]_\\d+");
1750 std::regex pattern(R"(Unit(\d{2}[LR])_(\d+))");
1751
1753
1754 for (const auto& str : path) {
1755 std::string Str(str.Data());
1756 std::smatch match;
1757
1758 if (std::regex_search(Str, match, pattern)) {
1759 int unitid = std::stoi(match[2].str());
1760 std::string unitname = (Str.find("Unit") != std::string::npos) ? Str.substr(Str.find("Unit")) : "";
1761
1762 v = sts->AddView(unitname.c_str(), str.Data(), {unitid - 1, -1, -1});
1763 v->SetSetup(eSetup::kDefault);
1764 }
1765 else {
1766 std::cout << "No match found in string: " << str << std::endl;
1767 }
1768 }
1769 }
1770
1771 if (setup->IsActive(ECbmModuleId::kTrd)) {
1772 processDetector("trd", "module");
1773 std::regex pattern("layer(\\d+)_(\\d+)/module(\\d+)_(\\d+)");
1775 char name[256];
1776 for (const auto& str : path) {
1777 std::string Str(str.Data());
1778 std::smatch match;
1779 if (std::regex_search(Str, match, pattern)) {
1780 int layer = std::stoi(match[1]);
1781 int layercopyNr = std::stoi(match[2]);
1782
1783 int module = std::stoi(match[3]);
1784 int modulecopyNr = std::stoi(match[4]);
1785
1786 int fLayer = ((layercopyNr / 100) % 10);
1787 int fModuleCopy = (modulecopyNr % 100);
1788
1789 sprintf(name, "layer%d_%d_module_%d_%d", layer, layercopyNr, module, modulecopyNr);
1790
1791 v = trd->AddView(name, str.Data(), {fLayer - 1, fModuleCopy - 1, -1});
1792 v->SetSetup(eSetup::kDefault);
1793 }
1794 else {
1795 std::cout << "No match found in string: " << str << std::endl;
1796 }
1797 }
1798 }
1799
1800 if (setup->IsActive(ECbmModuleId::kRich)) {
1801 processDetector("rich", "sens");
1803 for (const auto& str : path) {
1804 v = rich->AddView("rich", str.Data(), {-1, -1, -1});
1805 v->SetSetup(eSetup::kDefault);
1806 }
1807 }
1808
1809 if (setup->IsActive(ECbmModuleId::kTof)) {
1810 processDetector("tof", "module");
1811
1813 tof->hit.name = "TofHit";
1814 std::regex pattern("module_(\\d+)_(\\d+)");
1815 for (const auto& str : path) {
1816 std::string Str(str.Data());
1817 std::smatch match;
1818 if (std::regex_search(Str, match, pattern)) {
1819 int type = std::stoi(match[1]);
1820 int smid = std::stoi(match[2]);
1821
1822 std::string modulename = (Str.find("module") != std::string::npos) ? Str.substr(Str.find("module")) : "";
1823
1824 v = tof->AddView(modulename.c_str(), str.Data(), {smid, type, -1});
1825 v->SetSetup(eSetup::kDefault);
1826 }
1827 else {
1828 std::cout << "No match found in string: " << str << std::endl;
1829 }
1830 }
1831 }
1832}
1833
1834//========= DETECTOR ======================
1836{
1837 id = did;
1838 switch (id) {
1839 case ECbmModuleId::kMvd:
1840 new (&hit) Data(ECbmDataType::kMvdHit, "MvdHit");
1841 new (&point) Data(ECbmDataType::kMvdPoint, "MvdPoint");
1842 break;
1843 case ECbmModuleId::kSts:
1844 new (&cl) Data(ECbmDataType::kStsCluster, "StsCluster");
1845 new (&hit) Data(ECbmDataType::kStsHit, "StsHit");
1846 new (&point) Data(ECbmDataType::kStsPoint, "StsPoint");
1847 new (&trk) Data(ECbmDataType::kStsTrack, "StsTrack");
1848 break;
1850 new (&hit) Data(ECbmDataType::kMuchPixelHit, "MuchHit");
1851 new (&point) Data(ECbmDataType::kMuchPoint, "MuchPoint");
1852 break;
1854 new (&hit) Data(ECbmDataType::kRichHit, "RichHit");
1855 new (&point) Data(ECbmDataType::kRichPoint, "RichPoint");
1856 break;
1857 case ECbmModuleId::kTrd:
1859 new (&cl) Data(ECbmDataType::kTrdCluster, "TrdCluster");
1860 new (&hit) Data(ECbmDataType::kTrdHit, "TrdHit");
1861 new (&point) Data(ECbmDataType::kTrdPoint, "TrdPoint");
1862 new (&trk) Data(ECbmDataType::kTrdTrack, "TrdTrack");
1863 break;
1864 case ECbmModuleId::kTof:
1865 // new (&cl) Data(ECbmDataType::kTofCalDigi, "TofCalDigi");
1866 new (&hit) Data(ECbmDataType::kTofHit, "TofHit");
1867 new (&point) Data(ECbmDataType::kTofPoint, "TofPoint");
1868 new (&trk) Data(ECbmDataType::kTofTrack, "TofTrack");
1869 break;
1870 case ECbmModuleId::kFsd:
1871 new (&hit) Data(ECbmDataType::kFsdHit, "FsdHit");
1872 new (&point) Data(ECbmDataType::kFsdHit, "FsdPoint");
1873 break;
1874 case ECbmModuleId::kPsd:
1875 new (&hit) Data(ECbmDataType::kPsdHit, "PsdHit");
1876 new (&point) Data(ECbmDataType::kPsdPoint, "PsdPoint");
1877 break;
1878 default:
1879 LOG(warn) << "QA unsupported for Detector=" << did;
1881 break;
1882 }
1883}
1884
1885//+++++++++++++++++++++ Detector ++++++++++++++++++++++++++++++++
1886//_________________________________________________________________
1887CbmRecoQaTask::View* CbmRecoQaTask::Detector::AddView(const char* n, const char* p, std::vector<int> set, bool debug)
1888{
1889 View* v(nullptr);
1890 fViews.emplace_back(n, p, set);
1891 v = &fViews.back();
1903
1915
1916 if (debug) {
1919 }
1920 return v;
1921}
1922
1924{
1925 for (auto& view : fViews)
1926 if (view.name.compare(n) == 0) return &view;
1927
1928 return nullptr;
1929}
1930
1932{
1933 for (auto& v : fViews) {
1934 // printf("Looking for p[%f %f %f] in V[%s-%s] @ %f %f %f (%f %f %f)\n", x,
1935 // y, z, ToString(id).data(), v.name.data(), v.pos[0], v.pos[1], v.pos[2],
1936 // v.size[0], v.size[1], v.size[2]);
1937 if (abs(v.pos[0] - x) > 0.5 * v.size[0]) continue;
1938 if (abs(v.pos[1] - y) > 0.5 * v.size[1]) continue;
1939 if (abs(v.pos[2] - z) > 0.5 * v.size[2]) continue;
1940 return &v;
1941 }
1942
1943 return nullptr;
1944}
1945
1946bool CbmRecoQaTask::Detector::Init(TDirectoryFile* fOut, bool mc)
1947{
1948 /* Query the geometry and trigger detector views init
1949 */
1950 if (!gGeoManager) {
1951 LOG(fatal) << "CbmRecoQaTask::Detector::Init() " << id << " missing geometry.";
1952 return false;
1953 }
1954 LOG(info) << "CbmRecoQaTask::Detector::Init() : " << cbm::util::ToString(id) << " MC = " << mc;
1955
1956 TDirectoryFile* modDir = (TDirectoryFile*) fOut->mkdir(
1957 std::string(cbm::util::ToString(id)).c_str(), Form("Reco QA for %s", std::string(cbm::util::ToString(id)).c_str()));
1958 bool ret(true);
1959 for (auto& view : fViews) {
1960 bool vret = view.Init(std::string(cbm::util::ToString(id)).c_str(), mc);
1961 view.Register(modDir);
1962 ret = ret && vret;
1963 }
1964 return ret;
1965}
1966
1968{
1969 stringstream s;
1970 s << "D[" << id << "] views[" << fViews.size() << "]\n";
1971 for (auto v : fViews)
1972 s << v.ToString();
1973 cout << s.str();
1974}
1975
1976//+++++++++++++++++++++ View ++++++++++++++++++++++++++++++++
1977//_______________________________________________________________________
1978bool CbmRecoQaTask::View::AddProjection(eProjectionType prj, float range, const char* unit)
1979{
1980 if (fProjection.find(prj) != fProjection.end()) {
1981 LOG(warn) << "Projection " << ToString(prj) << " already registered";
1982 return false;
1983 }
1984 int scale(1);
1985 if (strcmp(unit, "mm") == 0)
1986 scale = 10;
1987 else if (strcmp(unit, "um") == 0)
1988 scale = 10000;
1989 else if (strcmp(unit, "ps") == 0)
1990 scale = 1000;
1991 else if (strcmp(unit, "eV") == 0)
1992 scale = 1000;
1993 else if (strcmp(unit, "cm") == 0)
1994 scale = 1;
1995 else if (strcmp(unit, "ns") == 0)
1996 scale = 1;
1997 else if (strcmp(unit, "keV") == 0)
1998 scale = 1;
1999 else if (strcmp(unit, "a.u.") == 0)
2000 scale = 1;
2001 else
2002 LOG(warn) << "Projection units " << unit << " not registered. Natural units will be used.";
2003
2004 fProjection[prj] = make_tuple(scale, range, nullptr);
2005 return true;
2006}
2007
2009{
2010 if (fProjection.find(eProjectionType::kDebug0) != fProjection.end()) return true;
2011 if (fProjection.find(eProjectionType::kDebug1) != fProjection.end()) return true;
2012
2013 return false;
2014}
2015
2016bool CbmRecoQaTask::View::SetProjection(eProjectionType prj, float range, const char* unit)
2017{
2018 if (fProjection.find(prj) == fProjection.end()) {
2019 LOG(warn) << "Projection " << ToString(prj)
2020 << " not initialized. Calling "
2021 "\"CbmRecoQaTask::View::AddProjection()\"";
2022 return AddProjection(prj, range, unit);
2023 }
2024 int scale(1);
2025 if (strcmp(unit, "mm") == 0)
2026 scale = 10;
2027 else if (strcmp(unit, "um") == 0)
2028 scale = 10000;
2029 else if (strcmp(unit, "ps") == 0)
2030 scale = 1000;
2031 else if (strcmp(unit, "eV") == 0)
2032 scale = 1000;
2033 else if (strcmp(unit, "cm") == 0)
2034 scale = 1;
2035 else if (strcmp(unit, "ns") == 0)
2036 scale = 1;
2037 else if (strcmp(unit, "keV") == 0)
2038 scale = 1;
2039 else if (strcmp(unit, "a.u.") == 0)
2040 scale = 1;
2041 else
2042 LOG(warn) << "Projection units " << unit << " not registered. Natural units will be used.";
2043
2044 get<0>(fProjection[prj]) = scale;
2045 get<1>(fProjection[prj]) = range;
2046 return true;
2047}
2048
2049bool CbmRecoQaTask::View::Init(const char* dname, bool mc)
2050{
2055 if (path.size() && fType == eViewType::kDetUnit) { // applies only for detection units
2056 if (!gGeoManager->cd(path.data())) return false;
2057 TGeoHMatrix* m = gGeoManager->GetCurrentMatrix();
2058 const double* tr(m->GetTranslation());
2059 TGeoVolume* v = gGeoManager->GetCurrentVolume();
2060 TGeoShape* bb = v->GetShape();
2061 double w_lo, w_hi;
2062 for (int i(0); i < 3; i++) { // loop over the spatial dimensions
2063 size[i] = bb->GetAxisRange(i + 1, w_lo, w_hi);
2064 pos[i] = 0.5 * (w_lo + w_hi) + tr[i];
2065 }
2066
2067 LOG(info) << "CbmRecoQaTask::Detector(" << dname << ")::View(" << name << ")::Init() : size [" << size[0] << " x "
2068 << size[1] << " x " << size[2] << "]. mc[" << mc << "].";
2069 }
2070 else
2071 LOG(info) << "CbmRecoQaTask::Detector(" << dname << ")::View(" << name << ")::Init() : mc[" << mc << "].";
2072
2073
2074 // TODO short-hand for XY display resolution
2075 int dscale = 10;
2076 if (strcmp(dname, "Tof") == 0 || strcmp(dname, "Rich") == 0) dscale = 1;
2077
2078 int nbinsx, nbinsy;
2079 string unit;
2080 for (auto& projection : fProjection) {
2081 int scale = get<0>(projection.second);
2082 float yrange = get<1>(projection.second);
2083 char xy_id = 0;
2084 char mc_id[2] = {' ', ' '};
2085 double xlo = pos[0] - 0.5 * size[0], xhi = pos[0] + 0.5 * size[0], ylo = pos[1] - 0.5 * size[1],
2086 yhi = pos[1] + 0.5 * size[1];
2087 switch (projection.first) {
2089 if (!mc) break;
2090 xy_id = 'M';
2091 mc_id[0] = 'M';
2092 mc_id[1] = 'C';
2093 // fall through
2095 if (!xy_id) xy_id = 't';
2096 nbinsx = 10 * ceil(size[0]); // mm binning
2097 if (strcmp(dname, "Trd") == 0 && name.compare("2D") == 0) nbinsx *= 10;
2098 unit = makeYrange(scale, yrange);
2099 nbinsy = 200; //* ceil(yrange);
2100 get<2>(projection.second) =
2101 new TH2D(Form("hxx%s_%s%s", (xy_id == 'M' ? "MC" : ""), dname, name.data()),
2102 Form("X resolution %s %s [%s]; X_{%s-%s} (cm); X_{%s} - X_{Trk} (%s)", name.data(), dname, mc_id,
2103 dname, name.data(), (xy_id == 'M' ? "Pnt" : "Hit"), unit.data()),
2104 nbinsx, xlo, xhi, nbinsy, -yrange, yrange);
2105 break;
2106
2108 if (!mc) break;
2109 xy_id = 'M';
2110 mc_id[0] = 'M';
2111 mc_id[1] = 'C';
2112 // fall through
2114 if (!xy_id) xy_id = 't';
2115 nbinsx = 10 * ceil(size[1]); // mm binning
2116 if (strcmp(dname, "Trd") == 0 && name.compare("2D") == 0) nbinsx *= 10;
2117 unit = makeYrange(scale, yrange);
2118 nbinsy = 200; //* ceil(yrange);
2119 get<2>(projection.second) =
2120 new TH2D(Form("hyy%s_%s%s", (xy_id == 'M' ? "MC" : ""), dname, name.data()),
2121 Form("Y resolution %s %s [%s]; Y_{%s-%s} (cm); Y_{%s} - Y_{Trk} (%s)", name.data(), dname, mc_id,
2122 dname, name.data(), (xy_id == 'M' ? "Pnt" : "Hit"), unit.data()),
2123 nbinsx, ylo, yhi, nbinsy, -yrange, yrange);
2124 break;
2125
2127 nbinsx = 10 * ceil(size[0]); // mm binning
2128 nbinsy = 200; //* ceil(yrange);
2129 unit = makeYrange(scale, yrange);
2130 get<2>(projection.second) =
2131 new TH2D(Form("hdxT_%s%s", dname, name.data()),
2132 Form("X_{TRK} resolution %s [%s]; X^{%s}_{%s-%s} (cm); #sigma_{Trk}(X) (%s)", name.data(), dname,
2133 mc_id, dname, name.data(), unit.data()),
2134 nbinsx, xlo, xhi, nbinsy, 0., yrange);
2135 break;
2136
2138 nbinsx = 10 * ceil(size[0]); // mm binning
2139 if (yrange < 0) {
2140 LOG(debug) << "ProjectionP[" << name << "] using default range.";
2141 yrange = 5; // +- 5 sigma range
2142 }
2143 nbinsy = 200; //* ceil(yrange);
2144 get<2>(projection.second) =
2145 new TH2D(Form("hpx_%s%s", dname, name.data()),
2146 Form("X pulls %s [%s]; X^{%s}_{%s-%s} (cm); pull(X)", name.data(), dname, mc_id, dname, name.data()),
2147 nbinsx, xlo, xhi, nbinsy, -yrange, yrange);
2148 break;
2149
2151 nbinsx = 10 * ceil(size[0]); // mm binning
2152 nbinsy = 200; //* ceil(yrange);
2153 unit = makeYrange(scale, yrange);
2154 get<2>(projection.second) =
2155 new TH2D(Form("hdyT_%s%s", dname, name.data()),
2156 Form("Y_{TRK} resolution %s [%s]; Y^{%s}_{%s-%s} (cm); #sigma_{Trk}(Y) (%s)", name.data(), dname,
2157 mc_id, dname, name.data(), unit.data()),
2158 nbinsx, xlo, xhi, nbinsy, 0., yrange);
2159 break;
2160
2162 nbinsx = 10 * ceil(size[1]); // mm binning
2163 if (yrange < 0) {
2164 LOG(debug) << "ProjectionP[" << name << "] using default range.";
2165 yrange = 5; // +- 5 sigma range
2166 }
2167 nbinsy = 200; //* ceil(yrange);
2168 get<2>(projection.second) =
2169 new TH2D(Form("hpy_%s%s", dname, name.data()),
2170 Form("Y pulls %s [%s]; Y^{%s}_{%s-%s} (cm); pull(Y)", name.data(), dname, mc_id, dname, name.data()),
2171 nbinsx, ylo, yhi, nbinsy, -yrange, yrange);
2172 break;
2173
2175 nbinsx = 10 * ceil(size[0]); // mm binning
2176 unit = makeTrange(scale, yrange);
2177 nbinsy = 2 * ceil(yrange);
2178 get<2>(projection.second) = new TH2D(Form("hxt_%s%s", dname, name.data()),
2179 Form("Hit_Trk %s [%s]; X_{%s-%s} (cm); T_{Hit} - T_{Trk} (%s)",
2180 name.data(), dname, dname, name.data(), unit.data()),
2181 nbinsx, xlo, xhi, nbinsy, -yrange, yrange);
2182 break;
2183
2185 nbinsx = dscale * ceil(size[0]); // mm binning
2186 unit = makeTrange(scale, yrange);
2187 nbinsy = 10 * ceil(yrange);
2188 get<2>(projection.second) = new TH2D(Form("hct_%s%s", dname, name.data()),
2189 Form("Hit Event %s [%s]; X_{%s-%s} (cm); T_{Hit} - T_{Evt} (%s)",
2190 name.data(), dname, dname, name.data(), unit.data()),
2191 nbinsx, xlo, xhi, nbinsy, -yrange, yrange);
2192 break;
2194 if (!mc) break;
2195 xy_id = 'm';
2196 // fall through
2198 nbinsx = 100;
2199 xlo = -0.5;
2200 xhi = xlo + nbinsx;
2201 get<2>(projection.second) = new TH2D(
2202 Form("hdm%s_%s%s", (xy_id == 'm' ? "MC" : ""), dname, name.data()),
2203 Form("%s multiplicity [EbyE] %s [%s]; N_{%s}^{%s}; N_{%s-%s}^{%s} (%%)", (xy_id ? "point" : "hit"),
2204 name.data(), dname, dname, (xy_id ? "point" : "hit"), dname, name.data(), (xy_id ? "point" : "hit")),
2205 nbinsx, xlo, xhi, 200, 0, 1);
2206 break;
2207
2209 xy_id = 'a';
2210 // fall through
2212 if (!xy_id) xy_id = 'h';
2213 nbinsx = dscale * ceil(size[0]); // mm binning
2214 nbinsy = dscale * ceil(size[1]);
2215 get<2>(projection.second) =
2216 new TH2D(Form("hxy%c_%s%s", xy_id, dname, name.data()),
2217 Form("Hit_{%s} %s [%s]; X_{%s-%s} (cm); Y_{%s-%s} (cm)", (xy_id == 'h' ? "reco" : "attach"),
2218 name.data(), dname, dname, name.data(), dname, name.data()),
2219 nbinsx, xlo, xhi, nbinsy, ylo, yhi);
2220 break;
2221
2223 if (!mc) break;
2224 nbinsx = dscale * ceil(size[0]); // mm binning
2225 nbinsy = dscale * ceil(size[1]);
2226 get<2>(projection.second) = new TH2D(Form("hxymc_%s%s", dname, name.data()),
2227 Form("Point %s [%s]; X^{MC}_{%s-%s} (cm); Y^{MC}_{%s-%s} (cm)",
2228 name.data(), dname, dname, name.data(), dname, name.data()),
2229 nbinsx, xlo, xhi, nbinsy, ylo, yhi);
2230 break;
2231
2233 // fall through
2235 if (!mc) break;
2236 xy_id = (projection.first == eProjectionType::kResidualX ? 'X' : 'Y');
2237 nbinsx = dscale * ceil(size[0]); // mm binning
2238 if (strcmp(dname, "Trd") == 0 && name.compare("2D") == 0) nbinsx *= 10;
2239 nbinsy = 200; //dscale * ceil(size[1]);
2240 unit = makeYrange(scale, yrange);
2241 get<2>(projection.second) =
2242 new TH2D(Form("h%c%cR_%s%s", xy_id, xy_id, dname, name.data()),
2243 Form("%c resolution %s [%s]; %c_{%s-%s} (cm); %c_{Hit} - %c_{Pnt} (%s)", xy_id, name.data(), dname,
2244 xy_id, dname, name.data(), xy_id, xy_id, unit.data()),
2245 nbinsx, (xy_id == 'X' ? xlo : ylo), (xy_id == 'X' ? xhi : yhi), nbinsy, -yrange, yrange);
2246 break;
2247
2249 // fall through
2251 if (!mc) break;
2252 xy_id = (projection.first == eProjectionType::kResidualTX ? 'X' : 'Y');
2253 nbinsx = dscale * ceil(size[0]); // mm binning
2254 nbinsy = 200; // dscale * ceil(size[1]);
2255 unit = makeYrange(scale, yrange);
2256 get<2>(projection.second) =
2257 new TH2D(Form("ht%cR_%s%s", xy_id, dname, name.data()),
2258 Form("Time resolution %s [%s]; %c_{%s-%s} (cm); T_{Hit} - T_{Pnt} (ns)", name.data(), dname, xy_id,
2259 dname, name.data()),
2260 nbinsx, (xy_id == 'X' ? xlo : ylo), (xy_id == 'X' ? xhi : yhi), nbinsy, -yrange, yrange);
2261 break;
2262
2264 // fall through
2266 if (!mc) break;
2267 xy_id = (projection.first == eProjectionType::kPullX ? 'X' : 'Y');
2268 nbinsx = dscale * ceil(size[0]); // mm binning
2269 nbinsy = dscale * ceil(size[1]);
2270 unit = makeYrange(scale, yrange);
2271
2272 get<2>(projection.second) =
2273 new TH2D(Form("h%c%cP_%s%s", xy_id, xy_id, dname, name.data()),
2274 Form("%c pull %s [%s]; %c_{%s-%s} (cm); pull(%c)", xy_id, name.data(), dname, xy_id, dname,
2275 name.data(), xy_id),
2276 nbinsx, (xy_id == 'X' ? xlo : ylo), (xy_id == 'X' ? xhi : yhi), nbinsy, -yrange, yrange);
2277 break;
2278
2280 nbinsx = dscale * ceil(size[0] * 2.); // mm binning
2281 nbinsy = dscale * ceil(size[1] * 2.);
2282 xlo = pos[0] - size[0];
2283 xhi = pos[0] + size[0];
2284 ylo = pos[1] - size[1];
2285 yhi = pos[1] + size[1];
2286
2287 get<2>(projection.second) = new TH2D(Form("hxyp_%s%s", dname, name.data()),
2288 Form("Trk_{proj} %s [%s]; X_{%s-%s} (cm); Y_{%s-%s} (cm)", name.data(),
2289 dname, dname, name.data(), dname, name.data()),
2290 nbinsx, xlo, xhi, nbinsy, ylo, yhi);
2291 break;
2292 case eProjectionType::kXYt0: xy_id = '0';
2293 // fall through
2295 if (!xy_id) xy_id = '1';
2296 // fall through
2298 if (!xy_id) xy_id = '2';
2299 // fall through
2301 if (!xy_id) xy_id = '3';
2302 // fall through
2304 if (!xy_id) xy_id = '4';
2305 // fall through
2307 if (!xy_id) xy_id = '5';
2308 nbinsx = 4500; // mm binning
2309 nbinsy = 1000;
2310 xlo = -25;
2311 xhi = +20;
2312 ylo = -5;
2313 yhi = +5;
2314
2315 get<2>(projection.second) = new TH2D(Form("hxyt%c_%s%s", xy_id, dname, name.data()),
2316 Form("Trk_{proj} z = %+.2f [%s]; X_{%s-%s} (cm); Y_{%s-%s} (cm)", yrange,
2317 dname, dname, name.data(), dname, name.data()),
2318 nbinsx, xlo, xhi, nbinsy, ylo, yhi);
2319 break;
2320
2321 // Primary vertex plots
2322 case eProjectionType::kPVmult: // define primary vertex multiplicity
2323 nbinsx = 50;
2324 nbinsy = 20;
2325 xlo = -0.5;
2326 xhi = xlo + nbinsx;
2327 ylo = -0.5;
2328 yhi = ylo + nbinsy;
2329
2330 get<2>(projection.second) =
2331 new TH2D(Form("hMult_%s%s", dname, name.data()), "Vertex multiplicity; N_{trk}^{event}; N_{trk}^{PV}",
2332 nbinsx, xlo, xhi, nbinsy, ylo, yhi);
2333 break;
2334 case eProjectionType::kPVxz: // define X-Z vertex projection
2335 xy_id = 'y';
2336 mc_id[0] = 'z'; // use to store x-axis title
2337 mc_id[1] = 'x'; // use to store y-axis title
2338 nbinsx = 100;
2339 nbinsy = 200;
2340 xlo = -10;
2341 xhi = +10;
2342 ylo = -2;
2343 yhi = +2;
2344 // fall through
2345 case eProjectionType::kPVyz: // define Y-Z vertex projection
2346 if (!xy_id) {
2347 xy_id = 'x';
2348 mc_id[0] = 'z'; // use to store x-axis title
2349 mc_id[1] = 'y'; // use to store y-axis title
2350 nbinsx = 100;
2351 nbinsy = 200;
2352 xlo = -10;
2353 xhi = +10;
2354 ylo = -2;
2355 yhi = +2;
2356 }
2357 // fall through
2358 case eProjectionType::kPVxy: // define X-Y vertex projection
2359 if (!xy_id) {
2360 xy_id = 'z';
2361 mc_id[0] = 'x'; // use to store x-axis title
2362 mc_id[1] = 'y'; // use to store y-axis title
2363 nbinsx = 200;
2364 nbinsy = 200;
2365 xlo = -2;
2366 xhi = +2;
2367 ylo = -2;
2368 yhi = +2;
2369 }
2370 get<2>(projection.second) =
2371 new TH2D(Form("h%c%c_%s%s", mc_id[0], mc_id[1], dname, name.data()),
2372 Form("Vertex_{%c%c}; %c (cm); %c (cm)", mc_id[0], mc_id[1], mc_id[0], mc_id[1]), nbinsx, xlo, xhi,
2373 nbinsy, ylo, yhi);
2374 break;
2375
2376 case eProjectionType::kPVzsz: // define z-sz vertex projection
2377 xy_id = 'z';
2378 yhi = +0.5;
2379 // fall through
2380 case eProjectionType::kPVysy: // define y - sy vertex projection
2381 if (!xy_id) {
2382 xy_id = 'y';
2383 yhi = +0.2;
2384 }
2385 // fall through
2386 case eProjectionType::kPVxsx: // define x-sx vertex projection
2387 if (!xy_id) {
2388 xy_id = 'x';
2389 yhi = +0.1;
2390 }
2391 nbinsx = 200;
2392 nbinsy = 200;
2393 xlo = -0.5;
2394 xhi = +0.5;
2395 ylo = 0;
2396 get<2>(projection.second) = new TH2D(Form("hs%c_%s%s", xy_id, dname, name.data()),
2397 Form("Vertex_{%c}; %c (cm); #sigma %c (cm)", xy_id, xy_id, xy_id), nbinsx,
2398 xlo, xhi, nbinsy, ylo, yhi);
2399 break;
2400 case eProjectionType::kDebug0: // expand kXdX:
2401 xy_id = 'x';
2402
2403 // fall through
2404 case eProjectionType::kDebug1: // expand kYdY:
2405 if (!xy_id) xy_id = 'y';
2406 nbinsx = 10 * ceil(size[0]); // mm binning
2407 if (strcmp(dname, "Trd") == 0 && name.compare("2D") == 0) nbinsx *= 10;
2408 unit = makeYrange(scale, yrange);
2409 nbinsy = 200; //* ceil(yrange);
2410 get<2>(projection.second) =
2411 new TH3D(Form("h%c%cr_%s%s", xy_id, xy_id, dname, name.data()),
2412 Form("%c residuals %s [%s]; x_{%s-%s} (cm); %c_{Hit} - %c_{Trk} (%s); row", xy_id, name.data(),
2413 dname, dname, name.data(), xy_id, xy_id, unit.data()),
2414 nbinsx, xlo, xhi, nbinsy, -yrange, yrange, 20, -0.5, 19.5);
2415 break;
2416 }
2417 }
2418 return true;
2419}
2420
2422{
2423 stringstream s;
2424 s << "V[" << name << "] path[" << path << "] @ [" << pos[0] << ", " << pos[1] << ", " << pos[2] << "] size["
2425 << size[0] << ", " << size[1] << ", " << size[2] << "] projections[" << fProjection.size() << "] sel[";
2426 for (auto ii : fSelector)
2427 s << ii << " ";
2428 s << "]\n";
2429 return s.str();
2430}
2431
2432uint CbmRecoQaTask::View::Register(TDirectoryFile* fOut)
2433{
2434 uint n(0);
2435 TDirectoryFile* lDir = (TDirectoryFile*) fOut->mkdir(name.data(), Form("QA for vol[%s]", path.data()));
2436 TDirectoryFile *sDir(nullptr), *tDir(nullptr);
2437 // run extra directory structure for the case of detector view
2438 if (fType == eViewType::kDetUnit) {
2440 sDir = (TDirectoryFile*) lDir->mkdir("event", "Local Reco QA");
2441 else
2442 sDir = (TDirectoryFile*) lDir->mkdir("TS", "TimeSlice QA");
2443 tDir = (CbmRecoQaTask::fuRecoConfig[kRecoTracks] ? (TDirectoryFile*) lDir->mkdir("track", "CA QA") : nullptr);
2444 }
2445
2446 for (auto& projection : fProjection) {
2447 TH1* hh = get<2>(projection.second);
2448 if (!hh) continue;
2449 switch (projection.first) {
2463 if (tDir) tDir->Add(hh);
2464 break;
2476 if (sDir) sDir->Add(hh);
2477 break;
2491 if (lDir) lDir->Add(hh);
2492 break;
2493 }
2494 n++;
2495 }
2496 LOG(debug) << "CbmRecoQaTask::View[" << name << "]::Register() : " << n << " projections for " << fOut->GetName();
2497 return n;
2498}
2499
2501{
2502 string s;
2503 switch (prj) {
2504 case eProjectionType::kXYa: s = "x-y (attach)"; break;
2511 case eProjectionType::kXYt5: s = "x-y (track)"; break;
2512 case eProjectionType::kXdX: s = "dx-x"; break;
2513 case eProjectionType::kXdXMC: s = "dx-x (MC)"; break;
2514 case eProjectionType::kResidualX: s = "residual(x)-x:MC"; break;
2515 case eProjectionType::kResidualY: s = "residual(y)-y:MC"; break;
2516 case eProjectionType::kResidualTX: s = "residual(t)-x:MC"; break;
2517 case eProjectionType::kResidualTY: s = "residual(t)-y:MC"; break;
2518 case eProjectionType::kPullX: s = "pull(x)-x:MC"; break;
2519 case eProjectionType::kPullY: s = "pull(y)-y:MC"; break;
2520 case eProjectionType::kYdY: s = "dy-y"; break;
2521 case eProjectionType::kYdYMC: s = "dy-y (MC)"; break;
2522 case eProjectionType::kXpX: s = "pull(x)-x"; break;
2523 case eProjectionType::kYpY: s = "pull(y)-y"; break;
2524 case eProjectionType::kXdXT: s = "d_trk(x)-x"; break;
2525 case eProjectionType::kYdYT: s = "d_trk(y)-y"; break;
2526 case eProjectionType::kWdT: s = "dt(trk)-w"; break;
2527 case eProjectionType::kChdT: s = "dt(ev)-w"; break;
2528 case eProjectionType::kXYh: s = "x-y (hit)"; break;
2529 case eProjectionType::kXYhMC: s = "x-y (point)"; break;
2530 default: LOG(error) << "View::ToString() : Unknown projection " << int(prj); break;
2531 }
2532 return s;
2533}
2534
2535string CbmRecoQaTask::View::makeYrange(const int scale, float& yrange)
2536{
2537 bool kDefaultRange = false;
2538 string unit = "cm";
2539 if (yrange < 0) {
2540 LOG(debug) << "ProjectionY[" << name << "] using default range.";
2541 kDefaultRange = true;
2542 yrange = 3; // +- 6 cm default range
2543 }
2544 if (scale == 10) { // mm resolution
2545 unit = "mm";
2546 if (kDefaultRange) yrange = 10; // +- 20 mm default range
2547 }
2548 else if (scale == 10000) { // micron resolution
2549 unit = "#mu m";
2550 if (kDefaultRange) yrange = 150; // +- 300 um default range
2551 }
2552 return unit;
2553}
2554
2555string CbmRecoQaTask::View::makeTrange(const int scale, float& yrange)
2556{
2557 bool kDefaultRange = false;
2558 string unit = "ns";
2559 if (yrange < 0) {
2560 LOG(debug) << "ProjectionT[" << name << "] using default range.";
2561 kDefaultRange = true;
2562 yrange = 40; // +- 80 ns default range
2563 }
2564 if (scale == 1000) { // ps resolution
2565 unit = "ps";
2566 if (kDefaultRange) yrange = 300; // +- 600 ps default range
2567 }
2568 return unit;
2569}
2570
2572{
2573 for (auto cut : fFilterEv) {
2574 if (cut.fType == type) {
2575 LOG(warning) << GetName() << "::AddEventFilter event filter : " << cut.ToString() << " already on the list.";
2576 return nullptr;
2577 }
2578 }
2579 fFilterEv.emplace_back(type);
2580 return &fFilterEv.back();
2581}
2582
2583//+++++++++++++++++++++ TrackFilter ++++++++++++++++++++++++++++++++
2584//____________________________________________________________________
2586{
2587 // check if not already registered
2588 for (auto cut : fFilterTrk) {
2589 if (cut.fDet == type) {
2590 LOG(warning) << GetName() << "::AddTrackFilter track filter : " << type << " already on the list.";
2591 return nullptr;
2592 }
2593 }
2594 fFilterTrk.emplace_back(type);
2595 return &fFilterTrk.back();
2596}
2598{
2599 stringstream ss;
2600
2601 if (fDet == ECbmModuleId::kRef) { // take care of projection cuts
2602 for (auto cut : fProjFilter.fRef) {
2603 ss << "::TrackProjection(z = " << cut[0] << ") centered on [" << cut[1] << ", " << cut[2] << "] < " << cut[3]
2604 << "cm.";
2605 }
2606 }
2607 else {
2608 ss << "::TrackHitFilter(" << fDet << ") min hits[" << fNminHits << "]. ";
2609 auto detTopo = [&](vector<int> cut) {
2610 std::string label[3];
2611 switch (fDet) {
2612 case ECbmModuleId::kSts: ss << "U" << cut[0] << "L" << cut[1] << "M" << cut[2] << " / "; break;
2613 case ECbmModuleId::kTrd:
2614 switch (cut[3]) {
2615 case 0: label[0] = "n"; break;
2616 case 1: label[0] = "y"; break;
2617 default: label[0] = "any"; break;
2618 }
2619 switch (cut[4]) {
2620 case 0: label[1] = "rect"; break;
2621 case 1: label[1] = "tilt"; break;
2622 default: label[1] = "any"; break;
2623 }
2624 switch (cut[5]) {
2625 case 0: label[2] = "left"; break;
2626 case 1: label[2] = "center"; break;
2627 case 2: label[2] = "right"; break;
2628 default: label[2] = "any"; break;
2629 }
2630 ss << "Ly" << cut[0] << " Mod" << cut[1] << " ClSz[" << cut[2] << "] RowCross[" << label[0] << "] Max["
2631 << label[1] << "] Symm[" << label[2] << "] PadRow[" << cut[6] << "] / ";
2632 break;
2633 default: break;
2634 }
2635 };
2636 if (fHitsFilter.fAccept.size()) {
2637 ss << "accept topology : ";
2638 for (auto cut : fHitsFilter.fAccept)
2639 detTopo(cut);
2640 }
2641 if (fHitsFilter.fReject.size()) {
2642 ss << "reject topology : ";
2643 for (auto cut : fHitsFilter.fReject)
2644 detTopo(cut);
2645 }
2646 }
2647
2648 return ss.str();
2649}
2650
2651//+++++++++++++++++++++ EventFilter ++++++++++++++++++++++++++++++++
2652//____________________________________________________________________
2654{
2655 stringstream ss;
2656 bool ret(true);
2657 size_t val(0);
2658 switch (fType) {
2661 if (fMinTrack > 0 && val < size_t(fMinTrack)) {
2662 ss << "NofTrack[" << val << "] < min[" << fMinTrack << "].";
2663 ret = false;
2664 break;
2665 }
2666 if (ret && fMaxTrack > 0 && val > size_t(fMaxTrack)) {
2667 ss << "NofTrack[" << val << "] > max[" << fMaxTrack << "].";
2668 ret = false;
2669 }
2670 break;
2673 if (fMultHit[0] > 0 && val > size_t(fMultHit[0])) {
2674 ss << "Sts hits [" << val << "] > max[" << fMultHit[0] << "].";
2675 ret = false;
2676 break;
2677 }
2679 if (fMultHit[1] > 0 && val > size_t(fMultHit[1])) {
2680 ss << "Trd hits [" << val << "] > max[" << fMultHit[1] << "].";
2681 ret = false;
2682 break;
2683 }
2685 if (fMultHit[2] > 0 && val > size_t(fMultHit[2])) {
2686 ss << "Tof hits [" << val << "] > max[" << fMultHit[2] << "].";
2687 ret = false;
2688 }
2689 break;
2690 default: break;
2691 }
2692 if (!ret) LOG(debug2) << "EventFilter::Reject event for : " << ss.str();
2693 return ret;
2694}
2695bool CbmRecoQaTask::EventFilter::SetFilter(std::vector<float> cuts)
2696{
2697 switch (fType) {
2699 if (cuts.size() < 2 || cuts[1] < cuts[0]) {
2700 LOG(warning) << "Improper definition for event filter :\n\t" << ToString() << endl;
2701 HelpMess();
2702 return false;
2703 }
2704 fMinTrack = int(cuts[0]);
2705 fMaxTrack = int(cuts[1]);
2706 break;
2708 if (cuts.size() < 3) {
2709 LOG(warning) << "Improper definition for event filter :\n\t" << ToString() << endl;
2710 HelpMess();
2711 return false;
2712 }
2713 for (int i(0); i < int(CbmRecoQaTask::EventFilter::eEventDef::kNofDetHit); i++)
2714 fMultHit[i] = int(cuts[i]);
2715 break;
2716 case eEventCut::kTrigger: break;
2717 case eEventCut::kVertex: break;
2718 default: break;
2719 }
2720 return true;
2721}
2723{
2724 stringstream ss;
2725 switch (fType) {
2726 case eEventCut::kMultTrk: ss << "kMultTrk : \"cut on track multiplicity"; break;
2727 case eEventCut::kMultHit: ss << "kMultHit : \"cut on hit multiplicity"; break;
2728 case eEventCut::kTrigger: ss << "kTrigger : \"cut on trigger conditions"; break;
2729 case eEventCut::kVertex: ss << "kVertex : \"cut on vertex definition"; break;
2730 default: break;
2731 }
2732 return ss.str();
2733}
2735{
2736 LOG(info) << "CbmRecoQaTask::EventFilter : Usage";
2737 switch (fType) {
2739 LOG(info) << ToString();
2740 LOG(info) << "\tDepends one two values : min and max of the no of global "
2741 "tracks / event.";
2742 LOG(info) << "\tValue should follow the relation max >= min.";
2743 break;
2745 LOG(info) << ToString();
2746 LOG(info) << "\tDepends one three values : total hits in the following "
2747 "systems (in this order) : STS TRD TOF.";
2748 LOG(info) << "\tNegative values are interpreted as no-cut.";
2749 break;
2750 default:
2751 LOG(info) << ToString();
2752 LOG(info) << "\tNo user info.";
2753 break;
2754 }
2755}
2756//+++++++++++++++++++++ TrackFilter ++++++++++++++++++++++++++++++++
2757//____________________________________________________________________
2759{
2760 bool ret(true);
2761 stringstream ss;
2762 int idx(-1);
2763 const CbmTrack* trk(nullptr);
2764 // check if we have any registered cut for detector
2765 if (fNminHits <= 0) return false;
2766 // check if we have any found track for detector
2767 switch (fDet) {
2768 case ECbmModuleId::kSts: idx = ptr->GetStsTrackIndex(); break;
2769 case ECbmModuleId::kTrd: idx = ptr->GetTrdTrackIndex(); break;
2770 case ECbmModuleId::kTof: idx = ptr->GetTofTrackIndex(); break;
2771 case ECbmModuleId::kMuch: idx = ptr->GetMuchTrackIndex(); break;
2772 default: break;
2773 }
2774 if (idx < 0) {
2775 ss << fDet << " trk missing";
2776 ret = false;
2777 }
2778 if (ret && !(trk = lnk->GetData<CbmTrack>(fDet, idx))) {
2779 ss << fDet << " trk[" << idx << "]=nullptr.";
2780 ret = false;
2781 }
2782 // cut on the total no of STS hits/trk
2783 if (ret && trk->GetNofHits() < fNminHits) {
2784 ss << fDet << " hits/trk[" << idx << "]=" << trk->GetNofHits() << " < min[" << fNminHits << "].";
2785 ret = false;
2786 }
2787 // check topology of hits on track if topological cuts are defined for detector
2788 if (ret && (fHitsFilter.fAccept.size() || fHitsFilter.fReject.size())) {
2789 for (int ihit(0), jhit(0); ihit < trk->GetNofHits(); ihit++) {
2790 jhit = trk->GetHitIndex(ihit);
2791 auto hit = (CbmHit*) lnk->GetData<CbmHit>(fDet, jhit);
2792 if (!hit) {
2793 LOG(warning) << "TrackFilter::Accept : Missing " << ihit << "hit @ idx=" << jhit << " for " << fDet;
2794 continue;
2795 }
2796 //printf("check hit %d\n", ihit);
2797 if (!(ret = lnk->FilterHit(hit, fDet))) break;
2798 }
2799 }
2800
2801 if (!ret) LOG(debug) << "TrackFilter::Reject trk for : " << ss.str();
2802 return ret;
2803}
2804
2805//____________________________________________________________________
2806bool CbmRecoQaTask::TrackFilter::AddTopoCut(std::vector<int> cuts, const char opt)
2807{
2808 size_t ncuts(0);
2809 switch (fDet) {
2810 case ECbmModuleId::kSts: ncuts = stsSz; break;
2811 case ECbmModuleId::kTof: ncuts = tofSz; break;
2812 case ECbmModuleId::kTrd: ncuts = trdSz; break;
2813 default:
2814 LOG(warning) << "CbmRecoQaTask::TrackFilter::AddTopoCut : k" << fDet << " : \"specific cut on hit topology for "
2815 << fDet << "\" not implemented.";
2816 return false;
2817 }
2818 if (cuts.size() != ncuts) {
2819 LOG(warning) << "CbmRecoQaTask::TrackFilter::AddTopoCut : k" << fDet << " : \"specific cut on hit topology for "
2820 << fDet << "\" incorrect size " << cuts.size() << ". Needed size " << ncuts;
2821 return false;
2822 }
2823 switch (opt) {
2824 case 'a': fHitsFilter.fAccept.push_back(cuts); break;
2825 case 'r': fHitsFilter.fReject.push_back(cuts); break;
2826 }
2827
2828 return true;
2829}
2830
2831//____________________________________________________________________
2833{
2834 if (cuts.size() < 1) {
2835 LOG(warning) << "::SetFilter : k" << fDet << " : \"cut on no of " << fDet << " hits / track\" not defined.";
2836 return false;
2837 }
2838 fProjFilter.fRef.emplace_back(std::array<float, projSz>{cuts[0], cuts[1], cuts[2], cuts[3]});
2839 return true;
2840}
2841
2842/* clang-format off */
2849 /* clang-format on */
Base class for cluster objects.
ClassImp(CbmConverterManager)
std::string ToString(CbmCutId id)
Convert CbmCutId to a string representation.
Definition CbmCutId.cxx:7
ECbmModuleId
Enumerator for module Identifiers.
Definition CbmDefs.h:45
@ kMvd
Micro-Vertex Detector.
Definition CbmDefs.h:47
@ kTrd
Transition Radiation Detector.
Definition CbmDefs.h:51
@ kTof
Time-of-flight Detector.
Definition CbmDefs.h:52
@ kNotExist
If not found.
Definition CbmDefs.h:68
@ kPsd
Projectile spectator detector.
Definition CbmDefs.h:54
@ kSts
Silicon Tracking System.
Definition CbmDefs.h:48
@ kTrd2d
TRD-FASP Detector (FIXME)
Definition CbmDefs.h:58
@ kLastModule
For loops over all modules.
Definition CbmDefs.h:67
@ kRef
Reference plane.
Definition CbmDefs.h:46
@ kMuch
Muon detection system.
Definition CbmDefs.h:50
@ kFsd
Forward spectator detector.
Definition CbmDefs.h:59
@ kRich
Ring-Imaging Cherenkov Detector.
Definition CbmDefs.h:49
#define kNtrkProjections
@ kStsModule
@ kStsLadder
@ kStsUnit
Data class for STS clusters.
Data class for a reconstructed hit in the STS.
Helper class to convert unique channel ID back and forth.
Data Container for TRD clusters.
Class for hits in TRD detector.
friend fvec sqrt(const fvec &a)
friend fscal max(fscal x, fscal y)
fscal v[fmask::Size]
Definition KfSimdPseudo.h:4
int Int_t
Generates beam ions for transport simulation.
Base class for cluster objects.
Definition CbmCluster.h:30
virtual std::string ToString() const
Return string representation of the object.
Class characterising one event by a collection of links (indices) to data objects,...
Definition CbmEvent.h:34
size_t GetNofData() const
Definition CbmEvent.cxx:58
double GetStartTime() const
Definition CbmEvent.h:140
int32_t GetStsTrackIndex() const
int32_t GetTofTrackIndex() const
int32_t GetMuchTrackIndex() const
int32_t GetTrdTrackIndex() const
virtual std::string ToString() const
Virtual function. Must be implemented in derived class. Has to return string representation of the ob...
Definition CbmHit.h:108
int32_t GetRefId() const
Definition CbmHit.h:76
static int GetHitIndex(const Node &node)
static ECbmModuleId GetHitSystemId(const Node &node)
Task class creating and managing CbmMCDataArray objects.
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
static void SetPlaneId(Node &node, int planeId)
static int GetPlaneId(const Node &node)
int GetDebugInfo(const CbmHit *h)
Detector specific extra info.
CbmMCDataManager * cbm_mc_manager
static constexpr size_t stsSz
std::vector< TVector3 > fPrjPlanes
list of QA views
std::map< ECbmModuleId, TClonesArray * > MapDataList(std::string &s) const
link the right data list for the data type (Hit, Tracks, Clusters)
std::map< ECbmModuleId, TClonesArray * > fHitMatch
mc points
int GetNviews(eViewType type) const
count views types registered with the task
virtual EventFilter * AddEventFilter(EventFilter::eEventCut cut)
virtual Detector * GetDetector(ECbmModuleId did)
std::map< ECbmModuleId, CbmMCDataArray * > fPoints
reconstructed Clusters
TClonesArray * fGTracks
TClonesArray * fEvents
MC info for the global tracks.
static std::bitset< kRecoQaNConfigs > fuRecoConfig
virtual bool FilterTrack(const CbmGlobalTrack *ptr) const
Filter tracks based on cuts. The cuts describe track composition (type of detector hit attached) and ...
std::map< ECbmModuleId, Detector > fDetQa
void Activate(ECbmModuleId det, bool set=true)
Explcitely Activate/Deactivate detector for tracking. If set to false, the detector is QAed but it is...
virtual void Exec(Option_t *option)
Executed task.
std::map< ECbmModuleId, TClonesArray * > fHits
Time slice info.
std::vector< EventFilter > fFilterEv
reconstructed hits
std::vector< TrackFilter > fFilterTrk
static size_t GetHitDetectorId(const CbmHit *h, std::vector< int > &sel)
Retrieve detector specific hit to sensor identification array.
@ kXdXT
X to TRK residuals w.r.t MC points.
@ kPVxsx
y-z projection of the primary vertex:
@ kPVyz
x-z projection of the primary vertex:
@ kDebug1
debug slot for detectors
@ kXYh
Time to EV residuals as function of coordinate in view.
@ kPVxy
Residual distribution T:
@ kResidualX
Pull distribution Y:
@ kDmult
X-Y hit coorelation in local view.
@ kXYt3
X-Y track projections on a random plane (value 2)
@ kXYt5
X-Y track projections on a random plane (value 4)
@ kXYhMC
local view MC point multiplicity
@ kYpY
X to TRK pulls as function of local X in view.
@ kXYt1
X-Y track projections on a random plane (value 0)
@ kYdYMC
Y to TRK residuals as function of local Y in view.
@ kResidualY
Residual distribution X: (x_RC - x_MC) in cm.
@ kPVzsz
y-sy projection of the primary vertex:
@ kPullX
X-Y MC point coorelation in local view (using HitMatch)
@ kResidualTX
Residual distribution Y:
@ kDebug0
X-Y track projections on a random plane (value 5)
@ kXYt0
z-sz projection of the primary vertex:
@ kPVysy
x-sx projection of the primary vertex:
@ kXYt2
X-Y track projections on a random plane (value 1)
@ kResidualTY
Residual distribution T:
@ kXdX
X-Y track projections on detection unit.
@ kPullY
Pull distribution X: (RC - MC) / dx_RC.
@ kXYp
X-Y hit coorelation in track filtered data.
@ kPVmult
y-z projection of the primary vertex:
@ kYdY
TRK errors in X direction as function of local X.
@ kYdYT
Y to TRK residuals w.r.t MC points.
@ kXdXMC
X to TRK residuals as function of local X in view.
@ kWdT
TRK errors in Y direction as function of local Y.
@ kPVxz
x-y projection of the primary vertex:
@ kXYt4
X-Y track projections on a random plane (value 3)
@ kDmultMC
local view hit multiplicity
@ kChdT
Y to TRK pulls as function of local Y in view.
CbmKfTrackFitter fFitter
@ kTrdHits
has STS hits (StsHit branch)
@ kMuchHits
has Rich hits (RichHit branch)
@ kUseMC
has Much hits (MuchHit branch)
@ kRichHits
has ToF hits (TofHit branch)
@ kRecoQaNConfigs
use ToF hits in track refit
@ kUseSts
use MC even if available
@ kStsHits
has tracks reconstructed (GlobalTrack branch)
@ kUseTof
use TRD hits in track refit
@ kRecoTracks
has events reconstructed (CbmEvent branch)
@ kUseTrd
use STS hits in track refit
@ kTofHits
has TRD` hits (TrdHit branch)
std::map< ECbmModuleId, TClonesArray * > fClusters
reconstructed hits
virtual InitStatus Init()
Perform initialization of data sources and projections.
std::map< ECbmModuleId, TClonesArray * > fTracks
reconstructed global tracks / event
bool FilterHit(const CbmHit *h, ECbmModuleId d) const
Filter hit based on internal properties (for the originating sensor \call FilterView())
virtual TrackFilter * AddTrackFilter(ECbmModuleId cut)
TString GetGeoTagForDetector(const TString &detector)
std::vector< TString > GetPath(TGeoNode *node, TString, TString activeNodeName, int depth=0, const TString &path="")
@ kPV
set of track projection views
static constexpr size_t trdSz
static constexpr size_t tofSz
std::map< const char *, View > fViews
list of detector QA
TClonesArray * fTrackMatches
reconstructed global tracks / event
virtual Detector * AddDetector(ECbmModuleId did)
const Data * GetData(ECbmModuleId did, int id) const
Retrieve detector specific data type (Track, Hit, Match) by index.
TDirectoryFile fOutFolder
virtual void Finish()
void InitMcbm22()
build QA plots for particular setups
bool IsActive(eRecoConfig feature)
virtual bool FilterEvent(const CbmEvent *ptr) const
Filter events for QA use (e.g. event multiplicity)
static uint16_t GetDirichId(int Address)
Definition CbmRichUtil.h:30
Bool_t IsActive(ECbmModuleId moduleId)
Definition CbmSetup.cxx:169
static CbmSetup * Instance()
Definition CbmSetup.cxx:160
data class for a reconstructed 3-d hit in the STS
Definition CbmStsHit.h:35
Data class with information on a STS local track.
static int32_t GetSmId(uint32_t address)
static int32_t GetRpcId(uint32_t address)
static int32_t GetSmType(uint32_t address)
virtual int32_t GetNofHits() const
Definition CbmTrack.h:58
int32_t GetHitIndex(int32_t iHit) const
Definition CbmTrack.h:59
static uint32_t GetModuleId(uint32_t address)
Return module ID from address.
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.
Data Container for TRD clusters.
uint16_t GetRow() const
uint16_t GetSize() const
data class for a reconstructed Energy-4D measurement in the TRD
Definition CbmTrdHit.h:40
void Position(TVector3 &pos) const
Definition CbmVertex.h:73
bool FindTrackByIndex(uint32_t iTrack) const
Accessors to the Global track array. Check if track with global index iTrack was actually used for ve...
double GetCovariance(int32_t i, int32_t j) const
int32_t GetNTracks() const
Definition CbmVertex.h:72
Class to handle QA-objects in the online reconstruction.
Definition QaData.h:27
T X() const
Gets x position [cm].
T Y() const
Gets y position [cm].
T Time() const
Gets time [ns].
T GetCovariance(int i, int j) const
Get covariance matrix element.
void AddNodes(const std::vector< Node > &nodes)
Add multiple nodes to the trajectory.
size_t GetNofNodes() const
Get number of nodes on the trajectory.
const std::vector< Node > & GetNodes() const
Get reference to the vector of nodes.
void DisableMeasurementAtNode(const size_t index)
Disable measurement at the given node.
const Node & GetNode(const size_t index) const
Get const reference to the node by its index.
uint32_t GetElementId(int32_t address, int32_t level)
Get the index of an element.
TrackParam< double > TrackParamD
std::string_view ToString(T t)
Definition CbmEnumDict.h:64
Hash for CbmL1LinkKey.
View * GetView(const char *n)
Detector(ECbmModuleId did=ECbmModuleId::kNotExist)
View * FindView(double x, double y, double z)
std::vector< View > fViews
bool Init(TDirectoryFile *f, bool mc=false)
Check geometry and trigger Init() for all registered views. Build main directory outut for the curren...
View * AddView(const char *n, const char *p, std::vector< int > set, bool debug=false)
void HelpMess() const
max no of hits/ev for the systems [STS TRD ToF]
std::string ToString() const
int fMultHit[(int) eEventDef::kNofDetHit]
bool SetFilter(std::vector< float > cuts)
bool Accept(const CbmEvent *ptr, const CbmRecoQaTask *lnk)
@ kVertex
cut on trigger conditions
@ kMultHit
cut on track multiplicity
@ kTrigger
cut on hit multiplicity
std::vector< std::vector< int > > fAccept
std::vector< std::vector< int > > fReject
bool Accept(const CbmHit *h, const CbmCluster *c0=nullptr, const CbmCluster *c1=nullptr) const
std::string ToString() const
bool AddTopoCut(std::vector< int > cuts, const char opt)
Define hit conditions for the analysis.
TopoFilter fHitsFilter
definition of min number of hits/track
bool Accept(const CbmGlobalTrack *ptr, const CbmRecoQaTask *lnk) const
bool SetProjFilter(std::vector< float > cuts)
Define geometrical conditions for track acceptance in the analysis.
TopoFilter fProjFilter
definition of hits/track topology according to detection unit
bool AddProjection(eProjectionType prj, float range=-1, const char *unit="cm")
bool Init(const char *dname, bool mc=false)
Define all type of QA histo known to the class. In case of detector view type, convert geo address in...
std::string path
name describing the module
std::string makeYrange(const int scale, float &range)
bool Load(const CbmHit *h, const FairMCPoint *point, const CbmEvent *ev)
std::vector< int > fSelector
detection element center x0 y0 z0
uint Register(TDirectoryFile *f)
build directory structure for all projections of current view.
std::string makeTrange(const int scale, float &range)
helper functions to estimate the representation (y) axis
double pos[3]
detection element geometrical dx dy dz dimmensions
bool HasAddress(const CbmHit *h, double &x, double &y, double &dx, double &dy) const
std::map< eProjectionType, std::tuple< int, float, TH1 * > > fProjection
defining subset of the address set for this view
eSetup fSetup
multiplicity between 2 reset signals
double size[3]
path to the geo volume describing the module
bool SetProjection(eProjectionType prj, float range, const char *unit)
std::string ToString() const