File indexing completed on 2025-12-16 09:21:45
0001 #include "g4evaltools.h"
0002
0003 #include <mvtx/CylinderGeom_Mvtx.h>
0004
0005 #include <intt/CylinderGeomIntt.h>
0006
0007 #include <g4detectors/PHG4CylinderGeomContainer.h>
0008 #include <g4detectors/PHG4TpcGeom.h>
0009 #include <g4detectors/PHG4TpcGeomContainer.h>
0010
0011 #include <g4tracking/EmbRecoMatchContainer.h>
0012 #include <g4tracking/TrkrTruthTrack.h>
0013
0014 #include <trackbase_historic/SvtxTrack.h>
0015 #include <trackbase_historic/SvtxTrackMap.h>
0016
0017 #include <trackbase/ActsGeometry.h>
0018 #include <trackbase/TrkrCluster.h>
0019 #include <trackbase/TrkrClusterContainer.h>
0020
0021 #include <phool/PHCompositeNode.h>
0022 #include <phool/PHNode.h> // for PHNode
0023 #include <phool/PHNodeIterator.h>
0024 #include <phool/PHObject.h> // for PHObject
0025 #include <phool/getClass.h>
0026 #include <phool/phool.h> // for PHWHERE
0027
0028 #include <TFile.h>
0029 #include <TObjString.h>
0030
0031 #include <cmath>
0032 #include <iostream>
0033 #include <numeric> // for std::accumulate
0034
0035 namespace G4Eval
0036 {
0037 std::vector<int> unmatchedSvtxTrkIds(EmbRecoMatchContainer* matches, SvtxTrackMap* m_SvtxTrackMap)
0038 {
0039 std::set<unsigned int> ids_matched{};
0040 for (auto trkid : matches->ids_RecoMatched())
0041 {
0042 ids_matched.insert(trkid);
0043 }
0044
0045 std::set<int> ids_unmatched;
0046 for (auto& reco : *m_SvtxTrackMap)
0047 {
0048 auto trkid = reco.first;
0049 if (!ids_matched.contains(trkid))
0050 {
0051 ids_unmatched.insert(trkid);
0052 }
0053 }
0054 std::vector<int> ids_vec;
0055 ids_vec.reserve(ids_unmatched.size());
0056 for (auto id : ids_unmatched)
0057 {
0058 ids_vec.push_back((int) id);
0059 }
0060 std::sort(ids_vec.begin(), ids_vec.end());
0061 return ids_vec;
0062 }
0063
0064
0065
0066
0067 void write_StringToTFile(const std::string& msg_name, const std::string& msg)
0068 {
0069
0070
0071 TFile* s_current = gDirectory->GetFile();
0072 if (s_current == nullptr)
0073 {
0074 std::cout << PHWHERE << " Error no TFile open to which to wrote the "
0075 << std::endl
0076 << " TObjString mesaged." << std::endl;
0077 return;
0078 }
0079 TObjString obj(msg.c_str());
0080 s_current->WriteObject(&obj, msg_name.c_str());
0081 return;
0082 }
0083
0084
0085 int trklayer_0123(TrkrDefs::hitsetkey key)
0086 {
0087 auto layer = TrkrDefs::getLayer(key);
0088 if (layer < 3)
0089 {
0090 return 0;
0091 }
0092 if (layer < 7)
0093 {
0094 return 1;
0095 }
0096 if (layer < 55)
0097 {
0098 return 2;
0099 }
0100 return 3;
0101 }
0102
0103
0104 TrkrClusterComparer::TrkrClusterComparer(float _nphi_widths, float _nz_widths)
0105 : m_nphi_widths{_nphi_widths}
0106 , m_nz_widths{_nz_widths} {};
0107 int TrkrClusterComparer::init(PHCompositeNode* topNode,
0108 const std::string& name_phg4_clusters,
0109 const std::string& name_reco_clusters)
0110 {
0111
0112
0113 PHG4CylinderGeomContainer* geom_container_mvtx = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MVTX");
0114 if (!geom_container_mvtx)
0115 {
0116 std::cout << PHWHERE << " Could not locate CYLINDERGEOM_MVTX " << std::endl;
0117 return Fun4AllReturnCodes::ABORTRUN;
0118 }
0119 for (int this_layer = 0; this_layer < 3; ++this_layer)
0120 {
0121 auto* layergeom = dynamic_cast<CylinderGeom_Mvtx*>(geom_container_mvtx->GetLayerGeom(this_layer));
0122 const double pitch = layergeom->get_pixel_x();
0123 const double length = layergeom->get_pixel_z();
0124 m_phistep[this_layer] = pitch;
0125 if (this_layer == 0)
0126 {
0127 m_zstep_mvtx = length;
0128 }
0129 }
0130
0131
0132 PHG4CylinderGeomContainer* geom_container_intt = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
0133 if (!geom_container_intt)
0134 {
0135 std::cout << PHWHERE << " Could not locate CYLINDERGEOM_INTT " << std::endl;
0136 return Fun4AllReturnCodes::ABORTRUN;
0137 }
0138
0139 for (int this_layer = 3; this_layer < 7; ++this_layer)
0140 {
0141 CylinderGeomIntt* geom =
0142 dynamic_cast<CylinderGeomIntt*>(geom_container_intt->GetLayerGeom(this_layer));
0143 float pitch = geom->get_strip_y_spacing();
0144 m_phistep[this_layer] = pitch;
0145 }
0146
0147
0148 PHG4TpcGeomContainer* geom_tpc =
0149 findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
0150 if (!geom_tpc)
0151 {
0152 std::cout << PHWHERE << " Could not locate TPCGEOMCONTAINER, abort" << std::endl;
0153 return Fun4AllReturnCodes::ABORTRUN;
0154 }
0155
0156 for (int this_layer = 7; this_layer < 55; ++this_layer)
0157 {
0158 PHG4TpcGeom* layergeom = geom_tpc->GetLayerCellGeom(this_layer);
0159 if (this_layer == 7)
0160 {
0161 m_zstep_tpc = layergeom->get_zstep();
0162 }
0163 m_phistep[this_layer] = layergeom->get_phistep();
0164 }
0165
0166 m_TruthClusters =
0167 findNode::getClass<TrkrClusterContainer>(topNode, name_phg4_clusters);
0168 if (!m_TruthClusters)
0169 {
0170 std::cout << PHWHERE << " Could not locate " << name_phg4_clusters << " node" << std::endl;
0171 return Fun4AllReturnCodes::ABORTRUN;
0172 }
0173
0174 m_RecoClusters =
0175 findNode::getClass<TrkrClusterContainer>(topNode, name_reco_clusters);
0176 if (!m_TruthClusters)
0177 {
0178 std::cout << PHWHERE << " Could not locate " << name_reco_clusters << " node" << std::endl;
0179 return Fun4AllReturnCodes::ABORTRUN;
0180 }
0181
0182 m_ActsGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0183 if (!m_ActsGeometry)
0184 {
0185 std::cout << PHWHERE << " Could not locate ActsGeometry node" << std::endl;
0186 return Fun4AllReturnCodes::ABORTRUN;
0187 }
0188
0189 return Fun4AllReturnCodes::EVENT_OK;
0190 }
0191
0192
0193
0194
0195
0196
0197
0198 std::pair<bool, float> TrkrClusterComparer::operator()(TrkrDefs::cluskey key_T, TrkrDefs::cluskey key_R)
0199 {
0200
0201 layer = TrkrDefs::getLayer(key_T);
0202 if (layer > 55)
0203 {
0204 std::cout << " Error! Trying to compar cluster in layer > 55, "
0205 << "which is not programmed yet!" << std::endl;
0206 return {false, 0.};
0207 }
0208
0209 in_mvtx = (layer < 3);
0210 in_intt = (layer > 2 && layer < 7);
0211 in_tpc = (layer > 6 && layer < 55);
0212
0213 float phi_step = m_phistep[layer];
0214 float z_step = in_mvtx ? m_zstep_mvtx : m_zstep_tpc;
0215
0216 clus_T = m_TruthClusters->findCluster(key_T);
0217 clus_R = m_RecoClusters->findCluster(key_R);
0218
0219 phi_T = clus_T->getPosition(0);
0220 phi_R = clus_R->getPosition(0);
0221 phisize_R = clus_R->getPhiSize() * m_nphi_widths;
0222 phisize_T = clus_T->getPhiSize() * m_nphi_widths;
0223
0224 z_T = clus_T->getPosition(1);
0225 z_R = clus_R->getPosition(1);
0226
0227 if (!in_intt)
0228 {
0229 zsize_R = clus_R->getZSize() * m_nz_widths;
0230 zsize_T = clus_R->getZSize() * m_nz_widths;
0231 }
0232
0233 phi_delta = std::abs(phi_T - phi_R);
0234 while (phi_delta > M_PI)
0235 {
0236 phi_delta = fabs(phi_delta - 2 * M_PI);
0237 }
0238 phi_delta /= phi_step;
0239
0240 z_delta = std::abs(z_T - z_R) / z_step;
0241
0242
0243
0244 float phi_stat = std::max(phisize_T, phisize_R);
0245 float fit_statistic = (phi_delta / phi_stat);
0246 is_match = (fit_statistic <= 1.);
0247
0248 float z_stat = 0;
0249 if (!in_intt)
0250 {
0251 z_stat = std::max(zsize_T, zsize_R);
0252
0253 is_match = is_match && (z_delta < z_stat);
0254 fit_statistic += z_delta / z_stat;
0255 }
0256 return {is_match, fit_statistic};
0257 }
0258
0259 ClusLoc TrkrClusterComparer::clusloc_PHG4(
0260 std::pair<TrkrDefs::hitsetkey, TrkrDefs::cluskey> input)
0261 {
0262 auto* cluster = m_TruthClusters->findCluster(input.second);
0263 Eigen::Vector3d gloc = m_ActsGeometry->getGlobalPosition(input.second, cluster);
0264 return {TrkrDefs::getLayer(input.first), gloc,
0265 (int) cluster->getPhiSize(), (int) cluster->getZSize()};
0266 }
0267
0268 ClusLoc TrkrClusterComparer::clusloc_SVTX(
0269 std::pair<TrkrDefs::hitsetkey, TrkrDefs::cluskey> input)
0270 {
0271 auto* cluster = m_RecoClusters->findCluster(input.second);
0272 Eigen::Vector3d gloc = m_ActsGeometry->getGlobalPosition(input.second, cluster);
0273 return {TrkrDefs::getLayer(input.first), gloc,
0274 (int) cluster->getPhiSize(), (int) cluster->getZSize()};
0275 }
0276
0277
0278
0279
0280
0281
0282 ClusKeyIter::ClusKeyIter(SvtxTrack* _track)
0283 : track{_track}
0284 , in_silicon{_track->get_silicon_seed() != nullptr}
0285 , has_tpc{_track->get_tpc_seed() != nullptr}
0286 , no_data{!in_silicon && !has_tpc}
0287 {
0288 }
0289
0290 ClusKeyIter ClusKeyIter::begin() const
0291 {
0292 ClusKeyIter iter0{track};
0293 if (iter0.no_data)
0294 {
0295 return iter0;
0296 }
0297 if (iter0.in_silicon)
0298 {
0299 iter0.iter = track->get_silicon_seed()->begin_cluster_keys();
0300 iter0.iter_end_silicon = track->get_silicon_seed()->end_cluster_keys();
0301 }
0302 else if (has_tpc)
0303 {
0304 iter0.iter = track->get_tpc_seed()->begin_cluster_keys();
0305 }
0306 return iter0;
0307 }
0308
0309 ClusKeyIter ClusKeyIter::end() const
0310 {
0311 ClusKeyIter iter0{track};
0312 if (iter0.no_data)
0313 {
0314 return iter0;
0315 }
0316 if (has_tpc)
0317 {
0318 iter0.iter = track->get_tpc_seed()->end_cluster_keys();
0319 }
0320 else if (in_silicon)
0321 {
0322 iter0.iter = track->get_silicon_seed()->end_cluster_keys();
0323 }
0324 return iter0;
0325 }
0326
0327 void ClusKeyIter::operator++()
0328 {
0329 if (no_data)
0330 {
0331 return;
0332 }
0333 ++iter;
0334 if (in_silicon && has_tpc && iter == iter_end_silicon)
0335 {
0336 in_silicon = false;
0337 iter = track->get_tpc_seed()->begin_cluster_keys();
0338 }
0339 }
0340
0341 bool ClusKeyIter::operator!=(const ClusKeyIter& rhs) const
0342 {
0343 if (no_data)
0344 {
0345 return false;
0346 }
0347 return iter != rhs.iter;
0348 }
0349
0350 TrkrDefs::cluskey ClusKeyIter::operator*() const
0351 {
0352 return *iter;
0353 }
0354
0355 TrkrClusterContainer* ClusCntr::get_PHG4_clusters()
0356 {
0357 if (comp == nullptr)
0358 {
0359 return nullptr;
0360 }
0361
0362 return comp->m_TruthClusters;
0363 }
0364
0365 TrkrClusterContainer* ClusCntr::get_SVTX_clusters()
0366 {
0367 if (comp == nullptr)
0368 {
0369 return nullptr;
0370 }
0371
0372 return comp->m_RecoClusters;
0373 }
0374
0375 std::array<int, 5> ClusCntr::cntclus(Vector& keys)
0376 {
0377 std::array<int, 5> cnt{0, 0, 0, 0, 0};
0378 for (auto& it : keys)
0379 {
0380 cnt[trklayer_0123(it.first)] += 1;
0381 }
0382 for (int i = 0; i < 4; ++i)
0383 {
0384 cnt[4] += cnt[i];
0385 }
0386 return cnt;
0387 }
0388
0389 std::array<int, 5> ClusCntr::cnt_matchedclus(Vector& keys, std::vector<bool>& matches)
0390 {
0391 std::array<int, 5> cnt{0, 0, 0, 0, 0};
0392 if (keys.size() != matches.size())
0393 {
0394 std::cout << PHWHERE << " matching and key vector not the same size. "
0395 << std::endl
0396 << " run find_matches() first." << std::endl;
0397 return cnt;
0398 }
0399 for (unsigned int i = 0; i < keys.size(); ++i)
0400 {
0401 if (matches[i])
0402 {
0403 cnt[trklayer_0123(keys[i].first)] += 1;
0404 }
0405 }
0406 for (int i = 0; i < 4; ++i)
0407 {
0408 cnt[4] += cnt[i];
0409 }
0410 return cnt;
0411 }
0412
0413 int ClusCntr::addClusKeys(SvtxTrack* track)
0414 {
0415 svtx_keys.clear();
0416 for (auto ckey : ClusKeyIter(track))
0417 {
0418 svtx_keys.emplace_back(TrkrDefs::getHitSetKeyFromClusKey(ckey), ckey);
0419 }
0420 std::sort(svtx_keys.begin(), svtx_keys.end());
0421 return svtx_keys.size();
0422 }
0423
0424 int ClusCntr::addClusKeys(TrkrTruthTrack* track)
0425 {
0426 phg4_keys.clear();
0427 for (auto ckey : track->getClusters())
0428 {
0429 phg4_keys.emplace_back(TrkrDefs::getHitSetKeyFromClusKey(ckey), ckey);
0430 }
0431 std::sort(phg4_keys.begin(), phg4_keys.end());
0432 return phg4_keys.size();
0433 }
0434
0435 void ClusCntr::reset()
0436 {
0437 phg4_keys.clear();
0438 phg4_matches.clear();
0439 svtx_keys.clear();
0440 svtx_matches.clear();
0441 }
0442
0443 std::array<int, 3> ClusCntr::find_matches()
0444 {
0445 if (comp == nullptr)
0446 {
0447 std::cout << PHWHERE
0448 << " Won't compare tracks because of missing TrkrClusterComparer" << std::endl;
0449 return {0, 0, 0};
0450 }
0451
0452
0453
0454
0455
0456
0457 auto& vA = phg4_keys;
0458 auto& vB = svtx_keys;
0459
0460 auto& matchesA = phg4_matches;
0461 auto& matchesB = svtx_matches;
0462
0463 match_stat = 0.;
0464
0465
0466 matchesA = std::vector<bool>(vA.size(), false);
0467 matchesB = std::vector<bool>(vB.size(), false);
0468
0469
0470 auto iA0 = vA.begin();
0471 auto iA1 = vA.end();
0472
0473 auto iB0 = vB.begin();
0474 auto iB1 = vB.end();
0475
0476 auto iA = iA0;
0477 auto iB = iB0;
0478
0479 int n_match{0};
0480
0481 while (iA != iA1 && iB != iB1)
0482 {
0483 if (iA->first == iB->first)
0484 {
0485 auto hitset = iA->first;
0486
0487
0488 auto sAend = iA + 1;
0489 while (sAend != iA1 && sAend->first == hitset)
0490 {
0491 ++sAend;
0492 }
0493
0494 auto sBend = iB + 1;
0495 while (sBend != iB1 && sBend->first == hitset)
0496 {
0497 ++sBend;
0498 }
0499
0500 for (auto A = iA; A != sAend; ++A)
0501 {
0502 for (auto B = iB; B != sBend; ++B)
0503 {
0504 auto comp_val = comp->operator()(A->second, B->second);
0505 if (comp_val.first)
0506 {
0507 matchesA[A - iA0] = true;
0508 matchesB[B - iB0] = true;
0509 match_stat += comp_val.second;
0510 ++n_match;
0511 }
0512 }
0513 }
0514 iA = sAend;
0515 iB = sBend;
0516 }
0517 else if (iA->first < iB->first)
0518 {
0519 ++iA;
0520 }
0521 else
0522 {
0523 ++iB;
0524 }
0525 }
0526 return {n_match, (int) phg4_keys.size(), (int) svtx_keys.size()};
0527 }
0528
0529 std::array<int, 3> ClusCntr::find_matches(TrkrTruthTrack* g4_track, SvtxTrack* sv_track)
0530 {
0531 addClusKeys(sv_track);
0532 addClusKeys(g4_track);
0533 return find_matches();
0534 }
0535
0536 int ClusCntr::phg4_n_matched()
0537 {
0538 return std::accumulate(phg4_matches.begin(), phg4_matches.end(), 0);
0539 }
0540
0541 int ClusCntr::svtx_n_matched()
0542 {
0543 return std::accumulate(svtx_matches.begin(), svtx_matches.end(), 0);
0544 }
0545
0546 std::vector<ClusLoc> ClusCntr::phg4_clusloc_all()
0547 {
0548 std::vector<ClusLoc> vec{};
0549 for (auto& cluspair : phg4_keys)
0550 {
0551 vec.push_back(comp->clusloc_PHG4(cluspair));
0552 }
0553 return vec;
0554 }
0555
0556 std::vector<ClusLoc> ClusCntr::phg4_clusloc_unmatched()
0557 {
0558 std::vector<ClusLoc> vec{};
0559 auto cnt = phg4_keys.size();
0560 for (unsigned int i = 0; i < cnt; ++i)
0561 {
0562 if (!phg4_matches[i])
0563 {
0564 vec.push_back(comp->clusloc_PHG4(phg4_keys[i]));
0565 }
0566 }
0567 return vec;
0568 }
0569
0570 std::vector<ClusLoc> ClusCntr::svtx_clusloc_all()
0571 {
0572 std::vector<ClusLoc> vec{};
0573 for (auto& cluspair : svtx_keys)
0574 {
0575 vec.push_back(comp->clusloc_SVTX(cluspair));
0576 }
0577 return vec;
0578 }
0579
0580 std::vector<ClusLoc> ClusCntr::svtx_clusloc_unmatched()
0581 {
0582 std::vector<ClusLoc> vec{};
0583 auto cnt = svtx_keys.size();
0584 for (unsigned int i = 0; i < cnt; ++i)
0585 {
0586 if (!svtx_matches[i])
0587 {
0588 vec.push_back(comp->clusloc_SVTX(svtx_keys[i]));
0589 }
0590 }
0591 return vec;
0592 }
0593
0594 std::vector<ClusLoc> ClusCntr::clusloc_matched()
0595 {
0596 std::vector<ClusLoc> vec{};
0597 auto cnt = phg4_keys.size();
0598 for (unsigned int i = 0; i < cnt; ++i)
0599 {
0600 if (phg4_matches[i])
0601 {
0602 vec.push_back(comp->clusloc_PHG4(phg4_keys[i]));
0603 }
0604 }
0605 return vec;
0606 }
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616 }