Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
g4evaltools.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file g4evaltools.cc
1 #include "g4evaltools.h"
2 
4 
6 
10 
13 
16 
17 #include <trackbase/TrkrCluster.h>
19 
20 #include <phool/PHCompositeNode.h>
21 #include <phool/PHNode.h> // for PHNode
22 #include <phool/PHNodeIterator.h>
23 #include <phool/PHObject.h> // for PHObject
24 #include <phool/getClass.h>
25 #include <phool/phool.h> // for PHWHERE
26 
27 #include <TFile.h>
28 #include <TObjString.h>
29 
30 #include <iostream>
31 
32 namespace G4Eval
33 {
34  std::vector<int> unmatchedSvtxTrkIds(EmbRecoMatchContainer* matches, SvtxTrackMap* m_SvtxTrackMap)
35  {
36  std::set<unsigned int> ids_matched{};
37  for (auto trkid : matches->ids_RecoMatched())
38  {
39  ids_matched.insert(trkid);
40  }
41 
42  std::set<int> ids_unmatched;
43  for (auto& reco : *m_SvtxTrackMap)
44  {
45  auto trkid = reco.first;
46  if (ids_matched.count(trkid) == 0)
47  {
48  ids_unmatched.insert(trkid);
49  }
50  }
51  std::vector<int> ids_vec;
52  ids_vec.reserve(ids_unmatched.size());
53  for (auto id : ids_unmatched)
54  {
55  ids_vec.push_back((int) id);
56  }
57  std::sort(ids_vec.begin(), ids_vec.end());
58  return ids_vec;
59  }
60 
61  // function implementation mostly from
62  // https://root-forum.cern.ch/t/is-it-possible-to-save-plain-text-in-a-root-file/27674/4
63  // Note that there is also the code there to read it back from a TFile
64  void write_StringToTFile(const std::string& msg_name, const std::string& msg)
65  {
66  // the string is either written to the current file, or to a new file
67  // that is named f_outname
68  TFile* s_current = gDirectory->GetFile();
69  if (s_current == nullptr)
70  {
71  std::cout << PHWHERE << " Error no TFile open to which to wrote the "
72  << std::endl
73  << " TObjString mesaged." << std::endl;
74  return;
75  }
76  TObjString obj(msg.c_str());
77  s_current->WriteObject(&obj, msg_name.c_str());
78  return;
79  }
80 
81  // return the layer of the hit: 0:Mvtx 1:Intt 2:Tpc 3:Tpot
83  {
84  auto layer = TrkrDefs::getLayer(key);
85  if (layer < 3)
86  {
87  return 0;
88  }
89  if (layer < 7)
90  {
91  return 1;
92  }
93  if (layer < 55)
94  {
95  return 2;
96  }
97  return 3;
98  }
99 
100  // Implementation of Cluster comparator
101  TrkrClusterComparer::TrkrClusterComparer(float _nphi_widths, float _nz_widths)
102  : m_nphi_widths{_nphi_widths}
103  , m_nz_widths{_nz_widths} {};
105  const std::string& name_phg4_clusters,
106  const std::string& name_reco_clusters)
107  {
108  // fill bin/pixel sizes
109  // ------ MVTX data ------
110  PHG4CylinderGeomContainer* geom_container_mvtx = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MVTX");
111  if (!geom_container_mvtx)
112  {
113  std::cout << PHWHERE << " Could not locate CYLINDERGEOM_MVTX " << std::endl;
115  }
116  for (int this_layer = 0; this_layer < 3; ++this_layer)
117  {
118  auto layergeom = dynamic_cast<CylinderGeom_Mvtx*>(geom_container_mvtx->GetLayerGeom(this_layer));
119  const double pitch = layergeom->get_pixel_x();
120  const double length = layergeom->get_pixel_z();
121  m_phistep[this_layer] = pitch;
122  if (this_layer == 0)
123  {
125  }
126  }
127 
128  // ------ INTT data ------
129  PHG4CylinderGeomContainer* geom_container_intt = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
130  if (!geom_container_intt)
131  {
132  std::cout << PHWHERE << " Could not locate CYLINDERGEOM_INTT " << std::endl;
134  }
135  // get phi and Z steps for intt
136  for (int this_layer = 3; this_layer < 7; ++this_layer)
137  {
138  CylinderGeomIntt* geom =
139  dynamic_cast<CylinderGeomIntt*>(geom_container_intt->GetLayerGeom(this_layer));
140  float pitch = geom->get_strip_y_spacing();
141  m_phistep[this_layer] = pitch;
142  }
143 
144  // ------ TPC data ------
145  auto geom_tpc =
146  findNode::getClass<PHG4TpcCylinderGeomContainer>(topNode, "CYLINDERCELLGEOM_SVTX");
147  if (!geom_tpc)
148  {
149  std::cout << PHWHERE << " Could not locate CYLINDERCELLGEOM_SVTX node " << std::endl;
151  }
152  for (int this_layer = 7; this_layer < 55; ++this_layer)
153  {
154  PHG4TpcCylinderGeom* layergeom = geom_tpc->GetLayerCellGeom(this_layer);
155  if (this_layer == 7)
156  {
157  m_zstep_tpc = layergeom->get_zstep();
158  }
159  m_phistep[this_layer] = layergeom->get_phistep();
160  }
161 
163  findNode::getClass<TrkrClusterContainer>(topNode, name_phg4_clusters.c_str());
164  if (!m_TruthClusters)
165  {
166  std::cout << PHWHERE << " Could not locate " << name_phg4_clusters << " node" << std::endl;
168  }
169 
171  findNode::getClass<TrkrClusterContainer>(topNode, name_reco_clusters.c_str());
172  if (!m_TruthClusters)
173  {
174  std::cout << PHWHERE << " Could not locate " << name_reco_clusters << " node" << std::endl;
176  }
177 
178  m_ActsGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
179  if (!m_ActsGeometry)
180  {
181  std::cout << PHWHERE << " Could not locate ActsGeometry node" << std::endl;
183  }
184 
186  }
187 
188  // ok return tuple<bool is_match, float stat,
189  // float delta_phi (in pixels), float half_phi_width (in pixels),
190  // float half_eta_width (in pixels)
191  // float delta_z (in bins), flaot
192  //
193 
195  {
196  // note: can use returned values, or just pull from these values
197  layer = TrkrDefs::getLayer(key_T);
198  if (layer > 55)
199  {
200  std::cout << " Error! Trying to compar cluster in layer > 55, "
201  << "which is not programmed yet!" << std::endl;
202  return {false, 0.};
203  }
204 
205  in_mvtx = (layer < 3);
206  in_intt = (layer > 2 && layer < 7);
207  in_tpc = (layer > 6 && layer < 55);
208 
209  float phi_step = m_phistep[layer];
210  float z_step = in_mvtx ? m_zstep_mvtx : m_zstep_tpc;
211 
214 
215  phi_T = clus_T->getPosition(0);
216  phi_R = clus_R->getPosition(0);
217  phisize_R = clus_R->getPhiSize() * m_nphi_widths; // * phi_step;
218  phisize_T = clus_T->getPhiSize() * m_nphi_widths; // * phi_step; // only for user to get, if they want
219 
220  z_T = clus_T->getPosition(1);
221  z_R = clus_R->getPosition(1);
222 
223  if (!in_intt)
224  {
225  zsize_R = clus_R->getZSize() * m_nz_widths; // * z_step;
226  zsize_T = clus_R->getZSize() * m_nz_widths; // * z_step;
227  }
228 
229  phi_delta = fabs(phi_T - phi_R);
230  while (phi_delta > M_PI)
231  {
232  phi_delta = fabs(phi_delta - 2 * M_PI);
233  }
234  phi_delta /= phi_step;
235 
236  z_delta = fabs(z_T - z_R) / z_step;
237 
238  /* float phi_stat = (m_nphi_widths * phisize_R ); */
239 
240  float phi_stat = std::max(phisize_T, phisize_R);
241  float fit_statistic = (phi_delta / phi_stat);
242  is_match = (fit_statistic <= 1.);
243 
244  float z_stat = 0;
245  if (!in_intt)
246  {
247  z_stat = std::max(zsize_T, zsize_R);
248 
249  is_match = is_match && (z_delta < z_stat);
250  fit_statistic += z_delta / z_stat;
251  }
252  return {is_match, fit_statistic};
253  }
254 
256  std::pair<TrkrDefs::hitsetkey, TrkrDefs::cluskey> input)
257  {
258  auto cluster = m_TruthClusters->findCluster(input.second);
259  Eigen::Vector3d gloc = m_ActsGeometry->getGlobalPosition(input.second, cluster);
260  return {TrkrDefs::getLayer(input.first), gloc,
261  (int) cluster->getPhiSize(), (int) cluster->getZSize()};
262  }
263 
265  std::pair<TrkrDefs::hitsetkey, TrkrDefs::cluskey> input)
266  {
267  auto cluster = m_RecoClusters->findCluster(input.second);
268  Eigen::Vector3d gloc = m_ActsGeometry->getGlobalPosition(input.second, cluster);
269  return {TrkrDefs::getLayer(input.first), gloc,
270  (int) cluster->getPhiSize(), (int) cluster->getZSize()};
271  }
272 
273  // Implementation of the iterable struct to get cluster keys from
274  // a SvtxTrack. It is used like:
275  // for (auto& cluskey : ClusKeyIter(svtx_track)) {
276  // ... // do things with cluster keys
277  // }
279  : track{_track}
280  , in_silicon{_track->get_silicon_seed() != nullptr}
281  , has_tpc{_track->get_tpc_seed() != nullptr}
282  , no_data{!in_silicon && !has_tpc}
283  {
284  }
285 
287  {
288  ClusKeyIter iter0{track};
289  if (iter0.no_data)
290  {
291  return iter0;
292  }
293  if (iter0.in_silicon)
294  {
295  iter0.iter = track->get_silicon_seed()->begin_cluster_keys();
296  iter0.iter_end_silicon = track->get_silicon_seed()->end_cluster_keys();
297  }
298  else if (has_tpc)
299  {
300  iter0.iter = track->get_tpc_seed()->begin_cluster_keys();
301  }
302  return iter0;
303  }
304 
306  {
307  ClusKeyIter iter0{track};
308  if (iter0.no_data)
309  {
310  return iter0;
311  }
312  if (has_tpc)
313  {
314  iter0.iter = track->get_tpc_seed()->end_cluster_keys();
315  }
316  else if (in_silicon)
317  {
318  iter0.iter = track->get_silicon_seed()->end_cluster_keys();
319  }
320  return iter0;
321  }
322 
324  {
325  if (no_data)
326  {
327  return;
328  }
329  ++iter;
331  {
332  in_silicon = false;
334  }
335  }
336 
338  {
339  if (no_data)
340  {
341  return false;
342  }
343  return iter != rhs.iter;
344  }
345 
347  {
348  return *iter;
349  }
350 
352  {
353  if (comp == nullptr)
354  {
355  return nullptr;
356  }
357  else
358  {
359  return comp->m_TruthClusters;
360  }
361  }
362 
364  {
365  if (comp == nullptr)
366  {
367  return nullptr;
368  }
369  else
370  {
371  return comp->m_RecoClusters;
372  }
373  }
374 
375  std::array<int, 5> ClusCntr::cntclus(Vector& keys)
376  {
377  std::array<int, 5> cnt{0, 0, 0, 0, 0};
378  for (auto& it : keys)
379  {
380  cnt[trklayer_0123(it.first)] += 1;
381  }
382  for (int i = 0; i < 4; ++i)
383  {
384  cnt[4] += cnt[i];
385  }
386  return cnt;
387  }
388 
389  std::array<int, 5> ClusCntr::cnt_matchedclus(Vector& keys, std::vector<bool>& matches)
390  {
391  std::array<int, 5> cnt{0, 0, 0, 0, 0};
392  if (keys.size() != matches.size())
393  {
394  std::cout << PHWHERE << " matching and key vector not the same size. "
395  << std::endl
396  << " run find_matches() first." << std::endl;
397  return cnt;
398  }
399  for (unsigned int i = 0; i < keys.size(); ++i)
400  {
401  if (matches[i])
402  {
403  cnt[trklayer_0123(keys[i].first)] += 1;
404  }
405  }
406  for (int i = 0; i < 4; ++i)
407  {
408  cnt[4] += cnt[i];
409  }
410  return cnt;
411  }
412 
413  int ClusCntr::addClusKeys(SvtxTrack* track)
414  {
415  svtx_keys.clear();
416  for (auto ckey : ClusKeyIter(track))
417  {
418  svtx_keys.push_back({TrkrDefs::getHitSetKeyFromClusKey(ckey), ckey});
419  }
420  std::sort(svtx_keys.begin(), svtx_keys.end());
421  return svtx_keys.size();
422  }
423 
425  {
426  phg4_keys.clear();
427  for (auto ckey : track->getClusters())
428  {
429  phg4_keys.push_back({TrkrDefs::getHitSetKeyFromClusKey(ckey), ckey});
430  }
431  std::sort(phg4_keys.begin(), phg4_keys.end());
432  return phg4_keys.size();
433  }
434 
435  void ClusCntr::reset()
436  {
437  phg4_keys.clear();
438  phg4_matches.clear();
439  svtx_keys.clear();
440  svtx_matches.clear();
441  }
442 
443  std::array<int, 3> ClusCntr::find_matches()
444  {
445  if (comp == nullptr)
446  {
447  std::cout << PHWHERE
448  << " Won't compare tracks because of missing TrkrClusterComparer" << std::endl;
449  return {0, 0, 0};
450  }
451  // find the matches between the svtx_keys and phg4_keys
452  // also keep track of the sum of the comparison between then
453 
454  // ---------------------------------
455  // set aliases for notation cleaness
456  // use A for PHG4 and B for SVTX
457  auto& vA = phg4_keys;
458  auto& vB = svtx_keys;
459 
460  auto& matchesA = phg4_matches;
461  auto& matchesB = svtx_matches;
462 
463  match_stat = 0.;
464 
465  // matches will say, cluster by cluster, which clusters are matched
466  matchesA = std::vector<bool>(vA.size(), false);
467  matchesB = std::vector<bool>(vB.size(), false);
468 
469  // user iterators to access the vectors
470  auto iA0 = vA.begin();
471  auto iA1 = vA.end();
472 
473  auto iB0 = vB.begin();
474  auto iB1 = vB.end();
475 
476  auto iA = iA0;
477  auto iB = iB0;
478 
479  int n_match{0};
480 
481  while (iA != iA1 && iB != iB1)
482  {
483  if (iA->first == iB->first)
484  {
485  auto hitset = iA->first;
486 
487  // must compare ALL sets of iA and iB with this same hitset
488  auto sAend = iA + 1; // search A end
489  while (sAend != iA1 && sAend->first == hitset)
490  {
491  ++sAend;
492  }
493 
494  auto sBend = iB + 1; // search B end
495  while (sBend != iB1 && sBend->first == hitset)
496  {
497  ++sBend;
498  }
499 
500  for (auto A = iA; A != sAend; ++A)
501  {
502  for (auto B = iB; B != sBend; ++B)
503  {
504  auto comp_val = comp->operator()(A->second, B->second);
505  if (comp_val.first)
506  {
507  matchesA[A - iA0] = true;
508  matchesB[B - iB0] = true;
509  match_stat += comp_val.second;
510  ++n_match;
511  }
512  }
513  }
514  iA = sAend;
515  iB = sBend;
516  }
517  else if (iA->first < iB->first)
518  {
519  ++iA;
520  }
521  else
522  {
523  ++iB;
524  }
525  }
526  return {n_match, (int) phg4_keys.size(), (int) svtx_keys.size()};
527  }
528 
529  std::array<int, 3> ClusCntr::find_matches(TrkrTruthTrack* g4_track, SvtxTrack* sv_track)
530  {
531  addClusKeys(sv_track);
532  addClusKeys(g4_track);
533  return find_matches();
534  }
535 
537  {
538  return std::accumulate(phg4_matches.begin(), phg4_matches.end(), 0);
539  }
540 
542  {
543  return std::accumulate(svtx_matches.begin(), svtx_matches.end(), 0);
544  }
545 
546  std::vector<ClusLoc> ClusCntr::phg4_clusloc_all()
547  {
548  std::vector<ClusLoc> vec{};
549  for (auto& cluspair : phg4_keys)
550  {
551  vec.push_back(comp->clusloc_PHG4(cluspair));
552  }
553  return vec;
554  }
555 
556  std::vector<ClusLoc> ClusCntr::phg4_clusloc_unmatched()
557  {
558  std::vector<ClusLoc> vec{};
559  auto cnt = phg4_keys.size();
560  for (unsigned int i = 0; i < cnt; ++i)
561  {
562  if (!phg4_matches[i])
563  {
564  vec.push_back(comp->clusloc_PHG4(phg4_keys[i]));
565  }
566  }
567  return vec;
568  }
569 
570  std::vector<ClusLoc> ClusCntr::svtx_clusloc_all()
571  {
572  std::vector<ClusLoc> vec{};
573  for (auto& cluspair : svtx_keys)
574  {
575  vec.push_back(comp->clusloc_SVTX(cluspair));
576  }
577  return vec;
578  }
579 
580  std::vector<ClusLoc> ClusCntr::svtx_clusloc_unmatched()
581  {
582  std::vector<ClusLoc> vec{};
583  auto cnt = svtx_keys.size();
584  for (unsigned int i = 0; i < cnt; ++i)
585  {
586  if (!svtx_matches[i])
587  {
588  vec.push_back(comp->clusloc_SVTX(svtx_keys[i]));
589  }
590  }
591  return vec;
592  }
593 
594  std::vector<ClusLoc> ClusCntr::clusloc_matched()
595  {
596  std::vector<ClusLoc> vec{};
597  auto cnt = phg4_keys.size();
598  for (unsigned int i = 0; i < cnt; ++i)
599  {
600  if (phg4_matches[i])
601  {
602  vec.push_back(comp->clusloc_PHG4(phg4_keys[i]));
603  }
604  }
605  return vec;
606  }
607 
608  /* ClusCntr::layer_xyzLoc ClusCntr::xyzLoc(std::pair<TrkrDefs::hitsetkey,TrkrDefs::cluskey) { */
609  /* if (geom == nullptr) { */
610  /* std::cout << PHWHERE << " fatal: geom, type ActsGeometry*, must be set to call xyzLoc!" << std::endl; */
611  /* return {-1,{FLT_MAX,FLT_MAX,FLT_MAX}}; */
612  /* } */
613  /* Eigen::Vector3d gloc = m_ActsGeometry->getGlobalPosition(reco_ckey, cluster); */
614  /* } */
615 
616 } // namespace G4Eval