CMS 3D CMS Logo

MkStdSeqs.cc
Go to the documentation of this file.
3 
8 
10 
11 #include "oneapi/tbb/parallel_for.h"
12 
13 namespace mkfit {
14 
15  namespace StdSeq {
16 
17  //=========================================================================
18  // Hit processing
19  //=========================================================================
20 
21  void loadDeads(EventOfHits &eoh, const std::vector<DeadVec> &deadvectors) {
22  for (size_t il = 0; il < deadvectors.size(); il++) {
23  eoh.suckInDeads(int(il), deadvectors[il]);
24  }
25  }
26 
27  // Loading hits in CMSSW from two "large multi-layer vectors".
28  // orig_hitvectors[0] - pixels,
29  // orig_hitvectors[1] - strips.
30 
31  void cmssw_LoadHits_Begin(EventOfHits &eoh, const std::vector<const HitVec *> &orig_hitvectors) {
32  eoh.reset();
33  for (int i = 0; i < eoh.nLayers(); ++i) {
34  auto &&l = eoh[i];
35  l.beginRegistrationOfHits(*orig_hitvectors[l.is_pixel() ? 0 : 1]);
36  }
37  }
38 
39  // Loop with LayerOfHits::registerHit(int idx) - it takes Hit out of original HitVec to
40  // extract phi, r/z, and calculate qphifines
41  //
42  // Something like what is done in MkFitInputConverter::convertHits
43  //
44  // Problem is I don't know layers for each large-vector;
45  // Also, layer is calculated for each detset when looping over the HitCollection
46 
48  for (int i = 0; i < eoh.nLayers(); ++i) {
49  auto &&l = eoh[i];
50  l.endRegistrationOfHits(false);
51  }
52  }
53 
54  //=========================================================================
55  // Hit-index mapping / remapping
56  //=========================================================================
57 
59  for (auto &&track : seeds) {
60  for (int i = 0; i < track.nTotalHits(); ++i) {
61  const int hitidx = track.getHitIdx(i);
62  const int hitlyr = track.getHitLyr(i);
63  if (hitidx >= 0) {
64  const auto &loh = eoh[hitlyr];
65  track.setHitIdx(i, loh.getHitIndexFromOriginal(hitidx));
66  }
67  }
68  }
69  }
70 
71  void cmssw_ReMap_TrackHitIndices(const EventOfHits &eoh, TrackVec &out_tracks) {
72  for (auto &&track : out_tracks) {
73  for (int i = 0; i < track.nTotalHits(); ++i) {
74  const int hitidx = track.getHitIdx(i);
75  const int hitlyr = track.getHitLyr(i);
76  if (hitidx >= 0) {
77  const auto &loh = eoh[hitlyr];
78  track.setHitIdx(i, loh.getOriginalHitIndex(hitidx));
79  }
80  }
81  }
82  }
83 
84  //=========================================================================
85  // Seed cleaning (multi-iter)
86  //=========================================================================
87  int clean_cms_seedtracks_iter(TrackVec &seeds, const IterationConfig &itrcfg, const BeamSpot &bspot) {
89 
90  const float etamax_brl = Config::c_etamax_brl;
91  const float dpt_common = Config::c_dpt_common;
92 
93  const float dzmax_bh = itrcfg.sc_dzmax_bh;
94  const float drmax_bh = itrcfg.sc_drmax_bh;
95  const float dzmax_eh = itrcfg.sc_dzmax_eh;
96  const float drmax_eh = itrcfg.sc_drmax_eh;
97  const float dzmax_bl = itrcfg.sc_dzmax_bl;
98  const float drmax_bl = itrcfg.sc_drmax_bl;
99  const float dzmax_el = itrcfg.sc_dzmax_el;
100  const float drmax_el = itrcfg.sc_drmax_el;
101 
102  const float ptmin_hpt = itrcfg.sc_ptthr_hpt;
103 
104  const float dzmax2_inv_bh = 1.f / (dzmax_bh * dzmax_bh);
105  const float drmax2_inv_bh = 1.f / (drmax_bh * drmax_bh);
106  const float dzmax2_inv_eh = 1.f / (dzmax_eh * dzmax_eh);
107  const float drmax2_inv_eh = 1.f / (drmax_eh * drmax_eh);
108  const float dzmax2_inv_bl = 1.f / (dzmax_bl * dzmax_bl);
109  const float drmax2_inv_bl = 1.f / (drmax_bl * drmax_bl);
110  const float dzmax2_inv_el = 1.f / (dzmax_el * dzmax_el);
111  const float drmax2_inv_el = 1.f / (drmax_el * drmax_el);
112 
113  // Merge hits from overlapping seeds?
114  // For now always true, we require extra hits after seed,
115  // except for lowPtQuadStep, where we only merge hits for seeds at low pT and large pseudo-rapidity
116  const bool merge_hits = true; // itrcfg.merge_seed_hits_during_cleaning();
117  const float ptmax_merge_lowPtQuad = 0.2;
118  const float etamin_merge_lowPtQuad = 1.5;
119 
120  if (seeds.empty())
121  return 0;
122 
123  const int ns = seeds.size();
124 #ifdef DEBUG
125  std::cout << "before seed cleaning " << seeds.size() << std::endl;
126 #endif
127  TrackVec cleanSeedTracks;
128  cleanSeedTracks.reserve(ns);
129  std::vector<bool> writetrack(ns, true);
130 
131  const float invR1GeV = 1.f / Config::track1GeVradius;
132 
133  std::vector<int> nHits(ns);
134  std::vector<int> charge(ns);
135  std::vector<float> oldPhi(ns);
136  std::vector<float> pos2(ns);
137  std::vector<float> eta(ns);
138  std::vector<float> ctheta(ns);
139  std::vector<float> invptq(ns);
140  std::vector<float> pt(ns);
141  std::vector<float> x(ns);
142  std::vector<float> y(ns);
143  std::vector<float> z(ns);
144  std::vector<float> d0(ns);
145  int i1, i2; //for the sorting
146 
148  axis<float, unsigned short, 8, 8> ax_eta(-3.0, 3.0, 30u);
150 
151  phi_eta_binnor.begin_registration(ns);
152 
153  for (int ts = 0; ts < ns; ts++) {
154  const Track &tk = seeds[ts];
155  nHits[ts] = tk.nFoundHits();
156  charge[ts] = tk.charge();
157  oldPhi[ts] = tk.momPhi();
158  pos2[ts] = std::pow(tk.x(), 2) + std::pow(tk.y(), 2);
159  eta[ts] = tk.momEta();
160  ctheta[ts] = 1.f / std::tan(tk.theta());
161  invptq[ts] = tk.charge() * tk.invpT();
162  pt[ts] = tk.pT();
163  x[ts] = tk.x();
164  y[ts] = tk.y();
165  z[ts] = tk.z();
166  d0[ts] = tk.d0BeamSpot(bspot.x, bspot.y);
167 
168  phi_eta_binnor.register_entry_safe(oldPhi[ts], eta[ts]);
169  // If one is sure values are *within* axis ranges: b.register_entry(oldPhi[ts], eta[ts]);
170  }
171 
172  phi_eta_binnor.finalize_registration();
173 
174  for (int sorted_ts = 0; sorted_ts < ns; sorted_ts++) {
175  int ts = phi_eta_binnor.m_ranks[sorted_ts];
176 
177  if (not writetrack[ts])
178  continue; // Note: this speed up prevents transitive masking (possibly marginal gain).
179 
180  const float oldPhi1 = oldPhi[ts];
181  const float pos2_first = pos2[ts];
182  const float eta1 = eta[ts];
183  const float pt1 = pt[ts];
184  const float invptq_first = invptq[ts];
185 
186  // To study some more details -- need EventOfHits for this
187  int n_ovlp_hits_added = 0;
188 
189  auto phi_rng = ax_phi.from_R_rdr_to_N_bins(oldPhi[ts], 0.08f);
190  auto eta_rng = ax_eta.from_R_rdr_to_N_bins(eta[ts], .1f);
191 
192  for (auto i_phi = phi_rng.begin; i_phi != phi_rng.end; i_phi = ax_phi.next_N_bin(i_phi)) {
193  for (auto i_eta = eta_rng.begin; i_eta != eta_rng.end; i_eta = ax_eta.next_N_bin(i_eta)) {
194  const auto cbin = phi_eta_binnor.get_content(i_phi, i_eta);
195  for (auto i = cbin.first; i < cbin.end(); ++i) {
196  int tss = phi_eta_binnor.m_ranks[i];
197 
198  if (not writetrack[ts])
199  continue;
200  if (not writetrack[tss])
201  continue;
202  if (tss == ts)
203  continue;
204 
205  const float pt2 = pt[tss];
206 
207  // Always require charge consistency. If different charge is assigned, do not remove seed-track
208  if (charge[tss] != charge[ts])
209  continue;
210 
211  const float thisDPt = std::abs(pt2 - pt1);
212  // Require pT consistency between seeds. If dpT is large, do not remove seed-track.
213  if (thisDPt > dpt_common * pt1)
214  continue;
215 
216  const float eta2 = eta[tss];
217  const float deta2 = std::pow(eta1 - eta2, 2);
218 
219  const float oldPhi2 = oldPhi[tss];
220 
221  const float pos2_second = pos2[tss];
222  const float thisDXYSign05 = pos2_second > pos2_first ? -0.5f : 0.5f;
223 
224  const float thisDXY = thisDXYSign05 * sqrt(std::pow(x[ts] - x[tss], 2) + std::pow(y[ts] - y[tss], 2));
225 
226  const float invptq_second = invptq[tss];
227 
228  const float newPhi1 = oldPhi1 - thisDXY * invR1GeV * invptq_first;
229  const float newPhi2 = oldPhi2 + thisDXY * invR1GeV * invptq_second;
230 
231  const float dphi = cdist(std::abs(newPhi1 - newPhi2));
232 
233  const float dr2 = deta2 + dphi * dphi;
234 
235  const float thisDZ = z[ts] - z[tss] - thisDXY * (ctheta[ts] + ctheta[tss]);
236  const float dz2 = thisDZ * thisDZ;
237 
238  // Reject tracks within dR-dz elliptical window.
239  // Adaptive thresholds, based on observation that duplicates are more abundant at large pseudo-rapidity and low track pT
240  bool overlapping = false;
241  if (std::abs(eta1) < etamax_brl) {
242  if (pt1 > ptmin_hpt) {
243  if (dz2 * dzmax2_inv_bh + dr2 * drmax2_inv_bh < 1.0f)
244  overlapping = true;
245  } else {
246  if (dz2 * dzmax2_inv_bl + dr2 * drmax2_inv_bl < 1.0f)
247  overlapping = true;
248  }
249  } else {
250  if (pt1 > ptmin_hpt) {
251  if (dz2 * dzmax2_inv_eh + dr2 * drmax2_inv_eh < 1.0f)
252  overlapping = true;
253  } else {
254  if (dz2 * dzmax2_inv_el + dr2 * drmax2_inv_el < 1.0f)
255  overlapping = true;
256  }
257  }
258 
259  if (overlapping) {
260  //Mark tss as a duplicate
261  i1 = ts;
262  i2 = tss;
263  if (d0[tss] > d0[ts])
264  writetrack[tss] = false;
265  else {
266  writetrack[ts] = false;
267  i2 = ts;
268  i1 = tss;
269  }
270  // Add hits from tk2 to the seed we are keeping.
271  // NOTE: We have a limit in Track::Status for the number of seed hits.
272  // There is a check at entry and after adding of a new hit.
273  Track &tk = seeds[i1];
274  if (merge_hits && tk.nTotalHits() < Track::Status::kMaxSeedHits &&
276  (pt1 < ptmax_merge_lowPtQuad && std::abs(eta1) > etamin_merge_lowPtQuad))) {
277  const Track &tk2 = seeds[i2];
278  //We are not actually fitting to the extra hits; use chi2 of 0
279  float fakeChi2 = 0.0;
280 
281  for (int j = 0; j < tk2.nTotalHits(); ++j) {
282  int hitidx = tk2.getHitIdx(j);
283  int hitlyr = tk2.getHitLyr(j);
284  if (hitidx >= 0) {
285  bool unique = true;
286  for (int i = 0; i < tk.nTotalHits(); ++i) {
287  if ((hitidx == tk.getHitIdx(i)) && (hitlyr == tk.getHitLyr(i))) {
288  unique = false;
289  break;
290  }
291  }
292  if (unique) {
293  tk.addHitIdx(tk2.getHitIdx(j), tk2.getHitLyr(j), fakeChi2);
294  ++n_ovlp_hits_added;
296  break;
297  }
298  }
299  }
300  }
301  if (n_ovlp_hits_added > 0)
302  tk.sortHitsByLayer();
303  }
304  } //end of inner loop over tss
305  } //eta bin
306  } //phi bin
307 
308  if (writetrack[ts]) {
309  cleanSeedTracks.emplace_back(seeds[ts]);
310  }
311  }
312 
313  seeds.swap(cleanSeedTracks);
314 
315 #ifdef DEBUG
316  {
317  const int ns2 = seeds.size();
318  printf("Number of CMS seeds before %d --> after %d cleaning\n", ns, ns2);
319 
320  for (int it = 0; it < ns2; it++) {
321  const Track &ss = seeds[it];
322  printf(" %3i q=%+i pT=%7.3f eta=% 7.3f nHits=%i label=% i\n",
323  it,
324  ss.charge(),
325  ss.pT(),
326  ss.momEta(),
327  ss.nFoundHits(),
328  ss.label());
329  }
330  }
331 #endif
332 
333 #ifdef DEBUG
334  std::cout << "AFTER seed cleaning " << seeds.size() << std::endl;
335 #endif
336 
337  return seeds.size();
338  }
339 
340  namespace {
341  CMS_SA_ALLOW struct register_seed_cleaners {
342  register_seed_cleaners() {
344  }
345  } rsc_instance;
346  } // namespace
347 
348  //=========================================================================
349  // Duplicate cleaning
350  //=========================================================================
351 
353  tracks.erase(std::remove_if(tracks.begin(), tracks.end(), [](auto track) { return track.getDuplicateValue(); }),
354  tracks.end());
355  }
356 
358  const auto ntracks = tracks.size();
359  float eta1, phi1, pt1, deta, dphi, dr2;
360 
361  if (ntracks == 0) {
362  return;
363  }
364  for (auto itrack = 0U; itrack < ntracks - 1; itrack++) {
365  auto &track = tracks[itrack];
366  eta1 = track.momEta();
367  phi1 = track.momPhi();
368  pt1 = track.pT();
369  for (auto jtrack = itrack + 1; jtrack < ntracks; jtrack++) {
370  auto &track2 = tracks[jtrack];
371  if (track.label() == track2.label())
372  continue;
373  if (track.algoint() != track2.algoint())
374  continue;
375 
376  deta = std::abs(track2.momEta() - eta1);
377  if (deta > Config::maxdEta)
378  continue;
379 
380  dphi = std::abs(squashPhiMinimal(phi1 - track2.momPhi()));
381  if (dphi > Config::maxdPhi)
382  continue;
383 
384  float maxdR = Config::maxdR;
385  float maxdRSquared = maxdR * maxdR;
386  if (std::abs(eta1) > 2.5f)
387  maxdRSquared *= 16.0f;
388  else if (std::abs(eta1) > 1.44f)
389  maxdRSquared *= 9.0f;
390  dr2 = dphi * dphi + deta * deta;
391  if (dr2 < maxdRSquared) {
392  //Keep track with best score
393  if (track.score() > track2.score())
394  track2.setDuplicateValue(true);
395  else
396  track.setDuplicateValue(true);
397  continue;
398  } else {
399  if (pt1 == 0)
400  continue;
401  if (track2.pT() == 0)
402  continue;
403 
404  if (std::abs((1 / track2.pT()) - (1 / pt1)) < Config::maxdPt) {
406  float numHitsShared = 0;
407  for (int ihit2 = 0; ihit2 < track2.nTotalHits(); ihit2++) {
408  const int hitidx2 = track2.getHitIdx(ihit2);
409  const int hitlyr2 = track2.getHitLyr(ihit2);
410  if (hitidx2 >= 0) {
411  auto const it = std::find_if(track.beginHitsOnTrack(),
412  track.endHitsOnTrack(),
413  [&hitidx2, &hitlyr2](const HitOnTrack &element) {
414  return (element.index == hitidx2 && element.layer == hitlyr2);
415  });
416  if (it != track.endHitsOnTrack())
417  numHitsShared++;
418  }
419  }
420 
421  float fracHitsShared = numHitsShared / std::min(track.nFoundHits(), track2.nFoundHits());
422  //Only remove one of the tracks if they share at least X% of the hits (denominator is the shorter track)
423  if (fracHitsShared < Config::minFracHitsShared)
424  continue;
425  }
426  //Keep track with best score
427  if (track.score() > track2.score())
428  track2.setDuplicateValue(true);
429  else
430  track.setDuplicateValue(true);
431  } //end of if dPt
432  } //end of else
433  } //end of loop over track2
434  } //end of loop over track1
435 
437  }
438 
439  //=========================================================================
440  // SHARED HITS DUPLICATE CLEANING
441  //=========================================================================
442 
444  const float fraction = itconf.dc_fracSharedHits;
445  const auto ntracks = tracks.size();
446 
447  std::vector<float> ctheta(ntracks);
448  std::multimap<int, int> hitMap;
449 
450  for (auto itrack = 0U; itrack < ntracks; itrack++) {
451  auto &trk = tracks[itrack];
452  ctheta[itrack] = 1.f / std::tan(trk.theta());
453  for (int i = 0; i < trk.nTotalHits(); ++i) {
454  if (trk.getHitIdx(i) < 0)
455  continue;
456  int a = trk.getHitLyr(i);
457  int b = trk.getHitIdx(i);
458  hitMap.insert(std::make_pair(b * 1000 + a, i > 0 ? itrack : -itrack)); //negative for first hit in trk
459  }
460  }
461 
462  for (auto itrack = 0U; itrack < ntracks; itrack++) {
463  auto &trk = tracks[itrack];
464  auto phi1 = trk.momPhi();
465  auto ctheta1 = ctheta[itrack];
466 
467  std::map<int, int> sharingMap;
468  for (int i = 0; i < trk.nTotalHits(); ++i) {
469  if (trk.getHitIdx(i) < 0)
470  continue;
471  int a = trk.getHitLyr(i);
472  int b = trk.getHitIdx(i);
473  auto range = hitMap.equal_range(b * 1000 + a);
474  for (auto it = range.first; it != range.second; ++it) {
475  if (std::abs(it->second) >= (int)itrack)
476  continue; // don't check your own hits (==) nor sym. checks (>)
477  if (i == 0 && it->second < 0)
478  continue; // shared first - first is not counted
479  sharingMap[std::abs(it->second)]++;
480  }
481  }
482 
483  for (const auto &elem : sharingMap) {
484  auto &track2 = tracks[elem.first];
485 
486  // broad dctheta-dphi compatibility checks; keep mostly to preserve consistency with old results
487  auto dctheta = std::abs(ctheta[elem.first] - ctheta1);
488  if (dctheta > 1.)
489  continue;
490 
491  auto dphi = std::abs(squashPhiMinimal(phi1 - track2.momPhi()));
492  if (dphi > 1.)
493  continue;
494 
495  if (elem.second >= std::min(trk.nFoundHits(), track2.nFoundHits()) * fraction) {
496  if (trk.score() > track2.score())
497  track2.setDuplicateValue(true);
498  else
499  trk.setDuplicateValue(true);
500  }
501  } // end sharing hits loop
502  } // end trk loop
503 
505  }
506 
508  const float fraction = itconf.dc_fracSharedHits;
509  const float drth_central = itconf.dc_drth_central;
510  const float drth_obarrel = itconf.dc_drth_obarrel;
511  const float drth_forward = itconf.dc_drth_forward;
512  const auto ntracks = tracks.size();
513 
514  std::vector<float> ctheta(ntracks);
515  for (auto itrack = 0U; itrack < ntracks; itrack++) {
516  auto &trk = tracks[itrack];
517  ctheta[itrack] = 1.f / std::tan(trk.theta());
518  }
519 
520  float phi1, invpt1, dctheta, ctheta1, dphi, dr2;
521  for (auto itrack = 0U; itrack < ntracks; itrack++) {
522  auto &trk = tracks[itrack];
523  phi1 = trk.momPhi();
524  invpt1 = trk.invpT();
525  ctheta1 = ctheta[itrack];
526  for (auto jtrack = itrack + 1; jtrack < ntracks; jtrack++) {
527  auto &track2 = tracks[jtrack];
528  if (trk.label() == track2.label())
529  continue;
530 
531  dctheta = std::abs(ctheta[jtrack] - ctheta1);
532 
533  if (dctheta > Config::maxdcth)
534  continue;
535 
536  dphi = std::abs(squashPhiMinimal(phi1 - track2.momPhi()));
537 
538  if (dphi > Config::maxdphi)
539  continue;
540 
541  float maxdRSquared = drth_central * drth_central;
542  if (std::abs(ctheta1) > Config::maxcth_fw)
543  maxdRSquared = drth_forward * drth_forward;
544  else if (std::abs(ctheta1) > Config::maxcth_ob)
545  maxdRSquared = drth_obarrel * drth_obarrel;
546  dr2 = dphi * dphi + dctheta * dctheta;
547  if (dr2 < maxdRSquared) {
548  //Keep track with best score
549  if (trk.score() > track2.score())
550  track2.setDuplicateValue(true);
551  else
552  trk.setDuplicateValue(true);
553  continue;
554  }
555 
556  if (std::abs(track2.invpT() - invpt1) > Config::maxd1pt)
557  continue;
558 
559  auto sharedCount = 0;
560  auto sharedFirst = 0;
561  const auto minFoundHits = std::min(trk.nFoundHits(), track2.nFoundHits());
562 
563  for (int i = 0; i < trk.nTotalHits(); ++i) {
564  if (trk.getHitIdx(i) < 0)
565  continue;
566  const int a = trk.getHitLyr(i);
567  const int b = trk.getHitIdx(i);
568  for (int j = 0; j < track2.nTotalHits(); ++j) {
569  if (track2.getHitIdx(j) < 0)
570  continue;
571  const int c = track2.getHitLyr(j);
572  const int d = track2.getHitIdx(j);
573 
574  //this is to count once shared matched hits (may be done more properly...)
575  if (a == c && b == d)
576  sharedCount += 1;
577  if (j == 0 && i == 0 && a == c && b == d)
578  sharedFirst += 1;
579 
580  if ((sharedCount - sharedFirst) >= ((minFoundHits - sharedFirst) * fraction))
581  continue;
582  }
583  if ((sharedCount - sharedFirst) >= ((minFoundHits - sharedFirst) * fraction))
584  continue;
585  }
586 
587  //selection here - 11percent fraction of shared hits to label a duplicate
588  if ((sharedCount - sharedFirst) >= ((minFoundHits - sharedFirst) * fraction)) {
589  if (trk.score() > track2.score())
590  track2.setDuplicateValue(true);
591  else
592  trk.setDuplicateValue(true);
593  }
594  }
595  } //end loop one over tracks
596 
598  }
599 
600  namespace {
601  CMS_SA_ALLOW struct register_duplicate_cleaners {
602  register_duplicate_cleaners() {
604  IterationConfig::register_duplicate_cleaner("phase1:clean_duplicates_sharedhits",
606  IterationConfig::register_duplicate_cleaner("phase1:clean_duplicates_sharedhits_pixelseed",
608  }
609  } rdc_instance;
610  } // namespace
611 
612  //=========================================================================
613  // Quality filters
614  //=========================================================================
615 
616  // quality filter for n hits with seed hit "penalty" for strip-based seeds
617  // this implicitly separates triplets and doublet seeds with glued layers
618  template <class TRACK>
619  bool qfilter_n_hits(const TRACK &t, const MkJob &j) {
620  int seedHits = t.getNSeedHits();
621  int seedReduction = (seedHits <= 5) ? 2 : 3;
622  return t.nFoundHits() - seedReduction >= j.params_cur().minHitsQF;
623  }
624 
625  // simple hit-count quality filter; used with pixel-based seeds
626  template <class TRACK>
627  bool qfilter_n_hits_pixseed(const TRACK &t, const MkJob &j) {
628  return t.nFoundHits() >= j.params_cur().minHitsQF;
629  }
630 
631  // layer-dependent quality filter
632  // includes ad hoc tuning for phase-1
633  template <class TRACK>
634  bool qfilter_n_layers(const TRACK &t, const MkJob &j) {
635  const BeamSpot &bspot = j.m_beam_spot;
636  const TrackerInfo &trk_inf = j.m_trk_info;
637  int enhits = t.nHitsByTypeEncoded(trk_inf);
638  int npixhits = t.nPixelDecoded(enhits);
639  int enlyrs = t.nLayersByTypeEncoded(trk_inf);
640  int npixlyrs = t.nPixelDecoded(enlyrs);
641  int nmatlyrs = t.nTotMatchDecoded(enlyrs);
642  int llyr = t.getLastFoundHitLyr();
643  int lplyr = t.getLastFoundPixelHitLyr();
644  float invpt = t.invpT();
645 
646  // based on fr and eff vs pt (convert to native invpt)
647  float invptmin = 1.43; // min 1/pT (=1/0.7) for full filter on (npixhits<=3 .or. npixlyrs<=3)
648  float d0BS = t.d0BeamSpot(bspot.x, bspot.y);
649  float d0_max = 0.1; // 1 mm, max for somewhat prompt
650 
651  // next-to-outermost pixel layers (almost): BPIX3 or FPIX1
652  bool endsInsidePix = (llyr == 2 || llyr == 18 || llyr == 45);
653  // not last pixel layers: BPIX[123] or FPIX[12]
654  bool lastInsidePix = ((0 <= lplyr && lplyr < 3) || (18 <= lplyr && lplyr < 20) || (45 <= lplyr && lplyr < 47));
655  // reject short tracks missing last pixel layer except for prompt-looking
656  return !(((npixhits <= 3 || npixlyrs <= 3) && endsInsidePix &&
657  (invpt < invptmin || (invpt >= invptmin && std::abs(d0BS) > d0_max))) ||
658  ((npixlyrs <= 3 && nmatlyrs <= 6) && lastInsidePix && llyr != lplyr && std::abs(d0BS) > d0_max));
659  }
660 
662  // includes ad hoc tuning for phase-1
663  template <class TRACK>
664  bool qfilter_pixelLessFwd(const TRACK &t, const MkJob &j) {
665  const BeamSpot &bspot = j.m_beam_spot;
666  const TrackerInfo &tk_info = j.m_trk_info;
667  float d0BS = t.d0BeamSpot(bspot.x, bspot.y);
668  float d0_max = 0.05; // 0.5 mm, max for somewhat prompt
669 
670  int encoded;
671  encoded = t.nLayersByTypeEncoded(tk_info);
672  int nLyrs = t.nTotMatchDecoded(encoded);
673  encoded = t.nHitsByTypeEncoded(tk_info);
674  int nHits = t.nTotMatchDecoded(encoded);
675 
676  // to subtract stereo seed layers to count just r-phi seed layers (better pt err)
677  int seedReduction = (t.getNSeedHits() <= 5) ? 2 : 3;
678 
679  // based on fr and eff vs pt and eta (convert to native invpt and theta)
680  float invpt = t.invpT();
681  float invptmin = 1.11; // =1/0.9
682 
683  float thetasym = std::abs(t.theta() - Const::PIOver2);
684  float thetasymmin = 1.11; // -> |eta|=1.45
685 
686  // accept longer tracks, reject too short and displaced
687  return (((t.nFoundHits() - seedReduction >= 4 && invpt < invptmin) ||
688  (t.nFoundHits() - seedReduction >= 3 && invpt > invptmin && thetasym <= thetasymmin) ||
689  (t.nFoundHits() - seedReduction >= 4 && invpt > invptmin && thetasym > thetasymmin)) &&
690  !((nLyrs <= 4 || nHits <= 4) && std::abs(d0BS) > d0_max && invpt < invptmin));
691  }
692 
694  // includes ad hoc tuning for phase-1
695  template <class TRACK>
696  bool qfilter_pixelLessBkwd(const TRACK &t, const MkJob &j) {
697  const BeamSpot &bspot = j.m_beam_spot;
698  const TrackerInfo &tk_info = j.m_trk_info;
699  float d0BS = t.d0BeamSpot(bspot.x, bspot.y);
700  float d0_max = 0.1; // 1 mm
701 
702  int encoded;
703  encoded = t.nLayersByTypeEncoded(tk_info);
704  int nLyrs = t.nTotMatchDecoded(encoded);
705  encoded = t.nHitsByTypeEncoded(tk_info);
706  int nHits = t.nTotMatchDecoded(encoded);
707 
708  // based on fr and eff vs pt and eta (convert to native invpt and theta)
709  float invpt = t.invpT();
710  float invptmin = 1.11; // =1/0.9
711 
712  float thetasym = std::abs(t.theta() - Const::PIOver2);
713  float thetasymmin_l = 0.80; // -> |eta|=0.9
714  float thetasymmin_h = 1.11; // -> |eta|=1.45
715 
716  // reject too short or too displaced tracks
717  return !(
718  ((nLyrs <= 3 || nHits <= 3)) ||
719  ((nLyrs <= 4 || nHits <= 4) && (invpt < invptmin || (thetasym > thetasymmin_l && std::abs(d0BS) > d0_max))) ||
720  ((nLyrs <= 5 || nHits <= 5) && (invpt > invptmin && thetasym > thetasymmin_h && std::abs(d0BS) > d0_max)));
721  }
722 
723  namespace {
724  CMS_SA_ALLOW struct register_quality_filters {
725  register_quality_filters() {
726  IterationConfig::register_candidate_filter("phase1:qfilter_n_hits", qfilter_n_hits<TrackCand>);
727  IterationConfig::register_candidate_filter("phase1:qfilter_n_hits_pixseed",
728  qfilter_n_hits_pixseed<TrackCand>);
729  IterationConfig::register_candidate_filter("phase1:qfilter_n_layers", qfilter_n_layers<TrackCand>);
730  IterationConfig::register_candidate_filter("phase1:qfilter_pixelLessFwd", qfilter_pixelLessFwd<TrackCand>);
731  IterationConfig::register_candidate_filter("phase1:qfilter_pixelLessBkwd", qfilter_pixelLessBkwd<TrackCand>);
732  }
733  } rqf_instance;
734  } // namespace
735 
736  //=========================================================================
737  // Track scoring
738  //=========================================================================
739 
740  float trackScoreDefault(const int nfoundhits,
741  const int ntailholes,
742  const int noverlaphits,
743  const int nmisshits,
744  const float chi2,
745  const float pt,
746  const bool inFindCandidates) {
747  float maxBonus = 8.0;
748  float bonus = Config::validHitSlope_ * nfoundhits + Config::validHitBonus_;
749  float penalty = Config::missingHitPenalty_;
750  float tailPenalty = Config::tailMissingHitPenalty_;
751  float overlapBonus = Config::overlapHitBonus_;
752  if (pt < 0.9) {
753  penalty *= inFindCandidates ? 1.7f : 1.5f;
754  bonus = std::min(bonus * (inFindCandidates ? 0.9f : 1.0f), maxBonus);
755  }
756  float score =
757  bonus * nfoundhits + overlapBonus * noverlaphits - penalty * nmisshits - tailPenalty * ntailholes - chi2;
758  return score;
759  }
760 
761  namespace {
762  CMS_SA_ALLOW struct register_track_scorers {
763  register_track_scorers() {
766  }
767  } rts_instance;
768  } // namespace
769 
770  } // namespace StdSeq
771 } // namespace mkfit
int getHitIdx(int posHitIdx) const
Definition: Track.h:464
float d0BeamSpot(const float x_bs, const float y_bs, bool linearize=false) const
Definition: Track.cc:191
bool qfilter_pixelLessFwd(const TRACK &t, const MkJob &j)
quality filter tuned for pixelLess iteration during forward search
Definition: MkStdSeqs.cc:664
float squashPhiMinimal(float phi)
Definition: Hit.h:26
int getHitLyr(int posHitIdx) const
Definition: Track.h:465
const float maxdPt
Definition: Config.cc:17
const float maxdphi
Definition: Config.cc:24
const float maxd1pt
Definition: Config.cc:23
int charge() const
Definition: Track.h:185
#define CMS_SA_ALLOW
void cmssw_Map_TrackHitIndices(const EventOfHits &eoh, TrackVec &seeds)
Definition: MkStdSeqs.cc:58
void clean_duplicates(TrackVec &tracks, const IterationConfig &itconf)
Definition: MkStdSeqs.cc:357
const float maxdcth
Definition: Config.cc:25
constexpr float validHitSlope_
Definition: Config.h:76
static void register_track_scorer(const std::string &name, track_score_func func)
I_pair from_R_rdr_to_N_bins(R r, R dr) const
Definition: binnor.h:73
float pT() const
Definition: Track.h:171
constexpr float c_dpt_common
Definition: Config.h:95
void cmssw_LoadHits_End(EventOfHits &eoh)
Definition: MkStdSeqs.cc:47
bool qfilter_n_hits(const TRACK &t, const MkJob &j)
Definition: MkStdSeqs.cc:619
float trackScoreDefault(const int nfoundhits, const int ntailholes, const int noverlaphits, const int nmisshits, const float chi2, const float pt, const bool inFindCandidates)
Definition: MkStdSeqs.cc:740
C_pair get_content(B_pair n_bin) const
Definition: binnor.h:240
const float maxdR
Definition: Config.cc:20
static constexpr int kMaxSeedHits
Definition: Track.h:214
int nLayers() const
I next_N_bin(I bin) const
Definition: binnor.h:113
constexpr float PIOver2
Definition: Config.h:9
static void register_duplicate_cleaner(const std::string &name, clean_duplicates_func func)
float invpT() const
Definition: Track.h:172
void cmssw_LoadHits_Begin(EventOfHits &eoh, const std::vector< const HitVec *> &orig_hitvectors)
Definition: MkStdSeqs.cc:31
void finalize_registration()
Definition: binnor.h:289
axis_base< R, I, M, N >::I_pair from_R_rdr_to_N_bins(R r, R dr) const
Definition: binnor.h:110
const float maxcth_fw
Definition: Config.cc:27
float theta() const
Definition: Track.h:176
int nFoundHits() const
Definition: Track.h:525
float momEta() const
Definition: Track.h:175
void remove_duplicates(TrackVec &tracks)
Definition: MkStdSeqs.cc:352
float y() const
Definition: Track.h:161
const float maxcth_ob
Definition: Config.cc:26
std::vector< C > m_ranks
Definition: binnor.h:211
void sortHitsByLayer()
Definition: Track.cc:394
float x
Definition: Hit.h:283
constexpr float c_etamax_brl
Definition: Config.h:94
void cmssw_ReMap_TrackHitIndices(const EventOfHits &eoh, TrackVec &out_tracks)
Definition: MkStdSeqs.cc:71
const float maxdEta
Definition: Config.cc:19
constexpr float PI
Definition: Config.h:7
static void register_seed_cleaner(const std::string &name, clean_seeds_func func)
float y
Definition: Hit.h:283
const float maxdPhi
Definition: Config.cc:18
T sqrt(T t)
Definition: SSEVec.h:19
def unique(seq, keepstr=True)
Definition: tier0.py:24
void register_entry_safe(typename A1::real_t r1, typename A2::real_t r2)
Definition: binnor.h:282
constexpr float tailMissingHitPenalty_
Definition: Config.h:79
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
void loadDeads(EventOfHits &eoh, const std::vector< DeadVec > &deadvectors)
Definition: MkStdSeqs.cc:21
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
bool qfilter_pixelLessBkwd(const TRACK &t, const MkJob &j)
quality filter tuned for pixelLess iteration during backward search
Definition: MkStdSeqs.cc:696
void addHitIdx(int hitIdx, int hitLyr, float chi2)
Definition: Track.h:451
float cdist(float a)
Definition: Config.h:32
d
Definition: ztail.py:151
void begin_registration(C n_items)
Definition: binnor.h:264
constexpr float overlapHitBonus_
Definition: Config.h:77
bool qfilter_n_layers(const TRACK &t, const MkJob &j)
Definition: MkStdSeqs.cc:634
std::vector< Track > TrackVec
static constexpr float d0
float z() const
Definition: Track.h:162
constexpr float track1GeVradius
Definition: Config.h:93
double b
Definition: hdecay.h:120
int nTotalHits() const
Definition: Track.h:526
double a
Definition: hdecay.h:121
float x
TrackAlgorithm
track algorithm; copy from TrackBase.h to keep in standalone builds
Definition: Track.h:286
float x() const
Definition: Track.h:160
const bool useHitsForDuplicates
Definition: Config.h:109
int clean_cms_seedtracks_iter(TrackVec &seeds, const IterationConfig &itrcfg, const BeamSpot &bspot)
Definition: MkStdSeqs.cc:87
TupleMultiplicity< TrackerTraits > const *__restrict__ uint32_t nHits
float momPhi() const
Definition: Track.h:174
void clean_duplicates_sharedhits_pixelseed(TrackVec &tracks, const IterationConfig &itconf)
Definition: MkStdSeqs.cc:507
I next_N_bin(I bin) const
Definition: binnor.h:74
void suckInDeads(int layer, const DeadVec &deadv)
static void register_candidate_filter(const std::string &name, filter_candidates_func func)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
Definition: fakeMenu.h:6
void clean_duplicates_sharedhits(TrackVec &tracks, const IterationConfig &itconf)
Definition: MkStdSeqs.cc:443
std::vector< DeadVec > deadvectors
Definition: mkFit.cc:44
bool qfilter_n_hits_pixseed(const TRACK &t, const MkJob &j)
Definition: MkStdSeqs.cc:627
constexpr float validHitBonus_
Definition: Config.h:75
const float minFracHitsShared
Definition: Config.cc:21
constexpr float missingHitPenalty_
Definition: Config.h:78