Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHGenFitTrkFitter.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHGenFitTrkFitter.cc
1 
8 #include "PHGenFitTrkFitter.h"
9 
11 #include <fun4all/PHTFileServer.h>
12 #include <fun4all/SubsysReco.h> // for SubsysReco
13 
14 #include <g4detectors/PHG4CylinderGeom.h> // for PHG4CylinderGeom
16 
17 #include <g4main/PHG4Particle.h>
18 #include <g4main/PHG4Particlev2.h>
20 #include <g4main/PHG4VtxPoint.h> // for PHG4VtxPoint
21 #include <g4main/PHG4VtxPointv1.h>
22 
23 #include <intt/CylinderGeomIntt.h>
24 
27 
28 #include <mvtx/CylinderGeom_Mvtx.h>
29 
30 #include <phfield/PHFieldUtility.h>
31 
32 #include <phgenfit/Fitter.h>
33 #include <phgenfit/Measurement.h> // for Measurement
34 #include <phgenfit/PlanarMeasurement.h>
35 #include <phgenfit/SpacepointMeasurement.h>
36 #include <phgenfit/Track.h>
37 
38 #include <phgeom/PHGeomUtility.h>
39 
40 #include <phool/PHCompositeNode.h>
41 #include <phool/PHIODataNode.h>
42 #include <phool/PHNode.h> // for PHNode
43 #include <phool/PHNodeIterator.h>
44 #include <phool/PHObject.h> // for PHObject
45 #include <phool/getClass.h>
46 #include <phool/phool.h>
47 
49 
50 #include <trackbase/ActsGeometry.h>
51 #include <trackbase/InttDefs.h>
52 #include <trackbase/MvtxDefs.h>
53 #include <trackbase/TpcDefs.h>
54 #include <trackbase/TrkrDefs.h>
55 #include <trackbase/TrkrCluster.h> // for TrkrCluster
57 #include <trackbase/TrkrDefs.h>
58 
64 #include <trackbase_historic/SvtxTrackState.h> // for SvtxTrackState
67 
70 
71 #include <GenFit/AbsMeasurement.h> // for AbsMeasurement
72 #include <GenFit/EventDisplay.h> // for EventDisplay
73 #include <GenFit/Exception.h> // for Exception
74 #include <GenFit/GFRaveConverters.h>
75 #include <GenFit/GFRaveTrackParameters.h> // for GFRaveTrackParame...
76 #include <GenFit/GFRaveVertex.h>
77 #include <GenFit/GFRaveVertexFactory.h>
78 #include <GenFit/KalmanFitterInfo.h>
79 #include <GenFit/MeasuredStateOnPlane.h>
80 #include <GenFit/RKTrackRep.h>
81 #include <GenFit/Track.h>
82 #include <GenFit/TrackPoint.h> // for TrackPoint
83 
84 //Rave
85 #include <rave/ConstantMagneticField.h>
86 #include <rave/VacuumPropagator.h> // for VacuumPropagator
87 #include <rave/VertexFactory.h>
88 
89 #include <TClonesArray.h>
90 #include <TRotation.h>
91 #include <TTree.h>
92 #include <TVector3.h>
93 #include <TMath.h> // for ATan2
94 #include <TMatrixDSymfwd.h> // for TMatrixDSym
95 #include <TMatrixFfwd.h> // for TMatrixF
96 #include <TMatrixT.h> // for TMatrixT, operator*
97 #include <TMatrixTSym.h> // for TMatrixTSym
98 #include <TMatrixTUtils.h> // for TMatrixTRow
99 #include <TVectorDfwd.h> // for TVectorD
100 #include <TVectorT.h> // for TVectorT
101 
102 #include <cmath> // for sqrt, NAN
103 #include <iostream>
104 #include <map>
105 #include <memory>
106 #include <utility>
107 #include <vector>
108 
109 class PHField;
110 class TGeoManager;
111 namespace genfit { class AbsTrackRep; }
112 
113 #define LogDebug(exp) std::cout << "DEBUG: " << __FILE__ << ": " << __LINE__ << ": " << exp << std::endl
114 #define LogError(exp) std::cout << "ERROR: " << __FILE__ << ": " << __LINE__ << ": " << exp << std::endl
115 #define LogWarning(exp) std::cout << "WARNING: " << __FILE__ << ": " << __LINE__ << ": " << exp << std::endl
116 
117 static constexpr float WILD_FLOAT = -9999;
118 
119 #define _DEBUG_MODE_ 0
120 
121 //#define _DEBUG_
122 
123 using namespace std;
124 
125 //______________________________________________________
126 namespace {
127 
128  // square
129  template< class T > T square( T x ) { return x*x; }
130 
131  // convert gf state to SvtxTrackState_v1
132  SvtxTrackState_v1 create_track_state( float pathlength, const genfit::MeasuredStateOnPlane* gf_state )
133  {
134 
135  SvtxTrackState_v1 out( pathlength );
136  out.set_x(gf_state->getPos().x());
137  out.set_y(gf_state->getPos().y());
138  out.set_z(gf_state->getPos().z());
139 
140  out.set_px(gf_state->getMom().x());
141  out.set_py(gf_state->getMom().y());
142  out.set_pz(gf_state->getMom().z());
143 
144  for (int i = 0; i < 6; i++)
145  {
146  for (int j = i; j < 6; j++)
147  { out.set_error(i, j, gf_state->get6DCov()[i][j]); }
148  }
149 
150  return out;
151 
152  }
153 
154  // get cluster keys from a given track
155  std::vector<TrkrDefs::cluskey> get_cluster_keys( const SvtxTrack* track )
156  {
157  std::vector<TrkrDefs::cluskey> out;
158  for( const auto& seed: { track->get_silicon_seed(), track->get_tpc_seed() } )
159  {
160  if( seed )
161  { std::copy( seed->begin_cluster_keys(), seed->end_cluster_keys(), std::back_inserter( out ) ); }
162  }
163  return out;
164  }
165 
166  [[maybe_unused]] std::ostream& operator << (std::ostream& out, const Acts::Vector3& vector )
167  {
168  out << "(" << vector.x() << ", " << vector.y() << ", " << vector.z() << ")";
169  return out;
170  }
171 
172 }
173 
174 /*
175  * Constructor
176  */
178  : SubsysReco(name)
179 {
180  Verbosity(0);
187 }
188 
189 /*
190  * Init
191  */
194 
195 /*
196  * Init run
197  */
199 {
200  CreateNodes(topNode);
201 
202  auto tgeo_manager = PHGeomUtility::GetTGeoManager(topNode);
203  auto field = PHFieldUtility::GetFieldMapNode(nullptr, topNode);
204 
206  tgeo_manager,
208  "RKTrackRep", _do_evt_display) );
209 
210  _fitter->set_verbosity(Verbosity());
211 
213  if (!_vertex_finder)
214  {
215  cerr << PHWHERE << endl;
217  }
218  _vertex_finder->setMethod(_vertexing_method.data());
219 
220 
221  if (!_vertex_finder)
222  {
223  cerr << PHWHERE << endl;
225  }
226 
227  if (_do_eval)
228  {
229  if (Verbosity() > 1)
230  cout << PHWHERE << " Openning file: " << _eval_outname << endl;
231  PHTFileServer::get().open(_eval_outname, "RECREATE");
232  init_eval_tree();
233  }
234 
235  std::cout << "PHGenFitTrkFitter::InitRun - m_fit_silicon_mms: " << m_fit_silicon_mms << std::endl;
236  std::cout << "PHGenFitTrkFitter::InitRun - m_use_micromegas: " << m_use_micromegas << std::endl;
237 
238  // print disabled layers
239  // if( Verbosity() )
240  {
241  for( const auto& layer:_disabled_layers )
242  { std::cout << PHWHERE << " Layer " << layer << " is disabled." << std::endl; }
243  }
244 
246 }
247 
248 /*
249  * process_event():
250  * Call user instructions for every event.
251  * This function contains the analysis structure.
252  *
253  */
255 {
256  ++_event;
257 
258  if (Verbosity() > 1)
259  { std::cout << PHWHERE << "Events processed: " << _event << std::endl; }
260 
261  // clear global position map
262  GetNodes(topNode);
263 
264  // clear default track map, fill with seeds
265  m_trackMap->Reset();
266 
267  unsigned int trackid = 0;
268  for(auto trackiter = m_seedMap->begin(); trackiter != m_seedMap->end(); ++trackiter)
269  {
270  TrackSeed *track = *trackiter;
271  if(!track) continue;
272 
273  // get silicon seed and check
274  const auto siid = track->get_silicon_seed_index();
275  if(siid == std::numeric_limits<unsigned int>::max()) continue;
276  const auto siseed = m_siliconSeeds->get(siid);
277  if( !siseed ) continue;
278 
279  // get crossing number and check
280  const auto crossing = siseed->get_crossing();
281  if(crossing == SHRT_MAX) continue;
282 
283  // get tpc seed and check
284  const auto tpcid = track->get_tpc_seed_index();
285  const auto tpcseed = m_tpcSeeds->get(tpcid);
286  if( !tpcseed ) continue;
287 
288  // build track
289  auto svtxtrack = std::make_unique<SvtxTrack_v4>();
290  svtxtrack->set_id( trackid++ );
291  svtxtrack->set_silicon_seed( siseed );
292  svtxtrack->set_tpc_seed( tpcseed );
293  svtxtrack->set_crossing( crossing );
294 
295  // track position comes from silicon seed
296  svtxtrack->set_x(siseed->get_x());
297  svtxtrack->set_y(siseed->get_y());
298  svtxtrack->set_z(siseed->get_z());
299 
300  // track momentum comes from tpc seed
301  svtxtrack->set_charge( tpcseed->get_qOverR() > 0 ? 1 : -1);
302  svtxtrack->set_px(tpcseed->get_px(m_clustermap,m_tgeometry));
303  svtxtrack->set_py(tpcseed->get_py(m_clustermap,m_tgeometry));
304  svtxtrack->set_pz(tpcseed->get_pz());
305 
306  // insert in map
307  m_trackMap->insert(svtxtrack.get());
308 
309  }
310 
311  // stands for Refit_GenFit_Tracks
312  vector<genfit::Track*> rf_gf_tracks;
313  vector<std::shared_ptr<PHGenFit::Track> > rf_phgf_tracks;
314 
315  map<unsigned int, unsigned int> svtxtrack_genfittrack_map;
316 
317  // clear refit trackmap
319 
320  // m_trackMap is SvtxTrackMap from the node tree
321  for ( auto iter = m_trackMap->begin(); iter != m_trackMap->end(); ++iter)
322  {
323  auto svtx_track = iter->second;
324  if (!svtx_track) continue;
325 
326  if(Verbosity() > 10){
327  cout << " process SVTXTrack " << iter->first << endl;
328  svtx_track->identify();
329  }
330 
331  if (!(svtx_track->get_pt() > _fit_min_pT)) continue;
332 
333  // This is the final track (re)fit. It does not include the collision vertex. If fit_primary_track is set, a refit including the vertex is done below.
334  // rf_phgf_track stands for Refit_PHGenFit_Track
335  std::shared_ptr<PHGenFit::Track> rf_phgf_track = ReFitTrack(topNode, svtx_track);
336  if (rf_phgf_track)
337  {
338  svtxtrack_genfittrack_map[svtx_track->get_id()] = rf_phgf_tracks.size();
339  rf_phgf_tracks.push_back(rf_phgf_track);
340  if (rf_phgf_track->get_ndf() > _vertex_min_ndf)
341  rf_gf_tracks.push_back(rf_phgf_track->getGenFitTrack());
342  if(Verbosity() > 10) cout << "Done refitting input track" << svtx_track->get_id() << " or rf_phgf_track " << rf_phgf_tracks.size() << endl;
343  }
344  else{
345  if(Verbosity() >= 1)
346  cout << "failed refitting input track# " << iter->first << endl;
347  }
348 
349  }
350 
351  /*
352  * add tracks to event display
353  * needs to make copied for smart ptrs will be destroied even
354  * there are still references in TGeo::EventView
355  */
356  if (_do_evt_display)
357  {
358  vector<genfit::Track*> copy;
359  for (genfit::Track* t : rf_gf_tracks)
360  {
361  copy.push_back(new genfit::Track(*t));
362  }
363  _fitter->getEventDisplay()->addEvent(copy);
364  }
365 
366  // find vertices using final tracks
367  std::vector<genfit::GFRaveVertex*> rave_vertices;
368 
369  if (rf_gf_tracks.size() >= 2)
370  {
371  if(Verbosity() > 10)
372  {cout << "Call Rave vertex finder" << endl;
373  cout << " rf_gf_tracks size " << rf_gf_tracks.size() << endl;
374  for(long unsigned int i=0;i<rf_gf_tracks.size();++i)
375  {
376  cout << " track " << i << " num points " << rf_gf_tracks[i]->getNumPointsWithMeasurement() << endl;
377  }
378  }
379  try
380  {
381  _vertex_finder->findVertices(&rave_vertices, rf_gf_tracks);
382  }
383  catch (...)
384  {
385  if (Verbosity() > 1)
386  std::cout << PHWHERE << "GFRaveVertexFactory::findVertices failed!";
387  }
388  }
389 
390  if(Verbosity() > 10 && rave_vertices.size() == 0)
391  {
392  cout << PHWHERE << " Rave found no vertices - SvtxVertexMapRefit will be empty" << endl;
393  }
394 
395  // Creates new SvtxVertex objects and copies in the rave vertex info and associated rave tracks. Then adds the vertices to _svtxmap
396  // also makes a map of (trackid/vertex), _rave_vertex_gf_track_map for later use
397  FillSvtxVertexMap(rave_vertices, rf_gf_tracks);
398 
399  // Finds the refitted rf_phgf_track corresponding to each SvtxTrackMap entry
400  // Converts it to an SvtxTrack in MakeSvtxTrack
401  // MakeSvtxTrack takes a vertex that it gets from the map made in FillSvtxVertex
402  // If the refit was succesful, the track on the node tree is replaced with the new one
403  // If not, the track is erased from the node tree
404  for (SvtxTrackMap::Iter iter = m_trackMap->begin(); iter != m_trackMap->end();)
405  {
406  std::shared_ptr<PHGenFit::Track> rf_phgf_track;
407 
408  // find the genfit track that corresponds to this one on the node tree
409  unsigned int itrack =0;
410  if (svtxtrack_genfittrack_map.find(iter->second->get_id()) != svtxtrack_genfittrack_map.end())
411  {
412  itrack =
413  svtxtrack_genfittrack_map[iter->second->get_id()];
414  rf_phgf_track = rf_phgf_tracks[itrack];
415  }
416 
417  if (rf_phgf_track)
418  {
419  SvtxVertex* vertex = nullptr;
420 
421  unsigned int ivert = 0;
422  ivert = _rave_vertex_gf_track_map[itrack];
423 
424  if (m_vertexMap_refit->size() > 0)
425  {
426  vertex = m_vertexMap_refit->get(ivert);
427 
428  if(Verbosity() > 20) cout << PHWHERE << " gf track " << itrack << " will add to track: m_vertexMap_refit vertex " << ivert
429  << " with position x,y,z = " << vertex->get_x() << " " << vertex->get_y() << " " << vertex->get_z() << endl;
430  }
431  std::shared_ptr<SvtxTrack> rf_track = MakeSvtxTrack(iter->second, rf_phgf_track,
432  vertex);
433 
434 #ifdef _DEBUG_
435  cout << __LINE__ << endl;
436 #endif
437  if (!rf_track)
438  {
439  //if (_output_mode == OverwriteOriginalNode)
440 #ifdef _DEBUG_
441  LogDebug("!rf_track, continue.");
442 #endif
444  {
445  auto key = iter->first;
446  ++iter;
447  m_trackMap->erase(key);
448  continue;
449  } else {
450  ++iter;
451  continue;
452  }
453  }
454 
455  // delete vertex;//DEBUG
456 
457  // rf_phgf_tracks.push_back(rf_phgf_track);
458  // rf_gf_tracks.push_back(rf_phgf_track->getGenFitTrack());
459 
461  if (m_trackMap_refit)
462  { m_trackMap_refit->insert(rf_track.get()); }
463 
465  { iter->second->CopyFrom( rf_track.get() ); }
466  }
467  else
468  {
470  {
471  auto key = iter->first;
472  ++iter;
473  m_trackMap->erase(key);
474  continue;
475  }
476  }
477 
478  ++iter;
479  }
480 
481 #ifdef _DEBUG_
482  cout << __LINE__ << endl;
483 #endif
484 
485  // Need to keep tracks if _do_evt_display
486  if (!_do_evt_display)
487  {
488  rf_phgf_tracks.clear();
489  }
490 
491 #ifdef _DEBUG_
492  cout << __LINE__ << endl;
493 #endif
494 
498  if (_fit_primary_tracks && rave_vertices.size() > 0)
499  {
501 
502  //FIXME figure out which vertex to use.
503  SvtxVertex* vertex = nullptr;
504  if (m_vertexMap_refit->size() > 0)
505  vertex = m_vertexMap_refit->get(0);
506 
507  // fix this, have to get vertex ID from track
508 
509  if (vertex)
510  {
512  iter != m_trackMap->end(); ++iter)
513  {
514  SvtxTrack* svtx_track = iter->second;
515  if (!svtx_track)
516  continue;
517  if (!(svtx_track->get_pt() > _fit_min_pT))
518  continue;
522  std::shared_ptr<PHGenFit::Track> rf_phgf_track = ReFitTrack(topNode, svtx_track,
523  vertex);
524  if (rf_phgf_track)
525  {
526  // //FIXME figure out which vertex to use.
527  // SvtxVertex* vertex = nullptr;
528  // if (m_vertexMap_refit->size() > 0)
529  // vertex = m_vertexMap_refit->get(0);
530 
531  std::shared_ptr<SvtxTrack> rf_track = MakeSvtxTrack(svtx_track,
532  rf_phgf_track, vertex);
533  //delete rf_phgf_track;
534  if (!rf_track)
535  {
536 #ifdef _DEBUG_
537  LogDebug("!rf_track, continue.");
538 #endif
539  continue;
540  }
541  m_primary_trackMap->insert(rf_track.get());
542  }
543  }
544  }
545  else
546  {
547  LogError("No vertex in SvtxVertexMapRefit!");
548  }
549  }
550 #ifdef _DEBUG_
551  cout << __LINE__ << endl;
552 #endif
553  for (genfit::GFRaveVertex* vertex : rave_vertices)
554  {
555  delete vertex;
556  }
557  rave_vertices.clear();
558 
559  if (_do_eval)
560  {
561  fill_eval_tree(topNode);
562  }
563 #ifdef _DEBUG_
564  cout << __LINE__ << endl;
565 #endif
566 
568 }
569 
570 /*
571  * End
572  */
574 {
575  if (_do_eval)
576  {
577  if (Verbosity() > 1)
578  cout << PHWHERE << " Writing to file: " << _eval_outname << endl;
580  _eval_tree->Write();
581  _cluster_eval_tree->Write();
582  }
583 
584  if (_do_evt_display)
585  _fitter->displayEvent();
586 
588 }
589 
590 /*
591  * fill_eval_tree():
592  */
594 {
595  // Make sure to reset all the TTree variables before trying to set them.
597 
598  if( _truth_container )
599  {
600  int i = 0;
601  for (auto itr = _truth_container->GetPrimaryParticleRange().first; itr != _truth_container->GetPrimaryParticleRange().second; ++itr, ++i)
602  { new ((*_tca_particlemap)[i])(PHG4Particlev2)( *dynamic_cast<PHG4Particlev2*>(itr->second)); }
603  }
604 
605 
606  if( _truth_container )
607  {
608  int i = 0;
609  for (auto itr = _truth_container->GetPrimaryVtxRange().first; itr != _truth_container->GetPrimaryVtxRange().second; ++itr, ++i)
610  { new ((*_tca_vtxmap)[i])(PHG4VtxPointv1)(*dynamic_cast<PHG4VtxPointv1*>(itr->second)); }
611  }
612 
613  if( m_trackMap )
614  {
615  int i = 0;
616  for ( const auto& pair:*m_trackMap )
617  { new ((*_tca_trackmap)[i++])(SvtxTrack_v4)( *pair.second ); }
618  }
619 
620  if (_vertexmap)
621  {
622  int i = 0;
623  for ( const auto& pair:*_vertexmap )
624  { new ((*_tca_vertexmap)[i++])(SvtxVertex_v1)( *dynamic_cast<SvtxVertex_v1*>(pair.second) ); }
625  }
626 
627  if (m_trackMap_refit)
628  {
629  int i = 0;
630  for (const auto& pair:*m_trackMap_refit )
631  { new ((*_tca_trackmap_refit)[i++])(SvtxTrack_v4)(*pair.second); }
632  }
633 
635  {
636  int i = 0;
637  for ( const auto& pair:*m_primary_trackMap )
638  { new ((*_tca_primtrackmap)[i++])(SvtxTrack_v4)(*pair.second); }
639  }
640 
641  if (m_vertexMap_refit)
642  {
643  int i = 0;
644  for( const auto& pair:*m_vertexMap_refit )
645  { new ((*_tcam_vertexMap_refit)[i++])(SvtxVertex_v1)( *dynamic_cast<SvtxVertex_v1*>(pair.second)); }
646  }
647 
648  _eval_tree->Fill();
649 
650  return;
651 }
652 
653 /*
654  * init_eval_tree
655  */
657 {
658  if (!_tca_particlemap)
659  _tca_particlemap = new TClonesArray("PHG4Particlev2");
660  if (!_tca_vtxmap)
661  _tca_vtxmap = new TClonesArray("PHG4VtxPointv1");
662 
663  if (!_tca_trackmap)
664  _tca_trackmap = new TClonesArray("SvtxTrack_v4");
665  if (!_tca_vertexmap)
666  _tca_vertexmap = new TClonesArray("SvtxVertex_v1");
667  if (!_tca_trackmap_refit)
668  _tca_trackmap_refit = new TClonesArray("SvtxTrack_v4");
670  if (!_tca_primtrackmap)
671  _tca_primtrackmap = new TClonesArray("SvtxTrack_v4");
673  _tcam_vertexMap_refit = new TClonesArray("SvtxVertex_v1");
674 
675  // create TTree
676  _eval_tree = new TTree("T", "PHGenFitTrkFitter Evaluation");
677 
678  _eval_tree->Branch("PrimaryParticle", _tca_particlemap);
679  _eval_tree->Branch("TruthVtx", _tca_vtxmap);
680 
681  _eval_tree->Branch("SvtxTrack", _tca_trackmap);
682  _eval_tree->Branch("SvtxVertex", _tca_vertexmap);
683  _eval_tree->Branch("SvtxTrackRefit", _tca_trackmap_refit);
685  _eval_tree->Branch("PrimSvtxTrack", _tca_primtrackmap);
686  _eval_tree->Branch("SvtxVertexRefit", _tcam_vertexMap_refit);
687 
688  _cluster_eval_tree = new TTree("cluster_eval", "cluster eval tree");
689  _cluster_eval_tree->Branch("x", &_cluster_eval_tree_x, "x/F");
690  _cluster_eval_tree->Branch("y", &_cluster_eval_tree_y, "y/F");
691  _cluster_eval_tree->Branch("z", &_cluster_eval_tree_z, "z/F");
692  _cluster_eval_tree->Branch("gx", &_cluster_eval_tree_gx, "gx/F");
693  _cluster_eval_tree->Branch("gy", &_cluster_eval_tree_gy, "gy/F");
694  _cluster_eval_tree->Branch("gz", &_cluster_eval_tree_gz, "gz/F");
695 }
696 
697 /*
698  * reset_eval_variables():
699  * Reset all the tree variables to their default values.
700  * Needs to be called at the start of every event
701  */
703 {
704  _tca_particlemap->Clear();
705  _tca_vtxmap->Clear();
706 
707  _tca_trackmap->Clear();
708  _tca_vertexmap->Clear();
709  _tca_trackmap_refit->Clear();
711  _tca_primtrackmap->Clear();
712  _tcam_vertexMap_refit->Clear();
713 
720 }
721 
723 {
724  // create nodes...
725  PHNodeIterator iter(topNode);
726 
727  auto dstNode = static_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
728  if (!dstNode)
729  {
730  cerr << PHWHERE << "DST Node missing, doing nothing." << endl;
732  }
733  PHNodeIterator iter_dst(dstNode);
734 
735  // Create the SVTX node
736  auto svtx_node = dynamic_cast<PHCompositeNode*>(iter_dst.findFirst( "PHCompositeNode", "SVTX"));
737  if (!svtx_node)
738  {
739  svtx_node = new PHCompositeNode("SVTX");
740  dstNode->addNode(svtx_node);
741  if (Verbosity())
742  cout << "SVTX node added" << endl;
743  }
744 
745  // default track map
746  m_trackMap = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
747  if(!m_trackMap)
748  {
750  auto node = new PHIODataNode<PHObject>(m_trackMap,"SvtxTrackMap","PHObject");
751  svtx_node->addNode(node);
752  }
753 
755  {
757  auto tracks_node = new PHIODataNode<PHObject>( m_trackMap_refit, "SvtxTrackMapRefit", "PHObject");
758  svtx_node->addNode(tracks_node);
759  if (Verbosity())
760  { std::cout << "Svtx/SvtxTrackMapRefit node added" << std::endl; }
761  }
762 
763  if( _fit_primary_tracks )
764  {
766  auto primary_tracks_node = new PHIODataNode<PHObject>(m_primary_trackMap, "PrimaryTrackMap", "PHObject");
767  svtx_node->addNode(primary_tracks_node);
768  if (Verbosity())
769  { std::cout << "Svtx/PrimaryTrackMap node added" << std::endl; }
770  }
771 
772  // always write final vertex results to SvtxVertexMapRefit
774  auto vertexes_node = new PHIODataNode<PHObject>( m_vertexMap_refit, "SvtxVertexMapRefit", "PHObject");
775  svtx_node->addNode(vertexes_node);
776  if (Verbosity())
777  { cout << "Svtx/SvtxVertexMapRefit node added" << endl; }
778 
780 }
781 
782 //______________________________________________________
783 void PHGenFitTrkFitter::disable_layer( int layer, bool disabled )
784 {
785  if( disabled ) _disabled_layers.insert( layer );
786  else _disabled_layers.erase( layer );
787 }
788 
789 //______________________________________________________
790 void PHGenFitTrkFitter::set_disabled_layers( const std::set<int>& layers )
791 { _disabled_layers = layers; }
792 
793 //______________________________________________________
795 { _disabled_layers.clear(); }
796 
797 //______________________________________________________
798 const std::set<int>& PHGenFitTrkFitter::get_disabled_layers() const
799 { return _disabled_layers; }
800 
801 //______________________________________________________
803 {
804  // store flags
806 
807  // disable/enable layers accordingly
808  for( int layer = 7; layer < 23; ++layer ) { disable_layer( layer, value ); }
809  for( int layer = 23; layer < 39; ++layer ) { disable_layer( layer, value ); }
810  for( int layer = 39; layer < 55; ++layer ) { disable_layer( layer, value ); }
811 
812 }
813 
814 /*
815  * GetNodes():
816  * Get all the all the required nodes off the node tree
817  */
819 {
820 
821  // acts geometry
822  m_tgeometry = findNode::getClass<ActsGeometry>(topNode,"ActsGeometry");
823  if(!m_tgeometry)
824  {
825  std::cout << "PHGenFitTrkFitter::GetNodes - No acts tracking geometry, can't proceed" << std::endl;
827  }
828 
829  //DST objects
830  //Truth container
831  _truth_container = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
832 
833  // clusters
834  m_clustermap = findNode::getClass<TrkrClusterContainer>(topNode,"CORRECTED_TRKR_CLUSTER");
835  if(m_clustermap)
836  {
837 
838  if( _event < 2 )
839  { std::cout << "PHGenFitTrkFitter::GetNodes - Using CORRECTED_TRKR_CLUSTER node " << std::endl; }
840 
841  } else {
842 
843  if( _event < 2 )
844  { std::cout << "PHGenFitTrkFitter::GetNodes - CORRECTED_TRKR_CLUSTER node not found, using TRKR_CLUSTER" << std::endl; }
845  m_clustermap = findNode::getClass<TrkrClusterContainer>(topNode,"TRKR_CLUSTER");
846 
847  }
848 
849  if(!m_clustermap)
850  {
851  cout << PHWHERE << "PHGenFitTrkFitter::GetNodes - TRKR_CLUSTER node not found on node tree" << endl;
853  }
854 
855  // seeds
856  m_seedMap = findNode::getClass<TrackSeedContainer>(topNode,"SvtxTrackSeedContainer");
857  if(!m_seedMap)
858  {
859  std::cout << "PHGenFitTrkFitter::GetNodes - No Svtx seed map on node tree. Exiting." << std::endl;
861  }
862 
863  m_tpcSeeds = findNode::getClass<TrackSeedContainer>(topNode, "TpcTrackSeedContainer");
864  if(!m_tpcSeeds)
865  {
866  std::cout << "PHGenFitTrkFitter::GetNodes - TpcTrackSeedContainer not on node tree. Bailing"
867  << std::endl;
869  }
870 
871  m_siliconSeeds = findNode::getClass<TrackSeedContainer>(topNode, "SiliconTrackSeedContainer");
872  if(!m_siliconSeeds)
873  {
874  std::cout << "PHGenFitTrkFitter::GetNodes - SiliconTrackSeedContainer not on node tree. Bailing"
875  << std::endl;
877  }
878 
879  // Svtx Tracks
880  m_trackMap = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
881  if (!m_trackMap && _event < 2)
882  {
883  cout << "PHGenFitTrkFitter::GetNodes - SvtxTrackMap node not found on node tree" << endl;
885  }
886 
887  // Input Svtx Vertices
888  _vertexmap = findNode::getClass<SvtxVertexMap>(topNode, "SvtxVertexMap");
889  if (!_vertexmap && _event < 2)
890  {
891  cout << PHWHERE << " SvtxVertexrMap node not found on node tree"
892  << endl;
894  }
895 
896  // Output Svtx Tracks
898  {
899  m_trackMap_refit = findNode::getClass<SvtxTrackMap>(topNode,
900  "SvtxTrackMapRefit");
901  if (!m_trackMap_refit && _event < 2)
902  {
903  cout << PHWHERE << " SvtxTrackMapRefit node not found on node tree"
904  << endl;
906  }
907  }
908 
909  // Output Primary Svtx Tracks
911  {
912  m_primary_trackMap = findNode::getClass<SvtxTrackMap>(topNode,
913  "PrimaryTrackMap");
914  if (!m_primary_trackMap && _event < 2)
915  {
916  cout << PHWHERE << " PrimaryTrackMap node not found on node tree"
917  << endl;
919  }
920  }
921 
922  // Output Svtx Vertices
923  m_vertexMap_refit = findNode::getClass<SvtxVertexMap>(topNode,
924  "SvtxVertexMapRefit");
925  if (!m_vertexMap_refit && _event < 2)
926  {
927  cout << PHWHERE << " SvtxVertexMapRefit node not found on node tree"
928  << endl;
930  }
931 
932  // tpc distortion corrections
933  m_dcc_static = findNode::getClass<TpcDistortionCorrectionContainer>(topNode,"TpcDistortionCorrectionContainerStatic");
934  m_dcc_average = findNode::getClass<TpcDistortionCorrectionContainer>(topNode,"TpcDistortionCorrectionContainerAverage");
935  m_dcc_fluctuation = findNode::getClass<TpcDistortionCorrectionContainer>(topNode,"TpcDistortionCorrectionContainerFluctuation");
936 
938 }
939 
940 //_________________________________________________________________________________
942 {
943 
944  // get global position from Acts transform
945  auto globalPosition = m_tgeometry->getGlobalPosition(key, cluster);
946 
947  // for the TPC calculate the proper z based on crossing and side
948  const auto trkrid = TrkrDefs::getTrkrId(key);
949  if(trkrid == TrkrDefs::tpcId)
950  {
951  const auto side = TpcDefs::getSide(key);
952  globalPosition.z() = m_clusterCrossingCorrection.correctZ(globalPosition.z(), side, crossing);
953 
954  // apply distortion corrections
955  if(m_dcc_static)
956  {
957  globalPosition = m_distortionCorrection.get_corrected_position( globalPosition, m_dcc_static );
958  }
959 
960  if(m_dcc_average)
961  {
962  globalPosition = m_distortionCorrection.get_corrected_position( globalPosition, m_dcc_average );
963  }
964 
965  if(m_dcc_fluctuation)
966  {
967  globalPosition = m_distortionCorrection.get_corrected_position( globalPosition, m_dcc_fluctuation );
968  }
969  }
970 
971  return globalPosition;
972 }
973 
974 /*
975  * fit track with SvtxTrack as input seed.
976  * \param intrack Input SvtxTrack
977  * \param invertex Input Vertex, if fit track as a primary vertex
978  */
979 //PHGenFit::Track* PHGenFitTrkFitter::ReFitTrack(PHCompositeNode *topNode, const SvtxTrack* intrack,
980 std::shared_ptr<PHGenFit::Track> PHGenFitTrkFitter::ReFitTrack(PHCompositeNode* topNode, const SvtxTrack* intrack, const SvtxVertex* invertex)
981 {
982  //std::shared_ptr<PHGenFit::Track> empty_track(nullptr);
983  if (!intrack)
984  {
985  cerr << PHWHERE << " Input SvtxTrack is nullptr!" << endl;
986  return nullptr;
987  }
988 
989  auto geom_container_intt = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
990  assert( geom_container_intt );
991 
992  auto geom_container_mvtx = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MVTX");
993  assert( geom_container_mvtx );
994 
995  /* no need to check for the container validity here. The check is done if micromegas clusters are actually found in the track */
996  auto geom_container_micromegas = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MICROMEGAS_FULL");
997 
998  // get crossing from track
999  const auto crossing = intrack->get_crossing();
1000  assert( crossing != SHRT_MAX );
1001 
1002  // prepare seed
1003  TVector3 seed_mom(100, 0, 0);
1004  TVector3 seed_pos(0, 0, 0);
1005  TMatrixDSym seed_cov(6);
1006  for (int i = 0; i < 6; i++)
1007  {
1008  for (int j = 0; j < 6; j++)
1009  {
1010  seed_cov[i][j] = 100.;
1011  }
1012  }
1013 
1014  // Create measurements
1015  std::vector<PHGenFit::Measurement*> measurements;
1016 
1017  // 1000 is a arbitrary number for now
1018  const double vertex_chi2_over_dnf_cut = 1000;
1019  const double vertex_cov_element_cut = 10000; //arbitrary cut cm*cm
1020 
1021  if (invertex and invertex->size_tracks() > 1 and invertex->get_chisq() / invertex->get_ndof() < vertex_chi2_over_dnf_cut)
1022  {
1023  TVector3 pos(invertex->get_x(), invertex->get_y(), invertex->get_z());
1024  TMatrixDSym cov(3);
1025  cov.Zero();
1026  bool is_vertex_cov_sane = true;
1027  for (unsigned int i = 0; i < 3; i++)
1028  for (unsigned int j = 0; j < 3; j++)
1029  {
1030  cov(i, j) = invertex->get_error(i, j);
1031 
1032  if (i == j)
1033  {
1034  if (!(invertex->get_error(i, j) > 0 and invertex->get_error(i, j) < vertex_cov_element_cut))
1035  is_vertex_cov_sane = false;
1036  }
1037  }
1038 
1039  if (is_vertex_cov_sane)
1040  {
1041  auto meas = new PHGenFit::SpacepointMeasurement( pos, cov);
1042  measurements.push_back(meas);
1043  if(Verbosity() >= 2)
1044  {
1045  meas->getMeasurement()->Print();
1046  }
1047  }
1048  }
1049 
1050  // sort clusters with radius before fitting
1051  if(Verbosity() > 10) intrack->identify();
1052  std::map<float, TrkrDefs::cluskey> m_r_cluster_id;
1053 
1054  unsigned int n_silicon_clusters = 0;
1055  unsigned int n_micromegas_clusters = 0;
1056 
1057  for( const auto& cluster_key:get_cluster_keys( intrack ) )
1058  {
1059  // count clusters
1060  switch( TrkrDefs::getTrkrId(cluster_key) )
1061  {
1062  case TrkrDefs::mvtxId:
1063  case TrkrDefs::inttId:
1064  ++n_silicon_clusters;
1065  break;
1066 
1068  ++n_micromegas_clusters;
1069  break;
1070 
1071  default: break;
1072  }
1073 
1074 
1075  const auto cluster = m_clustermap->findCluster(cluster_key);
1076  const auto globalPosition = getGlobalPosition( cluster_key, cluster, crossing );
1077 
1078  float r = sqrt(square( globalPosition.x() ) + square( globalPosition.y() ));
1079  m_r_cluster_id.insert(std::pair<float, TrkrDefs::cluskey>(r, cluster_key));
1080  int layer_out = TrkrDefs::getLayer(cluster_key);
1081  if(Verbosity() > 10) cout << " Layer " << layer_out << " cluster " << cluster_key << " radius " << r << endl;
1082  }
1083 
1084  // discard track if not enough clusters when fitting with silicon + mm only
1085  if( m_fit_silicon_mms )
1086  {
1087  if( n_silicon_clusters == 0 ) return nullptr;
1088  if( m_use_micromegas && n_micromegas_clusters == 0 ) return nullptr;
1089  }
1090 
1091  for (auto iter = m_r_cluster_id.begin();
1092  iter != m_r_cluster_id.end();
1093  ++iter)
1094  {
1095  TrkrDefs::cluskey cluster_key = iter->second;
1096  const int layer = TrkrDefs::getLayer(cluster_key);
1097 
1098  // skip disabled layers
1099  if( _disabled_layers.find( layer ) != _disabled_layers.end() )
1100  { continue; }
1101 
1102  TrkrCluster* cluster = m_clustermap->findCluster(cluster_key);
1103  if (!cluster)
1104  {
1105  LogError("No cluster Found!");
1106  continue;
1107  }
1108 
1109 #ifdef _DEBUG_
1110  int output_layer = TrkrDefs::getLayer(cluster_key);
1111  cout
1112  << __LINE__
1113  << ": ID: " << cluster_key
1114  << ": layer: " << output_layer
1115  << endl;
1116 #endif
1117 
1118  const auto globalPosition_acts = getGlobalPosition( cluster_key, cluster, crossing );
1119 
1120  const TVector3 pos(globalPosition_acts.x(), globalPosition_acts.y(), globalPosition_acts.z() );
1121  seed_mom.SetPhi(pos.Phi());
1122  seed_mom.SetTheta(pos.Theta());
1123 
1124  // by default assume normal to local surface is along cluster azimuthal position
1125  TVector3 n( globalPosition_acts.x(), globalPosition_acts.y(), 0 );
1126 
1127  // replace normal by proper vector for specified subsystems
1128  switch( TrkrDefs::getTrkrId(cluster_key) )
1129  {
1130 
1131  case TrkrDefs::mvtxId:
1132  {
1133  double ladder_location[3] = {0.0, 0.0, 0.0};
1134  auto geom = static_cast<CylinderGeom_Mvtx*>(geom_container_mvtx->GetLayerGeom(layer));
1135  auto hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(cluster_key);
1137  // returns the center of the sensor in world coordinates - used to get the ladder phi location
1138  geom->find_sensor_center(surf, m_tgeometry, ladder_location);
1139 
1140  //cout << " MVTX stave phi tilt = " << geom->get_stave_phi_tilt()
1141  // << " seg.X " << ladder_location[0] << " seg.Y " << ladder_location[1] << " seg.Z " << ladder_location[2] << endl;
1142  n.SetXYZ(ladder_location[0], ladder_location[1], 0);
1143  n.RotateZ(geom->get_stave_phi_tilt());
1144  break;
1145  }
1146 
1147  case TrkrDefs::inttId:
1148  {
1149  auto geom = static_cast<CylinderGeomIntt*>(geom_container_intt->GetLayerGeom(layer));
1150  double hit_location[3] = {0.0, 0.0, 0.0};
1151  auto hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(cluster_key);
1153  geom->find_segment_center(surf, m_tgeometry, hit_location);
1154 
1155  //cout << " Intt strip phi tilt = " << geom->get_strip_phi_tilt()
1156  // << " seg.X " << hit_location[0] << " seg.Y " << hit_location[1] << " seg.Z " << hit_location[2] << endl;
1157  n.SetXYZ(hit_location[0], hit_location[1], 0);
1158  n.RotateZ(geom->get_strip_phi_tilt());
1159  break;
1160  }
1161 
1163  {
1164  // get geometry
1165  /* a situation where micromegas clusters are found, but not the geometry, should not happen */
1166  assert( geom_container_micromegas );
1167  auto geom = static_cast<CylinderGeomMicromegas*>(geom_container_micromegas->GetLayerGeom(layer));
1168  const auto tileid = MicromegasDefs::getTileId( cluster_key );
1169 
1170  // in local coordinate, n is along z axis
1171  // convert to global coordinates
1172  n = geom->get_world_from_local_vect( tileid, m_tgeometry, TVector3( 0, 0, 1 ) );
1173  }
1174 
1175  default: break;
1176  }
1177 
1178  // get cluster errors
1179  double cluster_rphi_error = cluster->getRPhiError();
1180  double cluster_z_error = cluster->getZError();
1181 
1182  // create measurement
1183  auto meas = new PHGenFit::PlanarMeasurement(pos, n, cluster_rphi_error, cluster_z_error);
1184 
1185  if(Verbosity() > 10)
1186  {
1187  cout << "Add meas layer " << layer << " cluskey " << cluster_key
1188  << " pos.X " << pos.X() << " pos.Y " << pos.Y() << " pos.Z " << pos.Z()
1189  << " r: " << std::sqrt(square( pos.x()) + square(pos.y()))
1190  << " n.X " << n.X() << " n.Y " << n.Y()
1191  << " RPhiErr " << cluster->getRPhiError()
1192  << " ZErr " << cluster->getZError()
1193  << endl;
1194  }
1195  measurements.push_back(meas);
1196  }
1197 
1198 
1207  //TODO Add multiple TrackRep choices.
1208  //int pid = 211;
1210  std::shared_ptr<PHGenFit::Track> track(new PHGenFit::Track(rep, seed_pos, seed_mom, seed_cov));
1211 
1212  //TODO unsorted measurements, should use sorted ones?
1213  track->addMeasurements(measurements);
1214 
1220  if (_fitter->processTrack(track.get(), false) != 0)
1221  {
1222  // if (Verbosity() >= 1)
1223  {
1224  LogWarning("Track fitting failed");
1225  }
1226  //delete track;
1227  return nullptr;
1228  }
1229 
1230  if(Verbosity() > 10)
1231  cout << " track->getChisq() " << track->get_chi2() << " get_ndf " << track->get_ndf()
1232  << " mom.X " << track->get_mom().X()
1233  << " mom.Y " << track->get_mom().Y()
1234  << " mom.Z " << track->get_mom().Z()
1235  << endl;
1236 
1237  return track;
1238 }
1239 
1240 /*
1241  * Make SvtxTrack from PHGenFit::Track and SvtxTrack
1242  */
1243 //SvtxTrack* PHGenFitTrkFitter::MakeSvtxTrack(const SvtxTrack* svtx_track,
1244 std::shared_ptr<SvtxTrack> PHGenFitTrkFitter::MakeSvtxTrack(const SvtxTrack* svtx_track,
1245  const std::shared_ptr<PHGenFit::Track>& phgf_track, const SvtxVertex* vertex)
1246 {
1247  double chi2 = phgf_track->get_chi2();
1248  double ndf = phgf_track->get_ndf();
1249 
1250  TVector3 vertex_position(0, 0, 0);
1251  TMatrixF vertex_cov(3, 3);
1252  double dvr2 = 0;
1253  double dvz2 = 0;
1254 
1255  if (_use_truth_vertex )
1256  {
1257  if( _truth_container )
1258  {
1260  vertex_position.SetXYZ(first_point->get_x(), first_point->get_y(), first_point->get_z());
1261  if (Verbosity() > 1)
1262  {
1263  std::cout << PHWHERE << "Using: truth vertex: {" << vertex_position.X() << ", " << vertex_position.Y() << ", " << vertex_position.Z() << "} " << std::endl;
1264  }
1265  } else {
1266  std::cout << PHWHERE << "PHG4TruthInfoContainer not found. Cannot use truth vertex." << std::endl;
1267  }
1268  }
1269  else if (vertex)
1270  {
1271  vertex_position.SetXYZ(vertex->get_x(), vertex->get_y(),
1272  vertex->get_z());
1273  dvr2 = vertex->get_error(0, 0) + vertex->get_error(1, 1);
1274  dvz2 = vertex->get_error(2, 2);
1275 
1276  for (int i = 0; i < 3; i++)
1277  for (int j = 0; j < 3; j++)
1278  vertex_cov[i][j] = vertex->get_error(i, j);
1279  }
1280 
1281  std::unique_ptr<genfit::MeasuredStateOnPlane> gf_state_beam_line_ca;
1282  try
1283  {
1284  gf_state_beam_line_ca.reset(phgf_track->extrapolateToLine(vertex_position,
1285  TVector3(0., 0., 1.)));
1286  }
1287  catch (...)
1288  {
1289  if (Verbosity() >= 2)
1290  LogWarning("extrapolateToLine failed!");
1291  }
1292  if (!gf_state_beam_line_ca) return nullptr;
1293 
1301  double u = gf_state_beam_line_ca->getState()[3];
1302  double v = gf_state_beam_line_ca->getState()[4];
1303 
1304  double du2 = gf_state_beam_line_ca->getCov()[3][3];
1305  double dv2 = gf_state_beam_line_ca->getCov()[4][4];
1306  //cout << PHWHERE << " u " << u << " v " << v << " du2 " << du2 << " dv2 " << dv2 << " dvr2 " << dvr2 << endl;
1307  //delete gf_state_beam_line_ca;
1308 
1309  // create new track
1310  auto out_track = std::make_shared<SvtxTrack_v4>(*svtx_track);
1311 
1312  // clear states and insert empty one for vertex position
1313  out_track->clear_states();
1314  {
1315  /*
1316  insert first, dummy state, as done in constructor,
1317  so that the track state list is never empty. Note that insert_state, despite taking a pointer as argument,
1318  does not take ownership of the state
1319  */
1320  SvtxTrackState_v1 first(0.0);
1321  out_track->insert_state( &first );
1322  }
1323 
1324  out_track->set_dca2d(u);
1325  out_track->set_dca2d_error(sqrt(du2 + dvr2));
1326 
1327  std::unique_ptr<genfit::MeasuredStateOnPlane> gf_state_vertex_ca;
1328  try
1329  {
1330  gf_state_vertex_ca.reset( phgf_track->extrapolateToPoint(vertex_position) );
1331  }
1332  catch (...)
1333  {
1334  if (Verbosity() >= 2)
1335  LogWarning("extrapolateToPoint failed!");
1336  }
1337  if (!gf_state_vertex_ca)
1338  {
1339  //delete out_track;
1340  return nullptr;
1341  }
1342 
1343  TVector3 mom = gf_state_vertex_ca->getMom();
1344  TVector3 pos = gf_state_vertex_ca->getPos();
1345  TMatrixDSym cov = gf_state_vertex_ca->get6DCov();
1346 
1347  // genfit::MeasuredStateOnPlane* gf_state_vertex_ca =
1348  // phgf_track->extrapolateToLine(vertex_position,
1349  // TVector3(0., 0., 1.));
1350 
1351  u = gf_state_vertex_ca->getState()[3];
1352  v = gf_state_vertex_ca->getState()[4];
1353 
1354  du2 = gf_state_vertex_ca->getCov()[3][3];
1355  dv2 = gf_state_vertex_ca->getCov()[4][4];
1356 
1357  double dca3d = sqrt(u * u + v * v);
1358  double dca3d_error = sqrt(du2 + dv2 + dvr2 + dvz2);
1359 
1360  out_track->set_dca(dca3d);
1361  out_track->set_dca_error(dca3d_error);
1362 
1363  //
1364  // in: X, Y, Z; out; r: n X Z, Z X r, Z
1365 
1366  float dca3d_xy = NAN;
1367  float dca3d_z = NAN;
1368  float dca3d_xy_error = NAN;
1369  float dca3d_z_error = NAN;
1370 
1371  try
1372  {
1373  TMatrixF pos_in(3, 1);
1374  TMatrixF cov_in(3, 3);
1375  TMatrixF pos_out(3, 1);
1376  TMatrixF cov_out(3, 3);
1377 
1378  TVectorD state6(6); // pos(3), mom(3)
1379  TMatrixDSym cov6(6, 6); //
1380 
1381  gf_state_vertex_ca->get6DStateCov(state6, cov6);
1382 
1383  TVector3 vn(state6[3], state6[4], state6[5]);
1384 
1385  // mean of two multivariate gaussians Pos - Vertex
1386  pos_in[0][0] = state6[0] - vertex_position.X();
1387  pos_in[1][0] = state6[1] - vertex_position.Y();
1388  pos_in[2][0] = state6[2] - vertex_position.Z();
1389 
1390  for (int i = 0; i < 3; ++i)
1391  {
1392  for (int j = 0; j < 3; ++j)
1393  {
1394  cov_in[i][j] = cov6[i][j] + vertex_cov[i][j];
1395  }
1396  }
1397 
1398  // vn is momentum vector, pos_in is position vector (of what?)
1399  pos_cov_XYZ_to_RZ(vn, pos_in, cov_in, pos_out, cov_out);
1400 
1401  if(Verbosity() > 30)
1402  {
1403  cout << " vn.X " << vn.X() << " vn.Y " << vn.Y() << " vn.Z " << vn.Z() << endl;
1404  cout << " pos_in.X " << pos_in[0][0] << " pos_in.Y " << pos_in[1][0] << " pos_in.Z " << pos_in[2][0] << endl;
1405  cout << " pos_out.X " << pos_out[0][0] << " pos_out.Y " << pos_out[1][0] << " pos_out.Z " << pos_out[2][0] << endl;
1406  }
1407 
1408 
1409  dca3d_xy = pos_out[0][0];
1410  dca3d_z = pos_out[2][0];
1411  dca3d_xy_error = sqrt(cov_out[0][0]);
1412  dca3d_z_error = sqrt(cov_out[2][2]);
1413 
1414 #ifdef _DEBUG_
1415  cout << __LINE__ << ": Vertex: ----------------" << endl;
1416  vertex_position.Print();
1417  vertex_cov.Print();
1418 
1419  cout << __LINE__ << ": State: ----------------" << endl;
1420  state6.Print();
1421  cov6.Print();
1422 
1423  cout << __LINE__ << ": Mean: ----------------" << endl;
1424  pos_in.Print();
1425  cout << "===>" << endl;
1426  pos_out.Print();
1427 
1428  cout << __LINE__ << ": Cov: ----------------" << endl;
1429  cov_in.Print();
1430  cout << "===>" << endl;
1431  cov_out.Print();
1432 
1433  cout << endl;
1434 #endif
1435  }
1436  catch (...)
1437  {
1438  if (Verbosity())
1439  LogWarning("DCA calculationfailed!");
1440  }
1441 
1442  out_track->set_dca3d_xy(dca3d_xy);
1443  out_track->set_dca3d_z(dca3d_z);
1444  out_track->set_dca3d_xy_error(dca3d_xy_error);
1445  out_track->set_dca3d_z_error(dca3d_z_error);
1446 
1447  //if(gf_state_vertex_ca) delete gf_state_vertex_ca;
1448 
1449  out_track->set_chisq(chi2);
1450  out_track->set_ndf(ndf);
1451  out_track->set_charge(phgf_track->get_charge());
1452 
1453  out_track->set_px(mom.Px());
1454  out_track->set_py(mom.Py());
1455  out_track->set_pz(mom.Pz());
1456 
1457  out_track->set_x(pos.X());
1458  out_track->set_y(pos.Y());
1459  out_track->set_z(pos.Z());
1460 
1461  for (int i = 0; i < 6; i++)
1462  {
1463  for (int j = i; j < 6; j++)
1464  {
1465  out_track->set_error(i, j, cov[i][j]);
1466  }
1467  }
1468 
1469 #ifdef _DEBUG_
1470  cout << __LINE__ << endl;
1471 #endif
1472 
1473  const genfit::Track* gftrack = phgf_track->getGenFitTrack();
1474  const genfit::AbsTrackRep* rep = gftrack->getCardinalRep();
1475  for (unsigned int id = 0; id < gftrack->getNumPointsWithMeasurement(); ++id)
1476  {
1477  genfit::TrackPoint* trpoint = gftrack->getPointWithMeasurementAndFitterInfo(id, gftrack->getCardinalRep());
1478 
1479  if (!trpoint)
1480  {
1481  if (Verbosity() > 1)
1482  LogWarning("!trpoint");
1483  continue;
1484  }
1485 
1486  auto kfi = static_cast<genfit::KalmanFitterInfo*>(trpoint->getFitterInfo(rep));
1487  if (!kfi)
1488  {
1489  if (Verbosity() > 1)
1490  LogWarning("!kfi");
1491  continue;
1492  }
1493 
1494  const genfit::MeasuredStateOnPlane* gf_state = nullptr;
1495  try
1496  {
1497  // this works because KalmanFitterInfo returns a const reference to internal object and not a temporary object
1498  gf_state = &kfi->getFittedState(true);
1499  }
1500  catch (...)
1501  {
1502  if (Verbosity() >= 1)
1503  LogWarning("Exrapolation failed!");
1504  }
1505  if (!gf_state)
1506  {
1507  if (Verbosity() >= 1)
1508  LogWarning("Exrapolation failed!");
1509  continue;
1510  }
1512  float pathlength = -phgf_track->extrapolateToPoint(temp, vertex_position, id);
1513 
1514  // create new svtx state and add to track
1515  auto state = create_track_state( pathlength, gf_state );
1516  out_track->insert_state( &state );
1517 
1518 #ifdef _DEBUG_
1519  cout
1520  << __LINE__
1521  << ": " << id
1522  << ": " << pathlength << " => "
1523  << sqrt( square(state->get_x()) + square(state->get_y()) )
1524  << endl;
1525 #endif
1526  }
1527 
1528  // loop over clusters, check if layer is disabled, include extrapolated SvtxTrackState
1529  if( !_disabled_layers.empty() )
1530  {
1531 
1532  // get crossing
1533  const auto crossing = svtx_track->get_crossing();
1534  assert( crossing != SHRT_MAX );
1535 
1536  unsigned int id_min = 0;
1537  for( const auto& cluster_key:get_cluster_keys( svtx_track ) )
1538  {
1539  const auto cluster = m_clustermap->findCluster(cluster_key);
1540  const auto layer = TrkrDefs::getLayer(cluster_key);
1541 
1542  // skip enabled layers
1543  if( _disabled_layers.find( layer ) == _disabled_layers.end() )
1544  { continue; }
1545 
1546  // get position
1547  const auto globalPosition = getGlobalPosition( cluster_key, cluster, crossing );
1548  const TVector3 pos(globalPosition.x(), globalPosition.y(), globalPosition.z() );
1549  const float r_cluster = std::sqrt( square(globalPosition.x()) + square(globalPosition.y()) );
1550 
1551  // loop over states
1552  /* find first state whose radius is larger than that of cluster if any */
1553  unsigned int id = id_min;
1554  for( ; id < gftrack->getNumPointsWithMeasurement(); ++id)
1555  {
1556 
1557  auto trpoint = gftrack->getPointWithMeasurementAndFitterInfo(id, rep);
1558  if (!trpoint) continue;
1559 
1560  auto kfi = static_cast<genfit::KalmanFitterInfo*>(trpoint->getFitterInfo(rep));
1561  if (!kfi) continue;
1562 
1563  const genfit::MeasuredStateOnPlane* gf_state = nullptr;
1564  try
1565  {
1566 
1567  gf_state = &kfi->getFittedState(true);
1568 
1569  } catch (...) {
1570 
1571  if(Verbosity())
1572  { LogWarning("Failed to get kf fitted state"); }
1573 
1574  }
1575 
1576  if( !gf_state ) continue;
1577 
1578  float r_track = std::sqrt( square( gf_state->getPos().x() ) + square( gf_state->getPos().y() ) );
1579  if( r_track > r_cluster ) break;
1580 
1581  }
1582 
1583  // forward extrapolation
1585  float pathlength = 0;
1586 
1587  // first point is previous, if valid
1588  if( id > 0 ) id_min = id-1;
1589 
1590  // extrapolate forward
1591  try
1592  {
1593  auto trpoint = gftrack->getPointWithMeasurementAndFitterInfo(id_min, rep);
1594  if( !trpoint ) continue;
1595 
1596  auto kfi = static_cast<genfit::KalmanFitterInfo*>(trpoint->getFitterInfo(rep));
1597  gf_state = *kfi->getForwardUpdate();
1598  pathlength = gf_state.extrapolateToPoint( pos );
1599  auto tmp = *kfi->getBackwardUpdate();
1600  pathlength -= tmp.extrapolateToPoint( vertex_position );
1601  } catch (...) {
1602  if(Verbosity())
1603  { std::cerr << PHWHERE << "Failed to forward extrapolate from id " << id_min << " to disabled layer " << layer << std::endl; }
1604  continue;
1605  }
1606 
1607  // also extrapolate backward from next state if any
1608  // and take the weighted average between both points
1609  if( id > 0 && id < gftrack->getNumPointsWithMeasurement() )
1610  try
1611  {
1612  auto trpoint = gftrack->getPointWithMeasurementAndFitterInfo(id, rep);
1613  if( !trpoint ) continue;
1614 
1615  auto kfi = static_cast<genfit::KalmanFitterInfo*>(trpoint->getFitterInfo(rep));
1616  genfit::KalmanFittedStateOnPlane gf_state_backward = *kfi->getBackwardUpdate();
1617  gf_state_backward.extrapolateToPlane( gf_state.getPlane() );
1618  gf_state = genfit::calcAverageState( gf_state, gf_state_backward );
1619  } catch (...) {
1620  if(Verbosity())
1621  { std::cerr << PHWHERE << "Failed to backward extrapolate from id " << id << " to disabled layer " << layer << std::endl; }
1622  continue;
1623  }
1624 
1625  // create new svtx state and add to track
1626  auto state = create_track_state( pathlength, &gf_state );
1627  out_track->insert_state( &state );
1628 
1629  }
1630 
1631  }
1632 
1633  // printout all track state
1634  if( Verbosity() )
1635  {
1636  for( auto&& iter = out_track->begin_states(); iter != out_track->end_states(); ++iter )
1637  {
1638  const auto& [pathlength, state] = *iter;
1639  const auto r = std::sqrt( square( state->get_x() ) + square( state->get_y() ));
1640  const auto phi = std::atan2( state->get_y(), state->get_x() );
1641  std::cout << "PHGenFitTrkFitter::MakeSvtxTrack -"
1642  << " pathlength: " << pathlength
1643  << " radius: " << r
1644  << " phi: " << phi
1645  << " z: " << state->get_z()
1646  << std::endl;
1647  }
1648 
1649  std::cout << std::endl;
1650  }
1651  return out_track;
1652 }
1653 
1654 /*
1655  * Fill SvtxVertexMap from GFRaveVertexes and Tracks
1656  */
1658  const std::vector<genfit::GFRaveVertex*>& rave_vertices,
1659  const std::vector<genfit::Track*>& gf_tracks)
1660 {
1661 
1662  if(Verbosity()) cout << "Rave vertices size " << rave_vertices.size() << endl;
1663  if(rave_vertices.size() > 0)
1664  {
1665  for (unsigned int ivtx = 0; ivtx < rave_vertices.size(); ++ivtx)
1666  {
1667  genfit::GFRaveVertex* rave_vtx = rave_vertices[ivtx];
1668 
1669  if (!rave_vtx)
1670  {
1671  cerr << PHWHERE << endl;
1672  return false;
1673  }
1674 
1675  if(Verbosity()) cout << " ivtx " << ivtx << " has Z = " << rave_vtx->getPos().Z() << endl;
1676 
1677  SvtxVertex_v1 svtx_vtx;
1678  svtx_vtx.set_chisq(rave_vtx->getChi2());
1679  svtx_vtx.set_ndof(rave_vtx->getNdf());
1680  svtx_vtx.set_position(0, rave_vtx->getPos().X());
1681  svtx_vtx.set_position(1, rave_vtx->getPos().Y());
1682  svtx_vtx.set_position(2, rave_vtx->getPos().Z());
1683 
1684  for (int i = 0; i < 3; i++)
1685  for (int j = 0; j < 3; j++)
1686  svtx_vtx.set_error(i, j, rave_vtx->getCov()[i][j]);
1687 
1688  for (unsigned int i = 0; i < rave_vtx->getNTracks(); i++)
1689  {
1690  //TODO Assume id's are sync'ed between m_trackMap_refit and gf_tracks, need to change?
1691  const genfit::Track* rave_track =
1692  rave_vtx->getParameters(i)->getTrack();
1693  for (unsigned int j = 0; j < gf_tracks.size(); j++)
1694  {
1695  if (rave_track == gf_tracks[j])
1696  {
1697  svtx_vtx.insert_track(j);
1698  _rave_vertex_gf_track_map.insert(std::pair<unsigned int, unsigned int>(j, ivtx));
1699  if(Verbosity()) cout << " rave vertex " << ivtx << " at Z " << svtx_vtx.get_position(2) << " rave track " << i << " genfit track ID " << j << endl;
1700  }
1701  }
1702  }
1703 
1704  if (m_vertexMap_refit)
1705  {
1706  if(Verbosity()) cout << "insert svtx_vtx into m_vertexMap_refit " << endl;
1707  m_vertexMap_refit->insert_clone( &svtx_vtx );
1708  if(Verbosity() > 10) m_vertexMap_refit->identify();
1709  }
1710  else
1711  {
1712  LogError("!m_vertexMap_refit");
1713  }
1714  } //loop over RAVE vertices
1715  }
1716 
1717  return true;
1718 }
1719 
1721  const TVector3& n, const TMatrixF& pos_in, const TMatrixF& cov_in,
1722  TMatrixF& pos_out, TMatrixF& cov_out) const
1723 {
1724  if (pos_in.GetNcols() != 1 || pos_in.GetNrows() != 3)
1725  {
1726  if (Verbosity()) LogWarning("pos_in.GetNcols() != 1 || pos_in.GetNrows() != 3");
1727  return false;
1728  }
1729 
1730  if (cov_in.GetNcols() != 3 || cov_in.GetNrows() != 3)
1731  {
1732  if (Verbosity()) LogWarning("cov_in.GetNcols() != 3 || cov_in.GetNrows() != 3");
1733  return false;
1734  }
1735 
1736  // produces a vector perpendicular to both the momentum vector and beam line - i.e. in the direction of the dca_xy
1737  // only the angle of r will be used, not the magnitude
1738  TVector3 r = n.Cross(TVector3(0., 0., 1.));
1739  if (r.Mag() < 0.00001)
1740  {
1741  if (Verbosity()) LogWarning("n is parallel to z");
1742  return false;
1743  }
1744 
1745  // R: rotation from u,v,n to n X Z, nX(nXZ), n
1746  TMatrixF R(3, 3);
1747  TMatrixF R_T(3, 3);
1748 
1749  try
1750  {
1751  // rotate u along z to up
1752  float phi = -TMath::ATan2(r.Y(), r.X());
1753  R[0][0] = cos(phi);
1754  R[0][1] = -sin(phi);
1755  R[0][2] = 0;
1756  R[1][0] = sin(phi);
1757  R[1][1] = cos(phi);
1758  R[1][2] = 0;
1759  R[2][0] = 0;
1760  R[2][1] = 0;
1761  R[2][2] = 1;
1762 
1763  R_T.Transpose(R);
1764  }
1765  catch (...)
1766  {
1767  if (Verbosity())
1768  LogWarning("Can't get rotation matrix");
1769 
1770  return false;
1771  }
1772 
1773  pos_out.ResizeTo(3, 1);
1774  cov_out.ResizeTo(3, 3);
1775 
1776  pos_out = R * pos_in;
1777  cov_out = R * cov_in * R_T;
1778 
1779  return true;
1780 }