31#include "FairMCPoint.h"
33#include <FairRootManager.h>
36#include <TClonesArray.h>
37#include <TGeoManager.h>
64 LOG(warn) << GetName() <<
"::AddDetector(" <<
id <<
")."
65 <<
" already registered. Using "
66 <<
"\"CbmRecoQaTask::GetDetector(ECbmModuleId).\"";
79 LOG(debug) << GetName() <<
"::AddDetector(" <<
id <<
").";
82 default: LOG(warn) << GetName() <<
"::AddDetector : unsupported det " << id;
return nullptr;
100 LOG(warn) << GetName() <<
"::Activate : unsupported operation on det " << id;
104 LOG(info) << GetName() <<
"::Activate " <<
id <<
" for track fit.";
108 LOG(info) << GetName() <<
"::Deactivate " <<
id <<
" for track fit.";
149 LOG(warning) << GetName() <<
" negative data idx for " << did;
154 if (datas.find(did) == datas.end()) {
155 LOG(debug1) << GetName() <<
" missing " << ss <<
"s for " << did;
158 auto dd = (
const Data*) (datas.at(did))->At(
id);
160 LOG(debug1) << GetName() <<
" missing " << ss <<
"_" <<
id <<
" for " << did;
171 fFitter.SetIgnorePoorCoordinates();
174 FairRootManager* ioman = FairRootManager::Instance();
176 LOG(fatal) << GetName() <<
"::Init :: RootManager not instantiated!";
180 fGTracks =
static_cast<TClonesArray*
>(ioman->GetObject(
"GlobalTrack"));
182 LOG(warn) << GetName() <<
"::Init: Global track array not found!";
186 fEvents =
static_cast<TClonesArray*
>(ioman->GetObject(
"CbmEvent"));
188 LOG(warn) << GetName() <<
"::Init: No event found. Some results will be missing.";
195 LOG(warn) << GetName() <<
"::Init: MC data manager not available even though asked by user !";
199 fTrackMatches =
static_cast<TClonesArray*
>(ioman->GetObject(
"GlobalTrackMatch"));
201 LOG(warn) << GetName() <<
"::Init: MC info for Global track not available !";
209 LOG(info) << GetName() <<
"::Init: Setup config for \"mCBM 2022\".";
213 LOG(info) << GetName() <<
"::Init: Setup config for \"mCBM 2024\". ";
217 LOG(info) << GetName() <<
"::Init: Setup config for \"mCBM 2025\". ";
221 LOG(info) << GetName() <<
"::Init: Setup config for \"Default\". ";
227 for (
auto& detp :
fDetQa) {
228 auto& det = detp.second;
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()));
235 if (!
fHitMatch[det.id]) LOG(warn) << GetName() <<
"::Init: Hit Match array for " << det.id <<
" not found!";
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!";
254 fClusters[det.id] =
static_cast<TClonesArray*
>(ioman->GetObject(det.cl.name.data()));
256 LOG(warn) << GetName() <<
"::Init: Cluster array for " << det.id <<
" not found!";
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!";
270 ? (TDirectoryFile*)
fOutFolder.mkdir(
"TRG",
"Target tomography with CA")
274 fViews.emplace(
"prj",
View(
"TrkProj",
"", {}));
279 LOG(warn) << GetName() <<
"::Init: Only " <<
kNtrkProjections <<
" are supported. Skipping the rest.";
289 fViews[
"prj"].Register(trgDir);
296 for (
auto rcut : trkCut.GetProjCuts()) {
298 bool projFound =
false;
300 if (abs(plane.Z() - rcut[0]) < 1.e-3) {
305 LOG(debug1) << GetName() <<
"::Init: Trk projection cut @ z=" << rcut[0]
306 <<
" already registered as projection plane";
323 fViews[
"vx"].Init(
"Prim");
324 fViews[
"vx"].Register(trgDir);
329 LOG(info) << GetName() << evSelector.ToString();
331 LOG(info) << GetName() << trkSelector.ToString();
343 LOG(error) <<
"Unprocessed hit in view " <<
name;
344 cout <<
h->ToString();
350template<ECbmModuleId d>
362 if (!ctrd)
return 0xab00;
363 return ctrd->GetRow();
371 int32_t a =
h->GetAddress();
383 int32_t a =
h->GetAddress();
394 int32_t a =
h->GetAddress();
406 int32_t a =
h->GetAddress();
409 sel.emplace_back((uId >> 8) & 0xF);
414template<ECbmModuleId d>
423 std::vector<int> sel;
427 auto filter = [&](vector<int> def) ->
size_t {
430 for (
size_t isel(0); isel < nsel; isel++) {
431 if (def[isel] < 0 || def[isel] == sel[isel])
440 if (def.size() < nsel) {
441 LOG(error) <<
"TopoFilter::Accept: Det[" << d <<
"] unsupported definition for [reject] cut of size["
442 << def.size() <<
"] expect " << nsel;
445 if (!filter(def))
return false;
449 if (def.size() < nsel) {
450 LOG(error) <<
"TopoFilter::Accept: Det[" << d <<
"] unsupported definition for [accept] cut of size["
451 << def.size() <<
"] expect " << nsel;
454 if (!filter(def))
return true;
456 return fAccept.size() ? false :
true;
467 if (!fReject.size() && !fAccept.size())
return true;
468 std::vector<int> sel;
472 auto htrd =
dynamic_cast<const CbmTrdHit*
>(
h);
475 auto filter = [&](vector<int> def) ->
size_t {
476 size_t accept(
trdSz);
479 for (; isel < nsel; isel++) {
480 if (def[isel] < 0 || def[isel] == sel[isel])
486 if (def[isel] < 0 || (c && c->
GetSize() == def[isel]))
492 auto rc = htrd->IsRowCross();
493 if (def[isel] < 0 || (rc ==
bool(def[isel])))
499 auto mx = htrd->GetMaxType();
500 if (def[isel] < 0 || (mx ==
bool(def[isel])))
507 if (def[isel] < 0 || (symm == def[isel]))
513 if (def[isel] < 0 || (c && c->
GetRow() == def[isel]))
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;
529 if (!filter(def))
return false;
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;
537 if (!filter(def))
return true;
539 return fAccept.size() ? false :
true;
548 std::vector<int> sel;
552 if (ii != sel[isel])
break;
562 LOG(debug4) <<
"Accept Sts hit for " << sel[0] <<
" " << sel[1] <<
" " << sel[2];
566 LOG(error) <<
"Failed loading STS hit in view " <<
name;
581 std::vector<int> sel;
585 if (sel[0] >= fSelector[0])
return false;
590 LOG(error) <<
"Failed loading RICH hit in view " << name;
605 std::vector<int> sel;
606 auto nsel = CbmRecoQaTask::GetHitDetectorId<ECbmModuleId::kTrd>(h, sel);
617 for (
auto ii : fSelector) {
618 if (ii != sel[isel])
break;
622 if (isel != nsel)
return false;
624 LOG(debug4) <<
"Accept TRD hit for " << sel[0] <<
" " << sel[1] <<
" " << sel[2];
626 const CbmTrdHit* h0 =
dynamic_cast<const CbmTrdHit*
>(h);
628 LOG(error) <<
"Failed loading TRD hit in view " << name;
643 std::vector<int> sel;
644 auto nsel = CbmRecoQaTask::GetHitDetectorId<ECbmModuleId::kTof>(h, sel);
646 for (
auto ii : fSelector) {
647 if (ii != sel[isel])
break;
657 LOG(debug4) <<
"Accept Tof hit for " << sel[0] <<
" " << sel[1] <<
" " << sel[2];
659 const CbmTofHit* h0 =
dynamic_cast<const CbmTofHit*
>(h);
661 LOG(error) <<
"Failed loading ToF hit in view " << name;
676 double x(0),
y(0), dx(0), dy(0);
678 LOG(debug4) <<
"view " <<
name <<
" does not own hit " <<
h->ToString();
684 auto fillView = [&](
eProjectionType proj,
double xx,
double yy,
bool scaleY =
true) {
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);
702 double prj =
h->GetZ() / point->GetZ();
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(),
726 int scale = get<0>(projection.second);
727 auto h = get<2>(projection.second);
730 auto hh =
dynamic_cast<TH2*
>(
h);
731 switch (projection.first) {
748 double prj = n->z / point->GetZ();
749 double dxMC = prj * point->GetX() - t.
X(), dyMC = prj * point->GetY() - t.
Y();
751 switch (projection.first) {
757 if (dinfo != 0xab00) {
758 auto hhh =
dynamic_cast<TH3*
>(
h);
759 switch (projection.first) {
772 int scale = get<0>(projection.second);
773 TH2* hh =
dynamic_cast<TH2*
>(get<2>(projection.second));
775 switch (projection.first) {
777 if (
int(p->Z()) == -123) hh->Fill(scale * p->X(), scale * p->Y());
780 if (
int(p->Z()) == -124) hh->Fill(p->X(), p->Y());
783 if (
int(p->Z()) == 0) hh->Fill(scale * p->X(), scale * p->Y());
787 if (
int(p->Z()) == 1) hh->Fill(scale * p->X(), scale * p->Y());
791 if (
int(p->Z()) == 2) hh->Fill(scale * p->X(), scale * p->Y());
795 if (
int(p->Z()) == 3) hh->Fill(scale * p->X(), scale * p->Y());
799 if (
int(p->Z()) == 4) hh->Fill(scale * p->X(), scale * p->Y());
803 if (
int(p->Z()) == 5) hh->Fill(scale * p->X(), scale * p->Y());
807 if (pe) hh->Fill(scale * p->X(), scale * p->Y());
810 if (pe) hh->Fill(p->Z(), scale * p->X());
813 if (pe) hh->Fill(p->Z(), scale * p->Y());
816 if (pe) hh->Fill(scale * p->X(), scale * pe->X());
819 if (pe) hh->Fill(scale * p->Y(), scale * pe->Y());
822 if (pe) hh->Fill(scale * p->Z(), scale * pe->Z());
834 LOG(info) << GetName() <<
"::Exec : Evs[" << (
fEvents ?
fEvents->GetEntriesFast() : 0) <<
"] Trks["
840 int iev = 0, itrack = 0;
843 const FairMCPoint* mcpoint =
nullptr;
853 if (match && match->GetNofLinks() > 0) {
854 const auto& link = match->GetMatchedLink();
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();
862 event_id = FairRootManager::Instance()->GetEntryNr();
864 if (link.GetFile() != file_id || link.GetEntry() != event_id) {
865 LOG(warn) <<
"match from different event";
868 mcpoint =
dynamic_cast<FairMCPoint*
>(
fPoints[d]->Get(link));
875 auto processHits = [&](
CbmEvent* ev) {
876 for (
auto& detp :
fDetQa) {
877 auto& det = detp.second;
898 if (!
fHits[det.id]) {
899 LOG(error) << GetName() <<
"::Exec() : Hits for " <<
cbm::util::ToString(det.id) <<
" not available. Skip.";
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;
907 auto hit =
dynamic_cast<const CbmHit*
>(
fHits[det.id]->At(jh));
909 LOG(warning) << GetName() <<
"::Exec() : Hit " << jh <<
" for " << det.id <<
" not available. Skip.";
916 const FairMCPoint* mcpoint = matchMC(hit, jh, det.id, ev);
919 for (
auto& view : det.fViews) {
930 default: LOG(fatal) << GetName() <<
"::Exec : unsupported det " << det.id;
break;
936 for (
auto&
v : det.fViews) {
937 mult.SetXYZ(nh,
double(
v.fMult) / nh, -124);
944 auto processTracks = [&](
CbmEvent* ev) {
948 int ntrkDet[3] = {0};
953 vx = ev->GetVertex();
958 for (
int i(0); i < 3; i++) {
960 if (evx[i] > 0.) evx[i] =
sqrt(evx[i]);
964 pvx.SetXYZ(ntrk, nTrkVx, -123);
969 View* viewPrj =
nullptr;
973 LOG(warning) << GetName() <<
"::Exec: view for track projection with wrong type. Skipping.";
978 for (
int itrk = 0; itrk < ntrk; ++itrk) {
980 auto track =
dynamic_cast<const CbmGlobalTrack*
>((*fGTracks)[trkIdx]);
986 if (track->GetStsTrackIndex() >= 0) ntrkDet[0]++;
987 if (track->GetTrdTrackIndex() >= 0) ntrkDet[1]++;
988 if (track->GetTofTrackIndex() >= 0) ntrkDet[2]++;
996 if (!
fFitter.CreateFromGlobalTrack(trkKf, *track, (viewPrj ?
true :
false))) {
997 LOG(fatal) << GetName() <<
"::Exec: can not create the track for the fit!";
1005 std::vector<Trajectory::Node> nodesPrj;
1010 nodesPrj.push_back(n);
1017 for (
unsigned int i = 0; i < trkKf.
GetNofNodes(); ++i) {
1018 const auto& n = trkKf.
GetNode(i);
1022 if (
fDetQa.find(nodeSystemId) ==
fDetQa.end())
continue;
1023 switch (nodeSystemId) {
1045 if (!
fFitter.FitTrajectory(trkKf)) {
1049 if (!
fFitter.FitTrajectory(trkKf)) {
1055 LOG(debug) << GetName() <<
"::Exec: Accept track for QA.";
1059 for (
int iNode = 0; iNode < (int) trkKf.
GetNofNodes(); iNode++) {
1060 auto& n = trkKf.
GetNode(iNode);
1063 if (viewPrj && planeId >= 0 && n.isFitted) {
1064 TVector3 xyz(n.paramUp.X(), n.paramUp.Y(), planeId);
1065 viewPrj->
Load(&xyz);
1074 auto& det =
fDetQa[nodeSystemId];
1076 auto view = det.FindView(n.measurementXY.X(), n.measurementXY.Y(), n.z);
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.";
1084 auto hit =
dynamic_cast<CbmHit*
>(
fHits[nodeSystemId]->At(hitIndex));
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.";
1092 auto mcpoint = matchMC(hit, hitIndex, nodeSystemId);
1095 auto trkTmp = trkKf;
1096 const auto& nTmp = trkTmp.
GetNode(iNode);
1097 trkTmp.DisableMeasurementAtNode(iNode);
1098 if (!
fFitter.FitTrajectory(trkTmp) || !nTmp.isFitted)
continue;
1100 if (view->HasDebug())
1103 view->Load(&nTmp, mcpoint);
1104 nhit[(int) nodeSystemId]++;
1113 auto ev =
dynamic_cast<CbmEvent*
>(evObj);
1119 LOG(info) << GetName() <<
"::Exec : Evs(%)["
1120 << (
fEvents->GetEntriesFast() ? 1.e2 * iev /
fEvents->GetEntriesFast() : 0) <<
"] Trks(%)["
1125 processHits(
nullptr);
1128 LOG(info) << GetName() <<
"::Exec : TS local reco only.";
1132 processTracks(
nullptr);
1134 LOG(info) << GetName() <<
"::Exec : Trks(%)["
1144 if (
v.second.fType != type)
continue;
1154 FairSink* sink = FairRootManager::Instance()->GetSink();
1165 if (!evCut.Accept(ptr,
this))
return false;
1176 if (tf.fDet != d)
continue;
1177 auto filter = tf.GetHitsFilter();
1178 if (!filter)
continue;
1179 const CbmCluster *cl0(
nullptr), *cl1(
nullptr);
1200 LOG(debug1) << ss.str();
1212 if (!trkCut.Accept(ptr,
this))
return false;
1214 LOG(debug) << GetName() <<
"::FilterTrack : Accept hit cuts Sts[" << ptr->
GetStsTrackIndex() <<
"] Trd["
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;
1234 LOG(debug1) << GetName() <<
"::FilterTrack : Reject projection @ z[" << rcut[0] <<
"] r=" << r
1235 <<
" R=" << rcut[3];
1241 if (ret) LOG(debug) << GetName() <<
"::FilterTrack : Accept projection cuts.";
1248 gGeoManager->CdTop();
1249 TGeoNode* cave = gGeoManager->GetCurrentNode();
1251 LOG(error) <<
"Error: Could not get the top node in the geometry manager." << std::endl;
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));
1267 const TString& path)
1269 std::vector<TString> nodePaths;
1275 TString nodePath = path;
1276 if (!nodePath.IsNull()) {
1279 nodePath += node->GetName();
1281 if (TString(node->GetName()).Contains(activeNodeName)) {
1282 if (nodePath.Contains(detector)) nodePaths.push_back(nodePath);
1286 Int_t numDaughters = node->GetNdaughters();
1287 for (
Int_t i = 0; i < numDaughters; ++i) {
1288 TGeoNode* daughterNode = node->GetDaughter(i);
1290 std::vector<TString> result =
GetPath(daughterNode, detector, activeNodeName, depth + 1, nodePath);
1291 nodePaths.insert(nodePaths.end(), result.begin(), result.end());
1301 LOG(fatal) << GetName() <<
"::InitMcbm22() : Missing setup definition.";
1305 fFitter.SetDefaultMomentumForMs(0.5);
1306 fFitter.SetEnforceDefaultMomentumForMs();
1310 std::vector<TString> path;
1311 TGeoNode* topNode = gGeoManager->GetTopNode();
1313 LOG(error) <<
"Error: Top node not found.";
1317 auto processDetector = [&](
const std::string& detector,
const std::string& component) {
1320 if (geoTag.Length() > 0) {
1321 LOG(info) << detector <<
": geometry tag is " << geoTag;
1324 LOG(warn) <<
"Warning: No geometry tag found for detector " << detector;
1327 path =
GetPath(topNode, detector, component, 0);
1332 processDetector(
"sts",
"Sensor");
1334 std::regex pattern(
"/Station(\\d+)_(\\d+)/Ladder(\\d+)_(\\d+)/HalfLadder\\d+d_(\\d+)/"
1335 "HalfLadder\\d+d_Module(\\d+)_(\\d+)/Sensor(\\d+)_(\\d+)");
1338 for (
const auto& str : path) {
1339 std::string Str(str.Data());
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]);
1346 const char* fType = Form(
"U%dL%dM%d", station - 1, ladder - 1, module - 1);
1348 v =
sts->AddView(fType, str.Data(), {station - 1, ladder - 1, module - 1});
1359 std::cout <<
"No match found in string: " << str << std::endl;
1365 processDetector(
"trd",
"module");
1369 for (
const auto& str : path) {
1370 if (!str.Contains(
"module9"))
continue;
1371 v =
trd->AddView(
"2D", str.Data(), {5});
1383 for (
const auto& str : path) {
1385 if (str.Contains(
"layer02")) {
1386 v =
trd->AddView(
"1Dx", str.Data(), {21});
1394 if (str.Contains(
"layer03")) {
1395 v =
trd->AddView(
"1Dy", str.Data(), {37});
1408 processDetector(
"tof",
"counter");
1411 tof->hit.name =
"TofHit";
1412 std::regex pattern(
"module_(\\d+)_(\\d+)/gas_box_(\\d+)/counter_(\\d+)");
1414 for (
const auto& str : path) {
1415 std::string Str(str.Data());
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);
1423 v =
tof->AddView(name, str.Data(), {smid, type, rpc});
1427 v =
tof->AddView(name, str.Data(), {smid, type, rpc});
1431 std::cout <<
"No match found in string: " << str << std::endl;
1437 float angle = 25., L[] = {14.3, 0, -20, -38 , -50.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()));
1451 LOG(fatal) << GetName() <<
"::InitMcbm24() : Missing setup definition.";
1455 fFitter.SetDefaultMomentumForMs(1.5);
1456 fFitter.SetEnforceDefaultMomentumForMs();
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);
1492 v =
trd->AddView(
"2D", Form(
"/cave_1/trd_%s_0/layer01_20101/module9_101001001/gas_0", dtag.Data()), {0, 0});
1495 v =
trd->AddView(
"1Dx", Form(
"/cave_1/trd_%s_0/layer02_10202/module5_101002001", dtag.Data()), {1, 0});
1500 v =
trd->AddView(
"1Dy", Form(
"/cave_1/trd_%s_0/layer03_11303/module5_101103001", dtag.Data()), {2, 0});
1510 vector<int> tofSelect(3);
1512 for (
int ism(0); ism < 6; 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]),
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/"
1533 dtag.Data(), dtag.Data(), tofSelect[1], tofSelect[0], tofSelect[2]),
1538 for (
int ism(0); ism < 2; 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]),
1551 for (
int ism(0); ism < 2; 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]),
1569 rich->AddView(
"Aerogel", Form(
"/cave_1/rich_%s_0/box_1/Gas_1", dtag.Data()), {4});
1573 float angle = 25., L[] = {14.3, 0, -20, -38, -50.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()));
1586 LOG(fatal) << GetName() <<
"::InitMcbm25() : Missing setup definition.";
1590 fFitter.SetDefaultMomentumForMs(1.5);
1591 fFitter.SetEnforceDefaultMomentumForMs();
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);
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}}},
1639 for (
auto& [name, def] : modules) {
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);
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);
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);
1688 vector<int> tofSelect(3);
1691 for (
int ism(0); ism < 5; 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]),
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};
1713 fPrjPlanes.emplace_back(l * sina, 0., l * cosa);
1718 LOG(info) <<
"Init Default ....";
1721 LOG(fatal) << GetName() <<
"::InitDefault() : Missing setup definition.";
1726 std::vector<TString> path;
1727 TGeoNode* topNode = gGeoManager->GetTopNode();
1729 LOG(error) <<
"Error: Top node not found.";
1734 auto processDetector = [&](
const std::string& detector,
const std::string& component) {
1737 if (geoTag.Length() > 0) {
1738 LOG(info) << detector <<
": geometry tag is " << geoTag;
1741 LOG(warn) <<
"Warning: No geometry tag found for detector " << detector;
1743 path =
GetPath(topNode, detector, component, 0);
1747 processDetector(
"sts",
"Unit");
1750 std::regex pattern(R
"(Unit(\d{2}[LR])_(\d+))");
1754 for (
const auto& str : path) {
1755 std::string Str(str.Data());
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")) :
"";
1762 v =
sts->AddView(unitname.c_str(), str.Data(), {unitid - 1, -1, -1});
1766 std::cout <<
"No match found in string: " << str << std::endl;
1772 processDetector(
"trd",
"module");
1773 std::regex pattern(
"layer(\\d+)_(\\d+)/module(\\d+)_(\\d+)");
1776 for (
const auto& str : path) {
1777 std::string Str(str.Data());
1779 if (std::regex_search(Str, match, pattern)) {
1780 int layer = std::stoi(match[1]);
1781 int layercopyNr = std::stoi(match[2]);
1783 int module = std::stoi(match[3]);
1784 int modulecopyNr = std::stoi(match[4]);
1786 int fLayer = ((layercopyNr / 100) % 10);
1787 int fModuleCopy = (modulecopyNr % 100);
1789 sprintf(name,
"layer%d_%d_module_%d_%d", layer, layercopyNr, module, modulecopyNr);
1791 v =
trd->AddView(name, str.Data(), {fLayer - 1, fModuleCopy - 1, -1});
1795 std::cout <<
"No match found in string: " << str << std::endl;
1801 processDetector(
"rich",
"sens");
1803 for (
const auto& str : path) {
1804 v =
rich->AddView(
"rich", str.Data(), {-1, -1, -1});
1810 processDetector(
"tof",
"module");
1813 tof->hit.name =
"TofHit";
1814 std::regex pattern(
"module_(\\d+)_(\\d+)");
1815 for (
const auto& str : path) {
1816 std::string Str(str.Data());
1818 if (std::regex_search(Str, match, pattern)) {
1819 int type = std::stoi(match[1]);
1820 int smid = std::stoi(match[2]);
1822 std::string modulename = (Str.find(
"module") != std::string::npos) ? Str.substr(Str.find(
"module")) :
"";
1824 v =
tof->AddView(modulename.c_str(), str.Data(), {smid, type, -1});
1828 std::cout <<
"No match found in string: " << str << std::endl;
1879 LOG(warn) <<
"QA unsupported for Detector=" << did;
1890 fViews.emplace_back(n, p, set);
1925 for (
auto& view :
fViews)
1926 if (view.name.compare(n) == 0)
return &view;
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;
1951 LOG(fatal) <<
"CbmRecoQaTask::Detector::Init() " <<
id <<
" missing geometry.";
1954 LOG(info) <<
"CbmRecoQaTask::Detector::Init() : " <<
cbm::util::ToString(
id) <<
" MC = " << mc;
1956 TDirectoryFile* modDir = (TDirectoryFile*) fOut->mkdir(
1959 for (
auto& view :
fViews) {
1961 view.Register(modDir);
1970 s <<
"D[" <<
id <<
"] views[" <<
fViews.size() <<
"]\n";
1981 LOG(warn) <<
"Projection " <<
ToString(prj) <<
" already registered";
1985 if (strcmp(unit,
"mm") == 0)
1987 else if (strcmp(unit,
"um") == 0)
1989 else if (strcmp(unit,
"ps") == 0)
1991 else if (strcmp(unit,
"eV") == 0)
1993 else if (strcmp(unit,
"cm") == 0)
1995 else if (strcmp(unit,
"ns") == 0)
1997 else if (strcmp(unit,
"keV") == 0)
1999 else if (strcmp(unit,
"a.u.") == 0)
2002 LOG(warn) <<
"Projection units " << unit <<
" not registered. Natural units will be used.";
2004 fProjection[prj] = make_tuple(scale, range,
nullptr);
2019 LOG(warn) <<
"Projection " <<
ToString(prj)
2020 <<
" not initialized. Calling "
2021 "\"CbmRecoQaTask::View::AddProjection()\"";
2025 if (strcmp(unit,
"mm") == 0)
2027 else if (strcmp(unit,
"um") == 0)
2029 else if (strcmp(unit,
"ps") == 0)
2031 else if (strcmp(unit,
"eV") == 0)
2033 else if (strcmp(unit,
"cm") == 0)
2035 else if (strcmp(unit,
"ns") == 0)
2037 else if (strcmp(unit,
"keV") == 0)
2039 else if (strcmp(unit,
"a.u.") == 0)
2042 LOG(warn) <<
"Projection units " << unit <<
" not registered. Natural units will be used.";
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();
2062 for (
int i(0); i < 3; i++) {
2063 size[i] = bb->GetAxisRange(i + 1, w_lo, w_hi);
2064 pos[i] = 0.5 * (w_lo + w_hi) + tr[i];
2067 LOG(info) <<
"CbmRecoQaTask::Detector(" << dname <<
")::View(" <<
name <<
")::Init() : size [" <<
size[0] <<
" x "
2068 <<
size[1] <<
" x " <<
size[2] <<
"]. mc[" << mc <<
"].";
2071 LOG(info) <<
"CbmRecoQaTask::Detector(" << dname <<
")::View(" <<
name <<
")::Init() : mc[" << mc <<
"].";
2076 if (strcmp(dname,
"Tof") == 0 || strcmp(dname,
"Rich") == 0) dscale = 1;
2081 int scale = get<0>(projection.second);
2082 float yrange = get<1>(projection.second);
2084 char mc_id[2] = {
' ',
' '};
2087 switch (projection.first) {
2095 if (!xy_id) xy_id =
't';
2096 nbinsx = 10 * ceil(
size[0]);
2097 if (strcmp(dname,
"Trd") == 0 &&
name.compare(
"2D") == 0) nbinsx *= 10;
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);
2114 if (!xy_id) xy_id =
't';
2115 nbinsx = 10 * ceil(
size[1]);
2116 if (strcmp(dname,
"Trd") == 0 &&
name.compare(
"2D") == 0) nbinsx *= 10;
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);
2127 nbinsx = 10 * ceil(
size[0]);
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);
2138 nbinsx = 10 * ceil(
size[0]);
2140 LOG(debug) <<
"ProjectionP[" <<
name <<
"] using default range.";
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);
2151 nbinsx = 10 * ceil(
size[0]);
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);
2162 nbinsx = 10 * ceil(
size[1]);
2164 LOG(debug) <<
"ProjectionP[" <<
name <<
"] using default range.";
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);
2175 nbinsx = 10 * ceil(
size[0]);
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);
2185 nbinsx = dscale * ceil(
size[0]);
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);
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);
2212 if (!xy_id) xy_id =
'h';
2213 nbinsx = dscale * ceil(
size[0]);
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);
2224 nbinsx = dscale * ceil(
size[0]);
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);
2237 nbinsx = dscale * ceil(
size[0]);
2238 if (strcmp(dname,
"Trd") == 0 &&
name.compare(
"2D") == 0) nbinsx *= 10;
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);
2253 nbinsx = dscale * ceil(
size[0]);
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);
2268 nbinsx = dscale * ceil(
size[0]);
2269 nbinsy = dscale * ceil(
size[1]);
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);
2280 nbinsx = dscale * ceil(
size[0] * 2.);
2281 nbinsy = dscale * ceil(
size[1] * 2.);
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);
2295 if (!xy_id) xy_id =
'1';
2298 if (!xy_id) xy_id =
'2';
2301 if (!xy_id) xy_id =
'3';
2304 if (!xy_id) xy_id =
'4';
2307 if (!xy_id) xy_id =
'5';
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);
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);
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,
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);
2405 if (!xy_id) xy_id =
'y';
2406 nbinsx = 10 * ceil(
size[0]);
2407 if (strcmp(dname,
"Trd") == 0 &&
name.compare(
"2D") == 0) nbinsx *= 10;
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);
2424 s <<
"V[" <<
name <<
"] path[" <<
path <<
"] @ [" <<
pos[0] <<
", " <<
pos[1] <<
", " <<
pos[2] <<
"] size["
2435 TDirectoryFile* lDir = (TDirectoryFile*) fOut->mkdir(
name.data(), Form(
"QA for vol[%s]",
path.data()));
2436 TDirectoryFile *sDir(
nullptr), *tDir(
nullptr);
2440 sDir = (TDirectoryFile*) lDir->mkdir(
"event",
"Local Reco QA");
2442 sDir = (TDirectoryFile*) lDir->mkdir(
"TS",
"TimeSlice QA");
2447 TH1* hh = get<2>(projection.second);
2449 switch (projection.first) {
2463 if (tDir) tDir->Add(hh);
2476 if (sDir) sDir->Add(hh);
2491 if (lDir) lDir->Add(hh);
2496 LOG(debug) <<
"CbmRecoQaTask::View[" <<
name <<
"]::Register() : " << n <<
" projections for " << fOut->GetName();
2530 default: LOG(error) <<
"View::ToString() : Unknown projection " << int(prj);
break;
2537 bool kDefaultRange =
false;
2540 LOG(debug) <<
"ProjectionY[" <<
name <<
"] using default range.";
2541 kDefaultRange =
true;
2546 if (kDefaultRange) yrange = 10;
2548 else if (scale == 10000) {
2550 if (kDefaultRange) yrange = 150;
2557 bool kDefaultRange =
false;
2560 LOG(debug) <<
"ProjectionT[" <<
name <<
"] using default range.";
2561 kDefaultRange =
true;
2564 if (scale == 1000) {
2566 if (kDefaultRange) yrange = 300;
2574 if (cut.fType == type) {
2575 LOG(warning) << GetName() <<
"::AddEventFilter event filter : " << cut.ToString() <<
" already on the list.";
2589 if (cut.fDet == type) {
2590 LOG(warning) << GetName() <<
"::AddTrackFilter track filter : " << type <<
" already on the list.";
2603 ss <<
"::TrackProjection(z = " << cut[0] <<
") centered on [" << cut[1] <<
", " << cut[2] <<
"] < " << cut[3]
2608 ss <<
"::TrackHitFilter(" <<
fDet <<
") min hits[" <<
fNminHits <<
"]. ";
2609 auto detTopo = [&](vector<int> cut) {
2610 std::string label[3];
2612 case ECbmModuleId::kSts: ss <<
"U" << cut[0] <<
"L" << cut[1] <<
"M" << cut[2] <<
" / ";
break;
2615 case 0: label[0] =
"n";
break;
2616 case 1: label[0] =
"y";
break;
2617 default: label[0] =
"any";
break;
2620 case 0: label[1] =
"rect";
break;
2621 case 1: label[1] =
"tilt";
break;
2622 default: label[1] =
"any";
break;
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;
2630 ss <<
"Ly" << cut[0] <<
" Mod" << cut[1] <<
" ClSz[" << cut[2] <<
"] RowCross[" << label[0] <<
"] Max["
2631 << label[1] <<
"] Symm[" << label[2] <<
"] PadRow[" << cut[6] <<
"] / ";
2637 ss <<
"accept topology : ";
2642 ss <<
"reject topology : ";
2662 ss <<
"NofTrack[" << val <<
"] < min[" <<
fMinTrack <<
"].";
2667 ss <<
"NofTrack[" << val <<
"] > max[" <<
fMaxTrack <<
"].";
2674 ss <<
"Sts hits [" << val <<
"] > max[" <<
fMultHit[0] <<
"].";
2680 ss <<
"Trd hits [" << val <<
"] > max[" <<
fMultHit[1] <<
"].";
2686 ss <<
"Tof hits [" << val <<
"] > max[" <<
fMultHit[2] <<
"].";
2692 if (!ret) LOG(debug2) <<
"EventFilter::Reject event for : " << ss.str();
2699 if (cuts.size() < 2 || cuts[1] < cuts[0]) {
2700 LOG(warning) <<
"Improper definition for event filter :\n\t" <<
ToString() << endl;
2708 if (cuts.size() < 3) {
2709 LOG(warning) <<
"Improper definition for event filter :\n\t" <<
ToString() << endl;
2736 LOG(info) <<
"CbmRecoQaTask::EventFilter : Usage";
2740 LOG(info) <<
"\tDepends one two values : min and max of the no of global "
2742 LOG(info) <<
"\tValue should follow the relation max >= min.";
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.";
2752 LOG(info) <<
"\tNo user info.";
2775 ss <<
fDet <<
" trk missing";
2779 ss <<
fDet <<
" trk[" << idx <<
"]=nullptr.";
2789 for (
int ihit(0), jhit(0); ihit < trk->
GetNofHits(); ihit++) {
2793 LOG(warning) <<
"TrackFilter::Accept : Missing " << ihit <<
"hit @ idx=" << jhit <<
" for " <<
fDet;
2801 if (!ret) LOG(debug) <<
"TrackFilter::Reject trk for : " << ss.str();
2814 LOG(warning) <<
"CbmRecoQaTask::TrackFilter::AddTopoCut : k" <<
fDet <<
" : \"specific cut on hit topology for "
2815 <<
fDet <<
"\" not implemented.";
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;
2824 case 'a':
fHitsFilter.fAccept.push_back(cuts);
break;
2825 case 'r':
fHitsFilter.fReject.push_back(cuts);
break;
2834 if (cuts.size() < 1) {
2835 LOG(warning) <<
"::SetFilter : k" <<
fDet <<
" : \"cut on no of " <<
fDet <<
" hits / track\" not defined.";
2838 fProjFilter.fRef.emplace_back(std::array<float, projSz>{cuts[0], cuts[1], cuts[2], cuts[3]});
Base class for cluster objects.
ClassImp(CbmConverterManager)
std::string ToString(CbmCutId id)
Convert CbmCutId to a string representation.
ECbmModuleId
Enumerator for module Identifiers.
@ kMvd
Micro-Vertex Detector.
@ kTrd
Transition Radiation Detector.
@ kTof
Time-of-flight Detector.
@ kPsd
Projectile spectator detector.
@ kSts
Silicon Tracking System.
@ kTrd2d
TRD-FASP Detector (FIXME)
@ kLastModule
For loops over all modules.
@ kMuch
Muon detection system.
@ kFsd
Forward spectator detector.
@ kRich
Ring-Imaging Cherenkov Detector.
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)
Generates beam ions for transport simulation.
Base class for cluster objects.
virtual std::string ToString() const
Return string representation of the object.
Class characterising one event by a collection of links (indices) to data objects,...
size_t GetNofData() const
double GetStartTime() const
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...
static int GetHitIndex(const Node &node)
static ECbmModuleId GetHitSystemId(const Node &node)
Task class creating and managing CbmMCDataArray objects.
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 * 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.
@ 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
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)
Bool_t IsActive(ECbmModuleId moduleId)
static CbmSetup * Instance()
data class for a reconstructed 3-d hit in the STS
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
int32_t GetHitIndex(int32_t iHit) const
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.
data class for a reconstructed Energy-4D measurement in the TRD
void Position(TVector3 &pos) const
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
Class to handle QA-objects in the online reconstruction.
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)
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