ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHActsTrkFitter.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHActsTrkFitter.cc
1 
8 #include "PHActsTrkFitter.h"
10 
13 #include <trackbase/TrkrCluster.h>
20 
22 #include <phool/PHCompositeNode.h>
23 #include <phool/getClass.h>
24 #include <phool/phool.h>
25 #include <phool/PHDataNode.h>
26 #include <phool/PHNode.h>
27 #include <phool/PHNodeIterator.h>
28 #include <phool/PHObject.h>
29 #include <phool/PHTimer.h>
30 
36 #include <Acts/EventData/MultiTrajectoryHelpers.hpp>
37 
38 #include <ActsExamples/EventData/Track.hpp>
39 #include <ActsExamples/Framework/AlgorithmContext.hpp>
40 
41 #include <cmath>
42 #include <iostream>
43 #include <vector>
44 
46  : SubsysReco(name)
47  , m_trajectories(nullptr)
48 {}
49 
51 {
52  if(Verbosity() > 1)
53  std::cout << "Setup PHActsTrkFitter" << std::endl;
54 
57 
58  if (getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK)
60 
61  m_fitCfg.fit = ActsExamples::TrkrClusterFittingAlgorithm::makeFitterFunction(
64 
65  m_fitCfg.dFit = ActsExamples::TrkrClusterFittingAlgorithm::makeFitterFunction(
67 
68  if(m_timeAnalysis)
69  {
70  m_timeFile = new TFile(std::string(Name() + ".root").c_str(),
71  "RECREATE");
72  h_eventTime = new TH1F("h_eventTime", ";time [ms]",
73  100000, 0, 10000);
74  h_fitTime = new TH2F("h_fitTime",";p_{T} [GeV];time [ms]",
75  80, 0, 40, 100000, 0, 1000);
76  h_updateTime = new TH1F("h_updateTime",";time [ms]",
77  100000, 0, 1000);
78 
79  h_rotTime = new TH1F("h_rotTime", ";time [ms]",
80  100000, 0, 1000);
81  h_stateTime = new TH1F("h_stateTime", ";time [ms]",
82  100000, 0, 1000);
83  }
84 
85  if(Verbosity() > 1)
86  std::cout << "Finish PHActsTrkFitter Setup" << std::endl;
87 
89 }
90 
92 {
93  PHTimer eventTimer("eventTimer");
94  eventTimer.stop();
95  eventTimer.restart();
96 
97  m_event++;
98 
99  auto logLevel = Acts::Logging::FATAL;
100 
101  if (Verbosity() > 1)
102  {
103  std::cout << PHWHERE << "Events processed: " << m_event << std::endl;
104  std::cout << "Start PHActsTrkFitter::process_event" << std::endl;
105  if(Verbosity() > 4)
106  logLevel = Acts::Logging::VERBOSE;
107  }
108 
111  if(m_actsEvaluator)
112  {
115  m_seedTracks->clear();
116  for(const auto& [key, track] : *m_trackMap)
117  {
119  }
120  }
121 
122  loopTracks(logLevel);
123 
124  eventTimer.stop();
125  auto eventTime = eventTimer.get_accumulated_time();
126 
127  if(Verbosity() > 1)
128  std::cout << "PHActsTrkFitter total event time "
129  << eventTime << std::endl;
130 
131  if(m_timeAnalysis)
132  h_eventTime->Fill(eventTime);
133 
134 
135  if(Verbosity() > 1)
136  std::cout << "PHActsTrkFitter::process_event finished"
137  << std::endl;
138 
139  // put this in the output file
140  if(Verbosity() > 0)
141  std::cout << " SvtxTrackMap size is now " << m_trackMap->size()
142  << std::endl;
143 
145 }
146 
148 {
149 
150  if(Verbosity() > 1)
151  {
152  std::cout << "Reset PHActsTrkFitter" << std::endl;
153 
154  }
155 
156  m_trajectories->clear();
157 
158 
160 }
161 
163 {
164  if(m_timeAnalysis)
165  {
166  m_timeFile->cd();
167  h_fitTime->Write();
168  h_eventTime->Write();
169  h_rotTime->Write();
170  h_stateTime->Write();
171  h_updateTime->Write();
172  m_timeFile->Write();
173  m_timeFile->Close();
174  }
175 
176  if (Verbosity() > 0)
177  {
178  std::cout << "The Acts track fitter had " << m_nBadFits
179  << " fits return an error" << std::endl;
180 
181  std::cout << "Finished PHActsTrkFitter" << std::endl;
182  }
184 }
185 
187 {
188  auto logger = Acts::getDefaultLogger("PHActsTrkFitter", logLevel);
189 
192  std::vector<unsigned int> badTracks;
193 
194  for(const auto& [trackKey, track] : *m_trackMap)
195  {
196  if(!track)
197  { continue; }
198 
199  PHTimer trackTimer("TrackTimer");
200  trackTimer.stop();
201  trackTimer.restart();
202 
203  auto sourceLinks = getSourceLinks(track);
204  if(sourceLinks.size() == 0) continue;
205 
207 
208  SurfacePtrVec surfaces;
209  if(m_fitSiliconMMs)
210  {
211  sourceLinks = getSurfaceVector(sourceLinks, surfaces);
212 
213  // skip if there is no surfaces
214  if( surfaces.empty() ) continue;
215 
216  // make sure micromegas are in the tracks, if required
217  if( m_useMicromegas &&
218  std::none_of( surfaces.begin(), surfaces.end(), [this]( const auto& surface )
219  { return m_surfMaps->isMicromegasSurface( *surface ); } ) )
220  { continue; }
221  }
222 
223  Acts::Vector3D momentum(track->get_px(),
224  track->get_py(),
225  track->get_pz());
226 
228  track->get_y() * Acts::UnitConstants::cm,
229  track->get_z() * Acts::UnitConstants::cm);
230 
231  auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
232  position);
233  auto actsFourPos = Acts::Vector4D(position(0), position(1),
234  position(2),
237 
238  int charge = track->get_charge();
239  if(m_fieldMap.find("3d") != std::string::npos)
240  { charge *= -1; }
241 
242  if(Verbosity() > 2)
243  { printTrackSeed(track); }
244 
248  momentum,
249  track->get_p(),
250  charge,
251  cov);
252 
256  Acts::PropagatorPlainOptions ppPlainOptions;
257  ppPlainOptions.absPdgCode = m_pHypothesis;
263  Acts::LoggerWrapper(*logger),
264  ppPlainOptions,
265  &(*pSurface));
266 
267  PHTimer fitTimer("FitTimer");
268  fitTimer.stop();
269  fitTimer.restart();
270  auto result = fitTrack(sourceLinks, seed, kfOptions,
271  surfaces);
272  fitTimer.stop();
273  auto fitTime = fitTimer.get_accumulated_time();
274 
275  if(Verbosity() > 1)
276  std::cout << "PHActsTrkFitter Acts fit time "
277  << fitTime << std::endl;
278 
280  if (result.ok())
281  {
282  const FitResult& fitOutput = result.value();
283 
284  if(m_timeAnalysis)
285  {
286  h_fitTime->Fill(fitOutput.fittedParameters.value()
287  .transverseMomentum(),
288  fitTime);
289  }
290 
291  if(m_fitSiliconMMs)
292  {
293  auto newTrack = (SvtxTrack_v2*)(track->CloneMe());
294  getTrackFitResult(fitOutput, newTrack);
295  m_directedTrackMap->insert(newTrack);
296  }
297  else
298  {
299  getTrackFitResult(fitOutput, track);
300  }
301  }
302  else if (!m_fitSiliconMMs)
303  {
305  badTracks.push_back(trackKey);
306  m_nBadFits++;
307 
308  }
309 
310  trackTimer.stop();
311  auto trackTime = trackTimer.get_accumulated_time();
312 
313  if(Verbosity() > 1)
314  std::cout << "PHActsTrkFitter total single track time "
315  << trackTime << std::endl;
316 
317  }
318 
320  for(const auto& key : badTracks)
321  {
322  m_trackMap->erase(key);
323  }
324 
325  return;
326 
327 }
328 
329 
330 //___________________________________________________________________________________
332 {
333  const auto trkrid = TrkrDefs::getTrkrId(cluskey);
334  const auto hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(cluskey);
335 
336  switch( trkrid )
337  {
339  case TrkrDefs::TrkrId::tpcId: return getTpcSurface(hitsetkey, surfkey);
342  {
344  }
345  }
346 
347  // unreachable
348  return nullptr;
349 
350 }
351 
352 //___________________________________________________________________________________
354 {
355  auto surfMap = m_surfMaps->siliconSurfaceMap;
356  auto iter = surfMap.find(hitsetkey);
357  if(iter != surfMap.end())
358  {
359  return iter->second;
360  }
361 
363  return nullptr;
364 
365 }
366 
367 //___________________________________________________________________________________
369 {
370  unsigned int layer = TrkrDefs::getLayer(hitsetkey);
371  const auto iter = m_surfMaps->tpcSurfaceMap.find(layer);
372  if(iter != m_surfMaps->tpcSurfaceMap.end())
373  {
374  auto surfvec = iter->second;
375  return surfvec.at(surfkey);
376  }
377 
379  return nullptr;
380 }
381 
382 //___________________________________________________________________________________
384 {
385  const auto iter = m_surfMaps->mmSurfaceMap.find( hitsetkey );
386  return (iter == m_surfMaps->mmSurfaceMap.end()) ? nullptr:iter->second;
387 }
388 
389 //___________________________________________________________________________________
391 {
392 
393  SourceLinkVec sourcelinks;
394 
395  for (SvtxTrack::ConstClusterKeyIter clusIter = track->begin_cluster_keys();
396  clusIter != track->end_cluster_keys();
397  ++clusIter)
398  {
399  auto key = *clusIter;
400  auto cluster = m_clusterContainer->findCluster(key);
401  if(!cluster)
402  {
403  if(Verbosity() > 0) std::cout << "Failed to get cluster with key " << key << " for track " << track->get_id() << std::endl;
404  continue;
405  }
406 
407  auto subsurfkey = cluster->getSubSurfKey();
408 
411  auto surf = getSurface(key, subsurfkey);
412  if(!surf)
413  continue;
414 
415  Acts::BoundVector loc = Acts::BoundVector::Zero();
416  loc[Acts::eBoundLoc0] = cluster->getLocalX() * Acts::UnitConstants::cm;
417  loc[Acts::eBoundLoc1] = cluster->getLocalY() * Acts::UnitConstants::cm;
418 
419  Acts::BoundMatrix cov = Acts::BoundMatrix::Zero();
421  cluster->getActsLocalError(0,0) * Acts::UnitConstants::cm2;
423  cluster->getActsLocalError(0,1) * Acts::UnitConstants::cm2;
425  cluster->getActsLocalError(1,0) * Acts::UnitConstants::cm2;
427  cluster->getActsLocalError(1,1) * Acts::UnitConstants::cm2;
428 
429  SourceLink sl(key, surf, loc, cov);
430  if(Verbosity() > 3)
431  {
432  std::cout << "source link " << sl.cluskey() << ", loc : "
433  << sl.location().transpose() << std::endl << ", cov : " << sl.covariance().transpose() << std::endl
434  << " geo id " << sl.geoId() << std::endl;
435  std::cout << "Surface : " << std::endl;
436  sl.referenceSurface().toStream(m_tGeometry->geoContext, std::cout);
437  std::cout << std::endl;
438  std::cout << "Cluster error " << cluster->getRPhiError() << " , " << cluster->getZError() << std::endl;
439  std::cout << "For key " << key << " with local pos " << std::endl
440  << cluster->getLocalX() << ", " << cluster->getLocalY()
441  << std::endl;
442  }
443 
444  sourcelinks.push_back(sl);
445  }
446 
447  return sourcelinks;
448 
449 }
450 
452  SvtxTrack* track)
453 {
456  std::vector<size_t> trackTips;
457  trackTips.push_back(fitOutput.trackTip);
458  ActsExamples::IndexedParams indexedParams;
459  if (fitOutput.fittedParameters)
460  {
461  indexedParams.emplace(fitOutput.trackTip,
462  fitOutput.fittedParameters.value());
463 
464  if (Verbosity() > 2)
465  {
466  const auto& params = fitOutput.fittedParameters.value();
467 
468  std::cout << "Fitted parameters for track" << std::endl;
469  std::cout << " position : " << params.position(m_tGeometry->geoContext).transpose()
470 
471  << std::endl;
472  std::cout << "charge: "<<params.charge()<<std::endl;
473  std::cout << " momentum : " << params.momentum().transpose()
474  << std::endl;
475  std::cout << "For trackTip == " << fitOutput.trackTip << std::endl;
476  }
477  }
478 
479  auto trajectory = std::make_unique<Trajectory>(fitOutput.fittedStates,
480  trackTips, indexedParams,
481  track->get_vertex_id());
482 
483  m_trajectories->insert(std::make_pair(track->get_id(), *trajectory));
484 
485 
488  PHTimer updateTrackTimer("UpdateTrackTimer");
489  updateTrackTimer.stop();
490  updateTrackTimer.restart();
491  if(fitOutput.fittedParameters)
492  updateSvtxTrack(*trajectory, track);
493 
494  updateTrackTimer.stop();
495  auto updateTime = updateTrackTimer.get_accumulated_time();
496 
497  if(Verbosity() > 1)
498  std::cout << "PHActsTrkFitter update SvtxTrack time "
499  << updateTime << std::endl;
500 
501  if(m_timeAnalysis)
502  h_updateTime->Fill(updateTime);
503 
504  return;
505 }
506 
507 ActsExamples::TrkrClusterFittingAlgorithm::FitterResult PHActsTrkFitter::fitTrack(
508  const SourceLinkVec& sourceLinks,
511  kfOptions,
512  const SurfacePtrVec& surfSequence)
513 {
514  if(m_fitSiliconMMs)
515  return m_fitCfg.dFit(sourceLinks, seed, kfOptions, surfSequence);
516  else
517  return m_fitCfg.fit(sourceLinks, seed, kfOptions);
518 }
519 
521  SurfacePtrVec& surfaces) const
522 {
523  SourceLinkVec siliconMMSls;
524 
525  if(Verbosity() > 1)
526  std::cout << "Sorting " << sourceLinks.size() << " SLs" << std::endl;
527 
528  for(const auto& sl : sourceLinks)
529  {
530  if(Verbosity() > 1)
531  { std::cout<<"SL available on : " << sl.referenceSurface().geometryId()<<std::endl; }
532 
533  // skip TPC surfaces
534  if( m_surfMaps->isTpcSurface( sl.referenceSurface() ) ) continue;
535 
536  // also skip micromegas surfaces if not used
537  if( m_surfMaps->isMicromegasSurface( sl.referenceSurface() ) && !m_useMicromegas ) continue;
538 
539  // update vectors
540  siliconMMSls.push_back(sl);
541  surfaces.push_back(&sl.referenceSurface());
542 
543  }
544 
548  if(!surfaces.empty())
549  { checkSurfaceVec(surfaces); }
550 
551  if(Verbosity() > 1)
552  {
553  for(const auto& surf : surfaces)
554  {
555  std::cout << "Surface vector : " << surf->geometryId() << std::endl;
556  }
557  }
558 
559  return siliconMMSls;
560 
561 }
562 
564 {
565  for(int i = 0; i < surfaces.size() - 1; i++)
566  {
567  auto surface = surfaces.at(i);
568  auto thisVolume = surface->geometryId().volume();
569  auto thisLayer = surface->geometryId().layer();
570 
571  auto nextSurface = surfaces.at(i+1);
572  auto nextVolume = nextSurface->geometryId().volume();
573  auto nextLayer = nextSurface->geometryId().layer();
574 
576  if(nextVolume == thisVolume)
577  {
578  if(nextLayer < thisLayer)
579  {
580  if(Verbosity() > 2)
581  std::cout << PHWHERE
582  << "Surface not in order... removing surface"
583  << surface->geometryId() << std::endl;
584  surfaces.erase(surfaces.begin() + i);
586  i--;
587  continue;
588  }
589  }
590  else
591  {
592  if(nextVolume < thisVolume)
593  {
594  if(Verbosity() > 2)
595  std::cout << PHWHERE
596  << "Volume not in order... removing surface"
597  << surface->geometryId() << std::endl;
598  surfaces.erase(surfaces.begin() + i);
600  i--;
601  continue;
602  }
603  }
604  }
605 
606 }
607 
609  SvtxTrack* track)
610 {
611  const auto &[trackTips, mj] = traj.trajectory();
613  auto &trackTip = trackTips.front();
614 
615  if(Verbosity() > 2)
616  {
617  std::cout << "Identify (proto) track before updating with acts results " << std::endl;
618  track->identify();
619  std::cout << " cluster keys size " << track->size_cluster_keys() << std::endl;
620  }
621 
622 
623  if(!m_fitSiliconMMs)
624  { track->clear_states(); }
625 
626  // create a state at pathlength = 0.0
627  // This state holds the track parameters, which will be updated below
628  float pathlength = 0.0;
629  SvtxTrackState_v1 out(pathlength);
630  out.set_x(0.0);
631  out.set_y(0.0);
632  out.set_z(0.0);
633  track->insert_state(&out);
634 
635  auto trajState =
636  Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip);
637 
638  const auto& params = traj.trackParameters(trackTip);
639 
641  track->set_x(params.position(m_tGeometry->geoContext)(0)
643  track->set_y(params.position(m_tGeometry->geoContext)(1)
645  track->set_z(params.position(m_tGeometry->geoContext)(2)
647 
648  track->set_px(params.momentum()(0));
649  track->set_py(params.momentum()(1));
650  track->set_pz(params.momentum()(2));
651 
652  track->set_charge(params.charge());
653  track->set_chisq(trajState.chi2Sum);
654  track->set_ndf(trajState.NDF);
655 
656  ActsTransformations rotater;
657  rotater.setVerbosity(Verbosity());
658 
659  if(params.covariance())
660  {
661  Acts::BoundSymMatrix rotatedCov =
662  rotater.rotateActsCovToSvtxTrack(params,
664 
665  for(int i = 0; i < 6; i++)
666  {
667  for(int j = 0; j < 6; j++)
668  {
669  track->set_error(i,j, rotatedCov(i,j));
670  track->set_acts_covariance(i,j,
671  params.covariance().value()(i,j));
672  }
673  }
674  }
675 
676  // Also need to update the state list and cluster ID list for all measurements associated with the acts track
677  // loop over acts track states, copy over to SvtxTrackStates, and add to SvtxTrack
678 
679  PHTimer trackStateTimer("TrackStateTimer");
680  trackStateTimer.stop();
681  trackStateTimer.restart();
682 
684  rotater.fillSvtxTrackStates(traj, trackTip, track,
686 
687  trackStateTimer.stop();
688  auto stateTime = trackStateTimer.get_accumulated_time();
689 
690  if(Verbosity() > 1)
691  std::cout << "PHActsTrkFitter update SvtxTrackStates time "
692  << stateTime << std::endl;
693 
694  if(m_timeAnalysis)
695  { h_stateTime->Fill(stateTime); }
696 
697  if(Verbosity() > 2)
698  {
699  std::cout << " Identify fitted track after updating track states:"
700  << std::endl;
701  track->identify();
702  std::cout << " cluster keys size " << track->size_cluster_keys()
703  << std::endl;
704  }
705 
706  return;
707 
708 }
709 
711 {
713 
721 
724  if(m_fitSiliconMMs)
725  {
726  cov << 1000 * Acts::UnitConstants::um, 0., 0., 0., 0., 0.,
727  0., 1000 * Acts::UnitConstants::um, 0., 0., 0., 0.,
728  0., 0., 0.1, 0., 0., 0.,
729  0., 0., 0., 0.1, 0., 0.,
730  0., 0., 0., 0., 0.005 , 0.,
731  0., 0., 0., 0., 0., 1.;
732  }
733  else
734  {
735  cov << 1000 * Acts::UnitConstants::um, 0., 0., 0., 0., 0.,
736  0., 1000 * Acts::UnitConstants::um, 0., 0., 0., 0.,
737  0., 0., 0.05, 0., 0., 0.,
738  0., 0., 0., 0.05, 0., 0.,
739  0., 0., 0., 0., 0.00005 , 0.,
740  0., 0., 0., 0., 0., 1.;
741  }
742 
743  return cov;
744 }
745 
747 {
748  std::cout << PHWHERE << " Processing proto track with id: "
749  << seed->get_id() << " and position:"
750  << seed->get_x() << ", " << seed->get_y() << ", "
751  << seed->get_z() << std::endl
752  << "momentum: " << seed->get_px() << ", " << seed->get_py()
753  << ", " << seed->get_pz() << std::endl
754  << "charge : " << seed->get_charge()
755  << std::endl;
756 }
757 
759 {
760 
761  PHNodeIterator iter(topNode);
762 
763  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
764 
765  if (!dstNode)
766  {
767  std::cerr << "DST node is missing, quitting" << std::endl;
768  throw std::runtime_error("Failed to find DST node in PHActsTrkFitter::createNodes");
769  }
770 
771  PHCompositeNode *svtxNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "SVTX"));
772 
773  if (!svtxNode)
774  {
775  svtxNode = new PHCompositeNode("SVTX");
776  dstNode->addNode(svtxNode);
777  }
778 
779  if(m_fitSiliconMMs)
780  {
781  m_directedTrackMap = findNode::getClass<SvtxTrackMap>(topNode,
782  "SvtxSiliconMMTrackMap");
783  if(!m_directedTrackMap)
784  {
787 
788  PHIODataNode<PHObject> *trackNode =
789  new PHIODataNode<PHObject>(m_directedTrackMap,"SvtxSiliconMMTrackMap","PHObject");
790  svtxNode->addNode(trackNode);
791  }
792  }
793 
794  m_trajectories = findNode::getClass<std::map<const unsigned int, Trajectory>>(topNode, "ActsTrajectories");
795  if(!m_trajectories)
796  {
797  m_trajectories = new std::map<const unsigned int, Trajectory>;
800  svtxNode->addNode(node);
801 
802  }
803 
804  if(m_actsEvaluator)
805  {
806  m_seedTracks = findNode::getClass<SvtxTrackMap>(topNode,_seed_track_map_name);
807 
808  if(!m_seedTracks)
809  {
811 
812  PHIODataNode<PHObject> *seedNode =
814  svtxNode->addNode(seedNode);
815  }
816  }
817 
819 }
820 
822 {
823  m_surfMaps = findNode::getClass<ActsSurfaceMaps>(topNode, "ActsSurfaceMaps");
824  if(!m_surfMaps)
825  {
826  std::cout << PHWHERE << "ActsSurfaceMaps not on node tree, bailing."
827  << std::endl;
829  }
830 
831  m_clusterContainer = findNode::getClass<TrkrClusterContainer>(topNode,"CORRECTED_TRKR_CLUSTER");
833  {
834  std::cout << " Using CORRECTED_TRKR_CLUSTER node " << std::endl;
835  }
836  else
837  {
838  std::cout << " CORRECTED_TRKR_CLUSTER node not found, using TRKR_CLUSTER" << std::endl;
839  m_clusterContainer = findNode::getClass<TrkrClusterContainer>(topNode,"TRKR_CLUSTER");
840  }
841 
842  if(!m_clusterContainer)
843  {
844  std::cout << PHWHERE
845  << "No trkr cluster container, exiting." << std::endl;
847  }
848 
849  m_tGeometry = findNode::getClass<ActsTrackingGeometry>(topNode, "ActsTrackingGeometry");
850  if(!m_tGeometry)
851  {
852  std::cout << "ActsTrackingGeometry not on node tree. Exiting."
853  << std::endl;
854 
856  }
857 
858  m_trackMap = findNode::getClass<SvtxTrackMap>(topNode, _track_map_name);
859 
860  if(!m_trackMap)
861  {
862  std::cout << PHWHERE << "SvtxTrackMap not found on node tree. Exiting."
863  << std::endl;
865  }
866 
868 }
869