Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TpcPrototypeGenFitTrkFinder.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TpcPrototypeGenFitTrkFinder.cc
1 
9 
10 #include <trackbase/TrkrCluster.h> // for TrkrCluster
12 #include <trackbase/TrkrDefs.h>
14 
18 #include <trackbase_historic/SvtxVertexMap.h>
19 
21 #include <trackbase_historic/SvtxVertexMap_v1.h>
22 
23 #include <phgenfit/Fitter.h>
24 #include <phgenfit/PlanarMeasurement.h>
25 #include <phgenfit/Track.h>
26 
28 #include <fun4all/PHTFileServer.h>
29 #include <fun4all/SubsysReco.h> // for SubsysReco
30 
31 #include <phool/PHCompositeNode.h>
32 #include <phool/PHIODataNode.h>
33 #include <phool/PHNode.h> // for PHNode
34 #include <phool/PHNodeIterator.h>
35 #include <phool/PHObject.h> // for PHObject
36 #include <phool/getClass.h>
37 #include <phool/phool.h>
38 
39 #include <phfield/PHFieldUtility.h>
40 #include <phgeom/PHGeomUtility.h>
41 
42 #include <GenFit/EventDisplay.h> // for EventDisplay
43 #include <GenFit/RKTrackRep.h>
44 
45 #include <TClonesArray.h>
46 #include <TMatrixDSymfwd.h> // for TMatrixDSym
47 #include <TMatrixTSym.h> // for TMatrixTSym
48 #include <TMatrixTUtils.h> // for TMatrixTRow
49 #include <TTree.h>
50 #include <TVector3.h>
51 
52 #include <algorithm> // for find
53 #include <set> // for set
54 
55 #include <cassert>
56 #include <iostream>
57 #include <map>
58 #include <memory>
59 #include <utility>
60 #include <vector>
61 
62 class PHField;
63 class TGeoManager;
64 namespace genfit
65 {
66 class AbsTrackRep;
67 }
68 namespace PHGenFit { class Measurement; }
69 
70 #define LogDebug(exp) std::cout << "DEBUG: " << __FILE__ << ": " << __LINE__ << ": " << exp << std::endl
71 #define LogError(exp) std::cout << "ERROR: " << __FILE__ << ": " << __LINE__ << ": " << exp << std::endl
72 #define LogWarning(exp) std::cout << "WARNING: " << __FILE__ << ": " << __LINE__ << ": " << exp << std::endl
73 
74 #define WILD_FLOAT -9999.
75 
76 #define _DEBUG_MODE_ 0
77 
78 //#define _DEBUG_
79 
80 using namespace std;
81 
82 /*
83  * Constructor
84  */
86  : SubsysReco(name)
87  , _fitter(nullptr)
88  , _track_fitting_alg_name("KalmanFitter")
89  , nLayer(layers)
90  , minLayer(8)
91  , maxTracklet(50)
92  , _primary_pid_guess(2212)
93  , rphiWindow(2)
94  , ZWindow(2)
95  , _clustermap(nullptr)
96  , _trackmap(nullptr)
97  , _assoc_container(nullptr)
98  , _vertexmap(nullptr)
99  , _do_eval(false)
100  , _eval_outname("TpcPrototypeGenFitTrkFinder_eval.root")
101  , _eval_tree(nullptr)
102  , _tca_ntrack(-1)
103  , _tca_trackmap(nullptr)
104  , _do_evt_display(false)
105 {
106  Verbosity(0);
107 
108  _event = 0;
109 
110  _cluster_eval_tree = nullptr;
117 }
118 
119 /*
120  * Init
121  */
123 {
124  // CreateNodes(topNode);
125 
127 }
128 
129 /*
130  * Init run
131  */
133 {
134  CreateNodes(topNode);
135 
136  TGeoManager* tgeo_manager = PHGeomUtility::GetTGeoManager(topNode);
137  PHField* field = PHFieldUtility::GetFieldMapNode(nullptr, topNode);
138 
139  //_fitter = new PHGenFit::Fitter("sPHENIX_Geo.root","sPHENIX.2d.root", 1.4 / 1.5);
140  _fitter = PHGenFit::Fitter::getInstance(tgeo_manager,
142  "RKTrackRep", _do_evt_display);
144 
145  if (_do_eval)
146  {
147  if (Verbosity() >= 1)
148  cout << PHWHERE << " Openning file: " << _eval_outname << endl;
149  PHTFileServer::get().open(_eval_outname, "RECREATE");
150  init_eval_tree();
151  }
152 
154 }
155 /*
156  * process_event():
157  * Call user instructions for every event.
158  * This function contains the analysis structure.
159  *
160  */
162 {
163  _event++;
164 
165  if (Verbosity() > 1)
166  std::cout << PHWHERE << "Events processed: " << _event << std::endl;
167  // if (_event % 1000 == 0)
168  // cout << PHWHERE << "Events processed: " << _event << endl;
169 
170  //cout << "Start TpcPrototypeGenFitTrkFinder::process_event" << endl;
171 
172  GetNodes(topNode);
173 
174  vector<std::shared_ptr<PHGenFit::Track> > rf_phgf_tracks;
175  // rf_phgf_tracks.clear();
176 
177  // Need to keep tracks if _do_evt_display
178  if (!_do_evt_display)
179  {
180  rf_phgf_tracks.clear();
181  }
182 
184  set<tracklet_t> tracklets;
185 
186  //progressive search track finding
187  for (int layer = 0; layer < nLayer; ++layer)
188  {
189  set<tracklet_t> new_tracklets(tracklets);
190  auto cluster_range = _clustermap->getClusters(TrkrDefs::tpcId, layer);
191 
192  for (auto iter = cluster_range.first; iter != cluster_range.second; ++iter)
193  {
194  const TrkrCluster* cluster = iter->second;
195  assert(cluster);
196 
197  TVector3 pos(cluster->getPosition(0), cluster->getPosition(1), cluster->getPosition(2));
198  TVector3 n(cluster->getPosition(0), cluster->getPosition(1), 0);
199 
200  TVector3 n_dir(cluster->getPosition(0), cluster->getPosition(1), 0);
201  n_dir.SetMag(1);
202  TVector3 z_dir(0, 0, 1);
203  TVector3 azimuth_dir(z_dir.Cross(n_dir));
204 
205  bool matched = false;
206  for (const auto tracklet : tracklets)
207  {
208  assert(tracklet.size() >= 1);
209  const TrkrCluster* last_cluster = tracklet.back();
210  assert(last_cluster);
211 
212  TVector3 last_pos(last_cluster->getPosition(0), last_cluster->getPosition(1), last_cluster->getPosition(2));
213 
214  TVector3 pos_diff = pos - last_pos;
215  const double n_residual = pos_diff.Dot(n_dir);
216  const double z_residual = pos_diff.Dot(z_dir);
217  const double azimuth_residual = pos_diff.Dot(azimuth_dir);
218 
219  assert(n_residual > 0);
220  const double z_diff = z_residual / n_residual;
221  const double azimuth_diff = azimuth_residual / n_residual;
222  if (abs(azimuth_diff) < rphiWindow and abs(z_diff) < ZWindow)
223  { //have match
224 
225  if (Verbosity() >= 2)
226  {
227  cout << __PRETTY_FUNCTION__ << " adding cluster at layer " << layer << " to tracklet length " << tracklet.size() << endl;
228  }
229 
230  auto iter_old_tracklet =
231  new_tracklets.find(tracklet);
232  if (iter_old_tracklet != new_tracklets.end())
233  new_tracklets.erase(iter_old_tracklet); //remove the shorter tracklet
234 
235  tracklet_t new_tracklet(tracklet);
236  new_tracklet.push_back(cluster);
237  new_tracklets.insert(new_tracklet); // insert the longer tracklet
238  matched = true;
239 
240  if (new_tracklets.size() >= maxTracklet)
241  {
242  if (Verbosity())
243  cout << __PRETTY_FUNCTION__ << " skipping rest tracklet at layer " << layer
244  << " due to tracklet count " << new_tracklets.size() << " > " << maxTracklet << endl;
245  break;
246  }
247  } //have match
248 
249  } // for (auto& tracklet : tracklets)
250 
251  if (new_tracklets.size() >= maxTracklet)
252  {
253  if (Verbosity())
254  cout << __PRETTY_FUNCTION__ << " skipping rest clusters at layer " << layer
255  << " due to tracklet count " << new_tracklets.size() << " > " << maxTracklet << endl;
256  break;
257  }
258 
259  if (not matched)
260  { //new track seed from unused cluster
261  new_tracklets.insert(tracklet_t(1, cluster));
262  if (Verbosity() >= 2)
263  {
264  cout << __PRETTY_FUNCTION__ << " init tracket with cluster at layer " << layer << endl;
265  }
266  } // if (not matched)
267 
268  } // for (auto iter = cluster_range.first; iter != cluster_range.second; ++iter)
269 
270  tracklets = new_tracklets;
271  } // for (int layer = 0; layer < nLayer; ++layer)
272 
273  if (Verbosity())
274  {
275  cout << __PRETTY_FUNCTION__ << "print initial trackets: ";
276  for (const auto& tracklet : tracklets)
277  {
278  cout << ","
279  << "size = " << tracklet.size();
280  }
281  cout << endl;
282  }
283 
284  // track quality map
285  multimap<double, tracklet_t> quality_tracklets_map;
286  for (const auto& tracklet : tracklets)
287  {
288  double chi2Ndf = getChi2Ndf(tracklet);
289  if (chi2Ndf > 0)
290  quality_tracklets_map.insert(std::pair<double, tracklet_t>(chi2Ndf, tracklet));
291  }
292  if (Verbosity())
293  {
294  cout << __PRETTY_FUNCTION__ << "print fitted trackets: ";
295  for (const auto& tracklet : quality_tracklets_map)
296  {
297  cout << ","
298  << "size = " << tracklet.second.size() << " chi2/ndf = " << tracklet.first;
299  }
300  cout << endl;
301  } // if (Verbosity())
302 
303  // deghost
304  for (auto iter_current = quality_tracklets_map.begin(); iter_current != quality_tracklets_map.end(); ++iter_current)
305  {
306  const tracklet_t& track_current = iter_current->second;
307 
308  auto iter_check = iter_current;
309  ++iter_check;
310  for (; iter_check != quality_tracklets_map.end();)
311  {
312  const tracklet_t& track_check = iter_check->second;
313 
314  unsigned int identical_cluster = 0;
315 
316  for (const auto cluster : track_current)
317  {
318  assert(cluster);
319 
320  if (find(track_check.begin(), track_check.end(), cluster) != track_check.end())
321  ++identical_cluster;
322  }
323 
324  if (identical_cluster >= track_current.size() / 3 or identical_cluster >= track_check.size() / 3)
325  {
326  if (Verbosity())
327  {
328  cout << __PRETTY_FUNCTION__ << " found " << identical_cluster << "-shared ghost track size" << track_check.size() << " chi2ndf" << iter_check->first //
329  << " from base track size" << track_current.size() << " chi2ndf" << iter_current->first << endl;
330  }
331 
332  auto iter_tmp = iter_check;
333  ++iter_check;
334 
335  quality_tracklets_map.erase(iter_tmp);
336  }
337  else
338  {
339  if (Verbosity())
340  {
341  cout << __PRETTY_FUNCTION__ << "low " << identical_cluster << "-shared track size" << track_check.size() << " chi2ndf" << iter_check->first //
342  << " from base track size" << track_current.size() << " chi2ndf" << iter_current->first << endl;
343  }
344  ++iter_check;
345  }
346  }
347  }
348  if (Verbosity())
349  {
350  cout << __PRETTY_FUNCTION__ << "print deghosted trackets: ";
351  for (const auto& tracklet : quality_tracklets_map)
352  {
353  cout << ","
354  << "size = " << tracklet.second.size() << " chi2/ndf = " << tracklet.first;
355  }
356  cout << endl;
357  } // if (Verbosity())
358 
359  //output
360  assert(_trackmap);
362  for (const auto& quality_tracklet : quality_tracklets_map)
363  {
364  const tracklet_t& tracklet = quality_tracklet.second;
365  assert(tracklet.front());
366  assert(tracklet.back());
367  TVector3 pos_front(tracklet.front()->getPosition(0), tracklet.front()->getPosition(1), tracklet.front()->getPosition(2));
368  TVector3 pos_back(tracklet.back()->getPosition(0), tracklet.back()->getPosition(1), tracklet.back()->getPosition(2));
369 
370  TVector3 seed_mom(pos_back - pos_front);
371  seed_mom.SetMag(120);
372 
373  TVector3 seed_pos(pos_front);
374 
375  std::unique_ptr<SvtxTrack_v1> svtx_track(new SvtxTrack_v1());
376 
377  svtx_track->set_id(_trackmap->size());
378 
379  // dummy values, set px to make it through the minimum pT cut
380  svtx_track->set_px(seed_mom.x());
381  svtx_track->set_py(seed_mom.y());
382  svtx_track->set_pz(seed_mom.z());
383  svtx_track->set_x(seed_pos.x());
384  svtx_track->set_y(seed_pos.y());
385  svtx_track->set_z(seed_pos.z());
386  for (const TrkrCluster* cluster : tracklet)
387  {
388  svtx_track->insert_cluster_key(cluster->getClusKey());
389  _assoc_container->SetClusterTrackAssoc(cluster->getClusKey(), svtx_track->get_id());
390  }
391 
392  _trackmap->insert(svtx_track.get());
393  }
394 
395  if (_do_eval)
396  {
397  fill_eval_tree(topNode);
398  }
400 }
401 
403 {
405 
406  if (tracklet.size() < minLayer)
407  {
408  if (Verbosity())
409  {
410  cout << __PRETTY_FUNCTION__ << " drop short tracklet size = " << tracklet.size() << " < " << minLayer << endl;
411  }
412  return -1;
413  }
414 
415  // prepare seed
416  assert(tracklet.front());
417  assert(tracklet.back());
418  TVector3 pos_front(tracklet.front()->getPosition(0), tracklet.front()->getPosition(1), tracklet.front()->getPosition(2));
419  TVector3 pos_back(tracklet.back()->getPosition(0), tracklet.back()->getPosition(1), tracklet.back()->getPosition(2));
420 
421  TVector3 seed_mom(pos_back - pos_front);
422  seed_mom.SetMag(120);
423 
424  TVector3 seed_pos(pos_front);
425  TMatrixDSym seed_cov(6);
426  for (int i = 0; i < 6; i++)
427  {
428  for (int j = 0; j < 6; j++)
429  {
430  seed_cov[i][j] = 100.;
431  }
432  }
433 
434  // Create measurements
435  std::vector<PHGenFit::Measurement*> measurements;
436  for (const auto cluster : tracklet)
437  {
438  assert(cluster);
439  if (Verbosity() >= 2)
440  {
441  TrkrDefs::cluskey cluster_key = cluster->getClusKey();
442  int layer = TrkrDefs::getLayer(cluster_key);
443 
444  cout << __PRETTY_FUNCTION__ << "add cluster on layer " << layer << ": ";
445  cluster->identify();
446  }
447  TVector3 pos(cluster->getPosition(0), cluster->getPosition(1), cluster->getPosition(2));
448 
449  //TODO use u, v explicitly?
450  TVector3 n(cluster->getPosition(0), cluster->getPosition(1), 0);
451 
453  cluster->getRPhiError(),
454  cluster->getZError());
455 
456  measurements.push_back(meas);
457 
458  } // for (const auto cluster : clusterLayer)
459 
460  // do the fit
462  std::shared_ptr<PHGenFit::Track> phgf_track(new PHGenFit::Track(rep, seed_pos, seed_mom,
463  seed_cov));
464  phgf_track->addMeasurements(measurements);
465  if (_fitter->processTrack(phgf_track.get(), false) != 0)
466  {
467  if (Verbosity() >= 1)
468  {
469  LogWarning("Track fitting failed");
470  cout << __PRETTY_FUNCTION__ << " track->getChisq() " << phgf_track->get_chi2() << " get_ndf " << phgf_track->get_ndf()
471  << " mom.X " << phgf_track->get_mom().X()
472  << " mom.Y " << phgf_track->get_mom().Y()
473  << " mom.Z " << phgf_track->get_mom().Z()
474  << endl;
475  }
476  //delete track;
477  return -1;
478  }
479 
480  if (Verbosity() >= 1)
481  {
482  cout << __PRETTY_FUNCTION__ << " track->getChisq() " << phgf_track->get_chi2() << " get_ndf " << phgf_track->get_ndf()
483  << " mom.X " << phgf_track->get_mom().X()
484  << " mom.Y " << phgf_track->get_mom().Y()
485  << " mom.Z " << phgf_track->get_mom().Z()
486  << endl;
487  }
488  return phgf_track->get_chi2() / phgf_track->get_ndf();
489 }
490 
491 /*
492  * End
493  */
495 {
496  if (_do_eval)
497  {
498  if (Verbosity() >= 1)
499  cout << PHWHERE << " Writing to file: " << _eval_outname << endl;
501  _eval_tree->Write();
502  _cluster_eval_tree->Write();
503  }
504 
505  if (_do_evt_display)
506  {
507  // if(opts[i] == 'A') drawAutoScale_ = true;
508  // if(opts[i] == 'B') drawBackward_ = true;
509  // if(opts[i] == 'D') drawDetectors_ = true;
510  // if(opts[i] == 'E') drawErrors_ = true;
511  // if(opts[i] == 'F') drawForward_ = true;
512  // if(opts[i] == 'H') drawHits_ = true;
513  // if(opts[i] == 'M') drawTrackMarkers_ = true;
514  // if(opts[i] == 'P') drawPlanes_ = true;
515  // if(opts[i] == 'S') drawScaleMan_ = true;
516  // if(opts[i] == 'T') drawTrack_ = true;
517  // if(opts[i] == 'X') drawSilent_ = true;
518  // if(opts[i] == 'G') drawGeometry_ = true;
519  _fitter->getEventDisplay()->setOptions("ADEHPTG");
520 
522  }
524 }
525 
526 /*
527  * dtor
528  */
530 {
531  delete _fitter;
532 }
533 
534 /*
535  * fill_eval_tree():
536  */
538 {
541 
542  int i = 0;
544  itr != _trackmap->end(); ++itr)
545  {
546  new ((*_tca_trackmap)[i])(SvtxTrack_v1)(
547  *dynamic_cast<SvtxTrack_v1*>(itr->second));
548  }
549  _tca_ntrack = i;
550 
551  _eval_tree->Fill();
552 
553  return;
554 }
555 
556 /*
557  * init_eval_tree
558  */
560 {
561  if (!_tca_trackmap)
562  _tca_trackmap = new TClonesArray("SvtxTrack_v1");
563 
565  _eval_tree = new TTree("T", "TpcPrototypeGenFitTrkFinder Evaluation");
566  _eval_tree->Branch("nTrack", &_tca_ntrack, "nTrack/I");
567 
568  // _eval_tree->Branch("PrimaryParticle", _tca_particlemap);
569  // _eval_tree->Branch("TruthVtx", _tca_vtxmap);
570 
571  _eval_tree->Branch("SvtxTrack", _tca_trackmap);
572 
573  _cluster_eval_tree = new TTree("cluster_eval", "cluster eval tree");
574  _cluster_eval_tree->Branch("x", &_cluster_eval_tree_x, "x/F");
575  _cluster_eval_tree->Branch("y", &_cluster_eval_tree_y, "y/F");
576  _cluster_eval_tree->Branch("z", &_cluster_eval_tree_z, "z/F");
577  _cluster_eval_tree->Branch("gx", &_cluster_eval_tree_gx, "gx/F");
578  _cluster_eval_tree->Branch("gy", &_cluster_eval_tree_gy, "gy/F");
579  _cluster_eval_tree->Branch("gz", &_cluster_eval_tree_gz, "gz/F");
580 }
581 
582 /*
583  * reset_eval_variables():
584  * Reset all the tree variables to their default values.
585  * Needs to be called at the start of every event
586  */
588 {
589  _tca_ntrack = -1;
590  _tca_trackmap->Clear();
591 
598 }
599 
601 {
602  // create nodes...
603  PHNodeIterator iter(topNode);
604 
605  PHCompositeNode* dstNode = static_cast<PHCompositeNode*>(iter.findFirst(
606  "PHCompositeNode", "DST"));
607  if (!dstNode)
608  {
609  cerr << PHWHERE << "DST Node missing, doing nothing." << endl;
611  }
612  PHNodeIterator iter_dst(dstNode);
613 
614  // Create the SVTX node
615  PHCompositeNode* tb_node = dynamic_cast<PHCompositeNode*>(iter_dst.findFirst(
616  "PHCompositeNode", "SVTX"));
617  if (!tb_node)
618  {
619  tb_node = new PHCompositeNode("SVTX");
620  dstNode->addNode(tb_node);
621  if (Verbosity() > 0)
622  cout << "SVTX node added" << endl;
623  }
624 
627  _trackmap, "SvtxTrackMap", "PHObject");
628  tb_node->addNode(tracks_node);
629  if (Verbosity() > 0)
630  cout << "Svtx/SvtxTrackMap node added" << endl;
631 
633  PHIODataNode<PHObject>* vertexes_node = new PHIODataNode<PHObject>(
634  _vertexmap, "SvtxVertexMap", "PHObject");
635  tb_node->addNode(vertexes_node);
636  if (Verbosity() > 0)
637  cout << "Svtx/SvtxVertexMap node added" << endl;
638 
641  _assoc_container, "AssocInfoContainer", "PHObject");
642  tb_node->addNode(assoc_node);
643  if (Verbosity() > 0)
644  cout << "Svtx/AssocInfoContainer node added" << endl;
646 }
647 
648 /*
649  * GetNodes():
650  * Get all the all the required nodes off the node tree
651  */
653 {
654  // Input Svtx Clusters
655  //_clustermap = findNode::getClass<SvtxClusterMap>(topNode, "SvtxClusterMap");
656  _clustermap = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
657  if (!_clustermap && _event < 2)
658  {
660  }
661 
662  // Input Svtx Tracks
663  _trackmap = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
664  if (!_trackmap && _event < 2)
665  {
666  cout << PHWHERE << " SvtxTrackMap node not found on node tree"
667  << endl;
669  }
670 
671  // Input Svtx Vertices
672  _vertexmap = findNode::getClass<SvtxVertexMap>(topNode, "SvtxVertexMap");
673  if (!_vertexmap && _event < 2)
674  {
675  cout << PHWHERE << " SvtxVertexrMap node not found on node tree"
676  << endl;
678  }
679 
681 }