CMS 3D CMS Logo

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