EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sPHENIXTracker.h
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file sPHENIXTracker.h
1 #ifndef SPHENIX_SPHENIXTRACKER_H
2 #define SPHENIX_SPHENIXTRACKER_H
3 
4 #include "HelixHough.h"
5 #include "HelixKalmanState.h"
6 #include "HelixRange.h"
7 #include "SimpleHit3D.h"
8 #include "Seamstress.h"
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <map>
13 #include <memory>
14 #include <set>
15 #include <vector>
16 
17 class CylinderKalman;
18 class HelixResolution;
19 class SimpleTrack3D;
20 
21 namespace SeamStress { template <class TClass> class Pincushion; }
22 
23 class AngleIndexPair {
24  public:
25  AngleIndexPair(float ang, unsigned int idx) : angle(ang), index(idx) {
26  float twopi = 2. * M_PI;
27  int a = (int)(angle / twopi);
28  angle -= a * twopi;
29  while (angle < 0.) {
30  angle += twopi;
31  }
32  while (angle >= twopi) {
33  angle -= twopi;
34  }
35  }
37 
38  bool operator<(const AngleIndexPair& other) const {
39  return angle < other.angle;
40  }
41 
42  static float absDiff(float angle1, float angle2) {
43  float diff = (angle1 - angle2);
44  while (diff > M_PI) {
45  diff -= 2. * M_PI;
46  }
47  while (diff < -M_PI) {
48  diff += 2. * M_PI;
49  }
50  diff = fabs(diff);
51  return diff;
52  }
53 
54  float angle;
55  unsigned int index;
56 };
57 
58 class AngleIndexList {
59  public:
62 
63  void addPair(AngleIndexPair& angind) {
64  sorted = false;
65  vec.push_back(angind);
66  }
67 
68  void getRangeListSimple(float angle, float error,
69  std::vector<AngleIndexPair*>& result) {
70  result.clear();
71 
72  for (unsigned int i = 0; i < vec.size(); i++) {
73  if (AngleIndexPair::absDiff(angle, vec[i].angle) <= error) {
74  result.push_back(&(vec[i]));
75  }
76  }
77  }
78 
79  void getRangeList(float angle, float error,
80  std::vector<AngleIndexPair*>& result) {
81  float twopi = 2. * M_PI;
82  int a = (int)(angle / twopi);
83  angle -= a * twopi;
84  while (angle < 0.) {
85  angle += twopi;
86  }
87  while (angle >= twopi) {
88  angle -= twopi;
89  }
90 
91  if (vec.size() <= 4) {
92  return getRangeListSimple(angle, error, result);
93  }
94 
95  result.clear();
96 
97  unsigned int closest = findClosest(angle);
98  // first, traverse upward
99  unsigned int current = closest;
100  unsigned int lowest = 0;
101  unsigned int highest = vec.size() - 1;
102  while (true) {
103  if (AngleIndexPair::absDiff(angle, vec[current].angle) <= error) {
104  result.push_back(&(vec[current]));
105  current = (current + 1) % (vec.size());
106  if (current == closest) {
107  return;
108  }
109  } else {
110  break;
111  }
112  }
113 
114  // now, traverse downward
115  if (current <= closest) {
116  lowest = current;
117  } else {
118  highest = current;
119  }
120  current = ((closest + vec.size()) - 1) % (vec.size());
121  while (true) {
122  if ((current == lowest) || (current == highest)) {
123  break;
124  }
125  if (AngleIndexPair::absDiff(angle, vec[current].angle) <= error) {
126  result.push_back(&(vec[current]));
127  current = ((current + vec.size()) - 1) % (vec.size());
128  } else {
129  break;
130  }
131  }
132  }
133 
134  unsigned int findClosestSimple(float angle, unsigned int lower,
135  unsigned int upper) {
136  unsigned int closest = lower;
137  float diff = AngleIndexPair::absDiff(vec[closest].angle, angle);
138  for (unsigned int i = (lower + 1); i <= upper; i++) {
139  float tempdiff = AngleIndexPair::absDiff(vec[i].angle, angle);
140  if (tempdiff < diff) {
141  closest = i;
142  diff = tempdiff;
143  }
144  }
145 
146  return closest;
147  }
148 
149  unsigned int findClosest(float angle) {
150  if (vec.size() <= 4) {
151  return findClosestSimple(angle, 0, vec.size() - 1);
152  }
153 
154  if (sorted == false) {
155  std::sort(vec.begin(), vec.end());
156  sorted = true;
157  }
158 
159  unsigned int lower = 0;
160  unsigned int upper = vec.size() - 1;
161  unsigned int middle = vec.size() / 2;
162  while (true) {
163  if ((upper - lower) <= 4) {
164  return findClosestSimple(angle, lower, upper);
165  }
166 
167  if (angle <= vec[middle].angle) {
168  upper = middle;
169  middle = (lower + upper) / 2;
170  } else {
171  lower = middle;
172  middle = (lower + upper) / 2;
173  }
174  }
175  }
176 
177  std::vector<AngleIndexPair> vec;
178  bool sorted;
179 };
180 
181 class TrackSegment {
182  public:
184  : chi2(0.), ux(0.), uy(0.), kappa(0.), dkappa(0.), seed(0), n_hits(0) {}
186 
187  float chi2;
188  float ux, uy;
189  float kappa;
190  float dkappa;
191  std::vector<unsigned int> hits;
192  unsigned int seed;
193  unsigned int bin;
194  unsigned int n_hits;
195 };
196 
197 class sPHENIXTracker : public HelixHough {
198  public:
199  sPHENIXTracker(unsigned int n_phi, unsigned int n_d, unsigned int n_k,
200  unsigned int n_dzdl, unsigned int n_z0,
201  HelixResolution& min_resolution,
202  HelixResolution& max_resolution, HelixRange& range,
203  std::vector<float>& material, std::vector<float>& radius,
204  float Bfield);
205  sPHENIXTracker(std::vector<std::vector<unsigned int> >& zoom_profile,
206  unsigned int minzoom, HelixRange& range,
207  std::vector<float>& material, std::vector<float>& radius,
208  float Bfield, bool parallel = false,
209  unsigned int num_threads = 1);
210  virtual ~sPHENIXTracker();
211 
212  void finalize(std::vector<SimpleTrack3D>& input,
213  std::vector<SimpleTrack3D>& output);
214 
215  void findTracks(std::vector<SimpleHit3D>& hits,
216  std::vector<SimpleTrack3D>& tracks,
217  const HelixRange& range);
218 
219  void findTracksBySegments(std::vector<SimpleHit3D>& hits,
220  std::vector<SimpleTrack3D>& tracks,
221  const HelixRange& range);
222 
223  void initEvent(std::vector<SimpleHit3D>& hits, unsigned int /*min_hits*/) {
224  int min_layer = 999999;
225  int max_layer = 0;
226  for (unsigned int i = 0; i < hits.size(); ++i) {
227  if (hits[i].get_layer() < min_layer) {
228  min_layer = hits[i].get_layer();
229  }
230  if (hits[i].get_layer() > max_layer) {
231  max_layer = hits[i].get_layer();
232  }
233  }
234  setSeedLayer(min_layer);
235  setNLayers(max_layer + 1);
236 
237  nfits = 0;
238  combos.clear();
239  fail_combos.clear();
240  pass_combos.clear();
241  seeding = false;
242  // required_layers = min_hits;
244  findtracksiter = 0;
245  CAtime = 0.;
246  KALtime = 0.;
247  findtracks_bin = 0;
248  }
249 
250  void initSeeding(std::vector<SimpleTrack3D>& seeds) {
251  seeding = true;
252  seed_used.clear();
253  seed_used.assign(seeds.size(), false);
254  AngleIndexList templist;
255  angle_list.clear();
256  angle_list.assign(n_layers, templist);
257  }
258 
259  void clear() {
260  track_states.clear();
261  isolation_variable.clear();
262  }
263 
264  void findHelicesParallel(std::vector<SimpleHit3D>& hits,
265  unsigned int min_hits, unsigned int max_hits,
266  std::vector<SimpleTrack3D>& tracks);
267  void findHelicesParallelOneHelicity(std::vector<SimpleHit3D>& hits,
268  unsigned int min_hits,
269  unsigned int max_hits,
270  std::vector<SimpleTrack3D>& tracks);
271 
272  float dcaToVertexXY(SimpleTrack3D& track, float vx, float vy);
273 
274  bool breakRecursion(const std::vector<SimpleHit3D>& hits,
275  const HelixRange& range);
276 
277  float phiError(SimpleHit3D& hit, float min_k, float max_k, float min_d,
278  float max_d, float min_z0, float max_z0, float min_dzdl,
279  float max_dzdl, bool pairvoting = false);
280  float dzdlError(SimpleHit3D& hit, float min_k, float max_k, float min_d,
281  float max_d, float min_z0, float max_z0, float min_dzdl,
282  float max_dzdl, bool pairvoting = false);
283 
284  static float fitTrack(SimpleTrack3D& track);
285  static float fitTrack(SimpleTrack3D& track, std::vector<float>& chi2_hit);
286 
287  void setVerbosity(int v) { verbosity = v; }
288 
289  void setCutOnDca(bool dcut) { cut_on_dca = dcut; }
290  void setDcaCut(float dcut) { dca_cut = dcut; }
291  void setVertex(float vx, float vy, float vz) {
292  vertex_x = vx;
293  vertex_y = vy;
294  vertex_z = vz;
295  }
296 
297  void setRejectGhosts(bool rg) { reject_ghosts = rg; }
298 
299  std::vector<float>& getIsolation() { return isolation_variable; }
300 
301  static void calculateKappaTangents(
302  float* x1_a, float* y1_a, float* z1_a, float* x2_a, float* y2_a,
303  float* z2_a, float* x3_a, float* y3_a, float* z3_a, float* dx1_a,
304  float* dy1_a, float* dz1_a, float* dx2_a, float* dy2_a, float* dz2_a,
305  float* dx3_a, float* dy3_a, float* dz3_a, float* kappa_a, float* dkappa_a,
306  float* ux_mid_a, float* uy_mid_a, float* ux_end_a, float* uy_end_a,
307  float* dzdl_1_a, float* dzdl_2_a, float* ddzdl_1_a, float* ddzdl_2_a);
309  float* x1_a, float* y1_a, float* z1_a, float* x2_a, float* y2_a,
310  float* z2_a, float* x3_a, float* y3_a, float* z3_a, float* dx1_a,
311  float* dy1_a, float* dz1_a, float* dx2_a, float* dy2_a, float* dz2_a,
312  float* dx3_a, float* dy3_a, float* dz3_a, float* kappa_a, float* dkappa_a,
313  float* ux_mid_a, float* uy_mid_a, float* ux_end_a, float* uy_end_a,
314  float* dzdl_1_a, float* dzdl_2_a, float* ddzdl_1_a, float* ddzdl_2_a,
315  float sinang_cut, float cosang_diff_inv, float* cur_kappa_a,
316  float* cur_dkappa_a, float* cur_ux_a, float* cur_uy_a, float* cur_chi2_a,
317  float* chi2_a);
318  void projectToLayer(SimpleTrack3D& seed, unsigned int layer, float& x,
319  float& y, float& z);
320 
321  void setRangeFromSeed(HelixRange& range, SimpleTrack3D& seed);
322 
323  void pairRejection(std::vector<SimpleTrack3D>& input,
324  std::vector<SimpleTrack3D>& output,
325  std::vector<bool>& usetrack,
326  std::vector<float>& next_best_chi2);
327  void tripletRejection(std::vector<SimpleTrack3D>& input,
328  std::vector<SimpleTrack3D>& output,
329  std::vector<bool>& usetrack,
330  std::vector<float>& next_best_chi2);
331 
332  bool seedWasUsed(unsigned int seed_index) { return seed_used.at(seed_index); }
333 
334  void setSeparateByHelicity(bool sbh) {
335  separate_by_helicity = sbh;
336  if (is_parallel == true) {
337  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
338  thread_trackers[i]->setSeparateByHelicity(sbh);
339  }
340  }
341  }
342 
343  void requireLayers(unsigned int nl) {
344  check_layers = true;
345  req_layers = nl;
346  if (is_parallel == true) {
347  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
348  thread_trackers[i]->requireLayers(nl);
349  }
350  }
351  }
352 
353  virtual void setMaxHitsPairs(unsigned int mhp) {
354  max_hits_pairs = mhp;
355  if (is_parallel == true) {
356  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
357  thread_trackers[i]->setMaxHitsPairs(mhp);
358  }
359  }
360  }
361 
362  void setBinScale(float b_scl) {
363  bin_scale = b_scl;
364  if (is_parallel == true) {
365  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
366  thread_trackers[i]->setBinScale(b_scl);
367  }
368  }
369  }
370  void setZBinScale(float b_scl) {
371  z_bin_scale = b_scl;
372  if (is_parallel == true) {
373  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
374  thread_trackers[i]->setZBinScale(b_scl);
375  }
376  }
377  }
378  void setRemoveHits(bool rh) {
379  remove_hits = rh;
380  if (is_parallel == true) {
381  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
382  thread_trackers[i]->setRemoveHits(rh);
383  }
384  }
385  }
386 
387  void setSeedLayer(int sl) {
388  seed_layer = sl;
389  if (is_parallel == true) {
390  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
391  thread_trackers[i]->setSeedLayer(sl);
392  }
393  }
394  }
395 
396  void setNLayers(unsigned int n) {
397  n_layers = n;
398  std::vector<SimpleHit3D> one_layer;
399  layer_sorted.clear();
400  layer_sorted.assign(n_layers, one_layer);
401  temp_comb.assign(n_layers, 0);
402  if (is_parallel == true) {
403  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
404  thread_trackers[i]->setNLayers(n);
405  }
406  }
407  }
408 
409  void setFastChi2Cut(float par0, float par1, float max) {
410  fast_chi2_cut_par0 = par0;
411  fast_chi2_cut_par1 = par1;
413  if (is_parallel == true) {
414  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
415  thread_trackers[i]->setFastChi2Cut(par0, par1, max);
416  }
417  }
418  }
419  void setChi2Cut(float c) {
420  chi2_cut = c;
421  if (is_parallel == true) {
422  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
423  thread_trackers[i]->setChi2Cut(c);
424  }
425  }
426  }
427  void setChi2RemovalCut(float c) {
429  if (is_parallel == true) {
430  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
431  thread_trackers[i]->setChi2RemovalCut(c);
432  }
433  }
434  }
435 
436  void setNRemovalHits(unsigned int n) {
437  n_removal_hits = n;
438  if (is_parallel == true) {
439  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
440  thread_trackers[i]->setNRemovalHits(n);
441  }
442  }
443  }
444 
445  void setCosAngleCut(float cut) {
446  cosang_cut = cut;
447  if (is_parallel == true) {
448  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
449  thread_trackers[i]->setCosAngleCut(cut);
450  }
451  }
452  }
453 
454  void setCellularAutomatonChi2Cut(float cut) {
455  ca_chi2_cut = cut;
456  if (is_parallel == true) {
457  for (unsigned int i = 0; i < thread_trackers.size(); ++i) {
458  thread_trackers[i]->setCellularAutomatonChi2Cut(cut);
459  }
460  }
461  }
462 
463  void setThread() { is_thread = true; }
464 
465  void initSplitting(std::vector<SimpleHit3D>& hits, unsigned int min_hits,
466  unsigned int max_hits);
467 
468  void setHitErrorScale(unsigned int layer, float scale) {
469  if (layer >= hit_error_scale.size()) {
470  hit_error_scale.resize(layer + 1, 1.);
471  }
472  hit_error_scale[layer] = scale;
473  }
474 
475  private:
476  float kappaToPt(float kappa);
477  float ptToKappa(float pt);
478 
479  void findHelicesParallelThread(void* arg);
480  void splitHitsParallelThread(void* arg);
481 
482  void initDummyHits(std::vector<SimpleHit3D>& dummies, const HelixRange& range,
483  HelixKalmanState& init_state);
484 
488  float chi2_cut;
490  unsigned int n_removal_hits;
491  std::set<std::vector<unsigned int> > combos;
492  std::map<std::vector<unsigned int>, HelixKalmanState> pass_combos;
493  std::set<std::vector<unsigned int> > fail_combos;
494  std::vector<float> detector_scatter;
495  std::vector<float> integrated_scatter;
496  std::vector<float> detector_radii;
497  bool seeding;
500  float dca_cut;
502  unsigned int required_layers;
504  unsigned int nfits;
505 
507 
508  std::vector<float> isolation_variable;
509 
510  unsigned int findtracksiter;
511 
512  float prev_max_k;
514  float prev_p_inv;
515 
517 
518  std::vector<TrackSegment> segments1;
519  std::vector<TrackSegment> segments2;
520 
521  std::vector<std::vector<SimpleHit3D> > layer_sorted;
522  std::vector<unsigned int> temp_comb;
523 
525 
526  std::vector<bool> seed_used;
527 
528  unsigned int nthreads;
529  std::vector<SeamStress::Seamstress*> *vssp;
530  std::vector<SeamStress::Seamstress> vss;
532  std::vector<sPHENIXTracker*> thread_trackers;
533  std::vector<std::vector<SimpleTrack3D> > thread_tracks;
534  std::vector<HelixRange> thread_ranges;
535  std::vector<std::vector<SimpleHit3D> > thread_hits;
536  std::vector<std::vector<SimpleHit3D> > split_input_hits;
537  std::vector<std::vector<std::vector<SimpleHit3D> >* > split_output_hits;
538  std::vector<std::vector<HelixRange>* > split_ranges;
540  unsigned int thread_min_hits;
541  unsigned int thread_max_hits;
542  bool is_thread;
543 
544  std::vector<AngleIndexList> angle_list;
545 
546  double CAtime;
547  double KALtime;
548 
549  std::vector<std::vector<SimpleHit3D> > layer_sorted_1[4];
550  unsigned int findtracks_bin;
551 
552  float ca_chi2_cut;
553  float cosang_cut;
554 
555  std::vector<float> hit_error_scale;
556 };
557 
558 
559 #endif