StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFwdTrackMaker.cxx
1 #include "StFwdTrackMaker/StFwdTrackMaker.h"
2 #include "StFwdTrackMaker/include/Tracker/FwdHit.h"
3 #include "StFwdTrackMaker/include/Tracker/FwdTracker.h"
4 #include "StFwdTrackMaker/include/Tracker/TrackFitter.h"
5 #include "StFwdTrackMaker/include/Tracker/FwdGeomUtils.h"
6 #include "StFwdTrackMaker/include/Tracker/ObjExporter.h"
7 
8 #include "KiTrack/IHit.h"
9 #include "GenFit/Track.h"
10 
11 #include "TMath.h"
12 
13 #include <climits>
14 #include <map>
15 #include <string>
16 #include <string>
17 #include <vector>
18 
19 #include "StBFChain/StBFChain.h"
20 
21 #include "StEvent/StEvent.h"
22 #include "StEvent/StGlobalTrack.h"
23 #include "StEvent/StHelixModel.h"
24 #include "StEvent/StPrimaryTrack.h"
25 #include "StEvent/StRnDHit.h"
26 #include "StEvent/StRnDHitCollection.h"
27 #include "StEvent/StTrack.h"
28 #include "StEvent/StBTofCollection.h"
29 #include "StEvent/StBTofHeader.h"
30 #include "StEvent/StTrackGeometry.h"
31 #include "StEvent/StTrackNode.h"
32 #include "StEvent/StPrimaryVertex.h"
33 #include "StEvent/StEnumerations.h"
34 #include "StEvent/StTrackDetectorInfo.h"
35 #include "StEvent/StFttPoint.h"
36 #include "StEvent/StFcsHit.h"
37 #include "StEvent/StFcsCluster.h"
38 #include "StEvent/StFttCollection.h"
39 #include "StEvent/StFcsCollection.h"
40 #include "StEvent/StTriggerData.h"
41 #include "StEvent/StFstHitCollection.h"
42 #include "StEvent/StFstHit.h"
43 #include "StEvent/StFwdTrackCollection.h"
44 #include "StChain/StChainOpt.h"
45 
46 #include "StEventUtilities/StEventHelper.h"
47 
48 #include "StMcEvent/StMcEvent.hh"
49 #include "StMcEvent/StMcVertex.hh"
50 
51 #include "tables/St_g2t_fts_hit_Table.h"
52 #include "tables/St_g2t_track_Table.h"
53 #include "tables/St_g2t_vertex_Table.h"
54 #include "tables/St_g2t_event_Table.h"
55 
56 #include "StarMagField/StarMagField.h"
57 
58 #include "St_base/StMessMgr.h"
59 #include "StarClassLibrary/StPhysicalHelix.hh"
60 #include "StarClassLibrary/SystemOfUnits.h"
61 
62 #include <SystemOfUnits.h>
63 #include <exception>
64 
65 #include "TROOT.h"
66 #include "TLorentzVector.h"
67 
68 #include "StRoot/StEpdUtil/StEpdGeom.h"
69 #include "StFcsDbMaker/StFcsDb.h"
70 #include "StFstUtil/StFstCollection.h"
71 
72 #include "StEvent/StFwdTrack.h"
73 #include "GenFit/AbsMeasurement.h"
74 
75 #include "StMuDSTMaker/COMMON/StMuDstMaker.h"
76 #include "StMuDSTMaker/COMMON/StMuDst.h"
77 #include "StMuDSTMaker/COMMON/StMuFstCollection.h"
78 #include "StMuDSTMaker/COMMON/StMuFstHit.h"
79 #include "StMuDSTMaker/COMMON/StMuPrimaryVertex.h"
80 
81 #include "sys/types.h"
82 #include "sys/sysinfo.h"
83 
84 FwdSystem* FwdSystem::sInstance = nullptr;
85 
86 //_______________________________________________________________________________________
88  public:
89 
90  // For now, accept anything we are passed, no matter what it is or how bad it is
91  template<typename T> static bool accept( T ) { return true; }
92 }; // GenfitUtils
93 
94 // Basic sanity cuts on genfit tracks
95 template<> bool GenfitUtils::accept( genfit::Track *track )
96 {
97  // This also gets rid of failed fits (but may need to explicitly
98  // for fit failure...)
99  if (track->getNumPoints() <= 0 ) return false; // fit may have failed
100 
101  auto cardinal = track->getCardinalRep();
102 
103  // Check that the track fit converged
104  auto status = track->getFitStatus( cardinal );
105  if ( !status->isFitConverged() ) {
106  return false;
107  }
108 
109 
110  // Next, check that all points on the track have fitter info
111  // (may be another indication of a failed fit?)
112  for ( auto point : track->getPoints() ) {
113  if ( !point->hasFitterInfo(cardinal) ) {
114  return false;
115  }
116  }
117 
118  // Following line fails with an exception, because some tracks lack
119  // forward update, or prediction in fitter info at the first point
120  //
121  // genfit::KalmanFitterInfo::getFittedState(bool) const of
122  // GenFit/fitters/src/KalmanFitterInfo.cc:250
123 
124  // Fitted state at the first point
125  // const auto &atFirstPoint = track->getFittedState();
126 
127  // Getting the fitted state from a track occasionally fails, because
128  // the first point on the fit doesn't have forward/backward fit
129  // information. So we want the first point with fit info...
130 
131  genfit::TrackPoint* first = nullptr;
132  unsigned int ipoint = 0;
133  for ( ipoint = 0; ipoint < track->getNumPoints(); ipoint++ ) {
134  first = track->getPointWithFitterInfo( ipoint );
135  if ( first ) break;
136  }
137 
138  // No points on the track have fit information
139  if ( !first ) {
140  LOG_WARN << "No fit information on fwd genfit track" << endm;
141  return false;
142  }
143 
144  auto& fittedState= track->getFittedState(ipoint);
145 
146  TVector3 momentum = fittedState.getMom();
147  double pt = momentum.Perp();
148 
149  if (pt < 0.10 ) return false; // below this
150 
151  return true;
152 
153 };
154 
155 //______________________________________________________________________________________
157  public:
158  SiRasterizer() {}
159  SiRasterizer(FwdTrackerConfig &_cfg) { setup(_cfg); }
160  ~SiRasterizer() {}
161  void setup(FwdTrackerConfig &_cfg) {
162  cfg = _cfg;
163  mRasterR = cfg.get<double>("SiRasterizer:r", 3.0);
164  mRasterPhi = cfg.get<double>("SiRasterizer:phi", 0.004);
165  }
166 
167  bool active() {
168  return cfg.get<bool>("SiRasterizer:active", true);
169  }
170 
171  TVector3 raster(TVector3 p0) {
172  TVector3 p = p0;
173  double r = p.Perp();
174  double phi = p.Phi();
175  const double minR = 5.0;
176  // 5.0 is the r minimum of the Si
177  p.SetPerp(minR + (std::floor((r - minR) / mRasterR) * mRasterR + mRasterR / 2.0));
178  p.SetPhi(-TMath::Pi() + (std::floor((phi + TMath::Pi()) / mRasterPhi) * mRasterPhi + mRasterPhi / 2.0));
179  return p;
180  }
181 
182  FwdTrackerConfig cfg;
183  double mRasterR, mRasterPhi;
184 };
185 
186 // Wrapper class around the forward tracker
188  public:
189  // Replaces original initialization. Config file and hitloader
190  // will be provided by the maker.
191  void initialize( TString geoCache, bool genHistograms ) {
192  nEvents = 1; // only process single event
193 
194  // Create the forward system...
195  FwdSystem::sInstance = new FwdSystem();
196 
197  // initialize the track fitter
198  mTrackFitter = new TrackFitter(mConfig, geoCache);
199  mTrackFitter->setup();
200 
201  ForwardTrackMaker::initialize( geoCache, genHistograms );
202  }
203 
204  void finish() {
205 
206  if (FwdSystem::sInstance){
207  delete FwdSystem::sInstance;
208  FwdSystem::sInstance = 0;
209  }
210  if (mTrackFitter){
211  delete mTrackFitter;
212  mTrackFitter= 0;
213  }
214  }
215 };
216 
217 //________________________________________________________________________
218 StFwdTrackMaker::StFwdTrackMaker() : StMaker("fwdTrack"), mEventVertex(0,0,0), mForwardTracker(nullptr), mForwardData(nullptr), mGeoCache(""){
219 
220 
221  mEventVertexCov.ResizeTo(3, 3);
222  mEventVertexCov.Zero();
223 
224  SetAttr("useFtt",1); // Default Ftt on
225  SetAttr("useFst",1); // Default Fst on
226  SetAttr("useFcs",1); // Default Fcs on
227  SetAttr("config", "config.xml"); // Default configuration file (user may override before Init())
228  SetAttr("fillEvent",1); // fill StEvent
229 
230  // Load the default configuration
231  configLoaded = false;
232  LoadConfiguration();
233 
234  // set additional default configuration values
235  setOutputFilename( "stfwdtrackmaker_data.root" );
236 
237 
238 };
239 
241  mForwardTracker->finish();
242  return kStOk;
243 }
244 
245 void StFwdTrackMaker::LoadConfiguration() {
246  if (mConfigFile.length() < 5){
247  // no config file specified, use default
248  // 5 characters is the minimum length for a valid filename since we must have at least .xml
249  mFwdConfig.load( defaultConfig, true );
250  } else {
251  LOG_INFO << "Forward Tracker is using config from file : " << mConfigFile << endm;
252  mFwdConfig.load( mConfigFile );
253  }
254  configLoaded = true;
255 }
256 
257 //________________________________________________________________________
259 
260  if ( mGeoCache == "" ){
262  GetDataBase("VmcGeometry");
263 
264  mGeoCache = GetChainOpt()->GetFileOut();
265  if ( mGeoCache=="" )
266  mGeoCache = GetChainOpt()->GetFileIn();
267 
268  // Strip out @ symbol
269  mGeoCache = mGeoCache.ReplaceAll("@","");
270  // Strip off the last extention in the mGeoCache
271  mGeoCache = mGeoCache( 0, mGeoCache.Last('.') );
272  // Append geom.root to the extentionless mGeoCache
273  mGeoCache+=".geom.root";
274  }
275  // create an SiRasterizer in case we need it
276  mSiRasterizer = std::shared_ptr<SiRasterizer>( new SiRasterizer(mFwdConfig));
277  mForwardTracker = std::shared_ptr<ForwardTracker>(new ForwardTracker( ));
278  mForwardTracker->setConfig(mFwdConfig);
279 
280  // in production we disable crit saving.
281  mForwardTracker->setSaveCriteriaValues(false);
282 
283  mForwardData = std::shared_ptr<FwdDataSource>(new FwdDataSource());
284  mForwardTracker->setData(mForwardData);
285  mForwardTracker->initialize( mGeoCache, false );
286 
287  // geometry should be available from here (mForwardTracker will initialize cache if needed)
288  if (gGeoManager) {
289  FwdGeomUtils fwdGeoUtils( gGeoManager );
290  // get the z-locations from geometry model and fallback to the defaults
291  auto fstZ = fwdGeoUtils.fstZ( {151.750000, 165.248001, 178.781006} );
292  mFstZFromGeom.assign( fstZ.begin(), fstZ.end() );
293  auto fttZ = fwdGeoUtils.fttZ( {280.904999, 303.704987, 326.605011, 349.404999} );
294  mFttZFromGeom.assign( fttZ.begin(), fttZ.end() );
295  }
296  return kStOK;
297 };
298 
299 TMatrixDSym makeSiCovMat(TVector3 hit, FwdTrackerConfig &xfg) {
300  // we can calculate the CovMat since we know the det info, but in future we should probably keep this info in the hit itself
301 
302  float rSize = xfg.get<float>("SiRasterizer:r", 3.0);
303  float phiSize = xfg.get<float>("SiRasterizer:phi", 0.004);
304 
305  // measurements on a plane only need 2x2
306  // for Si geom we need to convert from cylindrical to cartesian coords
307  TMatrixDSym cm(2);
308  TMatrixD T(2, 2);
309  TMatrixD J(2, 2);
310  const float x = hit.X();
311  const float y = hit.Y();
312  const float R = sqrt(x * x + y * y);
313  const float cosphi = x / R;
314  const float sinphi = y / R;
315  const float sqrt12 = sqrt(12.);
316 
317  const float dr = rSize / sqrt12;
318  const float dphi = (phiSize) / sqrt12;
319 
320  // Setup the Transposed and normal Jacobian transform matrix;
321  // note, the si fast sim did this wrong
322  // row col
323  T(0, 0) = cosphi;
324  T(0, 1) = -R * sinphi;
325  T(1, 0) = sinphi;
326  T(1, 1) = R * cosphi;
327 
328  J(0, 0) = cosphi;
329  J(0, 1) = sinphi;
330  J(1, 0) = -R * sinphi;
331  J(1, 1) = R * cosphi;
332 
333  TMatrixD cmcyl(2, 2);
334  cmcyl(0, 0) = dr * dr;
335  cmcyl(1, 1) = dphi * dphi;
336 
337  TMatrixD r = T * cmcyl * J;
338 
339  // note: float sigmaX = sqrt(r(0, 0));
340  // note: float sigmaY = sqrt(r(1, 1));
341 
342  cm(0, 0) = r(0, 0);
343  cm(1, 1) = r(1, 1);
344  cm(0, 1) = r(0, 1);
345  cm(1, 0) = r(1, 0);
346 
347  TMatrixDSym tamvoc(3);
348  tamvoc( 0, 0 ) = cm(0, 0); tamvoc( 0, 1 ) = cm(0, 1); tamvoc( 0, 2 ) = 0.0;
349  tamvoc( 1, 0 ) = cm(1, 0); tamvoc( 1, 1 ) = cm(1, 1); tamvoc( 1, 2 ) = 0.0;
350  tamvoc( 2, 0 ) = 0.0; tamvoc( 2, 1 ) = 0.0; tamvoc( 2, 2 ) = 0.01*0.01;
351 
352 
353  return tamvoc;
354 }
355 
356 void StFwdTrackMaker::loadFttHits( FwdDataSource::McTrackMap_t &mcTrackMap, FwdDataSource::HitMap_t &hitMap, int count ){
357  LOG_DEBUG << "Loading FTT Hits" << endm;
358  // Get the StEvent handle to see if the rndCollection is available
359  StEvent *event = (StEvent *)GetDataSet("StEvent");
360  string fttFromSource = mFwdConfig.get<string>( "Source:ftt", "DATA" );
361 
362  if (!event){
363  LOG_ERROR << "No StEvent, cannot load Ftt Data" << endm;
364  return;
365  }
366 
367  StFttCollection *col = event->fttCollection();
368  // From Data
369  if ( col || "DATA" == fttFromSource ) {
370  loadFttHitsFromStEvent( mcTrackMap, hitMap, count );
371  return;
372  }
373 
374  // Load GEANT hits directly if requested
375  if ( true ) {
376  LOG_DEBUG << "Try loading sTGC hits directly from GEANT hits" << endm;
377  loadFttHitsFromGEANT( mcTrackMap, hitMap, count );
378  return;
379  }
380 } // loadFttHits
381 
382 void StFwdTrackMaker::loadFttHitsFromStEvent( FwdDataSource::McTrackMap_t &mcTrackMap, FwdDataSource::HitMap_t &hitMap, int count ){
383  LOG_DEBUG << "Loading FTT Hits from Data" << endm;
384  StEvent *event = (StEvent *)GetDataSet("StEvent");
385  StFttCollection *col = event->fttCollection();
386  size_t numFwdHitsPrior = mFwdHitsFtt.size();
387 
388  if ( col && col->numberOfPoints() > 0 ){
389  LOG_DEBUG << "The Ftt Collection has " << col->numberOfPoints() << " points" << endm;
390  TMatrixDSym hitCov3(3);
391  const double sigXY = 0.2; //
392  hitCov3(0, 0) = sigXY * sigXY;
393  hitCov3(1, 1) = sigXY * sigXY;
394  hitCov3(2, 2) = 4; // unused since they are loaded as points on plane
395  static const double mm_to_cm = 0.1;
396  for ( auto point : col->points() ){
397 
398  float xcm = point->xyz().x()*mm_to_cm;
399  float ycm = point->xyz().y()*mm_to_cm;
400  float zcm = point->xyz().z();
401 
402  // get the track id
403  int track_id = point->idTruth();
404  shared_ptr<McTrack> mcTrack = nullptr;
405  if ( mcTrackMap.count(track_id) ) {
406  mcTrack = mcTrackMap[track_id];
407  LOG_DEBUG << "Adding McTrack to FTT hit: " << track_id << endm;
408  }
409 
410  mFwdHitsFtt.push_back(FwdHit(count++, // id
411  xcm, ycm, zcm,
412  -point->plane(), // volume id
413  kFttId, // detid
414  track_id, // track id
415  hitCov3, // covariance matrix
416  mcTrack) // mcTrack
417  );
418  mFttHits.push_back( TVector3( xcm, ycm, zcm) );
419  } // end of loop over points
420  } else {
421  LOG_DEBUG << "The Ftt Collection is EMPTY points" << endm;
422  }
423 
424  // this has to be done AFTER because the vector reallocates mem when expanding, changing addresses
425  size_t numFwdHitsPost = mFwdHitsFtt.size();
426  for ( size_t iFwdHit = numFwdHitsPrior; iFwdHit < numFwdHitsPost; iFwdHit++){
427  FwdHit *hit = &(mFwdHitsFtt[ iFwdHit ]);
428  // Add the hit to the hit map
429  if ( hit->getLayer() >= 0 )
430  hitMap[hit->getSector()].push_back(hit);
431  // add to MC track map
432  if ( hit->getMcTrack() ){
433  hit->getMcTrack()->addFttHit(hit);
434  }
435  }
436 
437  if ( numFwdHitsPost != numFwdHitsPrior ){
438  LOG_INFO << "Loaded " << numFwdHitsPost - numFwdHitsPrior << " FTT hits from StEvent" << endm;
439  }
440 }
441 
442 void StFwdTrackMaker::loadFttHitsFromGEANT( FwdDataSource::McTrackMap_t &mcTrackMap, FwdDataSource::HitMap_t &hitMap, int count ){
443  /************************************************************/
444  // STGC Hits
445  St_g2t_fts_hit *g2t_stg_hits = (St_g2t_fts_hit *)GetDataSet("geant/g2t_stg_hit");
446 
447  size_t numFwdHitsPrior = mFwdHitsFtt.size();
448  if (!g2t_stg_hits){
449  LOG_WARN << "geant/g2t_stg_hit is empty" << endm;
450  return;
451  }
452 
453  // make the Covariance Matrix once and then reuse
454  TMatrixDSym hitCov3(3);
455  const double sigXY = 0.02;
456  hitCov3(0, 0) = sigXY * sigXY;
457  hitCov3(1, 1) = sigXY * sigXY;
458  hitCov3(2, 2) = 0.1; // unused since they are loaded as points on plane
459 
460  int nstg = g2t_stg_hits->GetNRows();
461 
462  LOG_DEBUG << "This event has " << nstg << " stg hits in geant/g2t_stg_hit " << endm;
463 
464  bool filterGEANT = mFwdConfig.get<bool>( "Source:fttFilter", false );
465  for (int i = 0; i < nstg; i++) {
466 
467  g2t_fts_hit_st *git = (g2t_fts_hit_st *)g2t_stg_hits->At(i);
468  if (0 == git)
469  continue; // geant hit
470  int track_id = git->track_p;
471  int volume_id = git->volume_id;
472  int plane_id = (volume_id - 1) / 100; // from 1 - 16. four chambers per station
473 
474  // only use the hits on the front modules
475  if ( volume_id % 2 ==0 )
476  continue;
477 
478  float x = git->x[0];// + gRandom->Gaus(0, sigXY); // 100 micron blur according to approx sTGC reso
479  float y = git->x[1];// + gRandom->Gaus(0, sigXY); // 100 micron blur according to approx sTGC reso
480  float z = git->x[2];
481 
482  if (plane_id < 0 || plane_id >= 4) {
483  continue;
484  }
485  mFwdHitsFtt.push_back(
486  FwdHit(
487  count++, // id
488  x, y, z, // position
489  -plane_id, // volume id
490  kFttId, // detid
491  track_id, // track id
492  hitCov3, // covariance matrix
493  mcTrackMap[track_id] // mcTrack
494  )
495  );
496  mFttHits.push_back( TVector3( x, y, z ) );
497  } // loop on hits
498 
499  // this has to be done AFTER because the vector reallocates mem when expanding, changing addresses
500  size_t numFwdHitsPost = mFwdHitsFtt.size();
501  for ( size_t iFwdHit = numFwdHitsPrior; iFwdHit < numFwdHitsPost; iFwdHit++){
502  FwdHit *hit = &(mFwdHitsFtt[ iFwdHit ]);
503  // Add the hit to the hit map
504  if ( hit->getLayer() >= 0 )
505  hitMap[hit->getSector()].push_back(hit);
506 
507  if ( dynamic_cast<FwdHit*>(hit)->_mcTrack ){
508  dynamic_cast<FwdHit*>(hit)->_mcTrack->addFttHit(hit);
509  }
510  }
511 
512  if ( numFwdHitsPost != numFwdHitsPrior ){
513  LOG_INFO << "Loaded " << numFwdHitsPost - numFwdHitsPrior << " FST hits from MuDst" << endm;
514  }
515 
516 } // loadFttHits
517 
531 int StFwdTrackMaker::loadFstHits( FwdDataSource::McTrackMap_t &mcTrackMap, FwdDataSource::HitMap_t &hitMap ){
532 
533  int count = loadFstHitsFromMuDst(mcTrackMap, hitMap);
534  if ( count > 0 ) return count; // only load from one source at a time
535 
536  count += loadFstHitsFromStEvent(mcTrackMap, hitMap);
537  if ( count > 0 ) return count; // only load from one source at a time
538 
539  bool siRasterizer = mFwdConfig.get<bool>( "SiRasterizer:active", false );
540 
541  if ( !siRasterizer ) count += loadFstHitsFromStRnDHits( mcTrackMap, hitMap );
542  if ( count > 0 ) return count; // only load from one source at a time
543 
544  return loadFstHitsFromGEANT( mcTrackMap, hitMap );
545 } // loadFstHits
546 
547 int StFwdTrackMaker::loadFstHitsFromMuDst( FwdDataSource::McTrackMap_t &mcTrackMap, FwdDataSource::HitMap_t &hitMap){
548  int count = 0;
549  StMuDstMaker *mMuDstMaker = (StMuDstMaker *)GetMaker("MuDst");
550  if(!mMuDstMaker) {
551  LOG_WARN << " No MuDstMaker ... bye-bye" << endm;
552  return 0;
553  }
554  StMuDst *mMuDst = mMuDstMaker->muDst();
555  if(!mMuDst) {
556  LOG_WARN << " No MuDst ... bye-bye" << endm;
557  return 0;
558  }
559 
560  StMuFstCollection * fst = mMuDst->muFstCollection();
561  if (!fst) {
562  LOG_WARN << "No StMuFstCollection ... bye-bye" << endm;
563  return 0;
564  }
565 
566  size_t numFwdHitsPrior = mFwdHitsFst.size();
567  LOG_INFO << "Loading " << fst->numberOfHits() << " StMuFstHits" << endm;
568  TMatrixDSym hitCov3(3);
569  for ( unsigned int index = 0; index < fst->numberOfHits(); index++){
570  StMuFstHit * muFstHit = fst->getHit( index );
571 
572  float vR = muFstHit->localPosition(0);
573  float vPhi = muFstHit->localPosition(1);
574  float vZ = muFstHit->localPosition(2);
575 
576  const float dz0 = fabs( vZ - mFstZFromGeom[0] );
577  const float dz1 = fabs( vZ - mFstZFromGeom[1] );
578  const float dz2 = fabs( vZ - mFstZFromGeom[2] );
579  static const float fstThickness = 2.0; // thickness in cm between inner and outer on sigle plane
580 
581  // assign disk according to which z value the hit has, within the z-plane thickness
582  int d = 0 * ( dz0 < fstThickness ) + 1 * ( dz1 < fstThickness ) + 2 * ( dz2 < fstThickness );
583 
584  float x0 = vR * cos( vPhi );
585  float y0 = vR * sin( vPhi );
586  hitCov3 = makeSiCovMat( TVector3( x0, y0, vZ ), mFwdConfig );
587 
588  LOG_DEBUG << "FST HIT: d = " << d << ", x=" << x0 << ", y=" << y0 << ", z=" << vZ << endm;
589  mFstHits.push_back( TVector3( x0, y0, vZ) );
590 
591  // we use d+4 so that both FTT and FST start at 4
592  mFwdHitsFst.push_back(
593  FwdHit(
594  count++, // id
595  x0, y0, vZ, // position
596  d+4, // volume id
597  kFstId, // detid
598  0, // track id
599  hitCov3, // covariance matrix
600  nullptr // mcTrack
601  )
602  );
603  } // index
604 
605  // this has to be done AFTER because the vector reallocates mem when expanding, changing addresses
606  size_t numFwdHitsPost = mFwdHitsFst.size();
607  for ( size_t iFwdHit = numFwdHitsPrior; iFwdHit < numFwdHitsPost; iFwdHit++){
608  FwdHit *hit = &(mFwdHitsFst[ iFwdHit ]);
609  // Add the hit to the hit map
610  if ( hit->getLayer() >= 0 )
611  hitMap[hit->getSector()].push_back(hit);
612  }
613 
614  if ( numFwdHitsPost != numFwdHitsPrior ){
615  LOG_INFO << "Loaded " << numFwdHitsPost - numFwdHitsPrior << " FST hits from MuDst" << endm;
616  }
617 
618  // TODO add to hitmap
619  return count;
620 } // loadFstHitsFromMuDst
621 
622 int StFwdTrackMaker::loadFstHitsFromStEvent( FwdDataSource::McTrackMap_t &mcTrackMap, FwdDataSource::HitMap_t &hitMap){
623  int count = 0;
624  StEvent *event = (StEvent *)GetDataSet("StEvent");
625  if (!event) {
626  LOG_WARN << "No StEvent, cannot load FST hits from StEvent StFstHitCollection" << endm;
627  return 0;
628  }
629  LOG_DEBUG << "Got StEvent, loading Fst Hits" << endm;
630  StFstHitCollection *fstHitCollection = event->fstHitCollection();
631  size_t numFwdHitsPrior = mFwdHitsFst.size();
632 
633  if ( fstHitCollection && fstHitCollection->numberOfHits() > 0){
634  // reuse this to store cov mat
635  TMatrixDSym hitCov3(3);
636  LOG_DEBUG << "StFstHitCollection is NOT NULL, loading hits" << endm;
637  for ( unsigned int iw = 0; iw < kFstNumWedges; iw++ ){
638  StFstWedgeHitCollection * wc = fstHitCollection->wedge( iw );
639  if ( !wc ) continue;
640  for ( unsigned int is = 0; is < kFstNumSensorsPerWedge; is++ ){
641  StFstSensorHitCollection * sc = wc->sensor( is );
642  if ( !sc ) continue;
643  StSPtrVecFstHit fsthits = sc->hits();
644  for ( unsigned int ih = 0; ih < fsthits.size(); ih++ ){
645  float vR = fsthits[ih]->localPosition(0);
646  float vPhi = fsthits[ih]->localPosition(1);
647  float vZ = fsthits[ih]->localPosition(2);
648 
649  const float dz0 = fabs( vZ - mFstZFromGeom[0] );
650  const float dz1 = fabs( vZ - mFstZFromGeom[1] );
651  const float dz2 = fabs( vZ - mFstZFromGeom[2] );
652  static const float fstThickness = 3.0; // thickness in cm between inner and outer on sigle plane
653 
654  // assign disk according to which z value the hit has, within the z-plane thickness
655  int d = 0 * ( dz0 < fstThickness ) + 1 * ( dz1 < fstThickness ) + 2 * ( dz2 < fstThickness );
656 
657  float x0 = vR * cos( vPhi );
658  float y0 = vR * sin( vPhi );
659  hitCov3 = makeSiCovMat( TVector3( x0, y0, vZ ), mFwdConfig );
660 
661  LOG_DEBUG << "FST HIT: d = " << d << ", x=" << x0 << ", y=" << y0 << ", z=" << vZ << endm;
662  mFstHits.push_back( TVector3( x0, y0, vZ) );
663  int track_id = fsthits[ih]->idTruth();
664  LOG_DEBUG << "FST Hit: idTruth = " << track_id << endm;
665  shared_ptr<McTrack> mcTrack = nullptr;
666  if ( mcTrackMap.count(track_id) ) {
667  mcTrack = mcTrackMap[track_id];
668  LOG_DEBUG << "Adding McTrack to FST hit" << endm;
669  }
670 
671  // we use d+4 so that both FTT and FST start at 4
672  mFwdHitsFst.push_back(
673  FwdHit(
674  count++, // id
675  x0, y0, vZ, // position
676  d+4, // volume id
677  kFstId, // detid
678  track_id, // mc track id
679  hitCov3, // covariance matrix
680  mcTrack // mcTrack
681  )
682  );
683  // store a pointer to the original StFstHit
684  mFwdHitsFst.back()._hit = fsthits[ih];
685  }
686  } // loop is
687  } // loop iw
688  LOG_DEBUG << " FOUND " << mFstHits.size() << " FST HITS in StFstHitCollection" << endm;
689  } // fstHitCollection
690  // this has to be done AFTER because the vector reallocates mem when expanding, changing addresses
691  size_t numFwdHitsPost = mFwdHitsFst.size();
692  for ( size_t iFwdHit = numFwdHitsPrior; iFwdHit < numFwdHitsPost; iFwdHit++){
693  FwdHit *hit = &(mFwdHitsFst[ iFwdHit ]);
694  // Add the hit to the hit map
695  if ( hit->getLayer() >= 0 )
696  hitMap[hit->getSector()].push_back(hit);
697  // add to MC track map
698  if ( hit->getMcTrack() ){
699  hit->getMcTrack()->addFstHit(hit);
700  }
701  }
702  if ( numFwdHitsPost != numFwdHitsPrior ){
703  LOG_INFO << "Loaded " << numFwdHitsPost - numFwdHitsPrior << " FST hits from StEvent" << endm;
704  }
705  return count;
706 } //loadFstHitsFromStEvent
707 
708 int StFwdTrackMaker::loadFstHitsFromStRnDHits( FwdDataSource::McTrackMap_t &mcTrackMap, FwdDataSource::HitMap_t &hitMap){
709  LOG_DEBUG << "Looking for FST hits in StEvent StRnDHit Collection" << endm;
710  int count = 0;
711  // Get the StEvent handle
712  StEvent *event = (StEvent *)GetDataSet("StEvent");
713  if (!event) {
714  LOG_DEBUG << "No StEvent, cannot load FST FastSim hits from StEvent StRndHitCollection" << endm;
715  return 0;
716  }
717 
718  size_t numFwdHitsPrior = mFwdHitsFst.size();
719  StRnDHitCollection *rndCollection = event->rndHitCollection();
720  if (!rndCollection) return 0;
721 
722  const StSPtrVecRnDHit &hits = rndCollection->hits();
723 
724  // we will reuse this to hold the cov mat
725  TMatrixDSym hitCov3(3);
726 
727  for (unsigned int fsthit_index = 0; fsthit_index < hits.size(); fsthit_index++) {
728  StRnDHit *hit = hits[fsthit_index];
729 
730  if ( hit->layer() > 6 ){
731  // skip sTGC hits here
732  continue;
733  }
734 
735  const StThreeVectorF pos = hit->position();
736 
737  StMatrixF covmat = hit->covariantMatrix();
738 
739  // copy covariance matrix element by element from StMatrixF
740  hitCov3(0,0) = covmat[0][0]; hitCov3(0,1) = covmat[0][1]; hitCov3(0,2) = covmat[0][2];
741  hitCov3(1,0) = covmat[1][0]; hitCov3(1,1) = covmat[1][1]; hitCov3(1,2) = covmat[1][2];
742  hitCov3(2,0) = covmat[2][0]; hitCov3(2,1) = covmat[2][1]; hitCov3(2,2) = covmat[2][2];
743 
744  mFwdHitsFst.push_back(
745  FwdHit(
746  count++, // id
747  hit->position().x(), hit->position().y(), hit->position().z(), // position
748  hit->layer(), // volume id
749  kFstId, // detid
750  hit->idTruth(), // mc track id
751  hitCov3, // covariance matrix
752  mcTrackMap[hit->idTruth()] // mcTrack
753  )
754  );
755  mFstHits.push_back( TVector3( hit->position().x(), hit->position().y(), hit->position().z()) );
756  }
757 
758  // this has to be done AFTER because the vector reallocates mem when expanding, changing addresses
759  size_t numFwdHitsPost = mFwdHitsFst.size();
760  for ( size_t iFwdHit = numFwdHitsPrior; iFwdHit < numFwdHitsPost; iFwdHit++){
761  FwdHit *hit = &(mFwdHitsFst[ iFwdHit ]);
762  // Add the hit to the hit map
763  if ( hit->getLayer() >= 0 )
764  hitMap[hit->getSector()].push_back(hit);
765  }
766  if ( numFwdHitsPost != numFwdHitsPrior ){
767  LOG_INFO << "Loaded " << numFwdHitsPost - numFwdHitsPrior << " FST hits from StEvent FastSim" << endm;
768  }
769 
770  return count;
771 } //loadFstHitsFromStEvent
772 
773 int StFwdTrackMaker::loadFstHitsFromGEANT( FwdDataSource::McTrackMap_t &mcTrackMap, FwdDataSource::HitMap_t &hitMap ){
774  int count = 0;
775  LOG_DEBUG << "Looking for FST hits in geant struct" << endm;
776  /************************************************************/
777  // Load FSI Hits from GEANT
778  St_g2t_fts_hit *g2t_fsi_hits = (St_g2t_fts_hit *)GetDataSet("geant/g2t_fsi_hit");
779 
780  if ( !g2t_fsi_hits ){
781  LOG_DEBUG << "No g2t_fts_hits, cannot load FST hits from GEANT" << endm;
782  return 0;
783  }
784 
785  int nfsi = g2t_fsi_hits->GetNRows();
786  size_t numFwdHitsPrior = mFwdHitsFst.size();
787 
788  // reuse this to store cov mat
789  TMatrixDSym hitCov3(3);
790 
791  for (int i = 0; i < nfsi; i++) {
792 
793  g2t_fts_hit_st *git = (g2t_fts_hit_st *)g2t_fsi_hits->At(i);
794 
795  if (0 == git)
796  continue; // geant hit
797 
798  int track_id = git->track_p;
799  int volume_id = git->volume_id; // 4, 5, 6
800  int d = volume_id / 1000; // disk id
801 
802  int plane_id = d - 4;
803  float x = git->x[0];
804  float y = git->x[1];
805  float z = git->x[2];
806 
807  if (mSiRasterizer->active()) {
808  TVector3 rastered = mSiRasterizer->raster(TVector3(git->x[0], git->x[1], git->x[2]));
809  LOG_INFO << TString::Format("Rastered: %f %f %f -> %f %f %f", git->x[0], git->x[1], git->x[2], rastered.X(), rastered.Y(), rastered.Z()) << endm;
810  x = rastered.X();
811  y = rastered.Y();
812  } else {
813  LOG_INFO << "Using GEANT FST hit positions without rasterization" << endm;
814  }
815 
816  if (plane_id > 3 || plane_id < 0) {
817  continue;
818  }
819 
820  hitCov3 = makeSiCovMat( TVector3( x, y, z ), mFwdConfig );
821  mFwdHitsFst.push_back(
822  FwdHit(
823  count++, // id
824  x, y, z, // position
825  d, // volume id
826  kFstId, // detid
827  track_id, // mc track id
828  hitCov3, // covariance matrix
829  mcTrackMap[track_id] // mcTrack
830  )
831  );
832  mFstHits.push_back( TVector3( x, y, z ) );
833  }
834 
835  // this has to be done AFTER because the vector reallocates mem when expanding, changing addresses
836  size_t numFwdHitsPost = mFwdHitsFst.size();
837  for ( size_t iFwdHit = numFwdHitsPrior; iFwdHit < numFwdHitsPost; iFwdHit++){
838  FwdHit *hit = &(mFwdHitsFst[ iFwdHit ]);
839  // Add the hit to the hit map
840  if ( hit->getLayer() >= 0 )
841  hitMap[hit->getSector()].push_back(hit);
842 
843  // add to MC track map
844  if ( hit->getMcTrack() )
845  hit->getMcTrack()->addFstHit(hit);
846  }
847  if ( numFwdHitsPost != numFwdHitsPrior ){
848  LOG_INFO << "Loaded " << numFwdHitsPost - numFwdHitsPrior << " FST hits from GEANT" << endm;
849  }
850 
851  return count;
852 } // loadFstHitsFromGEANT
853 
863 size_t StFwdTrackMaker::loadMcTracks( FwdDataSource::McTrackMap_t &mcTrackMap ){
864 
865  LOG_DEBUG << "Looking for GEANT sim vertex info" << endm;
866  St_g2t_vertex *g2t_vertex = (St_g2t_vertex *)GetDataSet("geant/g2t_vertex");
867 
868  if ( g2t_vertex != nullptr ) {
869  // Set the MC Vertex for track fitting
870  g2t_vertex_st *vert = (g2t_vertex_st*)g2t_vertex->At(0);
871  TMatrixDSym cov;
872  cov.ResizeTo(3, 3);
873  cov(0, 0) = 0.001;
874  cov(1, 1) = 0.001;
875  cov(2, 2) = 0.001;
876  mForwardTracker->setEventVertex( TVector3( vert->ge_x[0], vert->ge_x[1], vert->ge_x[2] ), cov );
877  }
878 
879 
880  // Get geant tracks
881  St_g2t_track *g2t_track = (St_g2t_track *)GetDataSet("geant/g2t_track");
882 
883  if (!g2t_track)
884  return 0;
885 
886  size_t nShowers = 0;
887  LOG_DEBUG << g2t_track->GetNRows() << " mc tracks in geant/g2t_track " << endm;
888 
889  for (int irow = 0; irow < g2t_track->GetNRows(); irow++) {
890  g2t_track_st *track = (g2t_track_st *)g2t_track->At(irow);
891 
892  if (0 == track)
893  continue;
894 
895  int track_id = track->id;
896  float pt2 = track->p[0] * track->p[0] + track->p[1] * track->p[1];
897  float pt = std::sqrt(pt2);
898  float eta = track->eta;
899  TVector3 pp( track->p[0], track->p[1], track->p[2] );
900  float phi = std::atan2(track->p[1], track->p[0]); //track->phi;
901  int q = track->charge;
902  // sometimes the track->eta is wrong, pt, phi
903  if (!mcTrackMap[track_id] )
904  mcTrackMap[track_id] = shared_ptr<McTrack>(new McTrack(pp.Pt(), pp.Eta(), pp.Phi(), q, track->start_vertex_p));
905 
906  } // loop on track (irow)
907 
908  // now check the Mc tracks against the McEvent filter
909  size_t nForwardTracks = 0;
910  size_t nForwardTracksNoThreshold = 0;
911  for (auto mctm : mcTrackMap ){
912  if ( mctm.second == nullptr ) continue;
913  if ( mctm.second->mEta > 2.5 && mctm.second->mEta < 4.0 ){
914  nForwardTracksNoThreshold++;
915  if ( mctm.second->mPt > 0.05 )
916  nForwardTracks++;
917  }
918  } // loop on mcTrackMap
919  return nForwardTracks;
920 } // loadMcTracks
921 
932  StEvent *stEvent = static_cast<StEvent *>(GetInputDS("StEvent"));
933  mFcsDb = static_cast<StFcsDb*>(GetDataSet("fcsDb"));
934  if ( !stEvent || !mFcsDb ){
935  return;
936  }
937  StFcsCollection* fcsCol = stEvent->fcsCollection();
938  if ( !fcsCol ){
939  return;
940  }
941 
942  StEpdGeom epdgeo;
943 
944  // LOAD ECAL / HCAL CLUSTERS
945  for ( int idet = 0; idet < 4; idet++ ){
946  StSPtrVecFcsCluster& clusters = fcsCol->clusters(idet);
947  int nc=fcsCol->numberOfClusters(idet);
948  for ( int i = 0; i < nc; i++ ){
949  StFcsCluster* clu = clusters[i];
950  StThreeVectorD xyz = mFcsDb->getStarXYZfromColumnRow(clu->detectorId(),clu->x(),clu->y());
951  mFcsClusters.push_back( TVector3( xyz.x(), xyz.y(), xyz.z() - 2 ) );
952  mFcsClusterEnergy.push_back( clu->energy() );
953  } // i
954  } // idet
955 
956  // LOAD PRESHOWER HITS (EPD)
957  for ( int det = 4; det < 6; det ++ ) {
958 
959  StSPtrVecFcsHit& hits = stEvent->fcsCollection()->hits(det);
960  int nh=fcsCol->numberOfHits(det);
961  for ( int i = 0; i < nh; i++ ){
962  StFcsHit* hit=hits[i];
963 
964  if(det==kFcsPresNorthDetId || det==kFcsPresSouthDetId){ //EPD
965  double zepd=375.0;
966  int pp,tt,n;
967  double x[5],y[5];
968 
969  if ( hit->energy() < 0.2 ) continue;
970  mFcsDb->getEPDfromId(det,hit->id(),pp,tt);
971  epdgeo.GetCorners(100*pp+tt,&n,x,y);
972  double x0 = (x[0] + x[1] + x[2] + x[3]) / 4.0;
973  double y0 = (y[0] + y[1] + y[2] + y[3]) / 4.0;
974  mFcsPreHits.push_back( TVector3( x0, y0, zepd ) );
975  } // if det
976  } // for i
977  } // for det
978 } // loadFcs
979 
980 TVector3 StFwdTrackMaker::GetEventPrimaryVertex(){
981  if ( mFwdVertexSource != kFwdVertexSourceUnknown ){
982  // This includes the case where we have already searched and found nothing
983  return mEventVertex;
984  }
985 
986  mEventVertexCov.ResizeTo(3, 3);
987  mEventVertexCov.Zero();
988  double sig2 = 1;// default resolution, overwritten if valid vtx found
989  mEventVertexCov(0, 0) = sig2;
990  mEventVertexCov(1, 1) = sig2;
991  mEventVertexCov(2, 2) = sig2;
992  // if something is found it will overwrite this, if not
993  // it will indicate that we have searched and found nothing
994  mFwdVertexSource = kFwdVertexSourceNone;
995 
996  /*****************************************************
997  * Add Primary Vertex to the track
998  */
999  St_g2t_vertex *g2t_vertex = (St_g2t_vertex *)GetDataSet("geant/g2t_vertex");
1000  LOG_DEBUG << "Searching for Event Vertex from geant/g2t_vertex: " << g2t_vertex << endm;
1001  if ( g2t_vertex != nullptr ) {
1002  // Set the MC Vertex for track fitting
1003  g2t_vertex_st *vert = (g2t_vertex_st*)g2t_vertex->At(0);
1004  LOG_INFO << "Setting Event Vertex from geant/g2t_vertex[0]: " << vert << endm;
1005  if ( vert ){
1006  mEventVertexCov.ResizeTo(3, 3);
1007  const double sigXY = 0.1; // TODO: read from MC vertex info?
1008  const double sigZ = 0.1;
1009  mEventVertexCov(0, 0) = pow(sigXY,2);
1010  mEventVertexCov(1, 1) = pow(sigXY,2);
1011  mEventVertexCov(2, 2) = pow(sigZ, 2);
1012  auto rhc = TVectorD( 3 );
1013  rhc[0] = vert->ge_x[0];
1014  rhc[1] = vert->ge_x[1];
1015  rhc[2] = vert->ge_x[2];
1016  mEventVertex.SetXYZ( vert->ge_x[0], vert->ge_x[1], vert->ge_x[2] );
1017  mFwdVertexSource = kFwdVertexSourceMc;
1018  return mEventVertex;
1019  }
1020  }
1021 
1022  // or try the McEvent
1023  StMcEvent *stMcEvent = static_cast<StMcEvent *>(GetInputDS("StMcEvent"));
1024  LOG_DEBUG << "Searching for Event Vertex from StMcEvent: " << stMcEvent << endm;
1025  if (stMcEvent && stMcEvent->primaryVertex() ) {
1026  StThreeVectorF vertex = stMcEvent->primaryVertex()->position();
1027  mEventVertex.SetXYZ( vertex.x(), vertex.y(), vertex.z() );
1028  mFwdVertexSource = kFwdVertexSourceMc;
1029  LOG_INFO << "FWD Tracking on event with MC Primary Vertex: " << mEventVertex.X() << ", " << mEventVertex.Y() << ", " << mEventVertex.Z() << endm;
1030 
1031  const double sigXY = 0.1; // TODO: read from MC vertex info?
1032  const double sigZ = 0.1;
1033  mEventVertexCov(0, 0) = pow(sigXY,2);
1034  mEventVertexCov(1, 1) = pow(sigXY,2);
1035  mEventVertexCov(2, 2) = pow(sigZ, 2);
1036  return mEventVertex;
1037  }
1038 
1039  StMuDstMaker *mMuDstMaker = (StMuDstMaker *)GetMaker("MuDst");
1040  if(mMuDstMaker && mMuDstMaker->muDst() && mMuDstMaker->muDst()->numberOfPrimaryVertices() > 0 && mMuDstMaker->muDst()->primaryVertex() ) {
1041  mEventVertex.SetX(mMuDstMaker->muDst()->primaryVertex()->position().x());
1042  mEventVertex.SetY(mMuDstMaker->muDst()->primaryVertex()->position().y());
1043  mEventVertex.SetZ(mMuDstMaker->muDst()->primaryVertex()->position().z());
1044  mFwdVertexSource = kFwdVertexSourceTpc;
1045  return mEventVertex;
1046  }
1047 
1048 
1049  LOG_DEBUG << "FWD Tracking on event without available Mu Primary Vertex" << endm;
1050  StEvent *stEvent = static_cast<StEvent *>(GetInputDS("StEvent"));
1051  if (!stEvent) return mEventVertex; // if we get here and there is no StEvent, we are done
1052 
1053  StBTofCollection *btofC = stEvent->btofCollection();
1054  if (!btofC) {
1055  LOG_WARN << "Cannot get BTOF collections, Cannot use VPD vertex" << endm;
1056  return mEventVertex;
1057  }
1058 
1059  StBTofHeader * btofHeader = btofC->tofHeader();
1060  if (!btofHeader){
1061  LOG_WARN << "Cannot get BTOF Header, Cannot use VPD vertex" << endm;
1062  return mEventVertex;
1063  }
1064 
1065  int nEast = btofHeader->numberOfVpdHits( east );
1066  int nWest = btofHeader->numberOfVpdHits( west );
1067  int nTof = btofC->tofHits().size();
1068 
1069  if ( btofHeader->vpdVz() && fabs(btofHeader->vpdVz()) < 100 ){
1070  // default event vertex
1071  LOG_DEBUG << "FWD Tracking on event using VPD z vertex: (, 0, 0, " << btofHeader->vpdVz() << " )" << endm;
1072  mFwdVertexSource = kFwdVertexSourceVpd;
1073  const double sigXY = 1;
1074  const double sigZ = 6; // approximate resolution of VPD in p+p collisions
1075  mEventVertexCov(0, 0) = pow(sigXY,2);
1076  mEventVertexCov(1, 1) = pow(sigXY,2);
1077  mEventVertexCov(2, 2) = pow(sigZ, 2);
1078  mEventVertex.SetXYZ( 0, 0, btofHeader->vpdVz() );
1079  return mEventVertex;
1080  }
1081 
1082  // if we get here we failed to find a valid vtx
1083  return mEventVertex;
1084 }
1085 
1086 //________________________________________________________________________
1088  // START time for measuring tracking
1089  long long itStart = FwdTrackerUtils::nowNanoSecond();
1090 
1091  StEvent *stEvent = static_cast<StEvent *>(GetInputDS("StEvent"));
1092  if (!stEvent) return kStOk;
1093 
1094  /**********************************************************************/
1095  // Access forward track and hit maps
1096  FwdDataSource::McTrackMap_t &mcTrackMap = mForwardData->getMcTracks();
1097  FwdDataSource::HitMap_t &hitMap = mForwardData->getFttHits();
1098  FwdDataSource::HitMap_t &fsiHitMap = mForwardData->getFstHits();
1099 
1100  /**********************************************************************/
1101  // get the primary vertex for use with FWD tracking
1102  mFwdVertexSource = StFwdTrackMaker::kFwdVertexSourceUnknown;
1103  GetEventPrimaryVertex();
1104  LOG_DEBUG << "FWD Vertex Source: " << mFwdVertexSource << endm;
1105  LOG_DEBUG << "Setting FWD event vertex to: " << TString::Format("mEventVertex=(%0.3f+/-%0.3f, %0.3f+/-%0.3f, %0.3f+/-%0.3f)", mEventVertex.X(), sqrt(mEventVertexCov(0, 0)), mEventVertex.Y(), sqrt(mEventVertexCov(1, 1)), mEventVertex.Z(), sqrt(mEventVertexCov(2, 2)) ) << endm;
1106  mForwardTracker->setEventVertex( mEventVertex, mEventVertexCov );
1107 
1108 
1109  /**********************************************************************/
1110  // Load MC tracks
1111  size_t nForwardTracks = loadMcTracks( mcTrackMap );
1112  size_t maxForwardTracks = mFwdConfig.get<size_t>( "McEvent.Mult:max", 10000 );
1113  if ( nForwardTracks > maxForwardTracks ){
1114  LOG_WARN << "Skipping event with more than " << maxForwardTracks << " forward tracks" << endm;
1115  return kStOk;
1116  }
1117  LOG_DEBUG << "We have " << nForwardTracks << " forward MC tracks" << endm;
1118 
1119  /**********************************************************************/
1120  // Load sTGC
1121  LOG_DEBUG << ">>StFwdTrackMaker::loadFttHits" << endm;
1122  if ( IAttr("useFtt") ) {
1123  loadFttHits( mcTrackMap, hitMap );
1124  }
1125 
1126  /**********************************************************************/
1127  // Load FST
1128  if ( IAttr("useFst") ) {
1129  LOG_DEBUG << ">>StFwdTrackMaker::loadFstHits" << endm;
1130  int fstCount = loadFstHits( mcTrackMap, fsiHitMap );
1131  LOG_DEBUG << "Loaded " << fstCount << " FST hits" << endm;
1132  }
1133 
1134  /**********************************************************************/
1135  // Load FCS
1136  LOG_DEBUG << ">>StFwdTrackMaker::loadFcsHits" << endm;
1137  if ( IAttr("useFcs") ) {
1138  loadFcs();
1139  }
1140 
1141  /**********************************************************************/
1142  // Print out the MC tracks and their hit counts
1143  for ( auto kv : mcTrackMap ){
1144  if ( kv.second == nullptr ) continue;
1145  LOG_DEBUG << "MC Track: id=" << kv.first << ", nFTT=" << kv.second->mFttHits.size() << ", nFST=" << kv.second->mFstHits.size() << endm;
1146  }
1147 
1148  /**********************************************************************/
1149  // Run Track finding + fitting
1150  LOG_DEBUG << ">>START Event Forward Tracking" << endm;
1151  LOG_INFO << "\tFinding FWD Track Seeds" << endm;
1152  mForwardTracker->findTrackSeeds();
1153  LOG_INFO << "\tFitting FWD Track Seeds" << endm;
1154  // in principle we could filter the track seeds further if we wanted
1155  mForwardTracker->doTrackFitting( mForwardTracker->getTrackSeeds() );
1156  LOG_DEBUG << "<<FINISH Event Forward Tracking" << endm;
1157  LOG_INFO << "<<Fwd Tracking Found : " << mForwardTracker -> getTrackSeeds().size() << " Track Seeds" << endm;
1158  LOG_INFO << "<<Fwd Tracking Fit :" << mForwardTracker -> getTrackResults().size() << " GenFit Tracks" << endm;
1159  /**********************************************************************/
1160 
1161 
1162  /**********************************************************************/
1163  // Output track visualization if configured to do so
1164  if ( mVisualize ){
1165  std::vector<genfit::Track *> genfitTracks;
1166  for ( auto gtr : mForwardTracker->getTrackResults() ) {
1167  if ( gtr.mIsFitConvergedFully == false ) continue;
1168  genfitTracks.push_back( gtr.mTrack.get() );
1169  }
1170 
1171  if ( mVisualize && genfitTracks.size() > 0 && genfitTracks.size() < 400 && eventIndex < 50 ) {
1172  const auto &seed_tracks = mForwardTracker -> getTrackSeeds();
1173 
1174  ObjExporter woe;
1175  woe.output(
1176  TString::Format( "ev%lu", eventIndex ).Data(),
1177  stEvent,
1178  seed_tracks, genfitTracks, mRaveVertices,
1179  mFttHits, mFstHits, mFcsPreHits, mFcsClusters, mFcsClusterEnergy );
1180  eventIndex++;
1181  LOG_DEBUG << "Done Writing OBJ " << endm;
1182  } else if (mVisualize && genfitTracks.size() == 0) {
1183  LOG_DEBUG << "Skipping visualization, no FWD tracks" << endm;
1184  } else if (mVisualize && genfitTracks.size() >= 400) {
1185  LOG_DEBUG << "Skipping visualization, too many FWD tracks" << endm;
1186  }
1187  }
1188 
1189  LOG_DEBUG << "Forward tracking on this event took " << (FwdTrackerUtils::nowNanoSecond() - itStart) * 1e-6 << " ms" << endm;
1190  if ( IAttr("fillEvent") ) {
1191  if (!stEvent) {
1192  LOG_WARN << "No StEvent found. Forward tracks will not be saved" << endm;
1193  return kStWarn;
1194  }
1195  FillEvent();
1196  } // IAttr FillEvent
1197 
1198  return kStOK;
1199 } // Make
1200 
1212  LOG_DEBUG << "StFwdTrackMaker::makeStFwdTrack()" << endm;
1213  StFwdTrack *fwdTrack = new StFwdTrack( );
1214 
1215  /*******************************************************************************/
1216  // store the seed points for the track
1217  int nSeedPoints = 0;
1218  for ( auto s : gtr.mSeed ){
1219  FwdHit * fh = static_cast<FwdHit*>( s );
1220  if (!fh) continue;
1221  float cov[9];
1222  cov[0] = fh->_covmat(0,0); cov[3] = fh->_covmat(1,0); cov[6] = fh->_covmat(2,0);
1223  cov[1] = fh->_covmat(0,1); cov[4] = fh->_covmat(1,1); cov[7] = fh->_covmat(2,1);
1224  cov[2] = fh->_covmat(0,2); cov[5] = fh->_covmat(1,2); cov[8] = fh->_covmat(2,2);
1225 
1227  StThreeVectorD( fh->getX(), fh->getY(), fh->getZ() ),
1228  fh->_detid * 10 + fh->getSector(), // 10 * detid + sector
1229  fh->getTrackId(),
1230  cov
1231  );
1232  if ( fh->isFst() )
1233  fwdTrack->mFSTPoints.push_back( p );
1234  else if ( fh->isFtt() )
1235  fwdTrack->mFTTPoints.push_back( p );
1236 
1237  nSeedPoints++;
1238  }
1239 
1240  // set total number of seed points
1241  fwdTrack->setNumberOfSeedPoints( nSeedPoints );
1242  int idt = 0;
1243  double qual = 0;
1244  idt = MCTruthUtils::dominantContribution(gtr.mSeed, qual);
1245  fwdTrack->setMc( idt, qual*100 ); // QAtruth stored as UChar_t
1246  LOG_DEBUG << "Dominant contribution: " << idt << " with quality " << qual << endm;
1247 
1248  // Fit failed beyond use
1249  if ( gtr.mTrack == nullptr ){
1250  gtr.Clear();
1251  LOG_DEBUG << "GenfitTrack is nullptr, making StFwdTrack with seed info only" << endm;
1252  return fwdTrack;
1253  }
1254  // Fill charge and quality info
1255  fwdTrack->setDidFitConverge( gtr.mStatus->isFitConverged() );
1256  fwdTrack->setDidFitConvergeFully( gtr.mStatus->isFitConvergedFully() );
1257  fwdTrack->setNumberOfFailedPoints( gtr.mStatus->getNFailedPoints() );
1258 
1259  fwdTrack->setNumberOfFitPoints( gtr.mTrack->getNumPoints() );
1260  fwdTrack->setChi2( gtr.mStatus->getChi2() );
1261  fwdTrack->setNDF( gtr.mStatus->getNdf() );
1262  fwdTrack->setPval( gtr.mStatus->getPVal() );
1263 
1264  // charge at first point
1265  fwdTrack->setCharge( gtr.mCharge );
1266  fwdTrack->setDCA( gtr.mDCA.X(), gtr.mDCA.Y(), gtr.mDCA.Z() );
1267 
1268  TVector3 p = gtr.mMomentum;//cr->getMom( gtr.mTrack->getFittedState( 0, cr ));
1269  fwdTrack->setPrimaryMomentum( StThreeVectorD( gtr.mMomentum.X(), gtr.mMomentum.Y(), gtr.mMomentum.Z() ) );
1270 
1271  if ( gtr.isPrimary ){
1272  fwdTrack->setVtxIndex( 0 );
1273  } else {
1274  fwdTrack->setVtxIndex( UCHAR_MAX );
1275  }
1276 
1277  /*******************************************************************************/
1278  // if the track is not (at least partially) converged, do not try to project it
1279  if ( !gtr.mStatus->isFitConvergedPartially() ){
1280  gtr.Clear();
1281  return fwdTrack;
1282  }
1283 
1284  /*******************************************************************************/
1285  // compute projections to z-planes of various detectors
1286  // TODO: update FCS to use correct z + angle
1287  map<int, float> mapDetectorToZPlane = {
1288  { kTpcId, 0.0 },
1289  { kFstId, mFstZFromGeom[0] },
1290  { kFstId, mFstZFromGeom[1] },
1291  { kFstId, mFstZFromGeom[2] },
1292  { kFttId, mFttZFromGeom[0] },
1293  { kFttId, mFttZFromGeom[1] },
1294  { kFttId, mFttZFromGeom[2] },
1295  { kFttId, mFttZFromGeom[3] },
1296  { kFcsPresId, 375.0 },
1297  { kFcsWcalId, 715.0 },
1298  { kFcsHcalId, 807.0 }
1299  };
1300 
1301  if ( gtr.mStatus->isFitConverged() ){ // dont project if the fit did not converge
1302  size_t zIndex = 0;
1303  TVector3 mom(0, 0, 0);
1304  float cov[9];
1305  TVector3 tv3(0, 0, 0);
1306  for ( auto zp : mapDetectorToZPlane ){
1307  int detIndex = zp.first;
1308  float z = zp.second;
1309  tv3.SetXYZ(0, 0, 0);
1310  if ( detIndex != kFcsHcalId && detIndex != kFcsWcalId ){
1311  float detpos[3] = {0,0,z};
1312  float detnorm[3] = {0,0,1};
1313  if( detIndex==kFcsPresId ){
1314  StThreeVectorD xyzoff = mFcsDb->getDetectorOffset(kFcsPresId);
1315  detpos[0] = (float)xyzoff.x();
1316  detpos[1] = (float)xyzoff.y();
1317  detpos[2] = (float)xyzoff.z();
1318  }
1319  tv3 = ObjExporter::trackPosition( gtr.mTrack.get(), detpos, detnorm, cov, mom );
1320  } else {
1321  // use a straight line projection to HCAL since GenFit cannot handle long projections
1322  int det=0;
1323  if( detIndex==kFcsWcalId ){
1324  det = 0; // North side for negative px
1325  // South side for positive px, since px==0 does not hit detector choose south side for that case
1326  if( p[2]>=0 && p[0]>=0 ){ det=1; }
1327  if( p[2]<0 && p[0]<0 ){ det=1; }
1328  }
1329  //Since detIndex cannot be both don't need "else if"
1330  if( detIndex==kFcsHcalId ){
1331  det = 2; // North side for negative px
1332  // South side for positive px, since px==0 does not hit detector choose south side for that case
1333  if( p[2]>=0 && p[0]>=0 ){ det=3; }
1334  if( p[2]<0 && p[0]<0 ){ det=3; }
1335  }
1336  StThreeVectorD xyzoff = mFcsDb->getDetectorOffset(det);
1337  StThreeVectorD planenormal = mFcsDb->getNormal(det);
1338  float xyz0[3] = { 0, 0, 575.0 };
1339  float xyz1[3] = { 0, 0, 625.0 };
1340  float xyzdet[3] = { (float)xyzoff.x(), (float)xyzoff.y(), (float)xyzoff.z() };
1341  float detnorm[3] = { (float)planenormal.x(), (float)planenormal.y(), (float)planenormal.z() };
1342  LOG_DEBUG << "Projecting to: " << detIndex << endm;
1343  tv3 = ObjExporter::projectAsStraightLine( gtr.mTrack.get(), xyz0, xyz1, xyzdet, detnorm, cov, mom );
1344  }
1345  fwdTrack->mProjections.push_back( StFwdTrackProjection( detIndex, StThreeVectorF( tv3.X(), tv3.Y(), tv3.Z() ), StThreeVectorF( mom.X(), mom.Y(), mom.Z() ), cov) );
1346  zIndex++;
1347  }
1348  }
1349  /*******************************************************************************/
1350 
1351  /*******************************************************************************/
1352  // clear the GenfitTrackResult
1353  gtr.Clear();
1354 
1355  // return the StFwdTrack we made
1356  return fwdTrack;
1357 }
1358 
1359 void StFwdTrackMaker::FillEvent() {
1360  StEvent *stEvent = static_cast<StEvent *>(GetInputDS("StEvent"));
1361  if (!stEvent)
1362  return;
1363  StFwdTrackCollection * ftc = stEvent->fwdTrackCollection();
1364  if ( !ftc ){
1365  LOG_INFO << "Creating the StFwdTrackCollection" << endm;
1366  ftc = new StFwdTrackCollection();
1367  stEvent->setFwdTrackCollection( ftc );
1368  }
1369 
1370  size_t indexTrack = 0;
1371  for ( auto gtr : mForwardTracker->getTrackResults() ) {
1372  StFwdTrack* fwdTrack = makeStFwdTrack( gtr, indexTrack );
1373  indexTrack++;
1374  if (nullptr == fwdTrack)
1375  continue;
1376  ftc->addTrack( fwdTrack );
1377  }
1378 
1379  LOG_INFO << "StFwdTrackCollection has " << ftc->numberOfTracks() << " tracks now" << endm;
1380 
1381  // Pico Dst requires a primary vertex,
1382  // if we have a PicoDst maker in the chain, we need to add a primary vertex
1383  // when one does not exist to get a "FWD" picoDst
1384  auto mk = GetMaker("PicoDst");
1385  if ( mk && stEvent->numberOfPrimaryVertices() == 0 ){
1386  LOG_INFO << "Adding a primary vertex to StEvent since PicoDst maker was found in chain, but no vertices found" << endm;
1387  stEvent->addPrimaryVertex( new StPrimaryVertex() );
1388  LOG_INFO << "StPrimaryVertex::numberOfPrimaryVertices = " << stEvent->numberOfPrimaryVertices() << endm;
1389  }
1390 
1391  // ProcessFwdTracks();
1392 }
1393 
1395  vector<genfit::Track *> genfitTracks;
1396 
1397  const auto &trackResults = mForwardTracker -> getTrackResults();
1398  if ( genfitTracks.size() >= 2 ){
1399  genfit::GFRaveVertexFactory gfrvf;
1400 
1401  TMatrixDSym bscm(3);
1402  const double bssXY = 2.0;
1403  bscm(0, 0) = bssXY*bssXY;
1404  bscm(1, 1) = bssXY*bssXY;
1405  bscm(2, 2) = 50.5 * 50.5;
1406  gfrvf.setBeamspot( TVector3( 0, 0, 0 ), bscm );
1407 
1408  mRaveVertices.clear();
1409  gfrvf.findVertices( &mRaveVertices, genfitTracks, false );
1410 
1411  LOG_DEBUG << "mRaveVertices.size() = " << mRaveVertices.size() << endm;
1412  for ( auto vert : mRaveVertices ){
1413  LOG_DEBUG << TString::Format( "RAVE vertex @(%f, %f, %f)\n\n", vert->getPos().X(), vert->getPos().Y(), vert->getPos().Z() ) << endm;
1414  }
1415  }
1416 } // FitVertex
1417 
1418 //________________________________________________________________________
1419 void StFwdTrackMaker::Clear(const Option_t *opts) {
1420  LOG_DEBUG << "StFwdTrackMaker::CLEAR" << endm;
1421  mForwardData->clear();
1422  mForwardTracker->Clear();
1423 
1424  // clear fwd hits from fst and ftt
1425  mFwdHitsFst.clear();
1426  mFwdHitsFtt.clear();
1427 
1428  // clear vectors for visualization OBJ hits
1429  mFttHits.clear();
1430  mFstHits.clear();
1431  mFcsPreHits.clear();
1432  mFcsClusters.clear();
1433  mFwdTracks.clear();
1434 
1435 }
1436 //________________________________________________________________________
1437 void StFwdTrackMaker::ProcessFwdTracks( ){
1438  // This is an example of how to process fwd track collection
1439  LOG_DEBUG << "StFwdTrackMaker::ProcessFwdTracks" << endm;
1440  StEvent *stEvent = static_cast<StEvent *>(GetInputDS("StEvent"));
1441  StFwdTrackCollection * ftc = stEvent->fwdTrackCollection();
1442  for ( auto fwdTrack : ftc->tracks() ){
1443  LOG_DEBUG << TString::Format("StFwdTrack[ nProjections=%lu, nFTTSeeds=%lu, nFSTSeeds=%lu, mPt=%f ]", fwdTrack->mProjections.size(), fwdTrack->mFTTPoints.size(), fwdTrack->mFSTPoints.size(), fwdTrack->momentum().perp()) << endm;
1444  for ( auto proj : fwdTrack->mProjections ) {
1445  LOG_DEBUG << TString::Format("Proj[ %d, %f, %f, %f ]", proj.mDetId, proj.mXYZ.x(), proj.mXYZ.y(), proj.mXYZ.z() ) << endm;
1446  }
1447  }
1448 }
1449 
1450 
1451 std::string StFwdTrackMaker::defaultConfig = R"( <?xml version="1.0" encoding="UTF-8"?> <config> <TrackFinder nIterations="1"> <Iteration nPhiSlices="1" > <!-- Options for first iteration --> <SegmentBuilder> <!-- <Criteria name="Crit2_RZRatio" min="0" max="1.20" /> --> <!-- <Criteria name="Crit2_DeltaRho" min="-50" max="50.9"/> --> <Criteria name="Crit2_DeltaPhi" min="0" max="10.0" /> <!-- <Criteria name="Crit2_StraightTrackRatio" min="0.01" max="5.85"/> --> </SegmentBuilder> <ThreeHitSegments> <!-- <Criteria name="Crit3_3DAngle" min="0" max="60" /> <Criteria name="Crit3_PT" min="0" max="100" /> <Criteria name="Crit3_ChangeRZRatio" min="0.8" max="1.21" /> <Criteria name="Crit3_2DAngle" min="0" max="30" /> --> </ThreeHitSegments> </Iteration> <Connector distance="2"/> <SubsetNN active="true" min-hits-on-track="2" > <!-- <InitialTemp>2.1</InitialTemp> --> <!-- <InfTemp>0.1</InfTemp> --> <Omega>0.99</Omega> <StableThreshold>0.001</StableThreshold> </SubsetNN> <HitRemover active="false" /> </TrackFinder> <TrackFitter refit="true" zeroB="false" active="true"> <Vertex sigmaXY="1" sigmaZ="10" includeInFit="true" smearMcVertex="false" /> </TrackFitter> </config> )";
1452 
1453 
1454 const std::vector<Seed_t> &StFwdTrackMaker::getTrackSeeds() const{
1455  return mForwardTracker->getTrackSeeds();
1456 }
1457 
1458 const std::vector<GenfitTrackResult> &StFwdTrackMaker::getFitResults()const{
1459  return mForwardTracker->getTrackResults();
1460 }
1461 
static StMuPrimaryVertex * primaryVertex()
return pointer to current primary vertex
Definition: StMuDst.h:322
int loadFstHits(std::map< int, std::shared_ptr< McTrack >> &mcTrackMap, std::map< int, std::vector< KiTrack::IHit * >> &hitMap)
Loads FST hits from various sources into the hitmap and McTrackMap (if availabale) ...
void FitVertex()
Fit the primary vertex using FWD tracks.
StMuDst * muDst()
Definition: StMuDstMaker.h:425
Definition: FwdHit.h:70
void initialize(TString geoCache, bool genHistograms)
Initialize FwdTracker.
StThreeVectorD getDetectorOffset(int det, double zdepth=-1) const
Utility functions related to DetectorPosition.
Definition: StFcsDb.cxx:578
StFwdTrack * makeStFwdTrack(GenfitTrackResult &gtr, size_t indexTrack)
StThreeVectorD getStarXYZfromColumnRow(int det, float col, float row, float FcsZ=-1.0) const
get the STAR frame cooridnates from other way
Definition: StFcsDb.cxx:863
Definition: FwdHit.h:37
void load(std::string filename, bool asString=false)
Main setup routine Loads the given XML file (or string) and maps it.
void getEPDfromId(int det, int id, int &pp, int &tt)
Get FCS&#39;s EPD map foom EPD mapping.
Definition: StFcsDb.cxx:1484
static StMuFstCollection * muFstCollection()
returns pointer to current StMuFstCollection
Definition: StMuDst.h:399
T get(std::string path, T dv) const
template function for getting any type that can be converted from string via stringstream ...
Definition: Stypes.h:42
Definition: Stypes.h:40
size_t loadMcTracks(std::map< int, std::shared_ptr< McTrack >> &mcTrackMap)
virtual void initialize(TString geoCache, bool genHistograms)
Initialize FwdTracker.
Definition: FwdTracker.h:295
void setup()
Setup the tracker object Load geometry Setup Material Effects Setup the magnetic field Setup the fitt...
Definition: TrackFitter.h:58
Event data structure to hold all information from a Monte Carlo simulation. This class is the interfa...
Definition: StMcEvent.hh:169
Definition: Stypes.h:41