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