CMS 3D CMS Logo

MkBuilder.cc
Go to the documentation of this file.
1 #include <memory>
2 #include <limits>
3 #include <algorithm>
4 
6 
10 
11 #include "Pool.h"
12 #include "CandCloner.h"
13 #include "FindingFoos.h"
14 #include "MkFitter.h"
15 #include "MkFinder.h"
16 
17 #ifdef MKFIT_STANDALONE
19 #endif
20 
21 //#define DEBUG
22 #include "Debug.h"
23 //#define DEBUG_FINAL_FIT
24 
25 #include "oneapi/tbb/parallel_for.h"
26 #include "oneapi/tbb/parallel_for_each.h"
27 
28 namespace mkfit {
29 
30  //==============================================================================
31  // Execution context -- Pools of helper objects
32  //==============================================================================
33 
35  ExecutionContext() = default;
36  ~ExecutionContext() = default;
37 
41 
42  void populate(int n_thr) {
43  m_cloners.populate(n_thr - m_cloners.size());
44  m_fitters.populate(n_thr - m_fitters.size());
45  m_finders.populate(n_thr - m_finders.size());
46  }
47  };
48 
50 
51 } // end namespace mkfit
52 
53 //------------------------------------------------------------------------------
54 
55 namespace {
56  using namespace mkfit;
57 
58  // Range of indices processed within one iteration of a TBB parallel_for.
59  struct RangeOfSeedIndices {
60  int m_rng_beg, m_rng_end;
61  int m_beg, m_end;
62 
63  RangeOfSeedIndices(int rb, int re) : m_rng_beg(rb), m_rng_end(re) { reset(); }
64 
65  void reset() {
66  m_end = m_rng_beg;
67  next_chunk();
68  }
69 
70  bool valid() const { return m_beg < m_rng_end; }
71 
72  int n_proc() const { return m_end - m_beg; }
73 
74  void next_chunk() {
75  m_beg = m_end;
76  m_end = std::min(m_end + NN, m_rng_end);
77  }
78 
79  RangeOfSeedIndices &operator++() {
80  next_chunk();
81  return *this;
82  }
83  };
84 
85  // Region of seed indices processed in a single TBB parallel for.
86  struct RegionOfSeedIndices {
87  int m_reg_beg, m_reg_end, m_vec_cnt;
88 
89  RegionOfSeedIndices(const std::vector<int> &seedEtaSeparators, int region) {
90  m_reg_beg = (region == 0) ? 0 : seedEtaSeparators[region - 1];
91  m_reg_end = seedEtaSeparators[region];
92  m_vec_cnt = (m_reg_end - m_reg_beg + NN - 1) / NN;
93  }
94 
95  int count() const { return m_reg_end - m_reg_beg; }
96 
97  tbb::blocked_range<int> tbb_blk_rng_std(int thr_hint = -1) const {
98  if (thr_hint < 0)
99  thr_hint = Config::numSeedsPerTask;
100  return tbb::blocked_range<int>(m_reg_beg, m_reg_end, thr_hint);
101  }
102 
103  tbb::blocked_range<int> tbb_blk_rng_vec() const {
104  return tbb::blocked_range<int>(0, m_vec_cnt, std::max(1, Config::numSeedsPerTask / NN));
105  }
106 
107  RangeOfSeedIndices seed_rng(const tbb::blocked_range<int> &i) const {
108  return RangeOfSeedIndices(m_reg_beg + NN * i.begin(), std::min(m_reg_beg + NN * i.end(), m_reg_end));
109  }
110  };
111 
112 #ifdef DEBUG
113  void pre_prop_print(int ilay, MkBase *fir) {
114  const float pt = 1.f / fir->getPar(0, 0, 3);
115  std::cout << "propagate to lay=" << ilay << " start from x=" << fir->getPar(0, 0, 0)
116  << " y=" << fir->getPar(0, 0, 1) << " z=" << fir->getPar(0, 0, 2)
117  << " r=" << getHypot(fir->getPar(0, 0, 0), fir->getPar(0, 0, 1))
118  << " px=" << pt * std::cos(fir->getPar(0, 0, 4)) << " py=" << pt * std::sin(fir->getPar(0, 0, 4))
119  << " pz=" << pt / std::tan(fir->getPar(0, 0, 5)) << " pT=" << pt << std::endl;
120  }
121 
122  void post_prop_print(int ilay, MkBase *fir) {
123  std::cout << "propagate to lay=" << ilay << " arrive at x=" << fir->getPar(0, 1, 0) << " y=" << fir->getPar(0, 1, 1)
124  << " z=" << fir->getPar(0, 1, 2) << " r=" << getHypot(fir->getPar(0, 1, 0), fir->getPar(0, 1, 1))
125  << std::endl;
126  }
127 
128  void print_seed(const Track &seed) {
129  std::cout << "MX - found seed with label=" << seed.label() << " nHits=" << seed.nFoundHits()
130  << " chi2=" << seed.chi2() << " posEta=" << seed.posEta() << " posPhi=" << seed.posPhi()
131  << " posR=" << seed.posR() << " posZ=" << seed.z() << " pT=" << seed.pT() << std::endl;
132  }
133 
134  void print_seed2(const TrackCand &seed) {
135  std::cout << "MX - found seed with nFoundHits=" << seed.nFoundHits() << " chi2=" << seed.chi2() << " x=" << seed.x()
136  << " y=" << seed.y() << " z=" << seed.z() << " px=" << seed.px() << " py=" << seed.py()
137  << " pz=" << seed.pz() << " pT=" << seed.pT() << std::endl;
138  }
139 
140  void print_seeds(const TrackVec &seeds) {
141  std::cout << "found total seeds=" << seeds.size() << std::endl;
142  for (auto &&seed : seeds) {
143  print_seed(seed);
144  }
145  }
146 
147  [[maybe_unused]] void print_seeds(const EventOfCombCandidates &event_of_comb_cands) {
148  for (int iseed = 0; iseed < event_of_comb_cands.size(); iseed++) {
149  print_seed2(event_of_comb_cands[iseed].front());
150  }
151  }
152 #endif
153 
154  bool sortCandByScore(const TrackCand &cand1, const TrackCand &cand2) {
155  return mkfit::sortByScoreTrackCand(cand1, cand2);
156  }
157 
158 } // end unnamed namespace
159 
160 //------------------------------------------------------------------------------
161 // Constructor and destructor
162 //------------------------------------------------------------------------------
163 
164 namespace mkfit {
165 
166  std::unique_ptr<MkBuilder> MkBuilder::make_builder(bool silent) { return std::make_unique<MkBuilder>(silent); }
167 
169 
170  std::pair<int, int> MkBuilder::max_hits_layer(const EventOfHits &eoh) const {
171  int maxN = 0;
172  int maxL = 0;
173  for (int l = 0; l < eoh.nLayers(); ++l) {
174  int lsize = eoh[l].nHits();
175  if (lsize > maxN) {
176  maxN = lsize;
177  maxL = eoh[l].layer_id();
178  }
179  }
180  return {maxN, maxL};
181  }
182 
184  int res = 0;
185  for (int i = 0; i < m_event_of_comb_cands.size(); ++i)
187  return res;
188  }
189 
190  //------------------------------------------------------------------------------
191  // Common functions
192  //------------------------------------------------------------------------------
193 
194  void MkBuilder::begin_event(MkJob *job, Event *ev, const char *build_type) {
196 
197  m_job = job;
198  m_event = ev;
199 
203 
204  for (int i = 0; i < m_job->num_regions(); ++i) {
205  m_seedEtaSeparators[i] = 0;
206  m_seedMinLastLayer[i] = 9999;
207  m_seedMaxLastLayer[i] = 0;
208  }
209 
210  if (!m_silent) {
211  std::cout << "MkBuilder building tracks with '" << build_type << "'"
212  << ", iteration_index=" << job->m_iter_config.m_iteration_index
213  << ", track_algorithm=" << job->m_iter_config.m_track_algorithm << std::endl;
214  }
215  }
216 
218  m_job = nullptr;
219  m_event = nullptr;
220  }
221 
223  TrackVec tmp;
224  m_tracks.swap(tmp);
226  }
227 
228  void MkBuilder::import_seeds(const TrackVec &in_seeds,
229  const bool seeds_sorted,
230  std::function<insert_seed_foo> insert_seed) {
231  // bool debug = true;
232 
233  const int size = in_seeds.size();
234 
236  std::vector<unsigned> ranks;
237  if (!seeds_sorted) {
238  // We don't care about bins in phi, use low N to reduce overall number of bins.
240  axis<float, unsigned short, 8, 8> ax_eta(-3.0, 3.0, 64u);
242  part.m_phi_eta_foo = [&](float phi, float eta) { phi_eta_binnor.register_entry_safe(phi, eta); };
243 
244  phi_eta_binnor.begin_registration(size);
246  phi_eta_binnor.finalize_registration();
247  ranks.swap(phi_eta_binnor.m_ranks);
248  } else {
250  }
251 
252  for (int i = 0; i < size; ++i) {
253  int j = seeds_sorted ? i : ranks[i];
254  int reg = part.m_region[j];
255  ++m_seedEtaSeparators[reg];
256  }
257 
258  // Sum up region counts to contain actual ending indices and prepare insertion cursors.
259  // Fix min/max layers.
260  std::vector<int> seed_cursors(m_job->num_regions());
261  for (int reg = 1; reg < m_job->num_regions(); ++reg) {
262  seed_cursors[reg] = m_seedEtaSeparators[reg - 1];
263  m_seedEtaSeparators[reg] += m_seedEtaSeparators[reg - 1];
264  }
265 
266  // Actually imports seeds, detect last-hit layer range per region.
267  for (int i = 0; i < size; ++i) {
268  int j = seeds_sorted ? i : ranks[i];
269  int reg = part.m_region[j];
270  const Track &seed = in_seeds[j];
271  insert_seed(seed, reg, seed_cursors[reg]++);
272 
273  HitOnTrack hot = seed.getLastHitOnTrack();
276  }
277 
278  // Fix min/max layers
279  for (int reg = 0; reg < m_job->num_regions(); ++reg) {
280  if (m_seedMinLastLayer[reg] == 9999)
281  m_seedMinLastLayer[reg] = -1;
282  if (m_seedMaxLastLayer[reg] == 0)
283  m_seedMaxLastLayer[reg] = -1;
284  }
285 
286  // clang-format off
287  dprintf("MkBuilder::import_seeds finished import of %d seeds (last seeding layer min, max):\n"
288  " ec- = %d(%d,%d), t- = %d(%d,%d), brl = %d(%d,%d), t+ = %d(%d,%d), ec+ = %d(%d,%d).\n",
289  size,
295  // dcall(print_seeds(m_event_of_comb_cands));
296  // clang-format on
297  }
298 
299  //------------------------------------------------------------------------------
300 
303  int i = 0, place_pos = 0;
304 
305  dprintf("MkBuilder::filter_comb_cands Entering filter size eoccs.size=%d\n", eoccs.size());
306 
307  std::vector<int> removed_cnts(m_job->num_regions());
308  while (i < eoccs.size()) {
309  if (eoccs.cands_in_backward_rep())
310  eoccs[i].repackCandPostBkwSearch(0);
311  bool passed = filter(eoccs[i].front(), *m_job);
312 
313  if (!passed && attempt_all_cands) {
314  for (int j = 1; j < (int)eoccs[i].size(); ++j) {
315  if (eoccs.cands_in_backward_rep())
316  eoccs[i].repackCandPostBkwSearch(j);
317  if (filter(eoccs[i][j], *m_job)) {
318  eoccs[i][0] = eoccs[i][j]; // overwrite front, no need to std::swap() them
319  passed = true;
320  break;
321  }
322  }
323  }
324  if (passed) {
325  if (place_pos != i)
326  std::swap(eoccs[place_pos], eoccs[i]);
327  ++place_pos;
328  } else {
329  assert(eoccs[i].front().getEtaRegion() < m_job->num_regions());
330  ++removed_cnts[eoccs[i].front().getEtaRegion()];
331  }
332  ++i;
333  }
334 
335  int n_removed = 0;
336  for (int reg = 0; reg < m_job->num_regions(); ++reg) {
337  dprintf("MkBuilder::filter_comb_cands reg=%d: n_rem_was=%d removed_in_r=%d n_rem=%d, es_was=%d es_new=%d\n",
338  reg,
339  n_removed,
340  removed_cnts[reg],
341  n_removed + removed_cnts[reg],
342  m_seedEtaSeparators[reg],
343  m_seedEtaSeparators[reg] - n_removed - removed_cnts[reg]);
344 
345  n_removed += removed_cnts[reg];
346  m_seedEtaSeparators[reg] -= n_removed;
347  }
348 
349  eoccs.resizeAfterFiltering(n_removed);
350 
351  dprintf("MkBuilder::filter_comb_cands n_removed = %d, eoccs.size=%d\n", n_removed, eoccs.size());
352 
353  return n_removed;
354  }
355 
358  int min[5], max[5], gmin = 0, gmax = 0;
359  int i = 0;
360  for (int reg = 0; reg < 5; ++reg) {
361  min[reg] = 9999;
362  max[reg] = 0;
363  for (; i < m_seedEtaSeparators[reg]; i++) {
364  min[reg] = std::min(min[reg], eoccs[i].hotsSize());
365  max[reg] = std::max(max[reg], eoccs[i].hotsSize());
366  }
367  gmin = std::max(gmin, min[reg]);
368  gmax = std::max(gmax, max[reg]);
369  }
370  // clang-format off
371  printf("MkBuilder::find_min_max_hots_size MIN %3d -- [ %3d | %3d | %3d | %3d | %3d ] "
372  "MAX %3d -- [ %3d | %3d | %3d | %3d | %3d ]\n",
373  gmin, min[0], min[1], min[2], min[3], min[4],
374  gmax, max[0], max[1], max[2], max[3], max[4]);
375  // clang-format on
376  }
377 
378  void MkBuilder::select_best_comb_cands(bool clear_m_tracks, bool remove_missing_hits) {
379  if (clear_m_tracks)
380  m_tracks.clear();
381  export_best_comb_cands(m_tracks, remove_missing_hits);
382  }
383 
384  void MkBuilder::export_best_comb_cands(TrackVec &out_vec, bool remove_missing_hits) {
386  out_vec.reserve(out_vec.size() + eoccs.size());
387  for (int i = 0; i < eoccs.size(); i++) {
388  // Take the first candidate, if it exists.
389  if (!eoccs[i].empty()) {
390  const TrackCand &bcand = eoccs[i].front();
391  out_vec.emplace_back(bcand.exportTrack(remove_missing_hits));
392  }
393  }
394  }
395 
397  out_vec.reserve(out_vec.size() + m_tracks.size());
398  for (auto &t : m_tracks) {
399  out_vec.emplace_back(t);
400  }
401  }
402 
403  //------------------------------------------------------------------------------
404  // PrepareSeeds
405  //------------------------------------------------------------------------------
406 
409  int count = 0;
410 
411  for (int i = 0; i < (int)tv.size(); ++i) {
412  bool silly = tv[i].hasSillyValues(Const::nan_n_silly_print_bad_seeds,
414  "Post-cleaning seed silly value check and fix");
415  if (silly) {
416  ++count;
418  // XXXX MT
419  // Could do somethin smarter here: set as Stopped ? check in seed cleaning ?
420  tv.erase(tv.begin() + i);
421  --i;
422  }
423  }
424  }
425 
426  if (count > 0 && !m_silent) {
427  printf("Nan'n'Silly detected %d silly seeds (fix=%d, remove=%d).\n",
428  count,
431  }
432  }
433  }
434 
435  //------------------------------------------------------------------------------
436  // FindTracksBestHit
437  //------------------------------------------------------------------------------
438 
439  void MkBuilder::find_tracks_load_seeds_BH(const TrackVec &in_seeds, const bool seeds_sorted) {
440  // bool debug = true;
441  assert(!in_seeds.empty());
442  m_tracks.resize(in_seeds.size());
443 
444  import_seeds(in_seeds, seeds_sorted, [&](const Track &seed, int region, int pos) {
445  m_tracks[pos] = seed;
446  m_tracks[pos].setNSeedHits(seed.nTotalHits());
447  m_tracks[pos].setEtaRegion(region);
448  });
449 
450  //dump seeds
451  dcall(print_seeds(m_tracks));
452  }
453 
455  // bool debug = true;
456 
458 
459  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
460  if (iteration_dir == SteeringParams::IT_BkwSearch && !m_job->steering_params(region).has_bksearch_plan()) {
461  printf("No backward search plan for region %d\n", region);
462  return;
463  }
464 
465  // XXXXXX Select endcap / barrel only ...
466  // if (region != TrackerInfo::Reg_Endcap_Neg && region != TrackerInfo::Reg_Endcap_Pos)
467  // if (region != TrackerInfo::Reg_Barrel)
468  // return;
469 
470  const SteeringParams &st_par = m_job->steering_params(region);
471  const TrackerInfo &trk_info = m_job->m_trk_info;
472  const PropagationConfig &prop_config = PropagationConfig::get_default();
473 
474  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
475 
476  tbb::parallel_for(rosi.tbb_blk_rng_vec(), [&](const tbb::blocked_range<int> &blk_rng) {
477  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
478 
479  RangeOfSeedIndices rng = rosi.seed_rng(blk_rng);
480 
481  std::vector<int> trk_idcs(NN); // track indices in Matriplex
482  std::vector<int> trk_llay(NN); // last layer on input track
483 
484  while (rng.valid()) {
485  dprint(std::endl << "processing track=" << rng.m_beg << ", label=" << cands[rng.m_beg].label());
486 
487  int prev_layer = 9999;
488 
489  for (int i = rng.m_beg, ii = 0; i < rng.m_end; ++i, ++ii) {
490  int llay = cands[i].getLastHitLyr();
491  trk_llay[ii] = llay;
492  prev_layer = std::min(prev_layer, llay);
493 
494  dprintf(" %2d %2d %2d lay=%3d prev_layer=%d\n", ii, i, cands[i].label(), llay, prev_layer);
495  }
496  int curr_tridx = 0;
497 
498  auto layer_plan_it = st_par.make_iterator(iteration_dir);
499 
500  dprintf("Made iterator for %d, first layer=%d ... end layer=%d\n",
501  iteration_dir,
502  layer_plan_it.layer(),
503  layer_plan_it.last_layer());
504 
505  assert(layer_plan_it.is_pickup_only());
506 
507  int curr_layer = layer_plan_it.layer();
508 
509  mkfndr->m_Stopped.setVal(0);
510 
511  // Loop over layers, starting from after the seed.
512  // Consider inverting loop order and make layer outer, need to
513  // trade off hit prefetching with copy-out of candidates.
514  while (++layer_plan_it) {
515  prev_layer = curr_layer;
516  curr_layer = layer_plan_it.layer();
517  mkfndr->setup(prop_config,
519  m_job->m_iter_config.m_layer_configs[curr_layer],
520  st_par,
521  m_job->get_mask_for_layer(curr_layer),
522  m_job->m_in_fwd);
523 
524  const LayerOfHits &layer_of_hits = m_job->m_event_of_hits[curr_layer];
525  const LayerInfo &layer_info = trk_info.layer(curr_layer);
526  const FindingFoos &fnd_foos = FindingFoos::get_finding_foos(layer_info.is_barrel());
527  dprint("at layer " << curr_layer << ", nHits in layer " << layer_of_hits.nHits());
528 
529  // Pick up seeds that become active on current layer -- unless already fully loaded.
530  if (curr_tridx < rng.n_proc()) {
531  int prev_tridx = curr_tridx;
532 
533  for (int i = rng.m_beg, ii = 0; i < rng.m_end; ++i, ++ii) {
534  if (trk_llay[ii] == prev_layer)
535  trk_idcs[curr_tridx++] = i;
536  }
537  if (curr_tridx > prev_tridx) {
538  dprintf("added %d seeds, started with %d\n", curr_tridx - prev_tridx, prev_tridx);
539 
540  mkfndr->inputTracksAndHitIdx(cands, trk_idcs, prev_tridx, curr_tridx, false, prev_tridx);
541  }
542  }
543 
544  if (layer_plan_it.is_pickup_only())
545  continue;
546 
547  dcall(pre_prop_print(curr_layer, mkfndr.get()));
548 
549  mkfndr->clearFailFlag();
550  (mkfndr.get()->*fnd_foos.m_propagate_foo)(
551  layer_info.propagate_to(), curr_tridx, prop_config.finding_inter_layer_pflags);
552 
553  dcall(post_prop_print(curr_layer, mkfndr.get()));
554 
555  mkfndr->selectHitIndices(layer_of_hits, curr_tridx);
556 
557  // Stop low-pT tracks that can not reach the current barrel layer.
558  if (layer_info.is_barrel()) {
559  const float r_min_sqr = layer_info.rin() * layer_info.rin();
560  for (int i = 0; i < curr_tridx; ++i) {
561  if (!mkfndr->m_Stopped[i]) {
562  if (mkfndr->radiusSqr(i, MkBase::iP) < r_min_sqr) {
564  mkfndr->m_Stopped[i] = 1;
565  mkfndr->outputTrackAndHitIdx(cands[rng.m_beg + i], i, false);
566  }
567  mkfndr->m_XWsrResult[i].m_wsr = WSR_Outside;
568  mkfndr->m_XHitSize[i] = 0;
569  }
570  } else { // make sure we don't add extra work for AddBestHit
571  mkfndr->m_XWsrResult[i].m_wsr = WSR_Outside;
572  mkfndr->m_XHitSize[i] = 0;
573  }
574  }
575  }
576 
577  // make candidates with best hit
578  dprint("make new candidates");
579 
580  mkfndr->addBestHit(layer_of_hits, curr_tridx, fnd_foos);
581 
582  // Stop tracks that have reached N_max_holes.
583  for (int i = 0; i < curr_tridx; ++i) {
584  if (!mkfndr->m_Stopped[i] && mkfndr->bestHitLastHoT(i).index == -2) {
585  mkfndr->m_Stopped[i] = 1;
586  mkfndr->outputTrackAndHitIdx(cands[rng.m_beg + i], i, false);
587  }
588  }
589 
590  } // end of layer loop
591 
592  mkfndr->outputNonStoppedTracksAndHitIdx(cands, trk_idcs, 0, curr_tridx, false);
593 
594  ++rng;
595  } // end of loop over candidates in a tbb chunk
596 
597  mkfndr->release();
598  }); // end parallel_for over candidates in a region
599  }); // end of parallel_for_each over regions
600  }
601 
602  //------------------------------------------------------------------------------
603  // FindTracksCombinatorial: Standard TBB and CloneEngine TBB
604  //------------------------------------------------------------------------------
605 
606  void MkBuilder::find_tracks_load_seeds(const TrackVec &in_seeds, const bool seeds_sorted) {
607  // This will sort seeds according to iteration configuration.
608  assert(!in_seeds.empty());
609  m_tracks.clear(); // m_tracks can be used for BkFit.
610 
611  m_event_of_comb_cands.reset((int)in_seeds.size(), m_job->max_max_cands());
612 
613  import_seeds(in_seeds, seeds_sorted, [&](const Track &seed, int region, int pos) {
615  });
616  }
617 
618  int MkBuilder::find_tracks_unroll_candidates(std::vector<std::pair<int, int>> &seed_cand_vec,
619  int start_seed,
620  int end_seed,
621  int layer,
622  int prev_layer,
623  bool pickup_only,
624  SteeringParams::IterationType_e iteration_dir) {
625  int silly_count = 0;
626 
627  seed_cand_vec.clear();
628 
629  auto &iter_params = (iteration_dir == SteeringParams::IT_BkwSearch) ? m_job->m_iter_config.m_backward_params
631 
632  for (int iseed = start_seed; iseed < end_seed; ++iseed) {
634 
635  if (ccand.state() == CombCandidate::Dormant && ccand.pickupLayer() == prev_layer) {
637  }
638  if (!pickup_only && ccand.state() == CombCandidate::Finding) {
639  bool active = false;
640  for (int ic = 0; ic < (int)ccand.size(); ++ic) {
641  if (ccand[ic].getLastHitIdx() != -2) {
642  // Stop candidates with pT<X GeV
643  if (ccand[ic].pT() < iter_params.minPtCut) {
644  ccand[ic].addHitIdx(-2, layer, 0.0f);
645  continue;
646  }
647  // Check if the candidate is close to it's max_r, pi/2 - 0.2 rad (11.5 deg)
648  if (iteration_dir == SteeringParams::IT_FwdSearch && ccand[ic].pT() < 1.2) {
649  const float dphi = std::abs(ccand[ic].posPhi() - ccand[ic].momPhi());
650  if (ccand[ic].posRsq() > 625.f && dphi > 1.371f && dphi < 4.512f) {
651  // printf("Stopping cand at r=%f, posPhi=%.1f momPhi=%.2f pt=%.2f emomEta=%.2f\n",
652  // ccand[ic].posR(), ccand[ic].posPhi(), ccand[ic].momPhi(), ccand[ic].pT(), ccand[ic].momEta());
653  ccand[ic].addHitIdx(-2, layer, 0.0f);
654  continue;
655  }
656  }
657 
658  active = true;
659  seed_cand_vec.push_back(std::pair<int, int>(iseed, ic));
660  ccand[ic].resetOverlaps();
661 
663  if (ccand[ic].hasSillyValues(Const::nan_n_silly_print_bad_cands_every_layer,
665  "Per layer silly check"))
666  ++silly_count;
667  }
668  }
669  }
670  if (!active) {
672  }
673  }
674  }
675 
676  if (Const::nan_n_silly_check_cands_every_layer && silly_count > 0) {
677  m_nan_n_silly_per_layer_count += silly_count;
678  }
679 
680  return seed_cand_vec.size();
681  }
682 
684  const LayerInfo &layer_info,
685  std::vector<std::vector<TrackCand>> &tmp_cands,
686  const std::vector<std::pair<int, int>> &seed_cand_idx,
687  const int region,
688  const int start_seed,
689  const int itrack,
690  const int end) {
691  // XXXX-1 If I miss a layer, insert the original track into tmp_cands
692  // AND do not do it in FindCandidates as the position can be badly
693  // screwed by then. See comment there, too.
694  // One could also do a pre-check ... so as not to use up a slot.
695 
696  // bool debug = true;
697 
698  for (int ti = itrack; ti < end; ++ti) {
699  TrackCand &cand = m_event_of_comb_cands[seed_cand_idx[ti].first][seed_cand_idx[ti].second];
700  WSR_Result &w = mkfndr->m_XWsrResult[ti - itrack];
701 
702  // XXXX-4 Low pT tracks can miss a barrel layer ... and should be stopped
703  const float cand_r =
704  std::hypot(mkfndr->getPar(ti - itrack, MkBase::iP, 0), mkfndr->getPar(ti - itrack, MkBase::iP, 1));
705 
706  dprintf("WSR Check label %d, seed %d, cand %d score %f -> wsr %d, in_gap %d\n",
707  cand.label(),
708  seed_cand_idx[ti].first,
709  seed_cand_idx[ti].second,
710  cand.score(),
711  w.m_wsr,
712  w.m_in_gap);
713 
714  if (layer_info.is_barrel() && cand_r < layer_info.rin()) {
715  // Fake outside so it does not get processed in FindTracks Std/CE... and
716  // create a stopped replica in barrel and original copy if there is
717  // still chance to hit endcaps.
718  dprintf("Barrel cand propagated to r=%f ... layer is %f - %f\n", cand_r, layer_info.rin(), layer_info.rout());
719 
720  mkfndr->m_XHitSize[ti - itrack] = 0;
721  w.m_wsr = WSR_Outside;
722 
723  tmp_cands[seed_cand_idx[ti].first - start_seed].push_back(cand);
725  dprintf(" creating extra stopped held back candidate\n");
726  tmp_cands[seed_cand_idx[ti].first - start_seed].back().addHitIdx(-2, layer_info.layer_id(), 0);
727  }
728  } else if (w.m_wsr == WSR_Outside) {
729  dprintf(" creating extra held back candidate\n");
730  tmp_cands[seed_cand_idx[ti].first - start_seed].push_back(cand);
731  } else if (w.m_wsr == WSR_Edge) {
732  // Do nothing special here, this case is handled also in MkFinder:findTracks()
733  }
734  }
735  }
736 
737  //------------------------------------------------------------------------------
738  // FindTracksCombinatorial: Standard TBB
739  //------------------------------------------------------------------------------
740 
742  // debug = true;
743 
745 
746  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
747  if (iteration_dir == SteeringParams::IT_BkwSearch && !m_job->steering_params(region).has_bksearch_plan()) {
748  printf("No backward search plan for region %d\n", region);
749  return;
750  }
751 
752  const TrackerInfo &trk_info = m_job->m_trk_info;
753  const SteeringParams &st_par = m_job->steering_params(region);
754  const IterationParams &params = m_job->params();
755  const PropagationConfig &prop_config = PropagationConfig::get_default();
756 
757  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
758 
759  // adaptive seeds per task based on the total estimated amount of work to divide among all threads
760  const int adaptiveSPT = std::clamp(
762  dprint("adaptiveSPT " << adaptiveSPT << " fill " << rosi.count() << "/" << eoccs.size() << " region " << region);
763 
764  // loop over seeds
765  tbb::parallel_for(rosi.tbb_blk_rng_std(adaptiveSPT), [&](const tbb::blocked_range<int> &seeds) {
766  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
767 
768  const int start_seed = seeds.begin();
769  const int end_seed = seeds.end();
770  const int n_seeds = end_seed - start_seed;
771 
772  std::vector<std::vector<TrackCand>> tmp_cands(n_seeds);
773  for (size_t iseed = 0; iseed < tmp_cands.size(); ++iseed) {
774  tmp_cands[iseed].reserve(2 * params.maxCandsPerSeed); //factor 2 seems reasonable to start with
775  }
776 
777  std::vector<std::pair<int, int>> seed_cand_idx;
778  seed_cand_idx.reserve(n_seeds * params.maxCandsPerSeed);
779 
780  auto layer_plan_it = st_par.make_iterator(iteration_dir);
781 
782  dprintf("Made iterator for %d, first layer=%d ... end layer=%d\n",
783  iteration_dir,
784  layer_plan_it.layer(),
785  layer_plan_it.last_layer());
786 
787  assert(layer_plan_it.is_pickup_only());
788 
789  int curr_layer = layer_plan_it.layer(), prev_layer;
790 
791  dprintf("\nMkBuilder::FindTracksStandard region=%d, seed_pickup_layer=%d, first_layer=%d\n",
792  region,
793  curr_layer,
794  layer_plan_it.next_layer());
795 
796  auto &iter_params = (iteration_dir == SteeringParams::IT_BkwSearch) ? m_job->m_iter_config.m_backward_params
798 
799  // Loop over layers, starting from after the seed.
800  while (++layer_plan_it) {
801  prev_layer = curr_layer;
802  curr_layer = layer_plan_it.layer();
803  mkfndr->setup(prop_config,
804  iter_params,
805  m_job->m_iter_config.m_layer_configs[curr_layer],
806  st_par,
807  m_job->get_mask_for_layer(curr_layer),
808  m_job->m_in_fwd);
809 
810  dprintf("\n* Processing layer %d\n", curr_layer);
811 
812  const LayerOfHits &layer_of_hits = m_job->m_event_of_hits[curr_layer];
813  const LayerInfo &layer_info = trk_info.layer(curr_layer);
814  const FindingFoos &fnd_foos = FindingFoos::get_finding_foos(layer_info.is_barrel());
815 
816  int theEndCand = find_tracks_unroll_candidates(seed_cand_idx,
817  start_seed,
818  end_seed,
819  curr_layer,
820  prev_layer,
821  layer_plan_it.is_pickup_only(),
822  iteration_dir);
823 
824  dprintf(" Number of candidates to process: %d, nHits in layer: %d\n", theEndCand, layer_of_hits.nHits());
825 
826  if (layer_plan_it.is_pickup_only() || theEndCand == 0)
827  continue;
828 
829  // vectorized loop
830  for (int itrack = 0; itrack < theEndCand; itrack += NN) {
831  int end = std::min(itrack + NN, theEndCand);
832 
833  dprint("processing track=" << itrack << ", label="
834  << eoccs[seed_cand_idx[itrack].first][seed_cand_idx[itrack].second].label());
835 
836  //fixme find a way to deal only with the candidates needed in this thread
837  mkfndr->inputTracksAndHitIdx(eoccs.refCandidates(), seed_cand_idx, itrack, end, false);
838 
839  //propagate to layer
840  dcall(pre_prop_print(curr_layer, mkfndr.get()));
841 
842  mkfndr->clearFailFlag();
843  (mkfndr.get()->*fnd_foos.m_propagate_foo)(
844  layer_info.propagate_to(), end - itrack, prop_config.finding_inter_layer_pflags);
845 
846  dcall(post_prop_print(curr_layer, mkfndr.get()));
847 
848  dprint("now get hit range");
849  mkfndr->selectHitIndices(layer_of_hits, end - itrack);
850 
852  mkfndr.get(), layer_info, tmp_cands, seed_cand_idx, region, start_seed, itrack, end);
853 
854  dprint("make new candidates");
855  mkfndr->findCandidates(layer_of_hits, tmp_cands, start_seed, end - itrack, fnd_foos);
856 
857  } //end of vectorized loop
858 
859  // sort the input candidates
860  for (int is = 0; is < n_seeds; ++is) {
861  dprint("dump seed n " << is << " with N_input_candidates=" << tmp_cands[is].size());
862 
863  std::sort(tmp_cands[is].begin(), tmp_cands[is].end(), sortCandByScore);
864  }
865 
866  // now fill out the output candidates
867  for (int is = 0; is < n_seeds; ++is) {
868  if (!tmp_cands[is].empty()) {
869  eoccs[start_seed + is].clear();
870 
871  // Put good candidates into eoccs, process -2 candidates.
872  int n_placed = 0;
873  bool first_short = true;
874  for (int ii = 0; ii < (int)tmp_cands[is].size() && n_placed < params.maxCandsPerSeed; ++ii) {
875  TrackCand &tc = tmp_cands[is][ii];
876 
877  // See if we have an overlap hit available, but only if we have a true hit in this layer
878  // and pT is above the pTCutOverlap
879  if (tc.pT() > params.pTCutOverlap && tc.getLastHitLyr() == curr_layer && tc.getLastHitIdx() >= 0) {
880  CombCandidate &ccand = eoccs[start_seed + is];
881 
882  HitMatch *hm = ccand[tc.originIndex()].findOverlap(
883  tc.getLastHitIdx(), layer_of_hits.refHit(tc.getLastHitIdx()).detIDinLayer());
884 
885  if (hm) {
886  tc.addHitIdx(hm->m_hit_idx, curr_layer, hm->m_chi2);
887  tc.incOverlapCount();
888  }
889  }
890 
891  if (tc.getLastHitIdx() != -2) {
892  eoccs[start_seed + is].emplace_back(tc);
893  ++n_placed;
894  } else if (first_short) {
895  first_short = false;
896  if (tc.score() > eoccs[start_seed + is].refBestShortCand().score()) {
897  eoccs[start_seed + is].setBestShortCand(tc);
898  }
899  }
900  }
901 
902  tmp_cands[is].clear();
903  }
904  }
905 
906  } // end of layer loop
907  mkfndr->release();
908 
909  // final sorting
910  for (int iseed = start_seed; iseed < end_seed; ++iseed) {
911  eoccs[iseed].mergeCandsAndBestShortOne(m_job->params(), st_par.m_track_scorer, true, true);
912  }
913  }); // end parallel-for over chunk of seeds within region
914  }); // end of parallel-for-each over eta regions
915 
916  // debug = false;
917  }
918 
919  //------------------------------------------------------------------------------
920  // FindTracksCombinatorial: CloneEngine TBB
921  //------------------------------------------------------------------------------
922 
924  // debug = true;
925 
927 
928  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
929  if (iteration_dir == SteeringParams::IT_BkwSearch && !m_job->steering_params(region).has_bksearch_plan()) {
930  printf("No backward search plan for region %d\n", region);
931  return;
932  }
933 
934  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
935 
936  // adaptive seeds per task based on the total estimated amount of work to divide among all threads
937  const int adaptiveSPT = std::clamp(
939  dprint("adaptiveSPT " << adaptiveSPT << " fill " << rosi.count() << "/" << eoccs.size() << " region " << region);
940 
941  tbb::parallel_for(rosi.tbb_blk_rng_std(adaptiveSPT), [&](const tbb::blocked_range<int> &seeds) {
942  auto cloner = g_exe_ctx.m_cloners.makeOrGet();
943  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
944 
945  cloner->setup(m_job->params());
946 
947  // loop over layers
948  find_tracks_in_layers(*cloner, mkfndr.get(), iteration_dir, seeds.begin(), seeds.end(), region);
949 
950  mkfndr->release();
951  cloner->release();
952  });
953  });
954 
955  // debug = false;
956  }
957 
959  MkFinder *mkfndr,
960  SteeringParams::IterationType_e iteration_dir,
961  const int start_seed,
962  const int end_seed,
963  const int region) {
965  const TrackerInfo &trk_info = m_job->m_trk_info;
966  const SteeringParams &st_par = m_job->steering_params(region);
967  const IterationParams &params = m_job->params();
968  const PropagationConfig &prop_config = PropagationConfig::get_default();
969 
970  const int n_seeds = end_seed - start_seed;
971 
972  std::vector<std::pair<int, int>> seed_cand_idx;
973  std::vector<UpdateIndices> seed_cand_update_idx;
974  seed_cand_idx.reserve(n_seeds * params.maxCandsPerSeed);
975  seed_cand_update_idx.reserve(n_seeds * params.maxCandsPerSeed);
976 
977  std::vector<std::vector<TrackCand>> extra_cands(n_seeds);
978  for (int ii = 0; ii < n_seeds; ++ii)
979  extra_cands[ii].reserve(params.maxCandsPerSeed);
980 
981  cloner.begin_eta_bin(&eoccs, &seed_cand_update_idx, &extra_cands, start_seed, n_seeds);
982 
983  // Loop over layers, starting from after the seed.
984 
985  auto layer_plan_it = st_par.make_iterator(iteration_dir);
986 
987  dprintf("Made iterator for %d, first layer=%d ... end layer=%d\n",
988  iteration_dir,
989  layer_plan_it.layer(),
990  layer_plan_it.last_layer());
991 
992  assert(layer_plan_it.is_pickup_only());
993 
994  int curr_layer = layer_plan_it.layer(), prev_layer;
995 
996  dprintf(
997  "\nMkBuilder::find_tracks_in_layers region=%d, seed_pickup_layer=%d, first_layer=%d; start_seed=%d, "
998  "end_seed=%d\n",
999  region,
1000  curr_layer,
1001  layer_plan_it.next_layer(),
1002  start_seed,
1003  end_seed);
1004 
1005  auto &iter_params = (iteration_dir == SteeringParams::IT_BkwSearch) ? m_job->m_iter_config.m_backward_params
1007 
1008  // Loop over layers according to plan.
1009  while (++layer_plan_it) {
1010  prev_layer = curr_layer;
1011  curr_layer = layer_plan_it.layer();
1012  mkfndr->setup(prop_config,
1013  iter_params,
1014  m_job->m_iter_config.m_layer_configs[curr_layer],
1015  st_par,
1016  m_job->get_mask_for_layer(curr_layer),
1017  m_job->m_in_fwd);
1018 
1019  const bool pickup_only = layer_plan_it.is_pickup_only();
1020 
1021  dprintf("\n\n* Processing layer %d, %s\n\n", curr_layer, pickup_only ? "pickup only" : "full finding");
1022 
1023  const LayerInfo &layer_info = trk_info.layer(curr_layer);
1024  const LayerOfHits &layer_of_hits = m_job->m_event_of_hits[curr_layer];
1025  const FindingFoos &fnd_foos = FindingFoos::get_finding_foos(layer_info.is_barrel());
1026 
1027  const int theEndCand = find_tracks_unroll_candidates(
1028  seed_cand_idx, start_seed, end_seed, curr_layer, prev_layer, pickup_only, iteration_dir);
1029 
1030  dprintf(" Number of candidates to process: %d, nHits in layer: %d\n", theEndCand, layer_of_hits.nHits());
1031 
1032  // Don't bother messing with the clone engine if there are no candidates
1033  // (actually it crashes, so this protection is needed).
1034  // If there are no cands on this iteration, there won't be any later on either,
1035  // by the construction of the seed_cand_idx vector.
1036  // XXXXMT There might be cases in endcap where all tracks will miss the
1037  // next layer, but only relevant if we do geometric selection before.
1038 
1039  if (pickup_only || theEndCand == 0)
1040  continue;
1041 
1042  cloner.begin_layer(curr_layer);
1043 
1044  //vectorized loop
1045  for (int itrack = 0; itrack < theEndCand; itrack += NN) {
1046  const int end = std::min(itrack + NN, theEndCand);
1047 
1048 #ifdef DEBUG
1049  dprintf("\nProcessing track=%d, start_seed=%d, n_seeds=%d, theEndCand=%d, end=%d, nn=%d, end_eq_tec=%d\n",
1050  itrack,
1051  start_seed,
1052  n_seeds,
1053  theEndCand,
1054  end,
1055  end - itrack,
1056  end == theEndCand);
1057  dprintf(" (seed,cand): ");
1058  for (int i = itrack; i < end; ++i)
1059  dprintf("(%d,%d) ", seed_cand_idx[i].first, seed_cand_idx[i].second);
1060  dprintf("\n");
1061 #endif
1062 
1063  mkfndr->inputTracksAndHitIdx(eoccs.refCandidates(), seed_cand_idx, itrack, end, false);
1064 
1065 #ifdef DEBUG
1066  for (int i = itrack; i < end; ++i)
1067  dprintf(" track %d, idx %d is from seed %d\n", i, i - itrack, mkfndr->m_Label(i - itrack, 0, 0));
1068 #endif
1069 
1070  // propagate to current layer
1071  mkfndr->clearFailFlag();
1072  (mkfndr->*fnd_foos.m_propagate_foo)(
1073  layer_info.propagate_to(), end - itrack, prop_config.finding_inter_layer_pflags);
1074 
1075  dprint("now get hit range");
1076 
1077 #ifdef DUMPHITWINDOW
1078  mkfndr->m_event = m_event;
1079 #endif
1080 
1081  mkfndr->selectHitIndices(layer_of_hits, end - itrack);
1082 
1084  mkfndr, layer_info, extra_cands, seed_cand_idx, region, start_seed, itrack, end);
1085 
1086  // copy_out the propagated track params, errors only.
1087  // Do not, keep cands at last valid hit until actual update,
1088  // this requires change to propagation flags used in MkFinder::updateWithLastHit()
1089  // from intra-layer to inter-layer.
1090  // mkfndr->copyOutParErr(eoccs.refCandidates_nc(), end - itrack, true);
1091 
1092  dprint("make new candidates");
1093  cloner.begin_iteration();
1094 
1095  mkfndr->findCandidatesCloneEngine(layer_of_hits, cloner, start_seed, end - itrack, fnd_foos);
1096 
1097  cloner.end_iteration();
1098  } //end of vectorized loop
1099 
1100  cloner.end_layer();
1101 
1102  // Update loop of best candidates. CandCloner prepares the list of those
1103  // that need update (excluding all those with negative last hit index).
1104 
1105  const int theEndUpdater = seed_cand_update_idx.size();
1106 
1107  for (int itrack = 0; itrack < theEndUpdater; itrack += NN) {
1108  const int end = std::min(itrack + NN, theEndUpdater);
1109 
1110  mkfndr->inputTracksAndHits(eoccs.refCandidates(), layer_of_hits, seed_cand_update_idx, itrack, end, true);
1111 
1112  mkfndr->updateWithLoadedHit(end - itrack, fnd_foos);
1113 
1114  // copy_out the updated track params, errors only (hit-idcs and chi2 already set)
1115  mkfndr->copyOutParErr(eoccs.refCandidates_nc(), end - itrack, false);
1116  }
1117 
1118  // Check if cands are sorted, as expected.
1119 #ifdef DEBUG
1120  for (int iseed = start_seed; iseed < end_seed; ++iseed) {
1121  auto &cc = eoccs[iseed];
1122 
1123  for (int i = 0; i < ((int)cc.size()) - 1; ++i) {
1124  if (cc[i].score() < cc[i + 1].score()) {
1125  printf("CloneEngine - NOT SORTED: layer=%d, iseed=%d (size=%lu)-- %d : %f smaller than %d : %f\n",
1126  curr_layer,
1127  iseed,
1128  cc.size(),
1129  i,
1130  cc[i].score(),
1131  i + 1,
1132  cc[i + 1].score());
1133  }
1134  }
1135  }
1136 #endif
1137 
1138  } // end of layer loop
1139 
1140  cloner.end_eta_bin();
1141 
1142  // final sorting
1143  for (int iseed = start_seed; iseed < end_seed; ++iseed) {
1144  eoccs[iseed].mergeCandsAndBestShortOne(m_job->params(), st_par.m_track_scorer, true, true);
1145  }
1146  }
1147 
1148  //==============================================================================
1149  // BackwardFit
1150  //==============================================================================
1151 
1152 #ifdef DEBUG_FINAL_FIT
1153  namespace {
1154  // clang-format off
1155  void dprint_tcand(const TrackCand &t, int i) {
1156  dprintf(" %4d with q=%+d chi2=%7.3f pT=%7.3f eta=% 7.3f x=%.3f y=%.3f z=%.3f"
1157  " nHits=%2d label=%4d findable=%d\n",
1158  i, t.charge(), t.chi2(), t.pT(), t.momEta(), t.x(), t.y(), t.z(),
1159  t.nFoundHits(), t.label(), t.isFindable());
1160  }
1161  // clang-format on
1162  } // namespace
1163 #endif
1164 
1166  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
1167  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
1168 
1169  tbb::parallel_for(rosi.tbb_blk_rng_vec(), [&](const tbb::blocked_range<int> &blk_rng) {
1170  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
1171 
1172  RangeOfSeedIndices rng = rosi.seed_rng(blk_rng);
1173 
1174  while (rng.valid()) {
1175  // final backward fit
1176  fit_cands_BH(mkfndr.get(), rng.m_beg, rng.m_end, region);
1177 
1178  ++rng;
1179  }
1180  });
1181  });
1182  }
1183 
1184  void MkBuilder::fit_cands_BH(MkFinder *mkfndr, int start_cand, int end_cand, int region) {
1185  const SteeringParams &st_par = m_job->steering_params(region);
1186  const PropagationConfig &prop_config = PropagationConfig::get_default();
1187 #ifdef DEBUG_FINAL_FIT
1189  bool debug = true;
1190 #endif
1191 
1192  for (int icand = start_cand; icand < end_cand; icand += NN) {
1193  const int end = std::min(icand + NN, end_cand);
1194 
1195 #ifdef DEBUG_FINAL_FIT
1196  dprintf("Pre Final fit for %d - %d\n", icand, end);
1197  for (int i = icand; i < end; ++i) {
1198  dprint_tcand(eoccs[i][0], i);
1199  }
1200 #endif
1201 
1202  bool chi_debug = false;
1203 #ifdef DEBUG_BACKWARD_FIT_BH
1204  redo_fit:
1205 #endif
1206 
1207  // input candidate tracks
1208  mkfndr->bkFitInputTracks(m_tracks, icand, end);
1209 
1210  // perform fit back to first layer on track
1211  mkfndr->bkFitFitTracksBH(m_job->m_event_of_hits, st_par, end - icand, chi_debug);
1212 
1213  // now move one last time to PCA
1214  if (prop_config.backward_fit_to_pca) {
1215  mkfndr->bkFitPropTracksToPCA(end - icand);
1216  }
1217 
1218 #ifdef DEBUG_BACKWARD_FIT_BH
1219  // Dump tracks with pT > 2 and chi2/dof > 20. Assumes MPT_SIZE=1.
1220  if (!chi_debug && 1.0f / mkfndr->m_Par[MkBase::iP].At(0, 3, 0) > 2.0f &&
1221  mkfndr->m_Chi2(0, 0, 0) / (eoccs[icand][0].nFoundHits() * 3 - 6) > 20.0f) {
1222  chi_debug = true;
1223 #ifdef MKFIT_STANDALONE
1224  printf("CHIHDR Event %d, Cand %3d, pT %f, chipdof %f ### NOTE x,y,z in cm, sigmas, deltas in mum ### !!!\n",
1225  m_event->evtID(),
1226 #else
1227  printf("CHIHDR Cand %3d, pT %f, chipdof %f ### NOTE x,y,z in cm, sigmas, deltas in mum ### !!!\n",
1228 #endif
1229  icand,
1230  1.0f / mkfndr->m_Par[MkBase::iP].At(0, 3, 0),
1231  mkfndr->m_Chi2(0, 0, 0) / (eoccs[icand][0].nFoundHits() * 3 - 6));
1232  // clang-format off
1233  printf("CHIHDR %3s %10s"
1234  " %10s %10s %10s %10s %11s %11s %11s"
1235  " %10s %10s %10s %10s %11s %11s %11s"
1236  " %10s %10s %10s %10s %10s %11s %11s\n",
1237  "lyr", "chi2",
1238  "x_h", "y_h", "z_h", "r_h", "sx_h", "sy_h", "sz_h",
1239  "x_t", "y_t", "z_t", "r_t", "sx_t", "sy_t", "sz_t",
1240  "pt", "phi", "theta", "phi_h", "phi_t", "d_xy", "d_z");
1241  // clang-format on
1242  goto redo_fit;
1243  }
1244 #endif
1245 
1246  // copy out full set of info at last propagated position
1247  mkfndr->bkFitOutputTracks(m_tracks, icand, end, prop_config.backward_fit_to_pca);
1248 
1249 #ifdef DEBUG_FINAL_FIT
1250  dprintf("Post Final fit for %d - %d\n", icand, end);
1251  for (int i = icand; i < end; ++i) {
1252  dprint_tcand(eoccs[i][0], i);
1253  }
1254 #endif
1255  }
1256  }
1257 
1258  //------------------------------------------------------------------------------
1259 
1262 
1263  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
1264  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
1265 
1266  // adaptive seeds per task based on the total estimated amount of work to divide among all threads
1267  const int adaptiveSPT = std::clamp(
1269  dprint("adaptiveSPT " << adaptiveSPT << " fill " << rosi.count() << "/" << eoccs.size() << " region " << region);
1270 
1271  tbb::parallel_for(rosi.tbb_blk_rng_std(adaptiveSPT), [&](const tbb::blocked_range<int> &cands) {
1272  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
1273 
1274  fit_cands(mkfndr.get(), cands.begin(), cands.end(), region);
1275  });
1276  });
1277  }
1278 
1279  void MkBuilder::fit_cands(MkFinder *mkfndr, int start_cand, int end_cand, int region) {
1281  const SteeringParams &st_par = m_job->steering_params(region);
1282  const PropagationConfig &prop_config = PropagationConfig::get_default();
1283  mkfndr->setup_bkfit(prop_config, st_par);
1284 
1285  int step = NN;
1286  for (int icand = start_cand; icand < end_cand; icand += step) {
1287  int end = std::min(icand + NN, end_cand);
1288 
1289  bool chi_debug = false;
1290 
1291 #ifdef DEBUG_FINAL_FIT
1292  bool debug = true;
1293  dprintf("Pre Final fit for %d - %d\n", icand, end);
1294  for (int i = icand; i < end; ++i) {
1295  dprint_tcand(eoccs[i][0], i);
1296  }
1297  chi_debug = true;
1298  static bool first = true;
1299  if (first) {
1300  // ./mkFit ... | perl -ne 'if (/^BKF_OVERLAP/) { s/^BKF_OVERLAP //og; print; }' > bkf_ovlp.rtt
1301  dprintf(
1302  "BKF_OVERLAP event/I:label/I:prod_type/I:is_findable/I:layer/I:is_stereo/I:is_barrel/I:"
1303  "pt/F:pt_cur/F:eta/F:phi/F:phi_cur/F:r_cur/F:z_cur/F:chi2/F:isnan/I:isfin/I:gtzero/I:hit_label/I:"
1304  "sx_t/F:sy_t/F:sz_t/F:d_xy/F:d_z/F\n");
1305  first = false;
1306  }
1307  mkfndr->m_event = m_event;
1308 #endif
1309 
1310  // input tracks
1311  mkfndr->bkFitInputTracks(eoccs, icand, end);
1312 
1313  // fit tracks back to first layer
1314  mkfndr->bkFitFitTracks(m_job->m_event_of_hits, st_par, end - icand, chi_debug);
1315 
1316  // now move one last time to PCA
1317  if (prop_config.backward_fit_to_pca) {
1318  mkfndr->bkFitPropTracksToPCA(end - icand);
1319  }
1320 
1321  mkfndr->bkFitOutputTracks(eoccs, icand, end, prop_config.backward_fit_to_pca);
1322 
1323 #ifdef DEBUG_FINAL_FIT
1324  dprintf("Post Final fit for %d - %d\n", icand, end);
1325  for (int i = icand; i < end; ++i) {
1326  dprint_tcand(eoccs[i][0], i);
1327  }
1328 #endif
1329  }
1330  mkfndr->release();
1331  }
1332 
1333 } // end namespace mkfit
const IterationConfig & m_iter_config
Definition: MkJob.h:12
size
Write out results.
void import_seeds(const TrackVec &in_seeds, const bool seeds_sorted, std::function< insert_seed_foo > insert_seed)
Definition: MkBuilder.cc:228
void addHitIdx(int hitIdx, int hitLyr, float chi2)
int find_tracks_unroll_candidates(std::vector< std::pair< int, int >> &seed_cand_vec, int start_seed, int end_seed, int layer, int prev_layer, bool pickup_only, SteeringParams::IterationType_e iteration_dir)
Definition: MkBuilder.cc:618
IterationParams m_params
static void populate()
Definition: MkBuilder.cc:168
std::pair< int, int > max_hits_layer(const EventOfHits &eoh) const
Definition: MkBuilder.cc:170
#define CMS_SA_ALLOW
void export_tracks(TrackVec &out_vec)
Definition: MkBuilder.cc:396
IterationParams m_backward_params
void findTracksBestHit(SteeringParams::IterationType_e iteration_dir=SteeringParams::IT_FwdSearch)
Definition: MkBuilder.cc:454
Track exportTrack(bool remove_missing_hits=false) const
static constexpr int iP
Definition: MkBase.h:17
void resizeAfterFiltering(int n_removed)
float rin() const
Definition: TrackerInfo.h:58
float pT() const
Definition: Track.h:171
T w() const
void inputTracksAndHitIdx(const std::vector< Track > &tracks, int beg, int end, bool inputProp)
Definition: MkFinder.cc:53
void bkFitInputTracks(TrackVec &cands, int beg, int end)
Definition: MkFinder.cc:1403
for(int i=first, nt=offsets[nh];i< nt;i+=gridDim.x *blockDim.x)
void setup_bkfit(const PropagationConfig &pc, const SteeringParams &sp)
Definition: MkFinder.cc:35
uint32_t cc[maxCellsPerHit]
Definition: gpuFishbone.h:49
constexpr bool nan_n_silly_print_bad_seeds
Definition: Config.h:62
std::atomic< int > m_nan_n_silly_per_layer_count
Definition: MkBuilder.h:137
void find_min_max_hots_size()
Definition: MkBuilder.cc:356
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
const auto regions_begin() const
Definition: MkJob.h:22
MPlexLV m_Par[2]
Definition: MkBase.h:99
void(MkBase::* m_propagate_foo)(float, const int, const PropagationFlags)
Definition: FindingFoos.h:22
constexpr Process operator++(Process p)
Definition: DataFormats.h:68
void selectHitIndices(const LayerOfHits &layer_of_hits, const int N_proc)
Definition: MkFinder.cc:248
void setState(SeedState_e ss)
void findTracksCloneEngine(SteeringParams::IterationType_e iteration_dir=SteeringParams::IT_FwdSearch)
Definition: MkBuilder.cc:923
int nLayers() const
void bkFitPropTracksToPCA(const int N_proc)
Definition: MkFinder.cc:1889
int evtID() const
Definition: Event.h:23
constexpr bool nan_n_silly_check_seeds
Definition: Config.h:61
void inputTracksAndHits(const std::vector< CombCandidate > &tracks, const LayerOfHits &layer_of_hits, const std::vector< UpdateIndices > &idxs, int beg, int end, bool inputProp)
Definition: MkFinder.cc:107
float propagate_to() const
Definition: TrackerInfo.h:64
void begin_event(MkJob *job, Event *ev, const char *build_type)
Definition: MkBuilder.cc:194
void release()
Definition: MkFinder.cc:40
assert(be >=bs)
const auto & params() const
Definition: MkJob.h:27
const EventOfHits & m_event_of_hits
Definition: MkJob.h:13
constexpr bool nan_n_silly_fixup_bad_cands_every_layer
Definition: Config.h:68
Definition: Electron.h:6
void finalize_registration()
Definition: binnor.h:289
void insertSeed(const Track &seed, const track_score_func &score_func, int region, int pos)
track_score_func m_track_scorer
void backwardFitBH()
Definition: MkBuilder.cc:1165
unsigned int nHits() const
Definition: HitStructures.h:68
U second(std::pair< T, U > const &p)
#define dcall(x)
Definition: Debug.h:97
void end_iteration()
Definition: CandCloner.cc:63
char const * label
PropagationFlags finding_inter_layer_pflags
Definition: Config.h:32
std::vector< C > m_ranks
Definition: binnor.h:211
void find_tracks_load_seeds_BH(const TrackVec &in_seeds, const bool seeds_sorted)
Definition: MkBuilder.cc:439
float score() const
Definition: Track.h:187
void findTracksStandard(SteeringParams::IterationType_e iteration_dir=SteeringParams::IT_FwdSearch)
Definition: MkBuilder.cc:741
std::function< filter_candidates_cf > filter_candidates_func
Definition: FunctionTypes.h:28
iterator make_iterator(IterationType_e type) const
static const PropagationConfig & get_default()
Definition: Config.h:41
std::vector< IterationLayerConfig > m_layer_configs
void reset(int new_capacity, int max_cands_per_seed, int expected_num_hots=128)
void find_tracks_load_seeds(const TrackVec &in_seeds, const bool seeds_sorted)
Definition: MkBuilder.cc:606
constexpr float PI
Definition: Config.h:50
void release_memory()
Definition: MkBuilder.cc:222
constexpr bool nan_n_silly_remove_bad_seeds
Definition: Config.h:64
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
TrackVec m_tracks
Definition: MkBuilder.h:127
void register_entry_safe(typename A1::real_t r1, typename A2::real_t r2)
Definition: binnor.h:282
constexpr Matriplex::idx_t NN
Definition: Matrix.h:43
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
partition_seeds_func m_seed_partitioner
int layer_id() const
Definition: TrackerInfo.h:56
std::vector< int > m_seedEtaSeparators
Definition: MkBuilder.h:133
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
MPlexQI m_XHitSize
Definition: MkFinder.h:316
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void seed_post_cleaning(TrackVec &tv)
Definition: MkBuilder.cc:407
ExecutionContext g_exe_ctx
Definition: MkBuilder.cc:49
Pool< MkFinder > m_finders
Definition: MkBuilder.cc:40
double f[11][100]
Event * m_event
Definition: MkBuilder.h:124
float getHypot(float x, float y)
Definition: Hit.h:47
void clearFailFlag()
Definition: MkBase.h:93
void select_best_comb_cands(bool clear_m_tracks=false, bool remove_missing_hits=false)
Definition: MkBuilder.cc:378
constexpr int numThreadsFinder
Definition: Config.h:128
int filter_comb_cands(filter_candidates_func filter, bool attempt_all_cands)
Definition: MkBuilder.cc:301
Pool< CandCloner > m_cloners
Definition: MkBuilder.cc:38
int total_cands() const
Definition: MkBuilder.cc:183
void begin_registration(C n_items)
Definition: binnor.h:264
ii
Definition: cuy.py:589
trk_cand_vec_type::size_type size() const
const LayerInfo & layer(int l) const
Definition: TrackerInfo.h:162
const auto & steering_params(int i)
Definition: MkJob.h:25
const TrackerInfo & m_trk_info
Definition: MkJob.h:10
bool m_in_fwd
Definition: MkJob.h:18
std::vector< Track > TrackVec
constexpr bool nan_n_silly_fixup_bad_seeds
Definition: Config.h:63
void begin_layer(int lay)
Definition: CandCloner.cc:46
Pool< MkFitter > m_fitters
Definition: MkBuilder.cc:39
#define debug
Definition: HDRShower.cc:19
const std::vector< CombCandidate > & refCandidates() const
int iseed
Definition: AMPTWrapper.h:134
bool sortByScoreTrackCand(const TrackCand &cand1, const TrackCand &cand2)
void bkFitFitTracks(const EventOfHits &eventofhits, const SteeringParams &st_par, const int N_proc, bool chiDebug=false)
Definition: MkFinder.cc:1661
EventOfCombCandidates m_event_of_comb_cands
Definition: MkBuilder.h:130
std::vector< CombCandidate > & refCandidates_nc()
void find_tracks_handle_missed_layers(MkFinder *mkfndr, const LayerInfo &layer_info, std::vector< std::vector< TrackCand >> &tmp_cands, const std::vector< std::pair< int, int >> &seed_cand_idx, const int region, const int start_seed, const int itrack, const int end)
Definition: MkBuilder.cc:683
static const FindingFoos & get_finding_foos(bool is_barrel)
Definition: FindingFoos.cc:18
part
Definition: HCALResponse.h:20
void updateWithLoadedHit(int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1351
std::vector< int > m_seedMaxLastLayer
Definition: MkBuilder.h:135
void populate(int n_thr)
Definition: MkBuilder.cc:42
float rout() const
Definition: TrackerInfo.h:59
constexpr bool nan_n_silly_check_cands_every_layer
Definition: Config.h:66
int getLastHitIdx() const
void begin_iteration()
Definition: CandCloner.cc:59
#define dprint(x)
Definition: Debug.h:95
MPlexQF m_Chi2
Definition: MkFinder.h:280
void export_best_comb_cands(TrackVec &out_vec, bool remove_missing_hits=false)
Definition: MkBuilder.cc:384
void bkFitOutputTracks(TrackVec &cands, int beg, int end, bool outputProp)
Definition: MkFinder.cc:1460
void bkFitFitTracksBH(const EventOfHits &eventofhits, const SteeringParams &st_par, const int N_proc, bool chiDebug=false)
Definition: MkFinder.cc:1508
static std::unique_ptr< MkBuilder > make_builder(bool silent=true)
Definition: MkBuilder.cc:166
constexpr int numSeedsPerTask
Definition: Config.h:130
constexpr int numThreadsEvents
Definition: Config.h:129
const auto regions_end() const
Definition: MkJob.h:23
int getLastHitLyr() const
void copyOutParErr(std::vector< CombCandidate > &seed_cand_vec, int N_proc, bool outputProp) const
Definition: MkFinder.cc:1382
void findCandidatesCloneEngine(const LayerOfHits &layer_of_hits, CandCloner &cloner, const int offset, const int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1151
void fit_cands(MkFinder *mkfndr, int start_cand, int end_cand, int region)
Definition: MkBuilder.cc:1279
const std::vector< bool > * get_mask_for_layer(int layer)
Definition: MkJob.h:33
void begin_eta_bin(EventOfCombCandidates *e_o_ccs, std::vector< UpdateIndices > *update_list, std::vector< std::vector< TrackCand >> *extra_cands, int start_seed, int n_seeds)
Definition: CandCloner.cc:25
while(__syncthreads_or(more))
int max_max_cands() const
Definition: MkJob.h:31
step
Definition: StallMonitor.cc:98
std::vector< int > m_seedMinLastLayer
Definition: MkBuilder.h:134
int originIndex() const
tmp
align.sh
Definition: createJobs.py:716
WSR_Result m_XWsrResult[NN]
Definition: MkFinder.h:315
constexpr bool nan_n_silly_print_bad_cands_every_layer
Definition: Config.h:67
void reset(double vett[256])
Definition: TPedValues.cc:11
int num_regions() const
Definition: MkJob.h:21
SeedState_e state() const
T & At(idx_t n, idx_t i, idx_t j)
Definition: Matriplex.h:54
#define dprintf(...)
Definition: Debug.h:98
MPlexQI m_Label
Definition: MkFinder.h:281
void fit_cands_BH(MkFinder *mkfndr, int start_cand, int end_cand, int region)
Definition: MkBuilder.cc:1184
bool is_barrel() const
Definition: TrackerInfo.h:68
void setup(const PropagationConfig &pc, const IterationParams &ip, const IterationLayerConfig &ilc, const SteeringParams &sp, const std::vector< bool > *ihm, bool infwd)
Definition: MkFinder.cc:21
void find_tracks_in_layers(CandCloner &cloner, MkFinder *mkfndr, SteeringParams::IterationType_e iteration_dir, const int start_seed, const int end_seed, const int region)
Definition: MkBuilder.cc:958
const Hit & refHit(int i) const
Definition: HitStructures.h:97
float getPar(int itrack, int i, int par) const
Definition: MkBase.h:19