Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHTruthSiliconAssociation.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHTruthSiliconAssociation.cc
2 
4 
6 #include <phool/getClass.h>
7 #include <phool/phool.h>
8 #include <phool/PHRandomSeed.h>
9 
11 #include <trackbase/ActsGeometry.h>
15 #include <trackbase/TrkrHitSet.h>
16 #include <trackbase/TrkrDefs.h>
24 
25 #include <g4main/PHG4Hit.h> // for PHG4Hit
26 #include <g4main/PHG4Particle.h> // for PHG4Particle
28 #include <g4main/PHG4HitDefs.h> // for keytype
30 #include <g4main/PHG4VtxPoint.h>
31 
32 #include <TDatabasePDG.h>
33 #include <TParticlePDG.h>
34 
35 #include <gsl/gsl_randist.h>
36 #include <gsl/gsl_rng.h> // for gsl_rng_alloc
37 
38 using namespace std;
39 
40 namespace
41 { template< class T> inline constexpr T square( const T& x ) { return x*x; } }
42 
43 //____________________________________________________________________________..
45  SubsysReco(name)
46 {
47  // initialize random generator
48  const uint seed = PHRandomSeed();
49  m_rng.reset( gsl_rng_alloc(gsl_rng_mt19937) );
50  gsl_rng_set( m_rng.get(), seed );
51 }
52 
53 //____________________________________________________________________________..
55 {
56 
58 }
59 
60 //____________________________________________________________________________..
62 {
63  int ret = GetNodes(topNode);
64 
65  return ret;
66 }
67 
68 //____________________________________________________________________________..
70 {
71  if (Verbosity() >= 1)
72  cout << "PHTruthSiliconAssociation::process_event(PHCompositeNode *topNode) Processing Event" << endl;
73 
74  // Reset the silicon seed node
76 
77  // Loop over all SeedTracks from the CA seeder
78  // These should contain all TPC clusters already
79 
80  for (unsigned int phtrk_iter = 0;
81  phtrk_iter < _tpc_track_map->size();
82  ++phtrk_iter)
83  {
84  _tracklet = _tpc_track_map->get(phtrk_iter);
85 
86  if(!_tracklet)
87  continue;
88 
89  if (Verbosity() >= 1)
90  {
91  std::cout
92  << __LINE__
93  << ": Processing seed itrack: " << phtrk_iter
94  << ": nhits: " << _tracklet-> size_cluster_keys()
95  << ": Total tracks: " << _tpc_track_map->size()
96  << endl;
97  }
98 
99  // identify the best truth track match(es) for this seed track
100  std::vector<PHG4Particle*> g4particle_vec = getG4PrimaryParticle(_tracklet);
101  if(Verbosity() > 0) std::cout << " g4particle_vec.size() " << g4particle_vec.size() << std::endl;
102 
103  if(g4particle_vec.size() < 1) continue;
104 
105  if (Verbosity() >= 1)
106  {
107  std::cout << " tpc seed track:" << endl;
108  _tracklet->identify();
109  }
110 
111  for(unsigned int ig4=0;ig4 < g4particle_vec.size(); ++ig4)
112  {
113  // identify the clusters that are associated with this g4particle
114  PHG4Particle* g4particle = g4particle_vec[ig4];
115  std::set<TrkrDefs::cluskey> clusters = getSiliconClustersFromParticle(g4particle);
116  if(clusters.size() < 3) continue;
117 
118  // Make a silicon track seed
119  unsigned int silicon_seed_index = buildTrackSeed(clusters, g4particle, _silicon_track_map);
120 
121 
122  // Add this entry to the SvtxTrackSeedContainer
123  auto seed = std::make_unique<SvtxTrackSeed_v1>();
124  seed->set_tpc_seed_index(phtrk_iter);
125  seed->set_silicon_seed_index(silicon_seed_index);
126  _svtx_seed_map->insert(seed.get());
127 
128  unsigned int combined_seed_index = _svtx_seed_map->size()-1;
129 
130  if (Verbosity() >= 1)
131  {
132  std::cout << " Created SvtxTrackSeed " << combined_seed_index
133  << " with tpcid " << _svtx_seed_map->get(combined_seed_index)->get_tpc_seed_index()
134  << " and silicon ID " << _svtx_seed_map->get(combined_seed_index)->get_silicon_seed_index()
135  << std::endl;
136  }
137  }
138  }
139 
140  if(Verbosity() > 0)
141  {
142  // loop over the assembled tracks
143  for (unsigned int phtrk_iter = 0;
144  phtrk_iter < _svtx_seed_map->size();
145  ++phtrk_iter)
146  {
147  auto seed = _svtx_seed_map->get(phtrk_iter);
148  if(!seed) continue;
149 
150  auto tpc_index = seed->get_tpc_seed_index();
151  auto silicon_index = seed->get_silicon_seed_index();
152 
153  std::cout << "SvtxSeedTrack: " << phtrk_iter
154  << " tpc_index " << tpc_index
155  << " silicon_index " << silicon_index
156  << std::endl;
157 
158  std::cout << " ---------- silicon tracklet " << silicon_index << std::endl;
159  auto silicon_tracklet = _silicon_track_map->get(silicon_index);
160  if(!silicon_tracklet) continue;
161  silicon_tracklet->identify();
162 
163  std::cout << " ---------- tpc tracklet " << tpc_index << std::endl;
164  auto tpc_tracklet = _tpc_track_map->get(tpc_index);
165  if(!tpc_tracklet) continue;
166  tpc_tracklet->identify();
167  }
168  }
169 
170  if (Verbosity() >= 1)
171  cout << "PHTruthSiliconAssociation::process_event(PHCompositeNode *topNode) Leaving process_event" << endl;
172 
174 }
175 
176 //____________________________________________________________________________..
178 {
179  //cout << "PHTruthSiliconAssociation::ResetEvent(PHCompositeNode *topNode) Resetting internal structures, prepare for next event" << endl;
181 }
182 
183 //____________________________________________________________________________..
184 int PHTruthSiliconAssociation::EndRun(const int /*runnumber*/)
185 {
187 }
188 
189 //____________________________________________________________________________..
191 {
193 }
194 
195 //____________________________________________________________________________..
197 {
199 }
200 
201 //____________________________________________________________________________..
203 {
204  //cout << "PHTruthSiliconAssociation::Print(const std::string &what) const Printing info for " << what << endl;
205 }
206 
207 /*
208 void PHTruthSiliconAssociation::makeSvtxSeedMap()
209 {
212 
213  for(unsigned int iter = 0; iter < _track_map->size(); ++iter)
214  {
215  auto seed = std::make_unique<SvtxTrackSeed_v1>();
216  seed->set_tpc_seed_index(iter);
217  _svtx_seed_map->insert(seed.get());
218  }
219 
220 }
221 */
222 
224 {
225  //---------------------------------
226  // Get Objects off of the Node Tree
227  //---------------------------------
228 
229  _g4truth_container = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
230  if (!_g4truth_container)
231  {
232  cerr << PHWHERE << " ERROR: Can't find node G4TruthInfo" << endl;
234  }
235 
236  _cluster_crossing_map = findNode::getClass<TrkrClusterCrossingAssoc>(topNode, "TRKR_CLUSTERCROSSINGASSOC");
238  {
239  cerr << PHWHERE << " ERROR: Can't find TRKR_CLUSTERCROSSINGASSOC " << endl;
241  }
242  /*
243  _corrected_cluster_map = findNode::getClass<TrkrClusterContainer>(topNode,"CORRECTED_TRKR_CLUSTER");
244  if(_corrected_cluster_map)
245  {
246  std::cout << " Found CORRECTED_TRKR_CLUSTER node " << std::endl;
247  }
248  */
249 
250  _cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
251  if (!_cluster_map)
252  {
253  cerr << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER" << endl;
255  }
256 
257  _hit_truth_map = findNode::getClass<TrkrHitTruthAssoc>(topNode, "TRKR_HITTRUTHASSOC");
258  if (!_hit_truth_map)
259  {
260  cerr << PHWHERE << " ERROR: Can't find TrkrHitTruthAssoc." << endl;
262  }
263 
264  _cluster_hit_map = findNode::getClass<TrkrClusterHitAssoc>(topNode, "TRKR_CLUSTERHITASSOC");
265  if (!_cluster_hit_map)
266  {
267  cerr << PHWHERE << " ERROR: Can't find TrkrClusterHitAssoc." << endl;
269  }
270 
271  _tgeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
272  if(!_tgeometry)
273  {
274  std::cerr << PHWHERE << "ERROR: can't find acts tracking geometry" << std::endl;
276  }
277 
279  PHNodeIterator iter(topNode);
280  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
281 
283  if (!dstNode)
284  {
285  std::cerr << "DST Node missing, quitting" << std::endl;
286  throw std::runtime_error("failed to find DST node in PHTruthSiliconAssociation::createNodes");
287  }
288 
290  PHNodeIterator dstIter(dstNode);
291  PHCompositeNode *svtxNode = dynamic_cast<PHCompositeNode *>(dstIter.findFirst("PHCompositeNode", "SVTX"));
292 
294  if (!svtxNode)
295  {
296  svtxNode = new PHCompositeNode("SVTX");
297  dstNode->addNode(svtxNode);
298  }
299 
300  _silicon_track_map = findNode::getClass<TrackSeedContainer>(topNode, "SiliconTrackSeedContainer");
301  if(!_silicon_track_map)
302  {
304  PHIODataNode<PHObject>* si_tracks_node =
305  new PHIODataNode<PHObject>(_silicon_track_map, "SiliconTrackSeedContainer", "PHObject");
306  svtxNode->addNode(si_tracks_node);
307  }
308 
309  _tpc_track_map = findNode::getClass<TrackSeedContainer>(topNode, "TpcTrackSeedContainer");
310  if (!_tpc_track_map)
311  {
312  cerr << PHWHERE << " ERROR: Can't find TpcTrackSeedContainer: " << endl;
314  }
315 
316  _svtx_seed_map = findNode::getClass<TrackSeedContainer>(topNode, "SvtxTrackSeedContainer");
317  if(!_svtx_seed_map)
318  {
320  PHIODataNode<PHObject> *node2 = new PHIODataNode<PHObject>(_svtx_seed_map, "SvtxTrackSeedContainer","PHObject");
321  svtxNode->addNode(node2);
322  }
323 
324  _g4hits_tpc = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_TPC");
325  _g4hits_intt = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_INTT");
326  _g4hits_mvtx = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_MVTX");
327 
329 }
330 
332 {
333  // Find the best g4particle match to the clusters associated with this reco track
334 
335  std::vector<PHG4Particle*> g4part_vec;
336  std::set<int> pid;
337  std::multimap<int, int> pid_count;
338  int minfound = 200; // require at least this many hits to be put on the list of contributing particles
339 
340  // loop over associated clusters to get hits
341  for (auto iter = track->begin_cluster_keys();
342  iter != track->end_cluster_keys();
343  ++iter)
344  {
345  TrkrDefs::cluskey cluster_key = *iter;
346 
347  // get all reco hits for this cluster
348  //TrkrClusterHitAssoc::ConstRange
349  std::pair<std::multimap<TrkrDefs::cluskey, TrkrDefs::hitkey>::const_iterator, std::multimap<TrkrDefs::cluskey, TrkrDefs::hitkey>::const_iterator>
350  hitrange = _cluster_hit_map->getHits(cluster_key); // returns range of pairs {cluster key, hit key} for this cluskey
351  //for(TrkrClusterHitAssoc::ConstIterator clushititer = hitrange.first; clushititer != hitrange.second; ++clushititer)
352  for(std::multimap<TrkrDefs::cluskey, TrkrDefs::hitkey>::const_iterator
353  clushititer = hitrange.first; clushititer != hitrange.second; ++clushititer)
354  {
355  TrkrDefs::hitkey hitkey = clushititer->second;
356  // TrkrHitTruthAssoc uses a map with (hitsetkey, std::pair(hitkey, g4hitkey)) - get the hitsetkey from the cluskey
358 
359  // get all of the g4hits for this hitkey
360  std::multimap< TrkrDefs::hitsetkey, std::pair<TrkrDefs::hitkey, PHG4HitDefs::keytype> > temp_map;
361  _hit_truth_map->getG4Hits(hitsetkey, hitkey, temp_map); // returns pairs (hitsetkey, std::pair(hitkey, g4hitkey)) for this hitkey only
362  for(std::multimap< TrkrDefs::hitsetkey, std::pair<TrkrDefs::hitkey, PHG4HitDefs::keytype> >::iterator htiter = temp_map.begin(); htiter != temp_map.end(); ++htiter)
363  {
364  // extract the g4 hit key
365  PHG4HitDefs::keytype g4hitkey = htiter->second.second;
366  PHG4Hit * g4hit = nullptr;
367  unsigned int trkrid = TrkrDefs::getTrkrId(hitsetkey);
368  switch( trkrid )
369  {
370  case TrkrDefs::tpcId: g4hit = _g4hits_tpc->findHit(g4hitkey); break;
371  case TrkrDefs::inttId: g4hit = _g4hits_intt->findHit(g4hitkey); break;
372  case TrkrDefs::mvtxId: g4hit = _g4hits_mvtx->findHit(g4hitkey); break;
373  default: break;
374  }
375  if( g4hit )
376  {
377  // get the g4particle ID for this g4hit
378  pid.insert(g4hit->get_trkid());
379  // this is for counting the number of times this g4particle was associated
380  int cnt = 1;
381  pid_count.insert(std::make_pair(g4hit->get_trkid(), cnt));
382  }
383  } // end loop over g4hits associated with hitsetkey and hitkey
384  } // end loop over hits associated with cluskey
385  } // end loop over clusters associated with this track
386 
387 
388  // loop over the particle id's, and count the number for each one
389  for( auto it = pid.begin(); it != pid.end(); ++it)
390  {
391  if(*it < 0) continue; // ignore secondary particles
392 
393  int nfound = 0;
394  std::pair<std::multimap<int, int>::iterator, std::multimap<int,int>::iterator> this_pid = pid_count.equal_range(*it);
395  for(auto cnt_it = this_pid.first; cnt_it != this_pid.second; ++cnt_it)
396  {
397  nfound++;
398  }
399 
400  if(Verbosity() >= 1) std::cout << " pid: " << *it << " nfound " << nfound << std::endl;
401  if(nfound > minfound)
402  {
403  g4part_vec.push_back(_g4truth_container->GetParticle(*it));
404  }
405  }
406 
407  return g4part_vec;
408 
409 }
410 
412 {
413  // Find the reco clusters in the silicon layers from this g4particle
414 
415  std::set<TrkrDefs::cluskey> clusters;
416 
417  // loop over all the clusters
418  for(const auto& hitsetkey:_cluster_map->getHitSetKeys())
419  {
420  const auto layer = TrkrDefs::getLayer(hitsetkey);
421  if(layer > 6) continue; // we need the silicon layers only
422 
423  auto range = _cluster_map->getClusters(hitsetkey);
424  for( auto clusIter = range.first; clusIter != range.second; ++clusIter ){
425  TrkrDefs::cluskey cluster_key = clusIter->first;
426 
427  // get all truth hits for this cluster
428  //TrkrClusterHitAssoc::ConstRange
429  std::pair<std::multimap<TrkrDefs::cluskey, TrkrDefs::hitkey>::const_iterator, std::multimap<TrkrDefs::cluskey, TrkrDefs::hitkey>::const_iterator>
430  hitrange = _cluster_hit_map->getHits(cluster_key); // returns range of pairs {cluster key, hit key} for this cluskey
431  //for(TrkrClusterHitAssoc::ConstIterator
432  for(std::multimap<TrkrDefs::cluskey, TrkrDefs::hitkey>::const_iterator
433  clushititer = hitrange.first; clushititer != hitrange.second; ++clushititer)
434  {
435  TrkrDefs::hitkey hitkey = clushititer->second;
436  // TrkrHitTruthAssoc uses a map with (hitsetkey, std::pair(hitkey, g4hitkey)) - get the hitsetkey from the cluskey
438 
439  // get all of the g4hits for this hitkey
440  std::multimap< TrkrDefs::hitsetkey, std::pair<TrkrDefs::hitkey, PHG4HitDefs::keytype> > temp_map;
441  _hit_truth_map->getG4Hits(hitsetkey, hitkey, temp_map); // returns pairs (hitsetkey, std::pair(hitkey, g4hitkey)) for this hitkey only
442  for(std::multimap< TrkrDefs::hitsetkey, std::pair<TrkrDefs::hitkey, PHG4HitDefs::keytype> >::iterator htiter = temp_map.begin(); htiter != temp_map.end(); ++htiter)
443  {
444  // extract the g4 hit key
445  PHG4HitDefs::keytype g4hitkey = htiter->second.second;
446  PHG4Hit * g4hit = nullptr;
447  unsigned int trkrid = TrkrDefs::getTrkrId(hitsetkey);
448  switch( trkrid )
449  {
450  case TrkrDefs::mvtxId: g4hit = _g4hits_mvtx->findHit(g4hitkey); break;
451  case TrkrDefs::inttId: g4hit = _g4hits_intt->findHit(g4hitkey); break;
452  default: break;
453  }
454  if( g4hit )
455  {
456  // get the g4particle for this g4hit
457  int trkid = g4hit->get_trkid();
458  if(trkid == g4particle->get_track_id())
459  {
460  clusters.insert(cluster_key);
461  }
462  }
463  } // end loop over g4hits associated with hitsetkey and hitkey
464  } // end loop over hits associated with cluskey
465  } // end loop over all cluster keys in silicon layers
466  }//end loop over hitsets
467  return clusters;
468 
469 }
470 
471 std::set<short int> PHTruthSiliconAssociation::getInttCrossings(TrackSeed *si_track) const
472 {
473  std::set<short int> intt_crossings;
474 
475  // If the Si track contains an INTT hit, use it to get the bunch crossing offset
476  // loop over associated clusters to get keys for silicon cluster
477  for (auto iter = si_track->begin_cluster_keys();
478  iter != si_track->end_cluster_keys();
479  ++iter)
480  {
481 
482  TrkrDefs::cluskey cluster_key = *iter;
483  const unsigned int trkrid = TrkrDefs::getTrkrId(cluster_key);
484  if(trkrid == TrkrDefs::inttId)
485  {
486  // std::cout << " INTT cluster key " << cluster_key << std::endl;
487 
488  const unsigned int layer = TrkrDefs::getLayer(cluster_key);
489 
490  // get the bunch crossings for all hits in this cluster
491  auto crossings = _cluster_crossing_map->getCrossings(cluster_key);
492  for(auto iter = crossings.first; iter != crossings.second; ++iter)
493  {
494  const auto& [key, crossing] = *iter;
495  if( Verbosity() )
496  { std::cout << "PHTruthSiliconAssociation::getInttCrossings - si Track cluster " << key << " layer " << layer << " crossing " << crossing << std::endl; }
497  intt_crossings.insert(crossing);
498  }
499  }
500  }
501  // std::cout << " intt_crossings size is " << intt_crossings.size() << std::endl;
502 
503  return intt_crossings;
504 }
505 
506 unsigned int PHTruthSiliconAssociation::buildTrackSeed(std::set<TrkrDefs::cluskey> clusters, PHG4Particle *g4particle, TrackSeedContainer* container)
507 {
508  auto track = std::make_unique<TrackSeed_FastSim_v1>();
509  bool silicon = false;
510  for (const auto& cluskey : clusters){
513  { silicon = true; }
514  track->insert_cluster_key(cluskey);
515  }
516 
517  const auto particle = TDatabasePDG::Instance()->GetParticle(g4particle->get_pid());
518  int charge = 1;
519  if(particle)
520  {
521  if(particle->Charge() < 0)
522  { charge = -1; }
523  }
524 
525  auto random1 = gsl_ran_flat(m_rng.get(), 0.95, 1.05);
526  float px = g4particle->get_px() * random1;
527  float py = g4particle->get_py() * random1;
528  float pz = g4particle->get_pz() * random1;
529 
530  const auto g4vertex = _g4truth_container->GetVtx(g4particle->get_vtx_id());
531  auto random2 = gsl_ran_flat(m_rng.get(), -0.002, 0.002);
532  float x = g4vertex->get_x() + random2;
533  float y = g4vertex->get_y() + random2;
534  float z = g4vertex->get_z() + random2;
535 
536  float pt = sqrt(px*px+py*py);
537  float phi = atan2(py,px);
538  float R = 100 * pt / (0.3*1.4);
539  float theta = atan2(pt,pz);
540  if(theta < 0)
541  { theta += M_PI; }
542  if(theta > M_PI)
543  { theta -= M_PI; }
544 
545  float eta = -log(tan(theta/2.));
546 
547  // We have two equations, phi = atan2(-(X0-x),y-Y0) and
548  //R^2 = (x-X0)^2 + (y-Y0)^2. Solve for X0 and Y0 knowing R and phi
549  float tanphisq = square(tan(phi));
550  float a = tanphisq + 1;
551  float b =-2*y*(tanphisq+1);
552  float c = (tanphisq+1)*square(y)-square(R);
553 
554  float Y0_1 = (-b + sqrt(square(b)-4*a*c)) / (2.*a);
555  float Y0_2 = (-b - sqrt(square(b)-4*a*c)) / (2.*a);
556  float X0_1 = sqrt(pow(R, 2) - pow(Y0_1 - y, 2)) + x;
557  float X0_2 = -sqrt(pow(R, 2) - pow(Y0_2 - y, 2)) + x;
558  track->set_X0(X0_1);
559  track->set_Y0(Y0_1);
560  track->set_qOverR(charge / R);
561  track->set_slope(1. / tan(theta));
562  track->set_Z0(z);
563 
565 
566  float newphi = track->get_phi(_cluster_map, _tgeometry);
569  if( fabs(newphi-phi) > 0.03)
570  {
571  track->set_X0(X0_2);
572  newphi = track->get_phi(_cluster_map, _tgeometry);
573 
574  if( fabs(newphi-phi) > 0.03)
575  {
576  track->set_Y0(Y0_2);
577  newphi = track->get_phi(_cluster_map, _tgeometry);
578 
579  if( fabs(newphi-phi) > 0.03)
580  {
581  track->set_X0(X0_1);
582  newphi = track->get_phi(_cluster_map, _tgeometry);
583  }
584  }
585  }
586 
587  if(Verbosity() > 2)
588  {
589  std::cout << "Charge is " << charge << std::endl;
590  std::cout << "truth/reco px " << px << ", " << track->get_px(_cluster_map, _tgeometry) << std::endl;
591  std::cout << "truth/reco py " << py << ", " << track->get_py(_cluster_map, _tgeometry) << std::endl;
592  std::cout << "truth/reco pz " << pz << ", " << track->get_pz() << std::endl;
593  std::cout << "truth/reco pt " << pt << ", " << track->get_pt() << std::endl;
594  std::cout << "truth/reco phi " << phi << ", " << track->get_phi(_cluster_map, _tgeometry) << std::endl;
595  std::cout << "truth/reco eta " << eta << ", " << track->get_eta() << std::endl;
596  std::cout << "truth/reco x " << x << ", " << track->get_x() << std::endl;
597  std::cout << "truth/reco y " << y << ", " << track->get_y() << std::endl;
598  std::cout << "truth/reco z " << z << ", " << track->get_z() << std::endl;
599 
600  }
601 
602  // set intt crossing
603  if(silicon)
604  {
605  // silicon tracklet
606  /* inspired from PHtruthSiliconAssociation */
607  const auto intt_crossings = getInttCrossings(track.get());
608  if(intt_crossings.empty())
609  {
610  if(Verbosity() > 1) std::cout << "PHTruthTrackSeeding::Process - Silicon track " << container->size() - 1 << " has no INTT clusters" << std::endl;
611  return (container->size() -1);
612  } else if( intt_crossings.size() > 1 ) {
613  if(Verbosity() > 1)
614  { std::cout << "PHTruthTrackSeeding::Process - INTT crossings not all the same for track " << container->size() - 1 << " crossing_keep - dropping this match " << std::endl; }
615 
616  } else {
617  const auto& crossing = *intt_crossings.begin();
618  track->set_crossing(crossing);
619  if(Verbosity() > 1)
620  std::cout << "PHTruthTrackSeeding::Process - Combined track " << container->size() - 1 << " bunch crossing " << crossing << std::endl;
621  }
622  } // end if _min_layer
623  else
624  {
625  // no INTT layers, crossing is unknown
626  track->set_crossing(SHRT_MAX);
627  }
628 
629  container->insert(track.get());
630 
631  return (container->size() - 1);
632 }