Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHSiliconTpcTrackMatching.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHSiliconTpcTrackMatching.cc
2 
4 #include <trackbase/TrkrDefs.h> // for cluskey, getTrkrId, tpcId
5 #include <trackbase/TpcDefs.h>
6 #include <trackbase/MvtxDefs.h>
10 
13 //#include <trackbase_historic/SvtxTrackSeed_v1.h>
15 
16 #include <globalvertex/SvtxVertex.h> // for SvtxVertex
18 
19 #include <g4main/PHG4Hit.h> // for PHG4Hit
20 #include <g4main/PHG4Particle.h> // for PHG4Particle
21 #include <g4main/PHG4HitDefs.h> // for keytype
22 
24 
25 #include <phool/phool.h>
26 #include <phool/PHCompositeNode.h>
27 #include <phool/getClass.h>
28 
29 #include <TF1.h>
30 
31 #include <climits> // for UINT_MAX
32 #include <iostream> // for operator<<, basic_ostream
33 #include <cmath> // for fabs, sqrt
34 #include <set> // for _Rb_tree_const_iterator
35 #include <utility> // for pair
36 #include <memory>
37 
38 using namespace std;
39 
40 //____________________________________________________________________________..
42  SubsysReco(name)
43  , PHParameterInterface(name)
44 {
46 }
47 
48 //____________________________________________________________________________..
50 {
51 
52 }
53 
54 //____________________________________________________________________________..
56 {
58 
59  // put these in the output file
60  cout << PHWHERE << " Search windows: phi " << _phi_search_win << " eta "
61  << _eta_search_win << " _pp_mode " << _pp_mode << " _use_intt_crossing " << _use_intt_crossing << endl;
62 
63 
64  int ret = GetNodes(topNode);
65  if (ret != Fun4AllReturnCodes::EVENT_OK) return ret;
66 
67  return ret;
68 }
69 
70 //_____________________________________________________________________
72 {
73  // Data on gasses @20 C and 760 Torr from the following source:
74  // http://www.slac.stanford.edu/pubs/icfa/summer98/paper3/paper3.pdf
75  // diffusion and drift velocity for 400kV for NeCF4 50/50 from calculations:
76  // http://skipper.physics.sunysb.edu/~prakhar/tpc/HTML_Gases/split.html
77 
78  return;
79 }
80 
81 //____________________________________________________________________________..
83 {
84  // _track_map contains the TPC seed track stubs
85  // _track_map_silicon contains the silicon seed track stubs
86  // _svtx_seed_map contains the combined silicon and tpc track seeds
87 
88  if(Verbosity() > 0)
89  cout << PHWHERE << " TPC track map size " << _track_map->size() << " Silicon track map size " << _track_map_silicon->size() << endl;
90 
91  if(_track_map->size() == 0)
93 
94  // loop over the silicon seeds and add the crossing to them
95  for (unsigned int trackid = 0; trackid != _track_map_silicon->size(); ++trackid)
96  {
97  _tracklet_si = _track_map_silicon->get(trackid);
98  if(!_tracklet_si) { continue; }
99 
100  // returns SHRT_MAX if no INTT clusters in silicon seed
101  short int crossing= getCrossingIntt(_tracklet_si);
102  if(_use_intt_crossing) { _tracklet_si->set_crossing(crossing); } // flag is for testing only, use_intt_crossing should always be true!
103 
104  if(Verbosity() > 8)
105  std::cout << " silicon stub: " << trackid << " eta " << _tracklet_si->get_eta() << " pt " << _tracklet_si->get_pt() << " si z " << _tracklet_si->get_z() << " crossing " << crossing << std::endl;
106 
107  if(Verbosity() > 1) cout << " Si track " << trackid << " crossing " << crossing << endl;
108  }
109 
110  // Find all matches of tpc and si tracklets in eta and phi, x and y
111  // If _pp_mode is not set, a match in z is also required - gives same behavior as old code
112  std::multimap<unsigned int, unsigned int> tpc_matches;
113  std::set<unsigned int> tpc_matched_set;
114  std::set<unsigned int> tpc_unmatched_set;
115  findEtaPhiMatches(tpc_matched_set, tpc_unmatched_set, tpc_matches);
116 
117  // Check that the crossing number is consistent with the tracklet z mismatch, removethe match otherwise
118  // This does nothing if the crossing number is not set
119  checkCrossingMatches(tpc_matches);
120 
121  // We have a complete list of all eta/phi matched tracks in the map "tpc_matches"
122  // make the combined track seeds from tpc_matches
123  for(auto [tpcid, si_id] : tpc_matches)
124  {
125  auto svtxseed = std::make_unique<SvtxTrackSeed_v2>();
126  svtxseed->set_silicon_seed_index(si_id);
127  svtxseed->set_tpc_seed_index(tpcid);
128  // In pp mode, if a matched track does not have INTT clusters we have to find the crossing geometrically
129  // Record the geometrically estimated crossing in the track seeds for later use if needed
130  short int crossing_estimate = findCrossingGeometrically(tpcid, si_id);
131  svtxseed->set_crossing_estimate(crossing_estimate);
132  _svtx_seed_map->insert(svtxseed.get());
133 
134  if(Verbosity() > 1) std::cout << " combined seed id " << _svtx_seed_map->size()-1 << " si id " << si_id << " tpc id " << tpcid << " crossing estimate " << crossing_estimate << std::endl;
135  }
136 
137  // Also make the unmatched TPC seeds into SvtxTrackSeeds
138  for(auto tpcid : tpc_unmatched_set)
139  {
140  auto svtxseed = std::make_unique<SvtxTrackSeed_v2>();
141  svtxseed->set_tpc_seed_index(tpcid);
142  _svtx_seed_map->insert(svtxseed.get());
143 
144  if(Verbosity() > 1) std::cout << " converted unmatched TPC seed id " << _svtx_seed_map->size()-1 << " tpc id " << tpcid << std::endl;
145  }
146 
147  if(Verbosity() > 0)
148  {
149  std::cout << "final svtx seed map size " << _svtx_seed_map->size() << std::endl;
150  }
151 
152  if(Verbosity() > 1)
153  {
154  for(const auto& seed : *_svtx_seed_map)
155  seed->identify();
156 
157  cout << "PHSiliconTpcTrackMatching::process_event(PHCompositeNode *topNode) Leaving process_event" << endl;
158  }
159 
161 
162  }
163 
164 short int PHSiliconTpcTrackMatching::findCrossingGeometrically(unsigned int tpcid, unsigned int si_id)
165 {
166  // loop over all matches and check for ones with no INTT clusters in the silicon seed
167  TrackSeed *si_track =_track_map_silicon->get(si_id);
168  short int crossing = si_track->get_crossing();
169 
170  double si_z = si_track->get_z();
171  TrackSeed *tpc_track = _track_map->get(tpcid);
172  double tpc_z = tpc_track->get_z();
173 
174  // this is an initial estimate of the bunch crossing based on the z-mismatch of the seeds for this track
175  short int crossing_estimate = (short int) getBunchCrossing(tpcid, tpc_z - si_z);
176 
177  if(Verbosity() > 1)
178  {
179  std::cout << "findCrossing: " << " tpcid " << tpcid << " si_id " << si_id << " tpc_z " << tpc_z << " si_z " << si_z << " dz " << tpc_z - si_z
180  << " INTT crossing " << crossing << " crossing_estimate " << crossing_estimate << std::endl;
181  }
182 
183  return crossing_estimate;
184 
185 }
186 
187 double PHSiliconTpcTrackMatching::getBunchCrossing(unsigned int trid, double z_mismatch )
188 {
189  double vdrift = _tGeometry->get_drift_velocity(); // cm/ns
190  vdrift *= 1000.0; // cm/microsecond
191  // double vdrift = 8.00; // cm /microsecond
192  //double z_bunch_separation = 0.106 * vdrift; // 106 ns bunch crossing interval, as in pileup generator
193  double z_bunch_separation = (crossing_period/1000.0) * vdrift; // 106 ns bunch crossing interval, as in pileup generator
194 
195  // The sign of z_mismatch will depend on which side of the TPC the tracklet is in
196  TrackSeed *track = _track_map->get(trid);
197 
198  double crossings = z_mismatch / z_bunch_separation;
199 
200  // Check the TPC side for the first cluster in the track
201  unsigned int side = 10;
202  std::set<short int> side_set;
204  iter != track->end_cluster_keys();
205  ++iter)
206  {
207  TrkrDefs::cluskey cluster_key = *iter;
208  unsigned int trkrid = TrkrDefs::getTrkrId(cluster_key);
209  if(trkrid == TrkrDefs::tpcId)
210  {
211  side = TpcDefs::getSide(cluster_key);
212  side_set.insert(side);
213  }
214  }
215 
216  if(side == 10) return SHRT_MAX;
217 
218  if(side_set.size() == 2 && Verbosity() > 1)
219  std::cout << " WARNING: tpc seed " << trid << " changed TPC sides, " << " final side " << side << std::endl;
220 
221  // if side = 1 (north, +ve z side), a positive t0 will make the cluster late relative to true z, so it will look like z is less positive
222  // so a negative z mismatch for side 1 means a positive t0, and positive crossing, so reverse the sign for side 1
223  if(side == 1)
224  crossings *= -1.0;
225 
226  if(Verbosity() > 1)
227  {
228  std::cout << " gettrackid " << trid << " side " << side << " z_mismatch " << z_mismatch << " crossings " << crossings << std::endl;
229  }
230 
231  return crossings;
232 }
233 
234 
236 {
238 }
239 
241 {
242  //---------------------------------
243  // Get additional objects off the Node Tree
244  //---------------------------------
245 
246  _cluster_crossing_map = findNode::getClass<TrkrClusterCrossingAssoc>(topNode, "TRKR_CLUSTERCROSSINGASSOC");
248  {
249  cerr << PHWHERE << " ERROR: Can't find TRKR_CLUSTERCROSSINGASSOC " << endl;
250  //return Fun4AllReturnCodes::ABORTEVENT;
251  }
252 
253  _track_map_silicon = findNode::getClass<TrackSeedContainer>(topNode, _silicon_track_map_name);
254  if (!_track_map_silicon)
255  {
256  cerr << PHWHERE << " ERROR: Can't find SiliconTrackSeedContainer " << endl;
258  }
259 
260  _track_map = findNode::getClass<TrackSeedContainer>(topNode, _track_map_name);
261  if (!_track_map)
262  {
263  cerr << PHWHERE << " ERROR: Can't find " << _track_map_name.c_str() << endl;
265  }
266 
267  _svtx_seed_map = findNode::getClass<TrackSeedContainer>(topNode, "SvtxTrackSeedContainer");
268  if(!_svtx_seed_map)
269  {
270  std::cout << "Creating node SvtxTrackSeedContainer" << std::endl;
272  PHNodeIterator iter(topNode);
273  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
274 
276  if (!dstNode)
277  {
278  std::cerr << "DST Node missing, quitting" << std::endl;
279  throw std::runtime_error("failed to find DST node in PHActsSourceLinks::createNodes");
280  }
281 
283  PHNodeIterator dstIter(dstNode);
284  PHCompositeNode *svtxNode = dynamic_cast<PHCompositeNode *>(dstIter.findFirst("PHCompositeNode", "SVTX"));
285 
287  if (!svtxNode)
288  {
289  svtxNode = new PHCompositeNode("SVTX");
290  dstNode->addNode(svtxNode);
291  }
292 
295  = new PHIODataNode<PHObject>(_svtx_seed_map, "SvtxTrackSeedContainer","PHObject");
296  svtxNode->addNode(node);
297 
298  }
299 
300  _cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
301  if (!_cluster_map)
302  {
303  std::cout << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER" << std::endl;
305  }
306 
307  _tGeometry = findNode::getClass<ActsGeometry>(topNode,"ActsGeometry");
308  if(!_tGeometry)
309  {
310  std::cout << PHWHERE << "Error, can't find acts tracking geometry" << std::endl;
312  }
313 
315 }
316 
318  std::set<unsigned int> &tpc_matched_set,
319  std::set<unsigned int> &tpc_unmatched_set,
320  std::multimap<unsigned int, unsigned int> &tpc_matches )
321 {
322  // loop over the TPC track seeds
323  for (unsigned int phtrk_iter = 0;
324  phtrk_iter < _track_map->size();
325  ++phtrk_iter)
326  {
327  _tracklet_tpc = _track_map->get(phtrk_iter);
328  if(!_tracklet_tpc)
329  { continue; }
330 
331  unsigned int tpcid = phtrk_iter;
332  if (Verbosity() > 1)
333  {
334  std::cout
335  << __LINE__
336  << ": Processing seed itrack: " << tpcid
337  << ": nhits: " << _tracklet_tpc-> size_cluster_keys()
338  << ": Total tracks: " << _track_map->size()
339  << ": phi: " << _tracklet_tpc->get_phi(_cluster_map,_tGeometry)
340  << endl;
341  }
342 
343  double tpc_phi = _tracklet_tpc->get_phi(_cluster_map,_tGeometry);
344  double tpc_eta = _tracklet_tpc->get_eta();
345  double tpc_pt = fabs(1./_tracklet_tpc->get_qOverR()) *( 0.3/100. ) * std::stod(m_fieldMap);
346  if(Verbosity() > 8)
347  std::cout << " tpc stub: " << tpcid << " eta " << tpc_eta << " pt " << tpc_pt << " tpc z " << _tracklet_tpc->get_z() << std::endl;
348 
349  // this factor will increase the window size at low pT
350  // otherwise the matching efficiency drops off at low pT
351  // it would be better if this was a smooth function
352  double mag = 1.0;
353  if(tpc_pt < 6.0) mag = 2;
354  if(tpc_pt < 3.0) mag = 4.0;
355  if(tpc_pt < 1.5) mag = 6.0;
356 
357  if(Verbosity() > 3)
358  {
359  cout << "TPC tracklet:" << endl;
361  }
362 
363  double tpc_x = _tracklet_tpc->get_x();
364  double tpc_y = _tracklet_tpc->get_y();
365  double tpc_z = _tracklet_tpc->get_z();
366 
367  bool matched = false;
368 
369  // Now search the silicon track list for a match in eta and phi
370  for (unsigned int phtrk_iter_si = 0;
371  phtrk_iter_si < _track_map_silicon->size();
372  ++phtrk_iter_si)
373  {
374  _tracklet_si = _track_map_silicon->get(phtrk_iter_si);
375  if(!_tracklet_si)
376  { continue; }
377 
378  bool eta_match = false;
379  double si_eta = _tracklet_si->get_eta();
380  if( fabs(tpc_eta - si_eta) < _eta_search_win * mag) eta_match = true;
381  if(!eta_match) continue;
382  unsigned int siid = phtrk_iter_si;
383  double si_x = _tracklet_si->get_x();
384  double si_y = _tracklet_si->get_y();
385  double si_z = _tracklet_si->get_z();
386  bool position_match = false;
387  if(_pp_mode)
388  {
389  if(
390  fabs(tpc_x - si_x) < _x_search_win * mag
391  && fabs(tpc_y - si_y) < _y_search_win * mag
392  )
393  position_match = true;
394  }
395  else
396  {
397  if(
398  fabs(tpc_x - si_x) < _x_search_win * mag
399  && fabs(tpc_y - si_y) < _y_search_win * mag
400  && fabs(tpc_z - si_z) < _z_search_win * mag
401  )
402  position_match = true;
403  }
404 
405  if(!position_match)
406  { continue; }
407 
408  bool phi_match = false;
409  double si_phi = _tracklet_si->get_phi(_cluster_map,_tGeometry);
410  if( fabs(tpc_phi - si_phi) < _phi_search_win * mag) phi_match = true;
411  if( fabs( fabs(tpc_phi - si_phi) - 2.0 * M_PI) < _phi_search_win * mag ) phi_match = true;
412  if(!phi_match) continue;
413  if(Verbosity() > 3)
414  {
415  cout << " testing for a match for TPC track " << tpcid << " with pT " << _tracklet_tpc->get_pt()
416  << " and eta " << _tracklet_tpc->get_eta() << " with Si track " << siid << " with crossing " << _tracklet_si->get_crossing() << endl;
417  cout << " tpc_phi " << tpc_phi << " si_phi " << si_phi << " dphi " << tpc_phi-si_phi << " phi search " << _phi_search_win*mag << " tpc_eta " << tpc_eta
418  << " si_eta " << si_eta << " deta " << tpc_eta-si_eta << " eta search " << _eta_search_win*mag << endl;
419  std::cout << " tpc x " << tpc_x << " si x " << si_x << " tpc y " << tpc_y << " si y " << si_y << " tpc_z " << tpc_z << " si z " << si_z << std::endl;
420  std::cout << " x search " << _x_search_win*mag << " y search " << _y_search_win*mag << " z search " << _z_search_win*mag << std::endl;
421  }
422 
423  // got a match, add to the list
424  // These stubs are matched in eta, phi, x and y already
425  matched = true;
426  tpc_matches.insert(std::make_pair(tpcid, siid));
427  tpc_matched_set.insert(tpcid);
428 
429  if(Verbosity() > 1)
430  {
431  cout << " found a match for TPC track " << tpcid << " with Si track " << siid << endl;
432  cout << " tpc_phi " << tpc_phi << " si_phi " << si_phi << " phi_match " << phi_match
433  << " tpc_eta " << tpc_eta << " si_eta " << si_eta << " eta_match " << eta_match << endl;
434  std::cout << " tpc x " << tpc_x << " si x " << si_x << " tpc y " << tpc_y << " si y " << si_y << " tpc_z " << tpc_z << " si z " << si_z << std::endl;
435  }
436 
437  // temporary!
438  if(_test_windows)
439  cout << " Try_silicon: pt " << tpc_pt << " tpc_phi " << tpc_phi << " si_phi " << si_phi << " dphi " << tpc_phi-si_phi
440  << " tpc_eta " << tpc_eta << " si_eta " << si_eta << " deta " << tpc_eta-si_eta << " tpc_x " << tpc_x << " tpc_y " << tpc_y << " tpc_z " << tpc_z
441  << " dx " << tpc_x - si_x << " dy " << tpc_y - si_y << " dz " << tpc_z - si_z
442  << endl;
443 
444  }
445  // if no match found, keep tpc seed for fitting
446  if(!matched)
447  {
448  if(Verbosity() > 1) cout << "inserted unmatched tpc seed " << tpcid << endl;
449  tpc_unmatched_set.insert(tpcid);
450  }
451  }
452 
453  return;
454 }
455 
457 {
458  // If the Si track contains an INTT hit, use it to get the bunch crossing offset
459 
460  std::vector<short int> intt_crossings = getInttCrossings(si_track);
461 
462  bool keep_it = true;
463  short int crossing_keep = 0;
464  if(intt_crossings.size() == 0)
465  {
466  keep_it = false ;
467  }
468  else
469  {
470  crossing_keep = intt_crossings[0];
471  for(unsigned int ic=1; ic<intt_crossings.size(); ++ic)
472  {
473  if(intt_crossings[ic] != crossing_keep)
474  {
475  if(Verbosity() > 1)
476  {
477  std::cout << " Warning: INTT crossings not all the same " << " crossing_keep " << crossing_keep << " new crossing " << intt_crossings[ic] << " keep the first one in the list" << std::endl;
478  }
479  }
480  }
481  }
482 
483  if(keep_it)
484  {
485  return crossing_keep;
486  }
487 
488  return SHRT_MAX;
489 }
490 
492 {
493  std::vector<short int> intt_crossings;
494 
495  // If the Si track contains an INTT hit, use it to get the bunch crossing offset
496  // loop over associated clusters to get keys for silicon cluster
497  for (TrackSeed::ConstClusterKeyIter iter = si_track->begin_cluster_keys();
498  iter != si_track->end_cluster_keys();
499  ++iter)
500  {
501 
502  TrkrDefs::cluskey cluster_key = *iter;
503  const unsigned int trkrid = TrkrDefs::getTrkrId(cluster_key);
504 
505  if(Verbosity() > 1)
506  {
507  unsigned int layer = TrkrDefs::getLayer(cluster_key);
508 
509  if(trkrid == TrkrDefs::mvtxId)
510  {
511  TrkrCluster *cluster = _cluster_map->findCluster(cluster_key);
512  if( !cluster ) continue;
513 
514  Acts::Vector3 global = _tGeometry->getGlobalPosition(cluster_key, cluster);
515 
516  std::cout << "Checking si Track " << _track_map_silicon->find(si_track) << " cluster " << cluster_key
517  << " in layer " << layer << " position " << global(0) << " " << global(1) << " " << global(2)
518  << " eta " << si_track->get_eta() << std::endl;
519  }
520  else
521  std::cout << "Checking si Track " << _track_map_silicon->find(si_track) << " cluster " << cluster_key
522  << " in layer " << layer << " with eta " << si_track->get_eta() << std::endl;
523  }
524 
525  if(trkrid == TrkrDefs::inttId)
526  {
527  TrkrCluster *cluster = _cluster_map->findCluster(cluster_key);
528  if( !cluster ) continue;
529 
530  unsigned int layer = TrkrDefs::getLayer(cluster_key);
531 
532  // get the bunch crossings for all hits in this cluster
533  auto crossings = _cluster_crossing_map->getCrossings(cluster_key);
534  for(auto iter = crossings.first; iter != crossings.second; ++iter)
535  {
536  if(Verbosity() > 1)
537  std::cout << " si Track " << _track_map_silicon->find(si_track) << " cluster " << iter->first << " layer " << layer << " crossing " << iter->second << std::endl;
538  intt_crossings.push_back(iter->second);
539  }
540  }
541  }
542 
543  return intt_crossings;
544 }
545 
546 void PHSiliconTpcTrackMatching::checkCrossingMatches( std::multimap<unsigned int, unsigned int> &tpc_matches )
547 {
548  // if the crossing was assigned correctly, the (crossing corrected) track position should satisfy the Z matching cut
549  // this is a rough check that this is the case
550 
551  float vdrift = _tGeometry->get_drift_velocity();
552 
553  std::multimap<unsigned int, unsigned int> bad_map;
554 
555  for(auto [tpcid, si_id] : tpc_matches)
556  {
557  TrackSeed *tpc_track = _track_map->get(tpcid);
558  TrackSeed *si_track = _track_map_silicon->get(si_id);
559  short int crossing = si_track->get_crossing();
560 
561  if(crossing == SHRT_MAX)
562  {
563  if(Verbosity() > 2) {
564  std::cout << " drop si_track " << si_id << " with eta " << si_track->get_eta() << " and z " << si_track->get_z() << " because crossing is undefined " << std::endl;
565  }
566  continue;
567  }
568 
569  float z_si = si_track->get_z();
570  float z_tpc = tpc_track->get_z();
571  float z_mismatch = z_tpc-z_si;
572 
573  float mag_crossing_z_mismatch = fabs(crossing) * crossing_period * vdrift;
574 
575  // We do not know the sign of the z mismatch for a given crossing unless we know the drift direction in the TPC, use magnitude
576  // could instead look up any TPC cluster key in the track to get side
577  // z-mismatch can occasionally be up to 2 crossings due to TPC extrapolation precision
578  if( fabs( fabs(z_mismatch) - mag_crossing_z_mismatch ) < 3.0)
579  {
580  if(Verbosity() > 1)
581  std::cout << " Success: crossing " << crossing << " tpcid " << tpcid << " si id " << si_id
582  << " tpc z " << z_tpc << " si z " << z_si << " z_mismatch " << z_mismatch
583  << " mag_crossing_z_mismatch " << mag_crossing_z_mismatch << " drift velocity " << vdrift << std::endl;
584  }
585  else
586  {
587  if(Verbosity() > 1)
588  std::cout << " FAILURE: crossing " << crossing << " tpcid " << tpcid << " si id " << si_id
589  << " tpc z " << z_tpc << " si z " << z_si << " z_mismatch " << z_mismatch
590  << " mag_crossing_z_mismatch " << mag_crossing_z_mismatch << std::endl;
591 
592  bad_map.insert(std::make_pair(tpcid, si_id));
593  }
594  }
595 
596  // remove bad entries from tpc_matches
597  for(auto [tpcid, si_id] : bad_map)
598  {
599  // Have to iterate over tpc_matches and examine each pair to find the one matching bad_map
600  // this logic works because we call the equal range on vertex_map for every id_pair
601  // so we only delete one entry per equal range call
602  auto ret = tpc_matches.equal_range(tpcid);
603  for(auto it = ret.first; it != ret.second; ++it)
604  {
605  if(it->first == tpcid && it->second == si_id)
606  {
607  if(Verbosity() > 1)
608  std::cout << " erasing tpc_matches entry for tpcid " << tpcid << " si_id " << si_id << std::endl;
609  tpc_matches.erase(it);
610  break; // the iterator is no longer valid
611  }
612  }
613  }
614 
615  return;
616 }
617 
618 
619 /*
620  {
621  // This section is to correct the TPC z positions of tracks for all bunch crossings without relying on INTT time
622  //==================================================================================
623 
624  // All tracks treated as if we do not know the bunch crossing
625  // The crossing estimate here is crude, for now
626  tagMatchCrossing(tpc_matches, crossing_set, crossing_matches, tpc_crossing_map);
627 
628  // Sort candidates by the silicon tracklet Z position by putting them in si_sorted map
629  // -- captures crossing, tpc_id and si_id
630  std::multimap<double, std::pair<unsigned int, unsigned int>> si_sorted_map;
631  for( auto ncross : crossing_set)
632  {
633  if(Verbosity() > 1) std::cout << " ncross = " << ncross << std::endl;
634 
635  auto ret = crossing_matches. equal_range(ncross);
636  for(auto it = ret.first; it != ret.second; ++it)
637  {
638  if(Verbosity() > 1)
639  std::cout << " crossing " << it->first << " tpc_id " << it->second.first << " si_id " << it->second.second
640  << " pT " << _track_map->get(it->second.first)->get_pt()
641  << " eta " << _track_map->get(it->second.first)->get_eta()
642  << " tpc_z " << _track_map->get(it->second.first)->get_z()
643  << " si_z " << _track_map_silicon->get(it->second.second)->get_z()
644  << std::endl;
645 
646  double z_si = _track_map_silicon->get(it->second.second)->get_z();
647  si_sorted_map.insert(std::make_pair(z_si, std::make_pair(it->second.first, it->second.second)));
648  }
649  }
650 
651 
652  // make a list of silicon vertices, and a multimap with all associated tpc/si pairs
653  std::multimap<unsigned int, std::pair<unsigned int, unsigned int>> vertex_map;
654  std::vector<double> vertex_list;
655  getSiVertexList(si_sorted_map, vertex_list, vertex_map);
656 
657  // find the crossing number for every track from the mismatch with the associated silicon vertex z position
658  std::map<unsigned int, short int> vertex_crossings_map;
659  getCrossingNumber(vertex_list, vertex_map, vertex_crossings_map);
660 
661  // Remove tracks from vertex_map where the vertex crossing is badly inconsistent with the initial crossing estimate
662  cleanVertexMap( vertex_crossings_map, vertex_map, tpc_crossing_map );
663 
664  // add silicon clusters to the surviving tracks
665  addSiliconClusters(vertex_map);
666 
667  // add the crossing to the combined track
668  addTrackBunchCrossing(vertex_crossings_map, vertex_map);
669 
670  //===================================================
671  }
672 */
673 
674 /*
675 void PHSiliconTpcTrackMatching::addTrackBunchCrossing(
676  std::map<unsigned int, short int> &vertex_crossings_map,
677  std::multimap<unsigned int, std::pair<unsigned int, unsigned int>> &vertex_map)
678 {
679 
680  for(auto [ivert, crossing] : vertex_crossings_map)
681  {
682  if(Verbosity() > 1)
683  std::cout << " ivert " << ivert << " crossing " << crossing << std::endl;
684 
685  // loop over all tracks associated with this vertex
686  // remember that any tracks not associated with one of the vertices are unusable
687  auto ret = vertex_map.equal_range(ivert);
688  for(auto it = ret.first; it != ret.second; ++it)
689  {
690  unsigned int tpcid = it->second.first;
691  SvtxTrack *tpc_track = _track_map->get(tpcid);
692  tpc_track->set_crossing(crossing);
693 
694  if(Verbosity() > 1) std::cout << PHWHERE << " Add bunch crossing to track " << tpcid << " crossing " << crossing << std::endl;
695  }
696  }
697  return;
698 }
699 */
700 
701 /*
702 void PHSiliconTpcTrackMatching::getSiVertexList(
703  std::multimap<double, std::pair<unsigned int, unsigned int>> &si_sorted_map,
704  std::vector<double> &vertex_list,
705  std::multimap<unsigned int, std::pair<unsigned int, unsigned int>> &vertex_map)
706 {
707  if(si_sorted_map.size() == 0) return;
708 
709  // process si_sorted_map to get the vertex list, and the average silicon z value for each vertex
710  double zkeep = 999;
711  double zavge = 0.0;
712  double zwt = 0.0;
713  unsigned int nvert = 0;
714  for(auto it = si_sorted_map.begin(); it != si_sorted_map.end(); ++it)
715  {
716  double z_si = it->first;
717  std::pair<unsigned int, unsigned int> id_pair = it->second;
718  if(Verbosity() > 1) std::cout << " z_si " << z_si << " tpc_id " << it->second.first << " si_id " << it->second.second << std::endl;
719 
720  if( (zkeep == 999) || (fabs(z_si - zkeep) < _si_vertex_dzmax) )
721  {
722  vertex_map.insert(std::make_pair(nvert, id_pair));
723  zavge+= z_si;
724  zwt++;
725  zkeep = z_si;
726  }
727  else
728  {
729  zavge /= zwt;
730  vertex_list.push_back(zavge);
731 
732  // start a new vertex
733  nvert++;
734  zavge = z_si;
735  zwt = 1.0;
736  zkeep = z_si;
737  vertex_map.insert(std::make_pair(nvert, id_pair));
738  }
739  }
740  // get the last one
741  zavge /= zwt;
742  vertex_list.push_back(zavge);
743 
744  return;
745 }
746 */
747 
748 /*
749 // Used for non-INTT matching
750 void PHSiliconTpcTrackMatching::addSiliconClusters( std::multimap<unsigned int, std::pair<unsigned int, unsigned int>> &vertex_map)
751 {
752 
753  for(auto it = vertex_map.begin(); it != vertex_map.end(); ++it)
754  {
755  unsigned int tpcid = it->second.first;
756  SvtxTrack *tpc_track = _track_map->get(tpcid);
757  if(Verbosity() > 1) std::cout << " tpcid " << tpcid << " original z " << tpc_track->get_z() << std::endl;
758 
759  // add the silicon cluster keys to the track
760  unsigned int si_id = it->second.second;
761  SvtxTrack *si_track = _track_map_silicon->get(si_id);
762  if(Verbosity() > 1) std::cout << " si track id " << si_id << std::endl;
763  for (SvtxTrack::ConstClusterKeyIter si_iter = si_track->begin_cluster_keys();
764  si_iter != si_track->end_cluster_keys();
765  ++si_iter)
766  {
767  TrkrDefs::cluskey si_cluster_key = *si_iter;
768 
769  if(Verbosity() > 1)
770  cout << " inserting si cluster key " << si_cluster_key << " into existing TPC track " << tpc_track->get_id() << endl;
771 
772  tpc_track->insert_cluster_key(si_cluster_key);
773 
774  }
775 
776  // update the track position to the si one
777  tpc_track->set_x(si_track->get_x());
778  tpc_track->set_y(si_track->get_y());
779  tpc_track->set_z(si_track->get_z());
780 
781  if(Verbosity() > 2)
782  {
783  std::cout << " TPC seed track ID " << tpc_track->get_id() << " si track id " << si_track->get_id()
784  << " new nclus " << tpc_track->size_cluster_keys() << std::endl;
785  }
786 
787  if(Verbosity() > 2)
788  tpc_track->identify();
789  }
790 
791  return;
792 }
793 */
794 
795 /*
796 void PHSiliconTpcTrackMatching::cleanVertexMap(
797  std::map<unsigned int, short int> &vertex_crossings_map,
798  std::multimap<unsigned int, std::pair<unsigned int, unsigned int>> &vertex_map,
799  std::map<unsigned int, short int> &tpc_crossing_map )
800 {
801  if(vertex_crossings_map.size() == 0) return;
802 
803  // Sanity check: is the initial rough crossing estimate consistent with the crossing number for this si vertex?
804 
805  std::multimap<unsigned int, std::pair<unsigned int, unsigned int>> bad_map;
806  for(auto [ivert, crossing] : vertex_crossings_map)
807  {
808  if(Verbosity() > 1)
809  std::cout << " CleanVertexMap: ivert " << ivert << " crossing " << crossing << std::endl;
810 
811  // loop over all tracks associated with this vertex
812  // remember that any tracks not associated with one of the vertices are unusable, they are ignored
813  auto ret = vertex_map.equal_range(ivert);
814  for(auto it = ret.first; it != ret.second; ++it)
815  {
816  unsigned int tpcid = it->second.first;
817  unsigned int si_id = it->second.second;
818 
819  // need the initial crossing estimate for comparison - stored in tpc_ crossing_map
820  auto sit = tpc_crossing_map.find(tpcid);
821  if(abs(sit->second - crossing) > 2)
822  {
823  // Fails the sanity check, mark for removal from the vertex map
824  if(Verbosity() > 1)
825  std::cout << " Crossing mismatch: ivert " << ivert << " tpc id " << tpcid << " vert crossing " << crossing << " track crossing " << sit->second << std::endl;
826 
827  bad_map.insert(std::make_pair(ivert, std::make_pair(tpcid, si_id)));
828  }
829  }
830  }
831 
832  // If we delete an entry from vertex map, the TPC track is not associated with a bunch crossing,
833  // -- the cluster z values are not changed, and the silicon clusters are not added.
834  // The track remains in the track map as a TPC-only track, by default assumed to be in bunch crossing zero
835  // If multiple entries are deleted from vertex map, the TPC-only track copies are left in the track map, and also in _seed-track_map
836  // The track cleaner will remove all but one of them, based on chisq from the Acts fitter.
837 
838  // remove bad entries from vertex_map so the wrong silicon is not associated
839  for(auto [ivert, id_pair] : bad_map)
840  {
841  unsigned int tpc_id = id_pair.first;
842  unsigned int si_id = id_pair.second;
843 
844  // Have to iterate over vertex_map and examine each pair to find the one matching bad_map
845  // this logic works because we call the equal range on vertex_map for every id_pair
846  // so we only delete one entry per equal range call
847  auto ret = vertex_map.equal_range(ivert);
848  for(auto it = ret.first; it != ret.second; ++it)
849  {
850  if(it->second.first == tpc_id && it->second.second == si_id)
851  {
852  if(Verbosity() > 1)
853  std::cout << " erasing entry for ivert " << ivert << " tpc_id " << tpc_id << " si_id " << si_id << std::endl;
854  vertex_map.erase(it);
855  break; // the iterator is no longer valid
856  }
857  }
858  }
859 
860  return;
861 }
862 */
863 
864 /*
865 void PHSiliconTpcTrackMatching::getCrossingNumber(
866  std::vector<double> &vertex_list,
867  std::multimap<unsigned int, std::pair<unsigned int, unsigned int>> &vertex_map,
868  std::map<unsigned int, short int> &vertex_crossings_map)
869 {
870  if(vertex_list.size() == 0) return;
871 
872  for(unsigned int ivert = 0; ivert<vertex_list.size(); ++ivert)
873  {
874  std::vector<double> crossing_vec;
875 
876  double vert_z = vertex_list[ivert];
877  if(Verbosity() > 1)
878  std::cout << "Vertex " << ivert << " vertex z " << vert_z << std::endl;
879 
880  auto ret = vertex_map.equal_range(ivert);
881  for(auto it = ret.first; it != ret.second; ++it)
882  {
883  unsigned int tpcid = it->second.first;
884  double tpc_z = _track_map->get(tpcid)->get_z();
885  double z_mismatch = tpc_z - vert_z;
886 
887  double crossings = getBunchCrossing(tpcid, z_mismatch);
888  crossing_vec.push_back(crossings);
889 
890  if(Verbosity() > 1)
891  std::cout << " tpc_id " << tpcid << " tpc pT " << _track_map->get(tpcid)->get_pt()
892  << " tpc eta " << _track_map->get(tpcid)->get_eta() << " si_id " << it->second.second
893  << " tpc z " << tpc_z << " crossings " << crossings << std::endl;
894  }
895 
896  if(crossing_vec.size() == 0) continue;
897  double crossing_median = getMedian(crossing_vec);
898 
899  double crossing_avge = 0.0;
900  double crossing_wt = 0.0;
901  for(auto cross : crossing_vec)
902  {
903  if(fabs(cross-crossing_median) < 1.0)
904  {
905  crossing_avge += cross;
906  crossing_wt++;
907  }
908  }
909  short int crossing = SHRT_MAX;
910  if(crossing_wt != 0)
911  {
912  crossing_avge /= crossing_wt;
913  double crossing_avge_rounded = round(crossing_avge);
914  crossing = (short int) crossing_avge_rounded;
915  }
916  vertex_crossings_map.insert(std::make_pair(ivert, crossing));
917 
918  if(Verbosity() > 1)
919  std::cout << " crossing_median " << crossing_median << " crossing average = " << crossing_avge << " crossing_wt " << crossing_wt
920  << " crossing integer " << crossing << std::endl;
921  }
922  return;
923 }
924 */
925 /*
926 // Used for triggered crossing only
927 void PHSiliconTpcTrackMatching::addSiliconClusters( std::multimap<unsigned int, unsigned int> &tpc_matches )
928 {
929 
930  for(auto it = tpc_matches.begin(); it != tpc_matches.end(); ++it)
931  {
932  unsigned int tpcid = it->first;
933  if(Verbosity() > 1) std::cout << " tpcid " << tpcid << " original z " << _track_map->get(tpcid)->get_z() << std::endl;
934 
935  // add the silicon cluster keys to the track
936  unsigned int si_id = it->second;
937 
938  auto svtxseed = std::make_unique<SvtxTrackSeed_v1>();
939  svtxseed->set_silicon_seed_index(si_id);
940  svtxseed->set_tpc_seed_index(tpcid);
941  _svtx_seed_map->insert(svtxseed.get());
942 
943  if(Verbosity() > 1) std::cout << " si track id " << si_id << std::endl;
944 
945  }
946 
947  return;
948 }
949 */
950 /*
951 // used for INTT matching
952 void PHSiliconTpcTrackMatching::addSiliconClusters( std::multimap<short int, std::pair<unsigned int, unsigned int>> &crossing_matches )
953 {
954 
955  for(auto it = crossing_matches.begin(); it != crossing_matches.end(); ++it)
956  {
957  unsigned int tpcid = it->second.first;
958  if(Verbosity() > 1) std::cout << " tpcid " << tpcid << " original z " << _track_map->get(tpcid)->get_z() << std::endl;
959 
960  // add the silicon cluster keys to the track
961  unsigned int si_id = it->second.second;
962  if(Verbosity() > 1) std::cout << " si track id " << si_id << std::endl;
963 
964  auto seed = std::make_unique<SvtxTrackSeed_v1>();
965  seed->set_silicon_seed_index(si_id);
966  seed->set_tpc_seed_index(tpcid);
967  _svtx_seed_map->insert(seed.get());
968 
969  }
970 
971  return;
972 }
973 */
974 
975 /*
976 void PHSiliconTpcTrackMatching::checkCrossingMatches( std::multimap<short int, std::pair<unsigned int, unsigned int>> &crossing_matches,
977  std::map<unsigned int, short int> &tpc_crossing_map )
978 {
979  bool make_crossing_guess = false;
980 
981  float vdrift = 8.0e-3;
982  // float crossing_period = 106.0;
983 
984  std::multimap<short int, std::pair<unsigned int, unsigned int>> good_map;
985  std::multimap<short int, std::pair<unsigned int, unsigned int>> bad_map;
986 
987  for(auto it = crossing_matches.begin(); it != crossing_matches.end(); ++it)
988  {
989  short int crossing = it->first;
990 
991  unsigned int tpcid = it->second.first;
992  TrackSeed *tpc_track = _track_map->get(tpcid);
993 
994  unsigned int si_id = it->second.second;
995  TrackSeed *si_track = _track_map_silicon->get(si_id);
996 
997  float tpc_eta = tpc_track->get_eta();
998  float si_eta = si_track->get_eta();
999 
1000  float z_si = si_track->get_z();
1001  float z_tpc = tpc_track->get_z();
1002  float z_mismatch = z_tpc-z_si;
1003 
1004  float mag_crossing_z_mismatch = fabs(crossing) * crossing_period * vdrift;
1005 
1006  // We do not know the sign of the z mismatch for a given crossing unless we know the drift direction in the TPC, use mag
1007  // could instead look up any TPC cluster key in the track to get side
1008  // z-mismatch can occasionally be up to 2 crossings due to TPC extrapolation precision
1009  if( fabs( fabs(z_mismatch) - mag_crossing_z_mismatch ) < 3.0)
1010  {
1011  if(Verbosity() > 1)
1012  std::cout << " Success: crossing " << crossing << " tpc_eta " << tpc_eta << " si eta " << si_eta << " tpcid " << tpcid << " si id " << si_id
1013  << " tpc z " << z_tpc << " si z " << z_si << " z_mismatch " << z_mismatch << " mag_crossing_z_mismatch " << mag_crossing_z_mismatch << std::endl;
1014  }
1015  else
1016  {
1017  if(Verbosity() > 1)
1018  std::cout << " FAILURE: crossing " << crossing << " tpc_eta " << tpc_eta << " si eta " << si_eta << " tpcid " << tpcid << " si id " << si_id
1019  << " tpc z " << z_tpc << " si z " << z_si << " z_mismatch " << z_mismatch << " mag_crossing_z_mismatch " << mag_crossing_z_mismatch << std::endl;
1020 
1021  bad_map.insert(std::make_pair(crossing, std::make_pair(tpcid, si_id)));
1022 
1023  if(make_crossing_guess)
1024  {
1025  // substitute a crossing estimate from the z_mismatch
1026  short int crossing_guess = (short int) getBunchCrossing(tpcid, z_mismatch);
1027 
1028  if(Verbosity() > 1) std::cout << " substitute crossing guess " << crossing_guess << " for crossing " << crossing << std::endl;
1029  good_map.insert(std::make_pair(crossing_guess, std::make_pair(tpcid, si_id)));
1030  }
1031  }
1032  }
1033 
1034  // remove bad entries from crossing_matches
1035  for(auto [crossing, id_pair] : bad_map)
1036  {
1037  unsigned int tpcid = id_pair.first;
1038  unsigned int si_id = id_pair.second;
1039 
1040  // Have to iterate over crossing_matches and examine each pair to find the one matching bad_map
1041  // this logic works because we call the equal range on vertex_map for every id_pair
1042  // so we only delete one entry per equal range call
1043  auto ret = crossing_matches.equal_range(crossing);
1044  for(auto it = ret.first; it != ret.second; ++it)
1045  {
1046  if(it->second.first == tpcid && it->second.second == si_id)
1047  {
1048  if(Verbosity() > 0) std::cout << " checkCrossingMatches: erasing tpc_crossing_map entry for crossing " << crossing << " tpcid " << tpcid << std::endl;
1049  tpc_crossing_map.erase(tpcid);
1050 
1051  if(Verbosity() > 1)
1052  std::cout << " erasing crossing_matches entry for crossing " << crossing << " tpcid " << tpcid << " si_id " << si_id << std::endl;
1053  crossing_matches.erase(it);
1054  break; // the iterator is no longer valid
1055  }
1056  }
1057  }
1058 
1059  if(make_crossing_guess)
1060  {
1061  // replace them with crossing guess
1062  for(auto [crossing_guess, id_pair] : good_map)
1063  {
1064  unsigned int tpcid = id_pair.first;
1065  unsigned int si_id = id_pair.second;
1066 
1067  if(Verbosity() > 1)
1068  std::cout << " checkCrossingMatches: adding crossing_matches and tpc_crossing_map entry for crossing_guess " << crossing_guess << " tpcid " << tpcid
1069  << " si_id " << si_id << std::endl;
1070  crossing_matches.insert(std::make_pair(crossing_guess,std::make_pair(tpcid, si_id)));
1071  tpc_crossing_map.insert(std::make_pair(tpcid, crossing_guess));
1072  }
1073  }
1074 
1075  return;
1076 }
1077 */
1078 
1079 /*
1080 // uses INTT time to get bunch crossing
1081 void PHSiliconTpcTrackMatching::getMatchCrossingIntt(
1082  std::multimap<unsigned int, unsigned int> &tpc_matches,
1083  std::multimap<short int, std::pair<unsigned int, unsigned int>> &crossing_matches,
1084  std::map<unsigned int, short int> &tpc_crossing_map )
1085 {
1086  if(Verbosity() > 0) std::cout << " tpc_matches size " << tpc_matches.size() << std::endl;
1087 
1088  for(auto [tpcid, si_id] : tpc_matches)
1089  {
1090  TrackSeed *si_track =_track_map_silicon->get(si_id);
1091 
1092  if(Verbosity() > 0)
1093  std::cout << "TPC track " << tpcid << " si track " << si_id << std::endl;
1094 
1095  // If the Si track contains an INTT hit, use it to get the bunch crossing offset
1096 
1097  std::vector<short int> intt_crossings = getInttCrossings(si_track);
1098 
1099  bool keep_it = true;
1100  short int crossing_keep = 0;
1101  if(intt_crossings.size() == 0)
1102  {
1103  if(Verbosity() > 0) std::cout << " Silicon track " << si_id << " has no INTT clusters, skip this combination " << std::endl;
1104  continue ;
1105  }
1106  else
1107  {
1108  crossing_keep = intt_crossings[0];
1109  for(unsigned int ic=1; ic<intt_crossings.size(); ++ic)
1110  {
1111  if(intt_crossings[ic] != crossing_keep)
1112  {
1113  if(Verbosity() > -1)
1114  {
1115  std::cout << " Warning: INTT crossings not all the same for tpc track " << tpcid << " silicon track " << si_id << " crossing_keep " << crossing_keep << " new crossing " << intt_crossings[ic] << " keep the first one in the list" << std::endl;
1116  }
1117  }
1118  }
1119  }
1120 
1121  if(keep_it)
1122  {
1123  crossing_matches.insert(std::make_pair(crossing_keep,std::make_pair(tpcid, si_id)));
1124  tpc_crossing_map.insert(std::make_pair(tpcid, crossing_keep));
1125 
1126  if(Verbosity() > 0)
1127  std::cout << " tpc track " << tpcid << " si Track " << si_id << " final crossing " << crossing_keep << std::endl;
1128  }
1129  }
1130  return;
1131 }
1132 */
1133 
1134 /*
1135 void PHSiliconTpcTrackMatching::addTrackBunchCrossing( std::map<unsigned int, short int> &tpc_crossing_map)
1136 {
1137  if(tpc_crossing_map.size() == 0) return;
1138 
1139  for(auto [tpcid, crossing] : tpc_crossing_map)
1140  {
1141  if(Verbosity() > 1)
1142  std::cout << PHWHERE << " Add bunch crossing to track " << tpcid << " crossing " << crossing << std::endl;
1143 
1144  TrackSeed *tpc_track = _track_map->get(tpcid);
1145  tpc_track->set_crossing(crossing);
1146  }
1147  return;
1148 }
1149 */
1150 /*
1151 double PHSiliconTpcTrackMatching::getMedian(std::vector<double> &v)
1152 {
1153  if(v.size() == 0) return NAN;
1154 
1155  double median = 0.0;
1156 
1157  if( (v.size() % 2) == 0)
1158  {
1159  // even number of entries
1160  // we want the average of the middle two numbers, v.size()/2 and v.size()/2-1
1161  auto m1 = v.begin() + v.size()/2;
1162  std::nth_element(v.begin(), m1, v.end());
1163  double median1 = v[v.size()/2];
1164 
1165  auto m2 = v.begin() + v.size()/2 - 1;
1166  std::nth_element(v.begin(), m2, v.end());
1167  double median2 = v[v.size()/2 - 1];
1168 
1169  median = (median1 + median2) / 2.0;
1170  if(Verbosity() > 2) std::cout << "The vector size is " << v.size()
1171  << " element m is " << v.size() / 2 << " = " << v[v.size()/2]
1172  << " element m-1 is " << v.size() / 2 -1 << " = " << v[v.size()/2-1]
1173  << std::endl;
1174  }
1175  else
1176  {
1177  // odd number of entries
1178  auto m = v.begin() + v.size()/2;
1179  std::nth_element(v.begin(), m, v.end());
1180  median = v[v.size()/2];
1181  if(Verbosity() > 2) std::cout << "The vector size is " << v.size() << " element m is " << v.size() / 2 << " = " << v[v.size()/2] << std::endl;
1182  }
1183 
1184  return median ;
1185 }
1186 */
1187 
1188 
1189 
1190 /*
1191 void PHSiliconTpcTrackMatching::tagInTimeTracks(
1192  std::multimap<unsigned int, unsigned int> &tpc_matches,
1193  std::multimap<int, std::pair<unsigned int, unsigned int>> &crossing_matches,
1194  std::map<unsigned int, int> &tpc_crossing_map )
1195 {
1196 
1197  for(auto [tpcid, si_id] : tpc_matches)
1198  {
1199  TrackSeed *tpc_track = _track_map->get(tpcid);
1200  double tpc_z = tpc_track->get_z();
1201  double tpc_pt = tpc_track->get_pt();
1202 
1203  TrackSeed *si_track =_track_map_silicon->get(si_id);
1204  double si_z = si_track->get_z();
1205 
1206  // this factor will increase the window size at low pT
1207  // otherwise the matching efficiency drops off at low pT
1208  // it would be better if this was a smooth function
1209  double mag = 1.0;
1210  if(tpc_pt < 6.0) mag = 2;
1211  if(tpc_pt < 3.0) mag = 4.0;
1212 
1213  // Check for a match in z
1214  if(fabs(tpc_z - si_z) < _z_search_win * mag)
1215  {
1216  //track from triggered event
1217  int crossing = 0;
1218  crossing_matches.insert(std::make_pair(crossing,std::make_pair(tpcid, si_id)));
1219  tpc_crossing_map.insert(std::make_pair(tpcid, crossing));
1220  if(Verbosity() > 1)
1221  std::cout << " triggered: tpc_trackid " << tpcid
1222  << " eta " << tpc_track->get_eta()
1223  << " pT " << tpc_track->get_pt()
1224  << " si_trackid " << si_id
1225  << " z_tpc " << tpc_track->get_z()
1226  << " z_si " << si_track->get_z()
1227  << " crossing " << crossing
1228  << std::endl;
1229  }
1230  }
1231  return;
1232 }
1233 
1234 void PHSiliconTpcTrackMatching::tagMatchCrossing(
1235  std::multimap<unsigned int, unsigned int> &tpc_matches,
1236  std::multimap<short int, std::pair<unsigned int, unsigned int>> &crossing_matches,
1237  std::map<unsigned int, short int> &tpc_crossing_map )
1238 {
1239 
1240  for(auto [tpcid, si_id] : tpc_matches)
1241  {
1242  TrackSeed *tpc_track = _track_map->get(tpcid);
1243  double tpc_z = tpc_track->get_z();
1244 
1245  TrackSeed *si_track =_track_map_silicon->get(si_id);
1246  double si_z = si_track->get_z();
1247 
1248  // this is an initial estimate of the bunch crossing based on the z-mismatch for this track
1249  short int crossing = (short int) getBunchCrossing(tpcid, tpc_z - si_z);
1250  crossing_matches.insert(std::make_pair(crossing,std::make_pair(tpcid, si_id)));
1251  tpc_crossing_map.insert(std::make_pair(tpcid, crossing));
1252  if(Verbosity() > 1)
1253  std::cout << " pileup: tpc_trackid " << tpcid
1254  << " eta " << tpc_track->get_eta()
1255  << " pT " << tpc_track->get_pt()
1256  << " si_trackid " << si_id
1257  << " z_tpc " << tpc_track->get_z()
1258  << " z_si " << si_track->get_z()
1259  << " crossing " << crossing
1260  << std::endl;
1261  }
1262 
1263 return;
1264 }
1265 
1266 // This is for non-pp mode, i.e. straight geometric matching including a z cut
1267 void PHSiliconTpcTrackMatching::addTrackBunchCrossing(std::multimap<unsigned int, unsigned int> &tpc_matches)
1268 {
1269  if(tpc_matches.size() == 0) return;
1270 
1271  for(auto [tpcid, si_id] : tpc_matches)
1272  {
1273  short int crossing = 0;
1274 
1275  TrackSeed *tpc_track = _track_map->get(tpcid);
1276  TrackSeed *si_track = _track_map_silicon->get(si_id);
1277  if(!tpc_track)
1278  {
1279  std::cout << PHWHERE << "Did not find track " << tpcid << std::endl;
1280  continue;
1281  }
1282 
1283  if(Verbosity() > 1)
1284  std::cout << PHWHERE << " Add bunch crossing to track " << tpcid << " crossing " << crossing << std::endl;
1285 
1286  si_track->set_crossing(crossing);
1287  tpc_track->set_crossing(crossing);
1288  }
1289 
1290  return;
1291 }
1292 */