Analysis Software
Documentation for sPHENIX simulation 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"
9 #include "MakeSourceLinks.h"
10 
12 #include <trackbase/Calibrator.h>
14 #include <trackbase/InttDefs.h>
15 #include <trackbase/MvtxDefs.h>
16 #include <trackbase/TpcDefs.h>
17 #include <trackbase/TrkrCluster.h>
19 
27 
29 
31 
33 #include <phool/PHCompositeNode.h>
34 #include <phool/PHDataNode.h>
35 #include <phool/PHNode.h>
36 #include <phool/PHNodeIterator.h>
37 #include <phool/PHObject.h>
38 #include <phool/PHTimer.h>
39 #include <phool/getClass.h>
40 #include <phool/phool.h>
41 
43 
52 
53 #include <TDatabasePDG.h>
54 
55 #include <cmath>
56 #include <iostream>
57 #include <vector>
58 
59 namespace
60 {
61  // check vector validity
62  inline bool is_valid(const Acts::Vector3 vec)
63  {
64  return !(std::isnan(vec.x()) || std::isnan(vec.y()) || std::isnan(vec.z()));
65  }
66  template <class T>
67  inline T square(const T& x)
68  {
69  return x * x;
70  }
71 } // namespace
72 
74 #include <Eigen/Dense>
75 #include <Eigen/Geometry>
76 
78  : SubsysReco(name)
79  , m_trajectories(nullptr)
80 {
81 }
82 
84 {
85  if (Verbosity() > 1)
86  {
87  std::cout << "Setup PHActsTrkFitter" << std::endl;
88  }
89 
91  {
93  }
94 
95  if (getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK)
96  {
98  }
99 
108 
112  true, true, 0.0, Acts::FreeToBoundCorrection(), *Acts::getDefaultLogger("Kalman", level));
113 
117 
119  std::map<long unsigned int, float> chi2Cuts;
120  chi2Cuts.insert(std::make_pair(10, 4));
121  chi2Cuts.insert(std::make_pair(12, 4));
122  chi2Cuts.insert(std::make_pair(14, 9));
123  chi2Cuts.insert(std::make_pair(16, 4));
124  m_outlierFinder.chi2Cuts = chi2Cuts;
125  if (m_useOutlierFinder)
126  {
127  m_fitCfg.fit->outlierFinder(m_outlierFinder);
128  }
129 
130  if (m_timeAnalysis)
131  {
132  m_timeFile = new TFile(std::string(Name() + ".root").c_str(),
133  "RECREATE");
134  h_eventTime = new TH1F("h_eventTime", ";time [ms]",
135  100000, 0, 10000);
136  h_fitTime = new TH2F("h_fitTime", ";p_{T} [GeV];time [ms]",
137  80, 0, 40, 100000, 0, 1000);
138  h_updateTime = new TH1F("h_updateTime", ";time [ms]",
139  100000, 0, 1000);
140 
141  h_rotTime = new TH1F("h_rotTime", ";time [ms]",
142  100000, 0, 1000);
143  h_stateTime = new TH1F("h_stateTime", ";time [ms]",
144  100000, 0, 1000);
145  }
146 
147  if (m_actsEvaluator)
148  {
149  m_evaluator = std::make_unique<ActsEvaluator>(m_evalname);
150  m_evaluator->Init(topNode);
151  m_evaluator->verbosity(Verbosity());
152  }
153 
154  if (Verbosity() > 1)
155  {
156  std::cout << "Finish PHActsTrkFitter Setup" << std::endl;
157  }
158 
160 }
161 
163 {
164  PHTimer eventTimer("eventTimer");
165  eventTimer.stop();
166  eventTimer.restart();
167 
168  m_event++;
169 
171 
172  if (m_actsEvaluator)
173  {
174  m_evaluator->next_event(topNode);
175  }
176 
177  if (Verbosity() > 1)
178  {
179  std::cout << PHWHERE << "Events processed: " << m_event << std::endl;
180  std::cout << "Start PHActsTrkFitter::process_event" << std::endl;
181  if (Verbosity() > 4)
183  }
184 
187  if (m_actsEvaluator)
188  {
191  m_seedTracks->clear();
192  for (const auto& [key, track] : *m_trackMap)
193  {
194  m_seedTracks->insert(track);
195  }
196  }
197 
199 
200  eventTimer.stop();
201  auto eventTime = eventTimer.get_accumulated_time();
202 
203  if (Verbosity() > 1)
204  std::cout << "PHActsTrkFitter total event time "
205  << eventTime << std::endl;
206 
207  if (m_timeAnalysis)
208  h_eventTime->Fill(eventTime);
209 
210  if (Verbosity() > 1)
211  std::cout << "PHActsTrkFitter::process_event finished"
212  << std::endl;
213 
214  // put this in the output file
215  if (Verbosity() > 0)
216  {
217  std::cout << " SvtxTrackMap size is now " << m_trackMap->size()
218  << std::endl;
219  }
220 
222 }
223 
225 {
226  if (Verbosity() > 1)
227  {
228  std::cout << "Reset PHActsTrkFitter" << std::endl;
229  }
230 
231  m_trajectories->clear();
232 
234 }
235 
237 {
238  if (m_timeAnalysis)
239  {
240  m_timeFile->cd();
241  h_fitTime->Write();
242  h_eventTime->Write();
243  h_rotTime->Write();
244  h_stateTime->Write();
245  h_updateTime->Write();
246  m_timeFile->Write();
247  m_timeFile->Close();
248  }
249 
250  if (m_actsEvaluator)
251  {
252  m_evaluator->End();
253  }
254 
255  if (Verbosity() > 0)
256  {
257  std::cout << "The Acts track fitter had " << m_nBadFits
258  << " fits return an error" << std::endl;
259 
260  std::cout << "Finished PHActsTrkFitter" << std::endl;
261  }
263 }
264 
266 {
267  auto logger = Acts::getDefaultLogger("PHActsTrkFitter", logLevel);
268 
269  if (Verbosity() > 0)
270  {
271  std::cout << " seed map size " << m_seedMap->size() << std::endl;
272  }
273 
274  for (auto trackiter = m_seedMap->begin(); trackiter != m_seedMap->end();
275  ++trackiter)
276  {
277  TrackSeed* track = *trackiter;
278  if (!track)
279  {
280  continue;
281  }
282 
283  unsigned int tpcid = track->get_tpc_seed_index();
284  unsigned int siid = track->get_silicon_seed_index();
285  short int crossing_estimate = track->get_crossing_estimate(); // geometric crossing estimate
286 
287 
290  if (m_pp_mode && siid == std::numeric_limits<unsigned int>::max())
291  {
292  if (Verbosity() > 3) std::cout << " tpcid " << tpcid << " siid " << siid << " running in pp mode and SvtxSeedTrack has no silicon match, skip it" << std::endl;
293  continue;
294  }
295 
296  // get the INTT crossing number
297  auto siseed = m_siliconSeeds->get(siid);
298  short crossing = SHRT_MAX;
299  if (siseed)
300  crossing = siseed->get_crossing();
301  else if (!m_pp_mode)
302  crossing = 0;
303 
304  // if the crossing was not determined at all in pp running, skip this case completely
305  if (m_pp_mode && crossing == SHRT_MAX && crossing_estimate == SHRT_MAX)
306  {
307  // Skip this in the pp case.
308  if (Verbosity() > 3) std::cout << "tpcid " << tpcid << " siid " << siid << " crossing and crossing_estimate not determined, skipping track" << std::endl;
309  continue;
310  }
311 
312  if (Verbosity() > 1)
313  {
314  std::cout << "tpc and si id " << tpcid << ", " << siid << " crossing " << crossing << " crossing estimate " << crossing_estimate << std::endl;
315  }
316 
317  // Can't do SC case without INTT crossing
318  if( m_fitSiliconMMs && (crossing == SHRT_MAX) ) continue;
319 
320  auto tpcseed = m_tpcSeeds->get(tpcid);
321 
323  if (!tpcseed)
324  {
325  std::cout << "no tpc seed" << std::endl;
326  continue;
327  }
328 
329  if (Verbosity() > 0)
330  {
331  if (siseed) std::cout << " silicon seed position is (x,y,z) = " << siseed->get_x() << " " << siseed->get_y() << " " << siseed->get_z() << std::endl;
332  std::cout << " tpc seed position is (x,y,z) = " << tpcseed->get_x() << " " << tpcseed->get_y() << " " << tpcseed->get_z() << std::endl;
333  }
334 
335  PHTimer trackTimer("TrackTimer");
336  trackTimer.stop();
337  trackTimer.restart();
338 
339  short int this_crossing = crossing;
340  bool use_estimate = false;
341  short int nvary = 0;
342  std::vector<float> chisq_ndf;
343  std::vector<SvtxTrack_v4> svtx_vec;
344 
345  if(Verbosity() > 1) { std::cout << " INTT crossing " << crossing << " crossing_estimate " << crossing_estimate << std::endl; }
346 
347  if(crossing == SHRT_MAX)
348  {
349  // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf
350  use_estimate = true;
351  nvary = max_bunch_search;
352  if(Verbosity() > 1) { std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl; }
353  }
354  else
355  {
356  // use INTT crossing
357  crossing_estimate = crossing;
358  }
359 
360  // Fit this track assuming either:
361  // crossing = INTT value, if it exists (uses nvary = 0)
362  // crossing = crossing_estimate +/- max_bunch_search, if no INTT value exists
363 
364  for(short int ivary = -nvary; ivary <= nvary; ++ivary)
365  {
366  this_crossing = crossing_estimate + ivary;
367 
368  if(Verbosity() > 1)
369  {
370  std::cout << " nvary " << nvary << " trial fit with ivary " << ivary << " this_crossing = " << this_crossing << std::endl;
371  }
372 
374 
375  SourceLinkVec sourceLinks;
376 
377  MakeSourceLinks makeSourceLinks;
378  makeSourceLinks.setVerbosity(Verbosity());
379  makeSourceLinks.set_pp_mode(m_pp_mode);
380 
381  // loop over modifiedTransformSet and replace transient elements modified for the previous track with the default transforms
382  makeSourceLinks.resetTransientTransformMap(
385  m_tGeometry);
386 
387  if (siseed) sourceLinks = makeSourceLinks.getSourceLinks(
388  siseed,
389  measurements,
391  m_tGeometry,
394  this_crossing);
395  const auto tpcSourceLinks = makeSourceLinks.getSourceLinks(
396  tpcseed,
397  measurements,
399  m_tGeometry,
402  this_crossing);
403  sourceLinks.insert(sourceLinks.end(), tpcSourceLinks.begin(), tpcSourceLinks.end());
404 
405  // copy transient map for this track into transient geoContext
407 
408  // position comes from the silicon seed, unless there is no silicon seed
409  Acts::Vector3 position(0, 0, 0);
410  if (siseed)
411  {
412  position(0) = siseed->get_x() * Acts::UnitConstants::cm;
413  position(1) = siseed->get_y() * Acts::UnitConstants::cm;
414  position(2) = siseed->get_z() * Acts::UnitConstants::cm;
415  }
416  else
417  {
418  position(0) = tpcseed->get_x() * Acts::UnitConstants::cm;
419  position(1) = tpcseed->get_y() * Acts::UnitConstants::cm;
420  position(2) = tpcseed->get_z() * Acts::UnitConstants::cm;
421  }
422  if (!is_valid(position)) continue;
423 
424  if (sourceLinks.empty())
425  {
426  continue;
427  }
428 
430  SurfacePtrVec surfaces;
431  if (m_fitSiliconMMs)
432  {
433  sourceLinks = getSurfaceVector(sourceLinks, surfaces);
434 
435  // skip if there is no surfaces
436  if (surfaces.empty()) continue;
437 
438  // make sure micromegas are in the tracks, if required
439  if (m_useMicromegas &&
440  std::none_of(surfaces.begin(), surfaces.end(), [this](const auto& surface)
441  { return m_tGeometry->maps().isMicromegasSurface(surface); }))
442  {
443  continue;
444  }
445  }
446 
447  float px = NAN;
448  float py = NAN;
449  float pz = NAN;
450  if (m_fieldMap.find(".root") != std::string::npos)
451  {
452  px = tpcseed->get_px(m_clusterContainer, m_tGeometry);
453  py = tpcseed->get_py(m_clusterContainer, m_tGeometry);
454  pz = tpcseed->get_pz();
455  }
456  else
457  {
458  float pt = fabs(1. / tpcseed->get_qOverR()) * (0.3 / 100) * std::stod(m_fieldMap);
459  float phi = tpcseed->get_phi(m_clusterContainer, m_tGeometry);
460  px = pt * std::cos(phi);
461  py = pt * std::sin(phi);
462  pz = pt * std::cosh(tpcseed->get_eta()) * std::cos(tpcseed->get_theta());
463  }
464 
465  Acts::Vector3 momentum(px, py, pz);
466  if (!is_valid(momentum)) continue;
467 
468  auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
469  position);
470 
471  auto actsFourPos = Acts::Vector4(position(0), position(1),
472  position(2),
475 
476  int charge = tpcseed->get_charge();
477 
480  pSurface,
482  actsFourPos,
483  momentum,
484  charge / momentum.norm(),
485  cov,
487  .value();
488 
489  if (Verbosity() > 2)
490  {
492  }
493 
495  Acts::PropagatorPlainOptions ppPlainOptions;
496 
497  auto calibptr = std::make_unique<Calibrator>();
498  CalibratorAdapter calibrator{*calibptr, measurements};
499 
500  auto magcontext = m_tGeometry->geometry().magFieldContext;
501  auto calibcontext = m_tGeometry->geometry().calibContext;
502 
504  kfOptions{
506  magcontext,
507  calibcontext,
508  pSurface.get(),
509  ppPlainOptions};
510 
511  PHTimer fitTimer("FitTimer");
512  fitTimer.stop();
513  fitTimer.restart();
514 
515  auto trackContainer =
516  std::make_shared<Acts::VectorTrackContainer>();
517  auto trackStateContainer =
518  std::make_shared<Acts::VectorMultiTrajectory>();
520  tracks(trackContainer, trackStateContainer);
521 
522  auto result = fitTrack(sourceLinks, seed, kfOptions,
523  surfaces, calibrator, tracks);
524  fitTimer.stop();
525  auto fitTime = fitTimer.get_accumulated_time();
526 
527  if (Verbosity() > 1)
528  {
529  std::cout << "PHActsTrkFitter Acts fit time " << fitTime << std::endl;
530  }
531 
533  if (result.ok())
534  {
535  if(use_estimate) // trial variation case
536  {
537  // this is a trial variation of the crossing estimate for this track
538  // Capture the chisq/ndf so we can choose the best one after all trials
539 
540  SvtxTrack_v4 newTrack;
541  newTrack.set_tpc_seed(tpcseed);
542  newTrack.set_crossing(this_crossing);
543  newTrack.set_silicon_seed(siseed);
544 
545  if (getTrackFitResult(result, track, &newTrack, tracks, measurements))
546  {
547  float chi2ndf = newTrack.get_quality();
548  chisq_ndf.push_back(chi2ndf);
549  svtx_vec.push_back(newTrack);
550  if(Verbosity() > 1) { std::cout << " tpcid " << tpcid << " siid " << siid << " ivary " << ivary << " this_crossing " << this_crossing << " chi2ndf " << chi2ndf << std::endl; }
551  }
552 
553  if(ivary != nvary) { continue; }
554 
555  // if we are here this is the last crossing iteration, evaluate the results
556  if(Verbosity() > 1) { std::cout << "Finished with trial fits, chisq_ndf size is " << chisq_ndf.size() << " chisq_ndf values are:" << std::endl; }
557  float best_chisq = 1000.0;
558  short int best_ivary = 0;
559  for(unsigned int i = 0; i<chisq_ndf.size(); ++i)
560  {
561  if(chisq_ndf[i] < best_chisq)
562  {
563  best_chisq = chisq_ndf[i];
564  best_ivary = i;
565  }
566  if(Verbosity() > 1) { std::cout << " trial " << i << " chisq_ndf " << chisq_ndf[i] << " best_chisq " << best_chisq << " best_ivary " << best_ivary << std::endl; }
567  }
568  unsigned int trid = m_trackMap->size();
569  svtx_vec[best_ivary].set_id(trid);
570 
571  m_trackMap->insertWithKey(&svtx_vec[best_ivary], trid);
572  }
573  else // case where INTT crossing is known
574  {
575  SvtxTrack_v4 newTrack;
576  newTrack.set_tpc_seed(tpcseed);
577  newTrack.set_crossing(this_crossing);
578  newTrack.set_silicon_seed(siseed);
579 
580  if (m_fitSiliconMMs)
581  {
582  unsigned int trid = m_directedTrackMap->size();
583  newTrack.set_id(trid);
584 
585  if (getTrackFitResult(result, track, &newTrack, tracks, measurements))
586  {
587  m_directedTrackMap->insertWithKey(&newTrack, trid);
588  }
589  } // end insert track for SC calib fit
590  else
591  {
592  unsigned int trid = m_trackMap->size();
593  newTrack.set_id(trid);
594 
595  if (getTrackFitResult(result, track, &newTrack, tracks, measurements))
596  {
597  m_trackMap->insertWithKey(&newTrack, trid);
598  }
599  } // end insert track for normal fit
600  } // end case where INTT crossing is known
601  }
602  else if (!m_fitSiliconMMs)
603  {
605  m_nBadFits++;
606  if (Verbosity() > 1)
607  {
608  std::cout << "Track fit failed for track " << m_seedMap->find(track)
609  << " with Acts error message "
610  << result.error() << ", " << result.error().message()
611  << std::endl;
612  }
613  } // end fit failed case
614  } // end ivary loop
615 
616  trackTimer.stop();
617  auto trackTime = trackTimer.get_accumulated_time();
618 
619  if (Verbosity() > 1)
620  {
621  std::cout << "PHActsTrkFitter total single track time " << trackTime << std::endl;
622  }
623  }
624 
625  return;
626 }
627 
629  TrackSeed* seed, SvtxTrack* track,
632 {
635  std::vector<Acts::MultiTrajectoryTraits::IndexType> trackTips;
636  trackTips.reserve(1);
637  auto& outtrack = fitOutput.value();
638  if (outtrack.hasReferenceSurface())
639  {
640  trackTips.emplace_back(outtrack.tipIndex());
641  Trajectory::IndexedParameters indexedParams;
642  indexedParams.emplace(std::pair{outtrack.tipIndex(),
644  outtrack.parameters(), outtrack.covariance(), outtrack.particleHypothesis()}});
645 
646  if (Verbosity() > 2)
647  {
648  std::cout << "Fitted parameters for track" << std::endl;
649  std::cout << " position : " << outtrack.referenceSurface().localToGlobal(m_transient_geocontext, Acts::Vector2(outtrack.loc0(), outtrack.loc1()), Acts::Vector3(1, 1, 1)).transpose()
650 
651  << std::endl;
652  int otcharge = outtrack.qOverP() > 0 ? 1 : -1;
653  std::cout << "charge: " << otcharge << std::endl;
654  std::cout << " momentum : " << outtrack.momentum().transpose()
655  << std::endl;
656  std::cout << "For trackTip == " << outtrack.tipIndex() << std::endl;
657  }
658 
661  PHTimer updateTrackTimer("UpdateTrackTimer");
662  updateTrackTimer.stop();
663  updateTrackTimer.restart();
664  updateSvtxTrack(trackTips, indexedParams, tracks, track);
665 
666  if (m_commissioning)
667  {
668  if (track->get_silicon_seed() && track->get_tpc_seed())
669  {
670  m_alignStates.fillAlignmentStateMap(tracks, trackTips,
671  track, measurements);
672  }
673  }
674 
675  updateTrackTimer.stop();
676  auto updateTime = updateTrackTimer.get_accumulated_time();
677 
678  if (Verbosity() > 1)
679  std::cout << "PHActsTrkFitter update SvtxTrack time "
680  << updateTime << std::endl;
681 
682  if (m_timeAnalysis)
683  {
684  h_updateTime->Fill(updateTime);
685  }
686 
687  Trajectory trajectory(tracks.trackStateContainer(),
688  trackTips, indexedParams);
689 
690  m_trajectories->insert(std::make_pair(track->get_id(), trajectory));
691 
692  if (m_actsEvaluator)
693  {
694  m_evaluator->evaluateTrackFit(tracks, trackTips, indexedParams, track,
695  seed, measurements);
696  }
697 
698  return true;
699  }
700 
701  return false;
702 }
703 
705  const std::vector<Acts::SourceLink>& sourceLinks,
708  const SurfacePtrVec& surfSequence,
709  const CalibratorAdapter& calibrator,
711 {
712  if (m_fitSiliconMMs)
713  {
714  return (*m_fitCfg.dFit)(sourceLinks, seed, kfOptions,
715  surfSequence, calibrator, tracks);
716  }
717  else
718  {
719  return (*m_fitCfg.fit)(sourceLinks, seed, kfOptions,
720  calibrator, tracks);
721  }
722 }
723 
725  SurfacePtrVec& surfaces) const
726 {
727  SourceLinkVec siliconMMSls;
728 
729  // if(Verbosity() > 1)
730  // std::cout << "Sorting " << sourceLinks.size() << " SLs" << std::endl;
731 
732  for (const auto& sl : sourceLinks)
733  {
734  const ActsSourceLink asl = sl.get<ActsSourceLink>();
735  if (Verbosity() > 1)
736  {
737  std::cout << "SL available on : " << asl.geometryId() << std::endl;
738  }
739 
740  const auto surf = m_tGeometry->geometry().tGeometry->findSurface(asl.geometryId());
741  // skip TPC surfaces
742  if (m_tGeometry->maps().isTpcSurface(surf)) continue;
743 
744  // also skip micromegas surfaces if not used
746 
747  // update vectors
748  siliconMMSls.push_back(sl);
749  surfaces.push_back(surf);
750  }
751 
755  if (!surfaces.empty())
756  {
757  checkSurfaceVec(surfaces);
758  }
759 
760  if (Verbosity() > 1)
761  {
762  for (const auto& surf : surfaces)
763  {
764  std::cout << "Surface vector : " << surf->geometryId() << std::endl;
765  }
766  }
767 
768  return siliconMMSls;
769 }
770 
772 {
773  for (int i = 0; i < surfaces.size() - 1; i++)
774  {
775  const auto& surface = surfaces.at(i);
776  const auto thisVolume = surface->geometryId().volume();
777  const auto thisLayer = surface->geometryId().layer();
778 
779  const auto nextSurface = surfaces.at(i + 1);
780  const auto nextVolume = nextSurface->geometryId().volume();
781  const auto nextLayer = nextSurface->geometryId().layer();
782 
784  if (nextVolume == thisVolume)
785  {
786  if (nextLayer < thisLayer)
787  {
788  std::cout
789  << "PHActsTrkFitter::checkSurfaceVec - "
790  << "Surface not in order... removing surface"
791  << surface->geometryId() << std::endl;
792 
793  surfaces.erase(surfaces.begin() + i);
794 
796  --i;
797  continue;
798  }
799  }
800  else
801  {
802  if (nextVolume < thisVolume)
803  {
804  std::cout
805  << "PHActsTrkFitter::checkSurfaceVec - "
806  << "Volume not in order... removing surface"
807  << surface->geometryId() << std::endl;
808 
809  surfaces.erase(surfaces.begin() + i);
810 
812  --i;
813  continue;
814  }
815  }
816  }
817 }
818 
819 void PHActsTrkFitter::updateSvtxTrack(std::vector<Acts::MultiTrajectoryTraits::IndexType>& tips,
822  SvtxTrack* track)
823 {
824  const auto& mj = tracks.trackStateContainer();
825 
827  auto& trackTip = tips.front();
828 
829  if (Verbosity() > 2)
830  {
831  std::cout << "Identify (proto) track before updating with acts results " << std::endl;
832  track->identify();
833  }
834 
835  if (!m_fitSiliconMMs)
836  {
837  track->clear_states();
838  }
839 
840  // create a state at pathlength = 0.0
841  // This state holds the track parameters, which will be updated below
842  float pathlength = 0.0;
843  SvtxTrackState_v1 out(pathlength);
844  out.set_x(0.0);
845  out.set_y(0.0);
846  out.set_z(0.0);
847  track->insert_state(&out);
848 
849  auto trajState =
851 
852  const auto& params = paramsMap.find(trackTip)->second;
853 
855  track->set_x(params.position(m_transient_geocontext)(0) / Acts::UnitConstants::cm);
856  track->set_y(params.position(m_transient_geocontext)(1) / Acts::UnitConstants::cm);
857  track->set_z(params.position(m_transient_geocontext)(2) / Acts::UnitConstants::cm);
858 
859  track->set_px(params.momentum()(0));
860  track->set_py(params.momentum()(1));
861  track->set_pz(params.momentum()(2));
862 
863  track->set_charge(params.charge());
864  track->set_chisq(trajState.chi2Sum);
865  track->set_ndf(trajState.NDF);
866 
867  ActsTransformations rotater;
868  rotater.setVerbosity(Verbosity());
869 
870  if (params.covariance())
871  {
872  auto rotatedCov = rotater.rotateActsCovToSvtxTrack(params);
873 
874  for (int i = 0; i < 6; i++)
875  {
876  for (int j = 0; j < 6; j++)
877  {
878  track->set_error(i, j, rotatedCov(i, j));
879  }
880  }
881  }
882 
883  // Also need to update the state list and cluster ID list for all measurements associated with the acts track
884  // loop over acts track states, copy over to SvtxTrackStates, and add to SvtxTrack
885  PHTimer trackStateTimer("TrackStateTimer");
886  trackStateTimer.stop();
887  trackStateTimer.restart();
888 
890  {
891  rotater.fillSvtxTrackStates(mj, trackTip, track,
893  }
894 
895  trackStateTimer.stop();
896  auto stateTime = trackStateTimer.get_accumulated_time();
897 
898  if (Verbosity() > 1)
899  std::cout << "PHActsTrkFitter update SvtxTrackStates time "
900  << stateTime << std::endl;
901 
902  if (m_timeAnalysis)
903  {
904  h_stateTime->Fill(stateTime);
905  }
906 
907  if (Verbosity() > 2)
908  {
909  std::cout << " Identify fitted track after updating track states:"
910  << std::endl;
911  track->identify();
912  }
913 
914  return;
915 }
916 
918 {
919  Acts::BoundSquareMatrix cov = Acts::BoundSquareMatrix::Zero();
920 
928 
931  if (m_fitSiliconMMs)
932  {
933  cov << 1000 * Acts::UnitConstants::um, 0., 0., 0., 0., 0.,
934  0., 1000 * Acts::UnitConstants::um, 0., 0., 0., 0.,
935  0., 0., 0.1, 0., 0., 0.,
936  0., 0., 0., 0.1, 0., 0.,
937  0., 0., 0., 0., 0.005, 0.,
938  0., 0., 0., 0., 0., 1.;
939  }
940  else
941  {
942  // cppcheck-suppress duplicateAssignExpression
943  double sigmaD0 = 50 * Acts::UnitConstants::um;
944  double sigmaZ0 = 50 * Acts::UnitConstants::um;
945  // cppcheck-suppress duplicateAssignExpression
946  double sigmaPhi = 1 * Acts::UnitConstants::degree;
947  double sigmaTheta = 1 * Acts::UnitConstants::degree;
948  double sigmaT = 1. * Acts::UnitConstants::ns;
949 
950  cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = sigmaD0 * sigmaD0;
951  cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = sigmaZ0 * sigmaZ0;
952  cov(Acts::eBoundTime, Acts::eBoundTime) = sigmaT * sigmaT;
953  cov(Acts::eBoundPhi, Acts::eBoundPhi) = sigmaPhi * sigmaPhi;
954  cov(Acts::eBoundTheta, Acts::eBoundTheta) = sigmaTheta * sigmaTheta;
957  }
958 
959  return cov;
960 }
961 
963 {
964  std::cout
965  << PHWHERE
966  << " Processing proto track:"
967  << std::endl;
968 
969  std::cout
970  << "position: " << seed.position(m_transient_geocontext).transpose()
971  << std::endl
972  << "momentum: " << seed.momentum().transpose()
973  << std::endl;
974 
975  std::cout << "charge : " << seed.charge() << std::endl;
976  std::cout << "absolutemom : " << seed.absoluteMomentum() << std::endl;
977 }
978 
980 {
981  PHNodeIterator iter(topNode);
982 
983  PHCompositeNode* dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
984 
985  if (!dstNode)
986  {
987  std::cerr << "DST node is missing, quitting" << std::endl;
988  throw std::runtime_error("Failed to find DST node in PHActsTrkFitter::createNodes");
989  }
990 
991  PHNodeIterator dstIter(topNode);
992  PHCompositeNode* svtxNode = dynamic_cast<PHCompositeNode*>(dstIter.findFirst("PHCompositeNode", "SVTX"));
993 
994  if (!svtxNode)
995  {
996  svtxNode = new PHCompositeNode("SVTX");
997  dstNode->addNode(svtxNode);
998  }
999 
1000  if (m_fitSiliconMMs)
1001  {
1002  m_directedTrackMap = findNode::getClass<SvtxTrackMap>(topNode,
1003  "SvtxSiliconMMTrackMap");
1004  if (!m_directedTrackMap)
1005  {
1008 
1009  PHIODataNode<PHObject>* trackNode =
1010  new PHIODataNode<PHObject>(m_directedTrackMap, "SvtxSiliconMMTrackMap", "PHObject");
1011  svtxNode->addNode(trackNode);
1012  }
1013  }
1014 
1015  m_trajectories = findNode::getClass<std::map<const unsigned int, Trajectory>>(topNode, "ActsTrajectories");
1016  if (!m_trajectories)
1017  {
1018  m_trajectories = new std::map<const unsigned int, Trajectory>;
1019  auto node =
1021  svtxNode->addNode(node);
1022  }
1023 
1024  m_trackMap = findNode::getClass<SvtxTrackMap>(topNode, _track_map_name);
1025 
1026  if (!m_trackMap)
1027  {
1030  svtxNode->addNode(node);
1031  }
1032 
1033  m_alignmentStateMap = findNode::getClass<SvtxAlignmentStateMap>(topNode, "SvtxAlignmentStateMap");
1034  if (!m_alignmentStateMap)
1035  {
1037  auto node = new PHDataNode<SvtxAlignmentStateMap>(m_alignmentStateMap, "SvtxAlignmentStateMap", "PHObject");
1038  svtxNode->addNode(node);
1039  }
1040 
1041  if (m_actsEvaluator)
1042  {
1043  m_seedTracks = findNode::getClass<SvtxTrackMap>(topNode, _seed_track_map_name);
1044 
1045  if (!m_seedTracks)
1046  {
1048 
1049  PHIODataNode<PHObject>* seedNode =
1051  svtxNode->addNode(seedNode);
1052  }
1053  }
1054 
1056 }
1057 
1059 {
1060 
1061  m_alignmentTransformationMap = findNode::getClass<alignmentTransformationContainer>(topNode, "alignmentTransformationContainer");
1063  {
1064  std::cout << PHWHERE << "alignmentTransformationContainer not on node tree. Bailing"
1065  << std::endl;
1067  }
1068 
1069  m_alignmentTransformationMapTransient = findNode::getClass<alignmentTransformationContainer>(topNode, "alignmentTransformationContainerTransient");
1071  {
1072  std::cout << PHWHERE << "alignmentTransformationContainerTransient not on node tree. Bailing"
1073  << std::endl;
1075  }
1076 
1077 
1078  m_tpcSeeds = findNode::getClass<TrackSeedContainer>(topNode, "TpcTrackSeedContainer");
1079  if (!m_tpcSeeds)
1080  {
1081  std::cout << PHWHERE << "TpcTrackSeedContainer not on node tree. Bailing"
1082  << std::endl;
1084  }
1085 
1086  m_siliconSeeds = findNode::getClass<TrackSeedContainer>(topNode, "SiliconTrackSeedContainer");
1087  if (!m_siliconSeeds)
1088  {
1089  std::cout << PHWHERE << "SiliconTrackSeedContainer not on node tree. Bailing"
1090  << std::endl;
1092  }
1093 
1094  m_clusterContainer = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
1095  if (!m_clusterContainer)
1096  {
1097  std::cout << PHWHERE
1098  << "No trkr cluster container, exiting." << std::endl;
1100  }
1101 
1102  m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
1103  if (!m_tGeometry)
1104  {
1105  std::cout << "ActsGeometry not on node tree. Exiting."
1106  << std::endl;
1107 
1109  }
1110 
1111  m_seedMap = findNode::getClass<TrackSeedContainer>(topNode, "SvtxTrackSeedContainer");
1112  if (!m_seedMap)
1113  {
1114  std::cout << "No Svtx seed map on node tree. Exiting."
1115  << std::endl;
1117  }
1118 
1119  // tpc distortion corrections
1120  _dcc_static = findNode::getClass<TpcDistortionCorrectionContainer>(topNode, "TpcDistortionCorrectionContainerStatic");
1121  if (_dcc_static)
1122  {
1123  std::cout << PHWHERE << " found static TPC distortion correction container" << std::endl;
1124  }
1125  _dcc_average = findNode::getClass<TpcDistortionCorrectionContainer>(topNode, "TpcDistortionCorrectionContainerAverage");
1126  if (_dcc_average)
1127  {
1128  std::cout << PHWHERE << " found average TPC distortion correction container" << std::endl;
1129  }
1130  _dcc_fluctuation = findNode::getClass<TpcDistortionCorrectionContainer>(topNode, "TpcDistortionCorrectionContainerFluctuation");
1131  if (_dcc_fluctuation)
1132  {
1133  std::cout << PHWHERE << " found fluctuation TPC distortion correction container" << std::endl;
1134  }
1135 
1137 }