ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHActsInitialVertexFinder.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHActsInitialVertexFinder.cc
2 
4 
7 #include <phool/PHIODataNode.h>
8 #include <phool/PHObject.h>
9 #include <phool/getClass.h>
10 #include <phool/phool.h>
11 #include <phool/PHRandomSeed.h>
12 
13 #if __cplusplus < 201402L
14 #include <boost/make_unique.hpp>
15 #endif
16 
22 
23 #include <ActsExamples/Plugins/BField/BFieldOptions.hpp>
24 #include <ActsExamples/Plugins/BField/ScalableBField.hpp>
25 
36 #include <Acts/Utilities/Units.hpp>
46 
49 
50 #include <memory>
51 
53  : PHInitVertexing(name)
54 {}
55 
57 {
60 
63 
64  m_seed = PHRandomSeed();
66 
68 }
69 
71 {
72  if(Verbosity() > 0)
73  std::cout << "PHActsInitialVertexFinder processing event "
74  << m_event << std::endl;
75 
76  if(m_trackMap->size() == 0)
77  {
78  std::cout << PHWHERE
79  << "No silicon track seeds found. Can't run initial vertexing, setting dummy vertex of (0,0,0)"
80  << std::endl;
81  createDummyVertex(0,0,0);
82  }
83  else if(m_trackMap->size() == 1)
84  {
85  auto track = m_trackMap->get(0);
86  createDummyVertex(track->get_x(),
87  track->get_y(),
88  track->get_z());
89  }
90  else
91  {
92  InitKeyMap keyMap;
93  auto trackPointers = getTrackPointers(keyMap);
94 
95  auto vertices = findVertices(trackPointers);
96 
97  fillVertexMap(vertices, keyMap);
98 
102 
103  for(auto track : trackPointers)
104  {
105  delete track;
106  }
107  }
108 
109  if(Verbosity() > 0)
110  std::cout << "PHActsInitialVertexFinder processed event "
111  << m_event << std::endl;
112 
113  m_event++;
114 
116 }
117 
119 {
121 }
122 
124 {
125 
126  std::cout << "Acts IVF succeeded " << m_successFits
127  << " out of " << m_totVertexFits << " total fits"
128  << std::endl;
129 
131 }
132 
134 {
135 
136  for(auto& [trackKey, track] : *m_trackMap)
137  {
142  if(track->get_vertex_id() != UINT_MAX)
143  continue;
144 
145  const auto trackZ = track->get_z();
146 
147  double closestVertZ = 9999;
148  int vertId = -1;
149  for(auto& [vertexKey, vertex] : *m_vertexMap)
150  {
151  double dz = fabs(trackZ - vertex->get_z());
152 
153  if(dz < closestVertZ)
154  {
155  vertId = vertexKey;
156  closestVertZ = dz;
157  }
158 
159  }
160 
161  auto vertex = m_vertexMap->get(vertId);
162  vertex->insert_track(trackKey);
163  track->set_vertex_id(vertId);
164  }
165 
166 }
168  InitKeyMap& keyMap)
169 {
170  unsigned int vertexId = 0;
171  if(vertices.size() != 0)
172  m_vertexMap->clear();
173 
176  if(vertices.size() == 0)
177  {
178  createDummyVertex(0,0,0);
179  if(Verbosity() > 1)
180  std::cout << "No vertices found. Adding a dummy vertex"
181  << std::endl;
182  return;
183  }
184 
185  for(auto vertex : vertices)
186  {
187  const auto &[chi2, ndf] = vertex.fitQuality();
188  const auto numTracks = vertex.tracks().size();
189 
190  if(Verbosity() > 1)
191  {
192  std::cout << "Found vertex at (" << vertex.position().x()
193  << ", " << vertex.position().y() << ", "
194  << vertex.position().z() << ")" << std::endl;
195  std::cout << "Vertex has ntracks = " << numTracks
196  << " with chi2/ndf " << chi2 / ndf << std::endl;
197  }
198 
200  #if __cplusplus < 201402L
201  auto svtxVertex = boost::make_unique<SvtxVertex_v1>();
202  #else
203  auto svtxVertex = std::make_unique<SvtxVertex_v1>();
204  #endif
205 
206  svtxVertex->set_x(vertex.position().x() / Acts::UnitConstants::cm);
207  svtxVertex->set_y(vertex.position().y() / Acts::UnitConstants::cm);
208  svtxVertex->set_z(vertex.position().z() / Acts::UnitConstants::cm);
209  for(int i = 0; i < 3; ++i)
210  for(int j = 0; j < 3; ++j)
211  svtxVertex->set_error(i, j,
212  vertex.covariance()(i,j)
214 
215  svtxVertex->set_chisq(chi2);
216  svtxVertex->set_ndof(ndf);
217  svtxVertex->set_t0(vertex.time());
218  svtxVertex->set_id(vertexId);
219 
220  for(const auto& track : vertex.tracks())
221  {
222  const auto originalParams = track.originalParams;
223 
224  const auto trackKey = keyMap.find(originalParams)->second;
225  svtxVertex->insert_track(trackKey);
226 
228  const auto svtxTrack = m_trackMap->find(trackKey)->second;
229 
230  if(Verbosity() > 3)
231  {
232  svtxTrack->identify();
233  std::cout << "Updating track key " << trackKey << " with vertex "
234  << vertexId << std::endl;
235  }
236 
237  svtxTrack->set_vertex_id(vertexId);
238  }
239 
240  m_vertexMap->insert(svtxVertex.release());
241 
242  ++vertexId;
243  }
244 
245  return;
246 }
247 
249  const float y,
250  const float z)
251 {
252 
257 
258  #if __cplusplus < 201402L
259  auto svtxVertex = boost::make_unique<SvtxVertex_v1>();
260  #else
261  auto svtxVertex = std::make_unique<SvtxVertex_v1>();
262  #endif
263 
264  svtxVertex->set_x(x);
265  svtxVertex->set_y(y);
266  svtxVertex->set_z(z);
267 
268  for(int i = 0; i < 3; ++i)
269  for(int j = 0; j < 3; ++j)
270  {
271  if( i == j)
272  svtxVertex->set_error(i, j, 10.);
273  else
274  svtxVertex->set_error(i,j, 0);
275  }
276 
277  float nan = NAN;
278  svtxVertex->set_chisq(nan);
279  svtxVertex->set_ndof(nan);
280  svtxVertex->set_t0(nan);
281  svtxVertex->set_id(0);
282 
283  m_vertexMap->insert(svtxVertex.release());
284  std::cout << "Created dummy vertex at " << x << ", " << y << ", " << z
285  << std::endl;
286  for(auto& [key, track] : *m_trackMap)
287  track->set_vertex_id(0);
288 
289 }
290 
292 {
293 
294  m_totVertexFits++;
295 
296  auto field = m_tGeometry->magField;
297 
300  return std::visit([tracks, this](auto &inputField) {
302  using InputMagneticField =
303  typename std::decay_t<decltype(inputField)>::element_type;
304  using MagneticField = Acts::SharedBField<InputMagneticField>;
305 
310  using VertexFitter =
312  using ImpactPointEstimator =
314  using VertexSeeder = Acts::ZScanVertexFinder<VertexFitter>;
315  using VertexFinder =
317  using VertexFinderOptions = Acts::VertexingOptions<TrackParameters>;
318 
319  static_assert(Acts::VertexFinderConcept<VertexSeeder>,
320  "VertexSeeder does not fulfill vertex finder concept.");
321  static_assert(Acts::VertexFinderConcept<VertexFinder>,
322  "VertexFinder does not fulfill vertex finder concept.");
323 
324  auto logLevel = Acts::Logging::FATAL;
325  if(Verbosity() > 4)
326  logLevel = Acts::Logging::VERBOSE;
327  auto logger = Acts::getDefaultLogger("PHActsInitialVertexFinder",
328  logLevel);
329 
330  MagneticField bField(inputField);
331  auto propagator = std::make_shared<Propagator>(Stepper(bField));
332 
334  typename VertexFitter::Config vertexFitterConfig;
335 
341  vertexFitterConfig.maxIterations = 1;
342 
343  VertexFitter vertexFitter(std::move(vertexFitterConfig));
344 
345  typename Linearizer::Config linearizerConfig(bField, propagator);
346  Linearizer linearizer(std::move(linearizerConfig));
347 
348  typename ImpactPointEstimator::Config ipEstConfig(bField, propagator);
349  ImpactPointEstimator ipEst(std::move(ipEstConfig));
350 
351  typename VertexSeeder::Config seederConfig(ipEst);
352 
355  if(m_disableWeights)
356  seederConfig.disableAllWeights = true;
357  VertexSeeder seeder(std::move(seederConfig));
358 
359  typename VertexFinder::Config finderConfig(std::move(vertexFitter),
360  std::move(linearizer),
361  std::move(seeder), ipEst);
362  finderConfig.maxVertices = m_maxVertices;
363  finderConfig.reassignTracksAfterFirstFit = true;
364  VertexFinder finder(finderConfig, std::move(logger));
365 
367  VertexFinderOptions finderOptions(m_tGeometry->geoContext,
369 
370  auto result = finder.find(tracks, finderOptions, state);
371 
372  VertexVector vertexVector;
373 
374  if(result.ok())
375  {
376  m_successFits++;
377 
378  auto vertexCollection = *result;
379 
380  if(Verbosity() > 1)
381  {
382  std::cout << "Acts IVF found " << vertexCollection.size()
383  << " vertices in event" << std::endl;
384  }
385 
386  for(const auto& vertex : vertexCollection)
387  {
388  vertexVector.push_back(vertex);
389  }
390  }
391  else
392  {
393  if(Verbosity() > 0)
394  {
395  std::cout << "Acts initial vertex finder returned error: "
396  << result.error().message() << std::endl;
397  std::cout << "Track positions IVF used are : " << std::endl;
398  for(const auto track : tracks)
399  {
400  const auto position = track->position(m_tGeometry->geoContext);
401  std::cout << "(" << position(0) << ", " << position(1)
402  << ", " << position(2) << std::endl;
403  }
404  }
405  }
406 
407  return vertexVector;
408 
409  }
410  , field
411  );
412 
413 }
414 
415 std::vector<SvtxTrack*> PHActsInitialVertexFinder::sortTracks()
416 {
417 
422 
423  std::vector<Acts::Vector3D> centroids(m_nCentroids);
424  std::uniform_int_distribution<int> indices(0,m_trackMap->size() - 1);
425  std::vector<int> usedIndices;
426 
428  for(auto& centroid : centroids)
429  {
430  auto index = indices(m_random_number_generator);
431  for(const auto used : usedIndices)
432  if(index == used)
433  index = indices(m_random_number_generator);
434 
435  usedIndices.push_back(index);
436 
437  centroid = Acts::Vector3D(m_trackMap->get(index)->get_x(),
438  m_trackMap->get(index)->get_y(),
439  m_trackMap->get(index)->get_z());
440 
441  if(Verbosity() > 3)
442  {
443  std::cout << "Centroid is (" << centroid(0)
444  << ", " << centroid(1) << ", "
445  << centroid(2) << ")" << std::endl;
446  }
447  }
448 
451  auto clusters = createCentroidMap(centroids);
452 
455  auto sortedTracks = getIVFTracks(clusters, centroids);
456 
457  return sortedTracks;
458 }
459 
461  CentroidMap& clusters,
462  std::vector<Acts::Vector3D>& centroids)
463 {
464 
465  std::vector<SvtxTrack*> sortedTracks;
466 
467  if(Verbosity() > 2)
468  {
469  std::cout << "Final centroids are : " << std::endl;
470  for(const auto& [centroidIndex, trackVec] : clusters)
471  {
472  std::cout << "Centroid: " << centroids.at(centroidIndex).transpose()
473  << " has tracks " << std::endl;
474  for(const auto& track : trackVec)
475  {
476  std::cout << "(" << track->get_x() << ", "
477  << track->get_y() << ", " << track->get_z()
478  << ")" << std::endl;
479  }
480  }
481  }
482 
484  int maxTrackCentroid = 0;
485  std::vector<Acts::Vector3D> stddev(m_nCentroids);
486 
487  for(const auto& [centroidIndex, trackVec] : clusters)
488  {
489  Acts::Vector3D sum = Acts::Vector3D::Zero();
490  if(trackVec.size() > maxTrackCentroid)
491  {
492  maxTrackCentroid = trackVec.size();
493  }
494 
495  for(const auto& track : trackVec)
496  {
497  for(int i = 0; i < sum.rows(); i++)
498  {
499  sum(i) += pow(track->get_pos(i) - centroids.at(centroidIndex)(i), 2);
500  }
501  }
502  for(int i = 0; i < 3; i++)
503  {
504  stddev.at(centroidIndex)(i) = sqrt(sum(i) / trackVec.size());
505  }
506  }
507 
508  for(const auto& [centroidIndex, trackVec] : clusters)
509  {
513  if(trackVec.size() < 0.2 * maxTrackCentroid)
514  continue;
515 
517  float centroidR = sqrt(pow(centroids.at(centroidIndex)(0), 2) +
518  pow(centroids.at(centroidIndex)(1), 2));
519 
520  if(Verbosity() > 2)
521  {
522  std::cout << "Checking to add tracks from centroid "
523  << centroids.at(centroidIndex).transpose() << std::endl;
524  }
525 
526  if(centroidR > m_pcaCut)
527  {
528  continue;
529  }
530 
531  for(const auto& track : trackVec)
532  {
533  Acts::Vector3D pulls = Acts::Vector3D::Zero();
534  for(int i = 0; i < 3; i++)
535  {
536  pulls(i) = fabs(track->get_pos(i) - centroids.at(centroidIndex)(i)) / stddev.at(centroidIndex)(i);
537  }
538 
539  if(Verbosity() > 3)
540  {
541  std::cout << "Track pos is (" << track->get_x() << ", "
542  << track->get_y() << ", " << track->get_z()
543  << ") and pull is " << pulls.transpose() << std::endl;
544  }
545 
546  if ((pulls(0) < 2 and pulls(1) < 2 and pulls(2) < 2))
547  {
548  sortedTracks.push_back(track);
549  }
550  else
551  {
552  if(m_removeSeeds)
553  {
554  m_trackMap->erase(track->get_id());
555  }
556 
557  if(Verbosity() > 3)
558  {
559  std::cout << "Not adding track with pos (" << track->get_x()
560  << ", " << track->get_y() << ", " << track->get_z()
561  << ") as it is incompatible with centroid "
562  << centroids.at(centroidIndex).transpose()
563  << " with std dev "
564  << stddev.at(centroidIndex).transpose() << std::endl;
565  }
566  }
567  }
568  }
569 
570  return sortedTracks;
571 
572 }
573 
574 CentroidMap PHActsInitialVertexFinder::createCentroidMap(std::vector<Acts::Vector3D>& centroids)
575 {
576  CentroidMap clusters;
577 
578  for(int niter = 0; niter < m_nIterations; niter++)
579  {
581  clusters.clear();
582  for(unsigned int i = 0; i<m_nCentroids; i++)
583  {
584  std::vector<SvtxTrack*> vec;
585  clusters.insert(std::make_pair(i, vec));
586  }
587 
588  if(Verbosity() > 3)
589  {
590  for(int i =0; i< m_nCentroids; i++)
591  std::cout << "Starting centroid is : "
592  << centroids.at(i).transpose() << std::endl;
593  }
594  for(const auto& [key, track] : *m_trackMap)
595  {
596  Acts::Vector3D trackPos(track->get_x(),
597  track->get_y(),
598  track->get_z());
599 
600  double minDist = std::numeric_limits<double>::max();
601  unsigned int centKey = std::numeric_limits<unsigned int>::max();
602  for(int i = 0; i < centroids.size(); i++)
603  {
604  double dist = sqrt(pow(trackPos(0) - centroids.at(i)(0), 2) +
605  pow(trackPos(1) - centroids.at(i)(1), 2) +
606  pow(trackPos(2) - centroids.at(i)(2), 2));
607  if(dist < minDist)
608  {
609  minDist = dist;
610  centKey = i;
611  if(Verbosity() > 3)
612  {
613  std::cout << "mindist and centkey are "
614  << minDist << ", " << centKey
615  << std::endl;
616  }
617  }
618  }
619 
621  if(Verbosity() > 3)
622  {
623  std::cout << "adding track with " << trackPos.transpose()
624  << " to centroid "
625  << centroids.at(centKey).transpose() << std::endl;
626  }
627 
628  clusters.find(centKey)->second.push_back(track);
629  }
630 
632  std::vector<Acts::Vector3D> newCentroids(m_nCentroids);
633  for(auto& centroid : newCentroids)
634  centroid = Acts::Vector3D(0,0,0);
635 
636  for(const auto& [centroidVal, trackVec] : clusters)
637  {
638  for(const auto& track : trackVec)
639  {
640  for(int i = 0; i < 3; i++)
641  newCentroids.at(centroidVal)(i) += track->get_pos(i);
642  }
643 
645  centroids.at(centroidVal) =
646  newCentroids.at(centroidVal) / trackVec.size();
647  }
648 
649  if(Verbosity() > 3)
650  {
651  for(int i = 0; i < m_nCentroids; i++)
652  std::cout << "new centroids " << centroids.at(i).transpose()
653  << std::endl;
654 
655  for(const auto& [centKey, trackVec] : clusters)
656  {
657  std::cout << "cent key : " << centKey << " has " << trackVec.size()
658  << "tracks" << std::endl;
659  for(const auto track : trackVec)
660  {
661  std::cout << "track id : " << track->get_id()
662  << " with pos (" << track->get_x() << ", "
663  << track->get_y() << ", " << track->get_z()
664  << ")" << std::endl;
665 
666  }
667  }
668  }
669  }
670 
671  return clusters;
672 
673 }
674 
676 {
677  TrackParamVec tracks;
678 
682  if(m_trackMap->size() < m_nCentroids)
683  {
684  m_nCentroids = 1;
685  }
686 
687  std::vector<SvtxTrack*> sortedTracks;
688  if(m_svtxTrackMapName.find("Silicon") != std::string::npos)
689  {
690  sortedTracks = sortTracks();
691  }
692  else
693  {
694  for(const auto& [key, track] : *m_trackMap)
695  sortedTracks.push_back(track);
696  }
697 
698  for(const auto& track : sortedTracks)
699  {
700  if(Verbosity() > 3)
701  {
702  std::cout << "Adding track seed to vertex finder "
703  << std::endl;
704  track->identify();
705  }
706 
708  if(m_svtxTrackMapName.find("Silicon") != std::string::npos)
709  {
710  if(track->size_cluster_keys() < 5)
711  {
712  continue;
713  }
714  }
715 
716  const Acts::Vector4D stubVec(
717  track->get_x() * Acts::UnitConstants::cm,
718  track->get_y() * Acts::UnitConstants::cm,
719  track->get_z() * Acts::UnitConstants::cm,
721 
722  const Acts::Vector3D stubMom(track->get_px(),
723  track->get_py(),
724  track->get_pz());
725  int trackQ = track->get_charge() * Acts::UnitConstants::e;
726 
731  if(m_magField.find("3d") != std::string::npos)
732  trackQ *= -1;
733 
734  const double p = track->get_p();
735 
740  cov << 50 * Acts::UnitConstants::um, 0., 0., 0., 0., 0.,
741  0., 30 * Acts::UnitConstants::um, 0., 0., 0., 0.,
742  0., 0., 0.005, 0., 0., 0.,
743  0., 0., 0., 0.001, 0., 0.,
744  0., 0., 0., 0., 0.3 , 0.,
745  0., 0., 0., 0., 0., 1.;
746 
747  else
748  {
750  transform.setVerbosity(Verbosity());
751  cov = transform.rotateSvtxTrackCovToActs(track,
753  }
754 
756  auto perigee = Acts::Surface::makeShared<Acts::PerigeeSurface>(
757  Acts::Vector3D(stubVec(0),
758  stubVec(1),
759  stubVec(2)));
760 
761 
762  const auto param = new Acts::BoundTrackParameters(
763  perigee,
765  stubVec, stubMom,
766  p, trackQ, cov);
767 
768  tracks.push_back(param);
769  keyMap.insert(std::make_pair(param, track->get_id()));
770  }
771 
772  return tracks;
773 }
774 
776 {
777 
778  m_trackMap = findNode::getClass<SvtxTrackMap>(topNode, m_svtxTrackMapName.c_str());
779  if(!m_trackMap)
780  {
781  std::cout << PHWHERE << "No " << m_svtxTrackMapName.c_str()
782  << " on node tree, bailing."
783  << std::endl;
785  }
786 
787  m_tGeometry = findNode::getClass<ActsTrackingGeometry>(topNode,
788  "ActsTrackingGeometry");
789  if(!m_tGeometry)
790  {
791  std::cout << PHWHERE << "ActsTrackingGeometry not on node tree. Exiting"
792  << std::endl;
794  }
795 
796 
798 }
799 
801 {
802 
803  PHNodeIterator iter(topNode);
804 
805  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
806 
808  if (!dstNode)
809  {
810  std::cerr << "DST Node missing, quitting" << std::endl;
811  throw std::runtime_error("failed to find DST node in PHActsInitialVertexFinder::createNodes");
812  }
813 
815  PHCompositeNode *svtxNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "SVTX"));
816 
817  if (!svtxNode)
818  {
819  svtxNode = new PHCompositeNode("SVTX");
820  dstNode->addNode(svtxNode);
821  }
822 
823  m_vertexMap = findNode::getClass<SvtxVertexMap>(topNode,
824  m_svtxVertexMapName.c_str());
825 
826  if(!m_vertexMap)
827  {
830  m_vertexMap, m_svtxVertexMapName.c_str(),"PHObject");
831 
832  svtxNode->addNode(vertexNode);
833 
834  }
835 
836 
838 }