CMS 3D CMS Logo

MkFinder.cc
Go to the documentation of this file.
1 #include "MkFinder.h"
2 
5 #include "CandCloner.h"
6 #include "FindingFoos.h"
7 #include "KalmanUtilsMPlex.h"
8 #include "MatriplexPackers.h"
9 #include "MiniPropagators.h"
10 
11 //#define DEBUG
12 #include "Debug.h"
13 
14 #if defined(MKFIT_STANDALONE)
16 #endif
17 
18 #ifdef RNT_DUMP_MkF_SelHitIdcs
19 // declares struct RntIfc_selectHitIndices rnt_shi in unnamed namespace;
20 #include "RecoTracker/MkFitCore/standalone/RntDumper/MkFinder_selectHitIndices.icc"
21 #endif
22 
23 #include "vdt/atan2.h"
24 
25 #include <algorithm>
26 #include <queue>
27 
28 namespace mkfit {
29 
31  const IterationConfig &ic,
32  const IterationParams &ip,
33  const IterationLayerConfig &ilc,
34  const SteeringParams &sp,
35  const std::vector<bool> *ihm,
36  const Event *ev,
37  int region,
38  bool infwd) {
39  m_prop_config = &pc;
40  m_iteration_config = &ic;
41  m_iteration_params = &ip;
43  m_steering_params = &sp;
45  m_event = ev;
47  m_in_fwd = infwd;
48  }
49 
50  void MkFinder::setup_bkfit(const PropagationConfig &pc, const SteeringParams &sp, const Event *ev) {
51  m_prop_config = &pc;
52  m_steering_params = &sp;
53  m_event = ev;
54  }
55 
57  m_prop_config = nullptr;
58  m_iteration_config = nullptr;
59  m_iteration_params = nullptr;
60  m_iteration_layer_config = nullptr;
61  m_steering_params = nullptr;
62  m_iteration_hit_mask = nullptr;
63  m_event = nullptr;
64  m_current_region = -1;
65  m_in_fwd = true;
66  }
67 
68  void MkFinder::begin_layer(const LayerOfHits &layer_of_hits) {
69 #ifdef RNT_DUMP_MkF_SelHitIdcs
70  const LayerOfHits &L = layer_of_hits;
71  const LayerInfo &LI = L.layer_info();
72  rnt_shi.ResetH();
73  rnt_shi.ResetF();
74  *rnt_shi.h = {m_event->evtID(),
78  L.layer_id(),
79  L.is_barrel() ? LI.rin() : LI.zmin(),
80  LI.is_barrel() ? LI.rout() : LI.zmax(),
81  L.is_barrel(),
82  L.is_pixel(),
83  L.is_stereo()};
84  *rnt_shi.f = *rnt_shi.h;
85 #endif
86  }
87 
89 #ifdef RNT_DUMP_MkF_SelHitIdcs
90  rnt_shi.FillH();
91  rnt_shi.FillF();
92 #endif
93  }
94 
95  //==============================================================================
96  // Input / Output TracksAndHitIdx
97  //==============================================================================
98 
99  void MkFinder::inputTracksAndHitIdx(const std::vector<Track> &tracks, int beg, int end, bool inputProp) {
100  // Assign track parameters to initial state and copy hit values in.
101 
102  // This might not be true for the last chunk!
103  // assert(end - beg == NN);
104 
105  const int iI = inputProp ? iP : iC;
106 
107  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
108  copy_in(tracks[i], imp, iI);
109  }
110  }
111 
113  const std::vector<Track> &tracks, const std::vector<int> &idxs, int beg, int end, bool inputProp, int mp_offset) {
114  // Assign track parameters to initial state and copy hit values in.
115 
116  // This might not be true for the last chunk!
117  // assert(end - beg == NN);
118 
119  const int iI = inputProp ? iP : iC;
120 
121  for (int i = beg, imp = mp_offset; i < end; ++i, ++imp) {
122  copy_in(tracks[idxs[i]], imp, iI);
123  }
124  }
125 
126  void MkFinder::inputTracksAndHitIdx(const std::vector<CombCandidate> &tracks,
127  const std::vector<std::pair<int, int>> &idxs,
128  int beg,
129  int end,
130  bool inputProp) {
131  // Assign track parameters to initial state and copy hit values in.
132 
133  // This might not be true for the last chunk!
134  // assert(end - beg == NN);
135 
136  const int iI = inputProp ? iP : iC;
137 
138  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
139  const TrackCand &trk = tracks[idxs[i].first][idxs[i].second];
140 
141  copy_in(trk, imp, iI);
142 
143  m_SeedIdx(imp, 0, 0) = idxs[i].first;
144  m_CandIdx(imp, 0, 0) = idxs[i].second;
145  m_SeedOriginIdx[imp] = tracks[idxs[i].first].seed_origin_index();
146  }
147  }
148 
149  void MkFinder::inputTracksAndHits(const std::vector<CombCandidate> &tracks,
150  const LayerOfHits &layer_of_hits,
151  const std::vector<UpdateIndices> &idxs,
152  int beg,
153  int end,
154  bool inputProp) {
155  // Assign track parameters to initial state and copy hit values in.
156 
157  // This might not be true for the last chunk!
158  // assert(end - beg == NN);
159 
160  const int iI = inputProp ? iP : iC;
161 
162  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
163  const TrackCand &trk = tracks[idxs[i].seed_idx][idxs[i].cand_idx];
164 
165  copy_in(trk, imp, iI);
166 
167  m_SeedIdx(imp, 0, 0) = idxs[i].seed_idx;
168  m_CandIdx(imp, 0, 0) = idxs[i].cand_idx;
169  m_SeedOriginIdx[imp] = tracks[idxs[i].seed_idx].seed_origin_index();
170 
171  // Reuse selectHitIndices() arrays -- used also in packModuleNormDir()
172  m_XHitArr(imp, 0, 0) = idxs[i].hit_idx;
173  m_XHitSize(imp, 0, 0) = 1;
174 
175  const Hit &hit = layer_of_hits.refHit(idxs[i].hit_idx);
176  m_msErr.copyIn(imp, hit.errArray());
177  m_msPar.copyIn(imp, hit.posArray());
178  }
179  }
180 
181  void MkFinder::inputOverlapHits(const LayerOfHits &layer_of_hits,
182  const std::vector<UpdateIndices> &idxs,
183  int beg,
184  int end) {
185  // Copy overlap hit values in.
186 
187  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
188  const Hit &hit = layer_of_hits.refHit(idxs[i].ovlp_idx);
189  m_msErr.copyIn(imp, hit.errArray());
190  m_msPar.copyIn(imp, hit.posArray());
191  }
192  }
193 
194  void MkFinder::inputTracksAndHitIdx(const std::vector<CombCandidate> &tracks,
195  const std::vector<std::pair<int, IdxChi2List>> &idxs,
196  int beg,
197  int end,
198  bool inputProp) {
199  // Assign track parameters to initial state and copy hit values in.
200 
201  // This might not be true for the last chunk!
202  // assert(end - beg == NN);
203 
204  const int iI = inputProp ? iP : iC;
205 
206  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
207  const TrackCand &trk = tracks[idxs[i].first][idxs[i].second.trkIdx];
208 
209  copy_in(trk, imp, iI);
210 
211  m_SeedIdx(imp, 0, 0) = idxs[i].first;
212  m_CandIdx(imp, 0, 0) = idxs[i].second.trkIdx;
213  m_SeedOriginIdx[imp] = tracks[idxs[i].first].seed_origin_index();
214  }
215  }
216 
217  void MkFinder::outputTracksAndHitIdx(std::vector<Track> &tracks, int beg, int end, bool outputProp) const {
218  // Copies requested track parameters into Track objects.
219  // The tracks vector should be resized to allow direct copying.
220 
221  const int iO = outputProp ? iP : iC;
222 
223  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
224  copy_out(tracks[i], imp, iO);
225  }
226  }
227 
229  std::vector<Track> &tracks, const std::vector<int> &idxs, int beg, int end, bool outputProp) const {
230  // Copies requested track parameters into Track objects.
231  // The tracks vector should be resized to allow direct copying.
232 
233  const int iO = outputProp ? iP : iC;
234 
235  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
236  copy_out(tracks[idxs[i]], imp, iO);
237  }
238  }
239 
241  const LayerOfHits &layer_of_hits, int hit_cnt, MPlexHV &norm, MPlexHV &dir, MPlexHV &pnt, int N_proc) const {
242  for (int itrack = 0; itrack < NN; ++itrack) {
243  if (itrack < N_proc && hit_cnt < m_XHitSize[itrack]) {
244  const auto &hit = layer_of_hits.refHit(m_XHitArr.constAt(itrack, hit_cnt, 0));
245  unsigned int mid = hit.detIDinLayer();
246  const ModuleInfo &mi = layer_of_hits.layer_info().module_info(mid);
247  norm.At(itrack, 0, 0) = mi.zdir[0];
248  norm.At(itrack, 1, 0) = mi.zdir[1];
249  norm.At(itrack, 2, 0) = mi.zdir[2];
250  dir.At(itrack, 0, 0) = mi.xdir[0];
251  dir.At(itrack, 1, 0) = mi.xdir[1];
252  dir.At(itrack, 2, 0) = mi.xdir[2];
253  pnt.At(itrack, 0, 0) = mi.pos[0];
254  pnt.At(itrack, 1, 0) = mi.pos[1];
255  pnt.At(itrack, 2, 0) = mi.pos[2];
256  //std::cout << "packModuleNormDirPnt id=" << hit_cnt << " norm=(" << mi.zdir[0] << ", " << mi.zdir[1] << ", " << mi.zdir[2] << ") - dir=(" << mi.xdir[0] << ", " << mi.xdir[1] << ", " << mi.xdir[2] << ") - pnt=(" << mi.pos[0] << ", " << mi.pos[1] << ", " << mi.pos[2] << ")" << std::endl;
257  }
258  }
259  }
260 
261  //==============================================================================
262  // getHitSelDynamicWindows
263  //==============================================================================
264  // From HitSelectionWindows.h: track-related config on hit selection windows
265 
267  const float invpt, const float theta, float &min_dq, float &max_dq, float &min_dphi, float &max_dphi) {
268  float max_invpt = std::min(invpt, 10.0f); // => pT>0.1 GeV
269 
270  enum SelWinParameters_e { dp_sf = 0, dp_0, dp_1, dp_2, dq_sf, dq_0, dq_1, dq_2 };
272 
273  if (!v.empty()) {
274  // dq hit selection window
275  const float this_dq = v[dq_sf] * (v[dq_0] * max_invpt + v[dq_1] * theta + v[dq_2]);
276  // In case value is below 0 (bad window derivation or other reasons), leave original limits
277  if (this_dq > 0.f) {
278  min_dq = this_dq;
279  max_dq = 2.0f * min_dq;
280  }
281 
282  // dphi hit selection window
283  const float this_dphi = v[dp_sf] * (v[dp_0] * max_invpt + v[dp_1] * theta + v[dp_2]);
284  // In case value is too low (bad window derivation or other reasons), leave original limits
285  if (this_dphi > min_dphi) {
286  min_dphi = this_dphi;
287  max_dphi = 2.0f * min_dphi;
288  }
289  }
290  }
291 
292  //==============================================================================
293  // getHitSelDynamicChi2Cut
294  //==============================================================================
295  // From HitSelectionWindows.h: track-related config on hit selection windows
296 
297  inline float MkFinder::getHitSelDynamicChi2Cut(const int itrk, const int ipar) {
298  const float minChi2Cut = m_iteration_params->chi2Cut_min;
299  const float invpt = m_Par[ipar].At(itrk, 3, 0);
300  const float theta = std::abs(m_Par[ipar].At(itrk, 5, 0) - Const::PIOver2);
301 
302  float max_invpt = std::min(invpt, 10.0f); // => pT>0.1 GeV
303 
304  enum SelWinParameters_e { c2_sf = 8, c2_0, c2_1, c2_2 };
306 
307  if (!v.empty()) {
308  float this_c2 = v[c2_sf] * (v[c2_0] * max_invpt + v[c2_1] * theta + v[c2_2]);
309  // In case value is too low (bad window derivation or other reasons), leave original limits
310  if (this_c2 > minChi2Cut)
311  return this_c2;
312  }
313  return minChi2Cut;
314  }
315 
316  //==============================================================================
317  // SelectHitIndices
318  //==============================================================================
319 
320  void MkFinder::selectHitIndices(const LayerOfHits &layer_of_hits, const int N_proc, bool fill_binsearch_only) {
321  // bool debug = true;
322  using bidx_t = LayerOfHits::bin_index_t;
323  using bcnt_t = LayerOfHits::bin_content_t;
324  const LayerOfHits &L = layer_of_hits;
326 
327  const int iI = iP;
328  const float nSigmaPhi = 3;
329  const float nSigmaZ = 3;
330  const float nSigmaR = 3;
331 
332  dprintf("LayerOfHits::SelectHitIndices %s layer=%d N_proc=%d\n",
333  L.is_barrel() ? "barrel" : "endcap",
334  L.layer_id(),
335  N_proc);
336 
337  float dqv[NN], dphiv[NN], qv[NN], phiv[NN];
338  bidx_t qb1v[NN], qb2v[NN], qbv[NN], pb1v[NN], pb2v[NN];
339 
340  const auto assignbins = [&](int itrack,
341  float q,
342  float dq,
343  float phi,
344  float dphi,
345  float min_dq,
346  float max_dq,
347  float min_dphi,
348  float max_dphi) {
349  dphi = std::clamp(std::abs(dphi), min_dphi, max_dphi);
350  dq = std::clamp(dq, min_dq, max_dq);
351  //
352  qv[itrack] = q;
353  phiv[itrack] = phi;
354  dphiv[itrack] = dphi;
355  dqv[itrack] = dq;
356  //
357  qbv[itrack] = L.qBinChecked(q);
358  qb1v[itrack] = L.qBinChecked(q - dq);
359  qb2v[itrack] = L.qBinChecked(q + dq) + 1;
360  pb1v[itrack] = L.phiBinChecked(phi - dphi);
361  pb2v[itrack] = L.phiMaskApply(L.phiBin(phi + dphi) + 1);
362  };
363 
364  const auto calcdphi2 = [&](int itrack, float dphidx, float dphidy) {
365  return dphidx * dphidx * m_Err[iI].constAt(itrack, 0, 0) + dphidy * dphidy * m_Err[iI].constAt(itrack, 1, 1) +
366  2 * dphidx * dphidy * m_Err[iI].constAt(itrack, 0, 1);
367  };
368 
369  const auto calcdphi = [&](float dphi2, float min_dphi) {
370  return std::max(nSigmaPhi * std::sqrt(std::abs(dphi2)), min_dphi);
371  };
372 
373  if (L.is_barrel()) {
374  // Pull out the part of the loop that vectorizes with icc and gcc
375  // In llvm16 clang issues a warning that it can't vectorize
376  // the loop. Unfortunately, there doesn't seem to be a
377  // pragma to suppress the warning, so we ifdef it out. This
378  // should be rechecked if llvm vectorization improves.
379 #if !defined(__clang__)
380 #pragma omp simd
381 #endif
382  for (int itrack = 0; itrack < NN; ++itrack) {
383  if (itrack >= N_proc)
384  continue;
385  m_XHitSize[itrack] = 0;
386 
387  float min_dq = ILC.min_dq();
388  float max_dq = ILC.max_dq();
389  float min_dphi = ILC.min_dphi();
390  float max_dphi = ILC.max_dphi();
391 
392  const float invpt = m_Par[iI].At(itrack, 3, 0);
393  const float theta = std::fabs(m_Par[iI].At(itrack, 5, 0) - Const::PIOver2);
394  getHitSelDynamicWindows(invpt, theta, min_dq, max_dq, min_dphi, max_dphi);
395 
396  const float x = m_Par[iI].constAt(itrack, 0, 0);
397  const float y = m_Par[iI].constAt(itrack, 1, 0);
398  const float r2 = x * x + y * y;
399  const float dphidx = -y / r2, dphidy = x / r2;
400  const float dphi2 = calcdphi2(itrack, dphidx, dphidy);
401 #ifdef HARD_CHECK
402  assert(dphi2 >= 0);
403 #endif
404 
405  const float phi = getPhi(x, y);
406  float dphi = calcdphi(dphi2, min_dphi);
407 
408  const float z = m_Par[iI].constAt(itrack, 2, 0);
409  const float dz = std::abs(nSigmaZ * std::sqrt(m_Err[iI].constAt(itrack, 2, 2)));
410  const float edgeCorr =
411  std::abs(0.5f * (L.layer_info().rout() - L.layer_info().rin()) / std::tan(m_Par[iI].constAt(itrack, 5, 0)));
412  // XXX-NUM-ERR above, m_Err(2,2) gets negative!
413 
414  m_XWsrResult[itrack] = L.is_within_z_sensitive_region(z, std::sqrt(dz * dz + edgeCorr * edgeCorr));
415  assignbins(itrack, z, dz, phi, dphi, min_dq, max_dq, min_dphi, max_dphi);
416 
417  // Relax propagation-fail detection to be in line with pre-43145.
418  if (m_FailFlag[itrack] && std::sqrt(r2) >= L.layer_info().rin()) {
419  m_FailFlag[itrack] = 0;
420  }
421  }
422  } else // endcap
423  {
424  //layer half-thikness for dphi spread calculation; only for very restrictive iters
425  const float layerD = std::abs(L.layer_info().zmax() - L.layer_info().zmin()) * 0.5f *
427  // Pull out the part of the loop that vectorizes with icc and gcc
428 #if !defined(__clang__)
429 #pragma omp simd
430 #endif
431  for (int itrack = 0; itrack < NN; ++itrack) {
432  m_XHitSize[itrack] = 0;
433 
434  float min_dq = ILC.min_dq();
435  float max_dq = ILC.max_dq();
436  float min_dphi = ILC.min_dphi();
437  float max_dphi = ILC.max_dphi();
438 
439  const float invpt = m_Par[iI].At(itrack, 3, 0);
440  const float theta = std::fabs(m_Par[iI].At(itrack, 5, 0) - Const::PIOver2);
441  getHitSelDynamicWindows(invpt, theta, min_dq, max_dq, min_dphi, max_dphi);
442 
443  const float x = m_Par[iI].constAt(itrack, 0, 0);
444  const float y = m_Par[iI].constAt(itrack, 1, 0);
445  const float r2 = x * x + y * y;
446  const float r2Inv = 1.f / r2;
447  const float dphidx = -y * r2Inv, dphidy = x * r2Inv;
448  const float phi = getPhi(x, y);
449  const float dphi2 =
450  calcdphi2(itrack, dphidx, dphidy)
451  //range from finite layer thickness
452  + std::pow(layerD * std::tan(m_Par[iI].At(itrack, 5, 0)) * std::sin(m_Par[iI].At(itrack, 4, 0) - phi), 2) *
453  r2Inv;
454 #ifdef HARD_CHECK
455  assert(dphi2 >= 0);
456 #endif
457 
458  float dphi = calcdphi(dphi2, min_dphi);
459 
460  const float r = std::sqrt(r2);
461  const float dr = nSigmaR * std::sqrt(std::abs(x * x * m_Err[iI].constAt(itrack, 0, 0) +
462  y * y * m_Err[iI].constAt(itrack, 1, 1) +
463  2 * x * y * m_Err[iI].constAt(itrack, 0, 1)) /
464  r2);
465  const float edgeCorr = std::abs(0.5f * (L.layer_info().zmax() - L.layer_info().zmin()) *
466  std::tan(m_Par[iI].constAt(itrack, 5, 0)));
467 
468  m_XWsrResult[itrack] = L.is_within_r_sensitive_region(r, std::sqrt(dr * dr + edgeCorr * edgeCorr));
469  assignbins(itrack, r, dr, phi, dphi, min_dq, max_dq, min_dphi, max_dphi);
470  }
471  }
472 
473 #ifdef RNT_DUMP_MkF_SelHitIdcs
474  if (fill_binsearch_only) {
475  // XXX loop over good indices (prepared in V2) and put in V1 BinSearch results
476  for (auto i : rnt_shi.f_h_idcs) {
477  CandInfo &ci = (*rnt_shi.ci)[rnt_shi.f_h_remap[i]];
478  ci.bso = BinSearch({phiv[i],
479  dphiv[i],
480  qv[i],
481  dqv[i],
482  pb1v[i],
483  pb2v[i],
484  qb1v[i],
485  qb2v[i],
488  false});
489  }
490  return;
491  }
492 #endif
493 
494  // Vectorizing this makes it run slower!
495  //#pragma omp simd
496  for (int itrack = 0; itrack < NN; ++itrack) {
497  if (itrack >= N_proc) {
498  continue;
499  }
500  // PROP-FAIL-ENABLE The following to be enabled when propagation failure
501  // detection is properly implemented in propagate-to-R/Z.
502  if (m_FailFlag[itrack]) {
503  m_XWsrResult[itrack].m_wsr = WSR_Failed;
504  continue;
505  }
506 
507  if (m_XWsrResult[itrack].m_wsr == WSR_Outside) {
508  continue;
509  }
510 
511  const bidx_t qb = qbv[itrack];
512  const bidx_t qb1 = qb1v[itrack];
513  const bidx_t qb2 = qb2v[itrack];
514  const bidx_t pb1 = pb1v[itrack];
515  const bidx_t pb2 = pb2v[itrack];
516 
517  const float q = qv[itrack];
518  const float phi = phiv[itrack];
519  const float dphi = dphiv[itrack];
520  const float dq = dqv[itrack];
521 
522  // clang-format off
523  dprintf(" %2d/%2d: %6.3f %6.3f %6.6f %7.5f %3u %3u %4u %4u\n",
524  L.layer_id(), itrack, q, phi, dq, dphi,
525  qb1, qb2, pb1, pb2);
526  // clang-format on
527 
528 #if defined(DUMPHITWINDOW) && defined(MKFIT_STANDALONE)
529  const auto ngr = [](float f) { return isFinite(f) ? f : -999.0f; };
530 
531  const int seed_lbl = m_event->currentSeed(m_SeedOriginIdx[itrack]).label();
533  const int seed_mcid = (slfh.is_set() && slfh.good_frac() > 0.7f) ? slfh.label : -999999;
534 #endif
535 
536  for (bidx_t qi = qb1; qi != qb2; ++qi) {
537  for (bidx_t pi = pb1; pi != pb2; pi = L.phiMaskApply(pi + 1)) {
538  // Limit to central Q-bin
539  if (qi == qb && L.isBinDead(pi, qi) == true) {
540  dprint("dead module for track in layer=" << L.layer_id() << " qb=" << qi << " pi=" << pi << " q=" << q
541  << " phi=" << phi);
542  m_XWsrResult[itrack].m_in_gap = true;
543  }
544 
545  // MT: The following line is the biggest hog (4% total run time).
546  // This comes from cache misses, I presume.
547  // It might make sense to make first loop to extract bin indices
548  // and issue prefetches at the same time.
549  // Then enter vectorized loop to actually collect the hits in proper order.
550 
551  //SK: ~20x1024 bin sizes give mostly 1 hit per bin. Commented out for 128 bins or less
552  // #pragma nounroll
553  auto pbi = L.phiQBinContent(pi, qi);
554  for (bcnt_t hi = pbi.begin(); hi < pbi.end(); ++hi) {
555  // MT: Access into m_hit_zs and m_hit_phis is 1% run-time each.
556 
557  const unsigned int hi_orig = L.getOriginalHitIndex(hi);
558 
559  if (m_iteration_hit_mask && (*m_iteration_hit_mask)[hi_orig]) {
560  dprintf(
561  "Yay, denying masked hit on layer %u, hi %u, orig idx %u\n", L.layer_info().layer_id(), hi, hi_orig);
562  continue;
563  }
564 
565  if (Config::usePhiQArrays) {
566  if (m_XHitSize[itrack] >= MPlexHitIdxMax)
567  break;
568 
569  const float ddq = std::abs(q - L.hit_q(hi));
570  const float ddphi = cdist(std::abs(phi - L.hit_phi(hi)));
571 
572  // clang-format off
573  dprintf(" SHI %3u %4u %5u %6.3f %6.3f %6.4f %7.5f %s\n",
574  qi, pi, hi, L.hit_q(hi), L.hit_phi(hi),
575  ddq, ddphi, (ddq < dq && ddphi < dphi) ? "PASS" : "FAIL");
576  // clang-format on
577 
578 #if defined(DUMPHITWINDOW) && defined(MKFIT_STANDALONE)
579  // clang-format off
580  MPlexQF thisOutChi2;
581  {
582  const MCHitInfo &mchinfo = m_event->simHitsInfo_[L.refHit(hi).mcHitID()];
583  int mchid = mchinfo.mcTrackID();
584  int st_isfindable = 0;
585  int st_label = -999999;
586  int st_prodtype = 0;
587  int st_nhits = -1;
588  int st_charge = 0;
589  float st_r = -999.;
590  float st_z = -999.;
591  float st_pt = -999.;
592  float st_eta = -999.;
593  float st_phi = -999.;
594  if (mchid >= 0) {
595  Track simtrack = m_event->simTracks_[mchid];
596  st_isfindable = (int)simtrack.isFindable();
597  st_label = simtrack.label();
598  st_prodtype = (int)simtrack.prodType();
599  st_pt = simtrack.pT();
600  st_eta = simtrack.momEta();
601  st_phi = simtrack.momPhi();
602  st_nhits = simtrack.nTotalHits();
603  st_charge = simtrack.charge();
604  st_r = simtrack.posR();
605  st_z = simtrack.z();
606  }
607 
608  const Hit &thishit = L.refHit(hi_orig);
609  m_msErr.copyIn(itrack, thishit.errArray());
610  m_msPar.copyIn(itrack, thishit.posArray());
611 
612  MPlexQI propFail;
613  MPlexLV tmpPropPar;
614  const FindingFoos &fnd_foos = FindingFoos::get_finding_foos(L.is_barrel());
615  (*fnd_foos.m_compute_chi2_foo)(m_Err[iI],
616  m_Par[iI],
617  m_Chg,
618  m_msErr,
619  m_msPar,
620  thisOutChi2,
621  tmpPropPar,
622  propFail,
623  N_proc,
626 
627  float hx = thishit.x();
628  float hy = thishit.y();
629  float hz = thishit.z();
630  float hr = std::hypot(hx, hy);
631  float hphi = std::atan2(hy, hx);
632  float hex = ngr( std::sqrt(thishit.exx()) );
633  float hey = ngr( std::sqrt(thishit.eyy()) );
634  float hez = ngr( std::sqrt(thishit.ezz()) );
635  float her = ngr( std::sqrt(
636  (hx * hx * thishit.exx() + hy * hy * thishit.eyy() + 2.0f * hx * hy * m_msErr.At(itrack, 0, 1)) /
637  (hr * hr)) );
638  float hephi = ngr( std::sqrt(thishit.ephi()) );
639  float hchi2 = ngr( thisOutChi2[itrack] );
640  float tx = m_Par[iI].At(itrack, 0, 0);
641  float ty = m_Par[iI].At(itrack, 1, 0);
642  float tz = m_Par[iI].At(itrack, 2, 0);
643  float tr = std::hypot(tx, ty);
644  float tphi = std::atan2(ty, tx);
645  // float tchi2 = ngr( m_Chi2(itrack, 0, 0) ); // unused
646  float tex = ngr( std::sqrt(m_Err[iI].At(itrack, 0, 0)) );
647  float tey = ngr( std::sqrt(m_Err[iI].At(itrack, 1, 1)) );
648  float tez = ngr( std::sqrt(m_Err[iI].At(itrack, 2, 2)) );
649  float ter = ngr( std::sqrt(
650  (tx * tx * tex * tex + ty * ty * tey * tey + 2.0f * tx * ty * m_Err[iI].At(itrack, 0, 1)) /
651  (tr * tr)) );
652  float tephi = ngr( std::sqrt(
653  (ty * ty * tex * tex + tx * tx * tey * tey - 2.0f * tx * ty * m_Err[iI].At(itrack, 0, 1)) /
654  (tr * tr * tr * tr)) );
655  float ht_dxy = std::hypot(hx - tx, hy - ty);
656  float ht_dz = hz - tz;
657  float ht_dphi = cdist(std::abs(hphi - tphi));
658 
659  static bool first = true;
660  if (first) {
661  printf(
662  "HITWINDOWSEL "
663  "evt_id/I:track_algo/I:"
664  "lyr_id/I:lyr_isbrl/I:hit_idx/I:"
665  "trk_cnt/I:trk_idx/I:trk_label/I:"
666  "trk_pt/F:trk_eta/F:trk_mphi/F:trk_chi2/F:"
667  "nhits/I:"
668  "seed_idx/I:seed_label/I:seed_mcid/I:"
669  "hit_mcid/I:"
670  "st_isfindable/I:st_prodtype/I:st_label/I:"
671  "st_pt/F:st_eta/F:st_phi/F:"
672  "st_nhits/I:st_charge/I:st_r/F:st_z/F:"
673  "trk_q/F:hit_q/F:dq_trkhit/F:dq_cut/F:trk_phi/F:hit_phi/F:dphi_trkhit/F:dphi_cut/F:"
674  "t_x/F:t_y/F:t_r/F:t_phi/F:t_z/F:"
675  "t_ex/F:t_ey/F:t_er/F:t_ephi/F:t_ez/F:"
676  "h_x/F:h_y/F:h_r/F:h_phi/F:h_z/F:"
677  "h_ex/F:h_ey/F:h_er/F:h_ephi/F:h_ez/F:"
678  "ht_dxy/F:ht_dz/F:ht_dphi/F:"
679  "h_chi2/F"
680  "\n");
681  first = false;
682  }
683 
684  if (!(std::isnan(phi)) && !(std::isnan(getEta(m_Par[iI].At(itrack, 5, 0))))) {
685  //|| std::isnan(ter) || std::isnan(her) || std::isnan(m_Chi2(itrack, 0, 0)) || std::isnan(hchi2)))
686  printf("HITWINDOWSEL "
687  "%d %d"
688  "%d %d %d "
689  "%d %d %d "
690  "%6.3f %6.3f %6.3f %6.3f "
691  "%d "
692  "%d %d %d "
693  "%d "
694  "%d %d %d "
695  "%6.3f %6.3f %6.3f "
696  "%d %d %6.3f %6.3f "
697  "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f "
698  "%6.3f %6.3f %6.3f %6.3f %6.3f "
699  "%6.6f %6.6f %6.6f %6.6f %6.6f "
700  "%6.3f %6.3f %6.3f %6.3f %6.3f "
701  "%6.6f %6.6f %6.6f %6.6f %6.6f "
702  "%6.3f %6.3f %6.3f "
703  "%6.3f"
704  "\n",
706  L.layer_id(), L.is_barrel(), hi_orig,
707  itrack, m_CandIdx(itrack, 0, 0), m_Label(itrack, 0, 0),
708  1.0f / m_Par[iI].At(itrack, 3, 0), getEta(m_Par[iI].At(itrack, 5, 0)), m_Par[iI].At(itrack, 4, 0), m_Chi2(itrack, 0, 0),
709  m_NFoundHits(itrack, 0, 0),
710  m_SeedOriginIdx(itrack, 0, 0), seed_lbl, seed_mcid,
711  mchid,
712  st_isfindable, st_prodtype, st_label,
713  st_pt, st_eta, st_phi,
714  st_nhits, st_charge, st_r, st_z,
715  q, L.hit_q(hi), ddq, dq, phi, L.hit_phi(hi), ddphi, dphi,
716  tx, ty, tr, tphi, tz,
717  tex, tey, ter, tephi, tez,
718  hx, hy, hr, hphi, hz,
719  hex, hey, her, hephi, hez,
720  ht_dxy, ht_dz, ht_dphi,
721  hchi2);
722  }
723  }
724  // clang-format on
725 #endif
726 
727  if (ddq >= dq)
728  continue;
729  if (ddphi >= dphi)
730  continue;
731 
732  // MT: Removing extra check gives full efficiency ...
733  // and means our error estimations are wrong!
734  // Avi says we should have *minimal* search windows per layer.
735  // Also ... if bins are sufficiently small, we do not need the extra
736  // checks, see above.
737  m_XHitArr.At(itrack, m_XHitSize[itrack]++, 0) = hi_orig;
738  } else {
739  // MT: The following check alone makes more sense with spiral traversal,
740  // we'd be taking in closest hits first.
741 
742  // Hmmh -- there used to be some more checks here.
743  // Or, at least, the phi binning was much smaller and no further checks were done.
744  assert(false && "this code has not been used in a while -- see comments in code");
745 
746  if (m_XHitSize[itrack] < MPlexHitIdxMax) {
747  m_XHitArr.At(itrack, m_XHitSize[itrack]++, 0) = hi_orig;
748  }
749  }
750  } //hi
751  } //pi
752  } //qi
753  } //itrack
754  }
755 
756  //==============================================================================
757  // SelectHitIndicesV2
758  //==============================================================================
759 
760  void MkFinder::selectHitIndicesV2(const LayerOfHits &layer_of_hits, const int N_proc) {
761  // bool debug = true;
762  using bidx_t = LayerOfHits::bin_index_t;
763  using bcnt_t = LayerOfHits::bin_content_t;
764  const LayerOfHits &L = layer_of_hits;
765  const LayerInfo &LI = L.layer_info();
766 
767  const int iI = iP;
768 
769  dprintf("LayerOfHits::SelectHitIndicesV2 %s layer=%d N_proc=%d\n",
770  L.is_barrel() ? "barrel" : "endcap",
771  L.layer_id(),
772  N_proc);
773 
774 #ifdef RNT_DUMP_MkF_SelHitIdcs
775  rnt_shi.InnerIdcsReset(N_proc);
776  Event::SimLabelFromHits sim_lbls[NN];
777  for (int i = 0; i < N_proc; ++i) {
779  if (m_FailFlag[i]) {
780  rnt_shi.RegisterFailedProp(i, m_Par[1 - iI], m_Par[iI], m_event, m_SeedOriginIdx[i]);
781  } else if (sim_lbls[i].is_set()) {
782  /* CandInfo &ci = */ rnt_shi.RegisterGoodProp(i, m_Par[iI], m_event, m_SeedOriginIdx[i]);
783  } // else ... could do something about the bad seeds ... probably better to collect elsewhere.
784  }
785  // Get BinSearch result from V1. Note -- it can clear m_FailFlag for some cands!
786  auto ff_stash = m_FailFlag;
787  selectHitIndices(layer_of_hits, N_proc, true);
788  m_FailFlag = ff_stash;
789 #endif
790 
791  constexpr int NEW_MAX_HIT = 6; // 4 - 6 give about the same # of tracks in quality-val
792  constexpr float DDPHI_PRESEL_FAC = 2.0f;
793  constexpr float DDQ_PRESEL_FAC = 1.2f;
794  constexpr float PHI_BIN_EXTRA_FAC = 2.75f;
795  constexpr float Q_BIN_EXTRA_FAC = 1.6f;
796 
797  namespace mp = mini_propagators;
798  struct Bins {
799  MPlexQUH q0, q1, q2, p1, p2;
800  mp::InitialStatePlex isp;
801  mp::StatePlex sp1, sp2;
802  int n_proc;
803 
804  MPlexQF dphi_track, dq_track; // 3 sigma track errors at initial state
805 
806  // debug & ntuple dump -- to be local in functions
807  MPlexQF phi_c, dphi;
808  MPlexQF q_c, qmin, qmax;
809 
810  Bins(const MPlexLV &par, const MPlexQI &chg, int np = NN) : isp(par, chg), n_proc(np) {}
811 
812  void prop_to_limits(const LayerInfo &li) {
813  // Positions 1 and 2 should really be by "propagation order", 1 is the closest/
814  // This should also work for backward propagation so not exactly trivial.
815  // Also, do not really need propagation to center.
816  if (li.is_barrel()) {
817  isp.propagate_to_r(mp::PA_Exact, li.rin(), sp1, true, n_proc);
818  isp.propagate_to_r(mp::PA_Exact, li.rout(), sp2, true, n_proc);
819  } else {
820  isp.propagate_to_z(mp::PA_Exact, li.zmin(), sp1, true, n_proc);
821  isp.propagate_to_z(mp::PA_Exact, li.zmax(), sp2, true, n_proc);
822  }
823  }
824 
825  void find_bin_ranges(const LayerInfo &li, const LayerOfHits &loh, const MPlexLS &err) {
826  // Below made members for debugging
827  // MPlexQF phi_c, dphi_min, dphi_max;
828  // phi_c = mp::fast_atan2(isp.y, isp.x); // calculated below as difference
829 
830  // Matriplex::min_max(sp1.dphi, sp2.dphi, dphi_min, dphi_max);
831  // the above is wrong: dalpha is not dphi --> renamed variable in State
832  MPlexQF xp1, xp2, pmin, pmax;
833  xp1 = mp::fast_atan2(sp1.y, sp1.x);
834  xp2 = mp::fast_atan2(sp2.y, sp2.x);
835  Matriplex::min_max(xp1, xp2, pmin, pmax);
836  // Matriplex::min_max(mp::fast_atan2(sp1.y, sp1.x), smp::fast_atan2(sp2.y, sp2.x), pmin, pmax);
837  MPlexQF dp = pmax - pmin;
838  phi_c = 0.5f * (pmax + pmin);
839  for (int ii = 0; ii < NN; ++ii) {
840  if (ii < n_proc) {
841  if (dp[ii] > Const::PI) {
842  std::swap(pmax[ii], pmin[ii]);
843  dp[ii] = Const::TwoPI - dp[ii];
844  phi_c[ii] = Const::PI - phi_c[ii];
845  }
846  dphi[ii] = 0.5f * dp[ii];
847  // printf("phic: %f p1: %f p2: %f pmin: %f pmax: %f dphi: %f\n",
848  // phi_c[ii], xp1[ii], xp2[ii], pmin[ii], pmax[ii], dphi[ii]);
849  }
850  }
851 
852  const auto calc_err_xy = [&](const MPlexQF &x, const MPlexQF &y) {
853  return x * x * err.ReduceFixedIJ(0, 0) + y * y * err.ReduceFixedIJ(1, 1) +
854  2.0f * x * y * err.ReduceFixedIJ(0, 1);
855  };
856 
857  // Calculate dphi_track, dq_track differs for barrel/endcap
858  MPlexQF r2_c = isp.x * isp.x + isp.y * isp.y;
859  MPlexQF r2inv_c = 1.0f / r2_c;
860  MPlexQF dphidx_c = -isp.y * r2inv_c;
861  MPlexQF dphidy_c = isp.x * r2inv_c;
862  dphi_track = 3.0f * calc_err_xy(dphidx_c, dphidy_c).abs().sqrt();
863 
864  // MPlexQF qmin, qmax;
865  if (li.is_barrel()) {
866  Matriplex::min_max(sp1.z, sp2.z, qmin, qmax);
867  q_c = isp.z;
868  dq_track = 3.0f * err.ReduceFixedIJ(2, 2).abs().sqrt();
869  } else {
870  Matriplex::min_max(Matriplex::hypot(sp1.x, sp1.y), Matriplex::hypot(sp2.x, sp2.y), qmin, qmax);
871  q_c = Matriplex::sqrt(r2_c);
872  dq_track = 3.0f * (r2inv_c * calc_err_xy(isp.x, isp.y).abs()).sqrt();
873  }
874 
875  for (int i = 0; i < p1.kTotSize; ++i) {
876  // Clamp crazy sizes. This actually only happens when prop-fail flag is set.
877  // const float dphi_clamp = 0.1;
878  // if (dphi_min[i] > 0.0f || dphi_min[i] < -dphi_clamp) dphi_min[i] = -dphi_clamp;
879  // if (dphi_max[i] < 0.0f || dphi_max[i] > dphi_clampf) dphi_max[i] = dphi_clamp;
880  p1[i] = loh.phiBinChecked(pmin[i] - dphi_track[i] - PHI_BIN_EXTRA_FAC * 0.0123f);
881  p2[i] = loh.phiBinChecked(pmax[i] + dphi_track[i] + PHI_BIN_EXTRA_FAC * 0.0123f);
882 
883  q0[i] = loh.qBinChecked(q_c[i]);
884  q1[i] = loh.qBinChecked(qmin[i] - dq_track[i] - Q_BIN_EXTRA_FAC * 0.5f * li.q_bin());
885  q2[i] = loh.qBinChecked(qmax[i] + dq_track[i] + Q_BIN_EXTRA_FAC * 0.5f * li.q_bin()) + 1;
886  }
887  }
888  };
889 
890  Bins B(m_Par[iI], m_Chg, N_proc);
891  B.prop_to_limits(LI);
892  B.find_bin_ranges(LI, L, m_Err[iI]);
893 
894  for (int i = 0; i < NN; ++i) {
895  if (i < N_proc) {
896  m_XHitSize[i] = 0;
897  // Notify failure. Ideally should be detected before selectHitIndices().
898  if (m_FailFlag[i]) {
900  } else {
901  if (LI.is_barrel()) {
902  m_XWsrResult[i] = L.is_within_z_sensitive_region(B.q_c[i], 0.5f * (B.q2[i] - B.q1[i]));
903  } else {
904  m_XWsrResult[i] = L.is_within_r_sensitive_region(B.q_c[i], 0.5f * (B.q2[i] - B.q1[i]));
905  }
906  }
907  }
908  }
909 
910  // for (int i = 0; i < N_proc; ++i) {
911  // printf("BinCheck %c %+8.6f %+8.6f | %3d %3d - %3d %3d || | %2d %2d - %2d %2d\n", LI.is_barrel() ? 'B' : 'E',
912  // B.phi[i], B.dphi[i], B.p1[i], B.p2[i], pb1v[i], pb2v[i],
913  // B.q[i], B.dq[i], B.q1[i], B.q2[i], qb1v[i], qb2v[i]);
914  // }
915 
916 #ifdef RNT_DUMP_MkF_SelHitIdcs
917  for (auto i : rnt_shi.f_h_idcs) {
918  CandInfo &ci = (*rnt_shi.ci)[rnt_shi.f_h_remap[i]];
919  ci.bsn = BinSearch({B.phi_c[i],
920  B.dphi[i],
921  B.q_c[i],
922  0.5f * (B.q2[i] - B.q1[i]),
923  B.p1[i],
924  B.p2[i],
925  B.q1[i],
926  B.q2[i],
929  false});
930  ci.ps_min = statep2propstate(B.sp1, i);
931  ci.ps_max = statep2propstate(B.sp2, i);
932  }
933 #endif
934 
935  struct PQE {
936  float score;
937  unsigned int hit_index;
938  };
939  auto pqe_cmp = [](const PQE &a, const PQE &b) { return a.score < b.score; };
940  std::priority_queue<PQE, std::vector<PQE>, decltype(pqe_cmp)> pqueue(pqe_cmp);
941  int pqueue_size = 0;
942 
943  // Vectorizing this makes it run slower!
944  //#pragma omp simd
945  for (int itrack = 0; itrack < NN; ++itrack) {
946  if (itrack >= N_proc) {
947  continue;
948  }
949 
950  if (m_FailFlag[itrack]) {
951  m_XWsrResult[itrack].m_wsr = WSR_Failed;
952  continue;
953  }
954 
955  if (m_XWsrResult[itrack].m_wsr == WSR_Outside) {
956  continue;
957  }
958 
959  // New binning -- known to be too restrictive, so scaled up. Probably esp. in stereo layers.
960  // Also, could take track covariance dphi / dq extras + known tilt stuff.
961  const bidx_t qb = B.q0[itrack];
962  const bidx_t qb1 = B.q1[itrack];
963  const bidx_t qb2 = B.q2[itrack];
964  const bidx_t pb1 = B.p1[itrack];
965  const bidx_t pb2 = B.p2[itrack];
966 
967  // clang-format off
968  dprintf(" %2d/%2d: %6.3f %6.3f %6.6f %7.5f %3u %3u %4u %4u\n",
969  L.layer_id(), itrack, B.q_c[itrack], B.phi_c[itrack],
970  B.qmax[itrack] - B.qmin[itrack], B.dphi[itrack],
971  qb1, qb2, pb1, pb2);
972 #ifdef RNT_DUMP_MkF_SelHitIdcs
973  int hit_out_idx = 0;
974  // phi-sorted position of matched hits
975  struct pos_match { float dphi, dq; int idx; bool matched; };
976  std::vector<pos_match> pos_match_vec;
977 #endif
978  // clang-format on
979 
980  mp::InitialState mp_is(m_Par[iI], m_Chg, itrack);
981  mp::State mp_s;
982 
983  for (bidx_t qi = qb1; qi != qb2; ++qi) {
984  for (bidx_t pi = pb1; pi != pb2; pi = L.phiMaskApply(pi + 1)) {
985  // Limit to central Q-bin
986  if (qi == qb && L.isBinDead(pi, qi) == true) {
987  dprint("dead module for track in layer=" << L.layer_id() << " qb=" << qi << " pi=" << pi
988  << " q=" << B.q_c[itrack] << " phi=" << B.phi_c[itrack]);
989  m_XWsrResult[itrack].m_in_gap = true;
990  }
991 
992  // It might make sense to make first loop to extract bin indices
993  // and issue prefetches at the same time.
994  // Then enter vectorized loop to actually collect the hits in proper order.
995 
996  //SK: ~20x1024 bin sizes give mostly 1 hit per bin. Commented out for 128 bins or less
997  // #pragma nounroll
998  auto pbi = L.phiQBinContent(pi, qi);
999  for (bcnt_t hi = pbi.begin(); hi < pbi.end(); ++hi) {
1000  // MT: Access into m_hit_zs and m_hit_phis is 1% run-time each.
1001 
1002  const unsigned int hi_orig = L.getOriginalHitIndex(hi);
1003 
1004  if (m_iteration_hit_mask && (*m_iteration_hit_mask)[hi_orig]) {
1005  dprintf(
1006  "Yay, denying masked hit on layer %u, hi %u, orig idx %u\n", L.layer_info().layer_id(), hi, hi_orig);
1007  continue;
1008  }
1009 
1010  float new_q, new_phi, new_ddphi, new_ddq;
1011  bool prop_fail;
1012 
1013  if (L.is_barrel()) {
1014  const Hit &hit = L.refHit(hi_orig);
1015  unsigned int mid = hit.detIDinLayer();
1016  const ModuleInfo &mi = LI.module_info(mid);
1017 
1018  // Original condition, for phase2
1019  // if (L.layer_id() >= 4 && L.layer_id() <= 9 && std::abs(mp_is.z) > 10.f) {
1020 
1021  // This could work well instead of prop-to-r, too. Limit to 0.05 rad, 2.85 deg.
1022  if (std::abs(mi.zdir(2)) > 0.05f) {
1023  prop_fail = mp_is.propagate_to_plane(mp::PA_Line, mi, mp_s, true);
1024  new_q = mp_s.z;
1025  /*
1026  // This for calculating ddq on the dector plane, along the "strip" direction.
1027  // NOTE -- should take full covariance and project it onto ydir.
1028  SVector3 ydir = mi.calc_ydir();
1029  new_ddq = (mp_s.x - mi.pos(0)) * ydir(0) +
1030  (mp_s.y - mi.pos(1)) * ydir(1) +
1031  (mp_s.z - mi.pos(2)) * ydir(2);
1032  new_ddq = std::abs(new_ddq);
1033  */
1034  new_ddq = std::abs(new_q - L.hit_q(hi));
1035  // dq from z direction is actually projected, so just take plain dz.
1036 
1037  } else {
1038  prop_fail = mp_is.propagate_to_r(mp::PA_Exact, L.hit_qbar(hi), mp_s, true);
1039  new_q = mp_s.z;
1040  new_ddq = std::abs(new_q - L.hit_q(hi));
1041  }
1042  } else {
1043  prop_fail = mp_is.propagate_to_z(mp::PA_Exact, L.hit_qbar(hi), mp_s, true);
1044  new_q = std::hypot(mp_s.x, mp_s.y);
1045  new_ddq = std::abs(new_q - L.hit_q(hi));
1046  }
1047 
1048  new_phi = vdt::fast_atan2f(mp_s.y, mp_s.x);
1049  new_ddphi = cdist(std::abs(new_phi - L.hit_phi(hi)));
1050  bool dqdphi_presel = new_ddq < B.dq_track[itrack] + DDQ_PRESEL_FAC * L.hit_q_half_length(hi) &&
1051  new_ddphi < B.dphi_track[itrack] + DDPHI_PRESEL_FAC * 0.0123f;
1052 
1053  // clang-format off
1054  dprintf(" SHI %3u %4u %5u %6.3f %6.3f %6.4f %7.5f PROP-%s %s\n",
1055  qi, pi, hi, L.hit_q(hi), L.hit_phi(hi),
1056  new_ddq, new_ddphi, prop_fail ? "FAIL" : "OK", dqdphi_presel ? "PASS" : "REJECT");
1057 #ifdef RNT_DUMP_MkF_SelHitIdcs
1058  if (rnt_shi.f_h_remap[itrack] >= 0) {
1059  int sim_lbl = sim_lbls[itrack].label;
1060  const Hit &thishit = L.refHit(hi_orig);
1061  m_msErr.copyIn(itrack, thishit.errArray());
1062  m_msPar.copyIn(itrack, thishit.posArray());
1063 
1064  MPlexQF thisOutChi2;
1065  MPlexQI propFail(0);
1066  MPlexLV tmpPropPar;
1067  const FindingFoos &fnd_foos = FindingFoos::get_finding_foos(L.is_barrel());
1068  (*fnd_foos.m_compute_chi2_foo)(
1069  m_Err[iI], m_Par[iI], m_Chg, m_msErr, m_msPar,
1070  thisOutChi2, tmpPropPar, propFail, N_proc,
1073  float hchi2 = thisOutChi2[itrack];
1074 
1075  CandInfo &ci = (*rnt_shi.ci)[rnt_shi.f_h_remap[itrack]];
1076 
1077  const MCHitInfo &mchinfo = m_event->simHitsInfo_[L.refHit(hi_orig).mcHitID()];
1078  int hit_lbl = mchinfo.mcTrackID();
1079  ci.hmi.emplace_back(HitMatchInfo{ HitInfo
1080  { hit2pos(thishit),
1081  new_q, L.hit_q_half_length(hi), L.hit_qbar(hi), new_phi,
1082  hit_lbl },
1083  state2pos(mp_s), state2mom(mp_s),
1084  new_ddq, new_ddphi, hchi2, (int) hi_orig,
1085  (sim_lbl == hit_lbl), dqdphi_presel, !prop_fail,
1086  false, IdxChi2List()
1087  });
1088  ci.hmi.back().ic2list.reset(); // zero initialize
1089 
1090  bool new_dec = dqdphi_presel && !prop_fail;
1091  ++ci.n_all_hits;
1092  if (sim_lbl == hit_lbl) {
1093  ++ci.n_hits_match;
1094  if (new_dec) ++ci.n_hits_pass_match;
1095  }
1096  if (new_dec) ++ci.n_hits_pass;
1097  if (new_dec)
1098  pos_match_vec.emplace_back(pos_match{ new_ddphi, new_ddq, hit_out_idx++,
1099  sim_lbl == hit_lbl });
1100  } // if cand is saved
1101 #endif
1102  // clang-format on
1103 
1104  if (prop_fail || !dqdphi_presel)
1105  continue;
1106  if (pqueue_size < NEW_MAX_HIT) {
1107  pqueue.push({new_ddphi, hi_orig});
1108  ++pqueue_size;
1109  } else if (new_ddphi < pqueue.top().score) {
1110  pqueue.pop();
1111  pqueue.push({new_ddphi, hi_orig});
1112  }
1113  } //hi
1114  } //pi
1115  } //qi
1116 
1117  dprintf(" PQUEUE (%d)", pqueue_size);
1118 #ifdef RNT_DUMP_MkF_SelHitIdcs
1119  // clang-format off
1120  if (sim_lbls[itrack].is_set()) {
1121  // Find ord number of matched hits.
1122  std::sort(pos_match_vec.begin(), pos_match_vec.end(),
1123  [](auto &a, auto &b){return a.dphi < b.dphi;});
1124  int pmvs = pos_match_vec.size();
1125 
1126  CandInfo &ci = (*rnt_shi.ci)[rnt_shi.f_h_remap[itrack]];
1127  for (int i = 0; i < pmvs; ++i) {
1128  if (pos_match_vec[i].matched) {
1129  ci.ord_first_match = i;
1130  ci.dphi_first_match = pos_match_vec[i].dphi;
1131  ci.dq_first_match = pos_match_vec[i].dq;
1132  break;
1133  }
1134  }
1135  }
1136  // clang-format off
1137 #endif
1138  // Reverse hits so best dphis/scores come first in the hit-index list.
1139  m_XHitSize[itrack] = pqueue_size;
1140  while (pqueue_size) {
1141  --pqueue_size;
1142  m_XHitArr.At(itrack, pqueue_size, 0) = pqueue.top().hit_index;
1143  dprintf(" %d: %f %d", pqueue_size, pqueue.top().score, pqueue.top().hit_index);
1144  pqueue.pop();
1145  }
1146  dprintf("\n");
1147 
1148  } //itrack
1149  }
1150 
1151  //==============================================================================
1152  // AddBestHit - Best Hit Track Finding
1153  //==============================================================================
1154 
1155  void MkFinder::addBestHit(const LayerOfHits &layer_of_hits, const int N_proc, const FindingFoos &fnd_foos) {
1156  // debug = true;
1157 
1158  MatriplexHitPacker mhp(layer_of_hits.hitArray());
1159 
1160  float minChi2[NN];
1161  int bestHit[NN];
1162  int maxSize = 0;
1163 
1164  // Determine maximum number of hits for tracks in the collection.
1165  for (int it = 0; it < NN; ++it) {
1166  if (it < N_proc) {
1167  if (m_XHitSize[it] > 0) {
1169  }
1170  }
1171 
1172  bestHit[it] = -1;
1174  }
1175 
1176  for (int hit_cnt = 0; hit_cnt < maxSize; ++hit_cnt) {
1177  //fixme what if size is zero???
1178 
1179  mhp.reset();
1180 
1181  //#pragma omp simd doesn't vectorize with current compilers
1182  for (int itrack = 0; itrack < NN; ++itrack) {
1183  if (itrack < N_proc && hit_cnt < m_XHitSize[itrack]) {
1184  mhp.addInputAt(itrack, layer_of_hits.refHit(m_XHitArr.At(itrack, hit_cnt, 0)));
1185  }
1186  }
1187 
1188  mhp.pack(m_msErr, m_msPar);
1189 
1190  //now compute the chi2 of track state vs hit
1191  MPlexQF outChi2;
1192  MPlexLV tmpPropPar;
1193  clearFailFlag();
1194  (*fnd_foos.m_compute_chi2_foo)(m_Err[iP],
1195  m_Par[iP],
1196  m_Chg,
1197  m_msErr,
1198  m_msPar,
1199  outChi2,
1200  tmpPropPar,
1201  m_FailFlag,
1202  N_proc,
1205 
1206  //update best hit in case chi2<minChi2
1207 #pragma omp simd
1208  for (int itrack = 0; itrack < NN; ++itrack) {
1209  if (itrack < N_proc && hit_cnt < m_XHitSize[itrack]) {
1210  const float chi2 = std::abs(outChi2[itrack]); //fixme negative chi2 sometimes...
1211  dprint("chi2=" << chi2 << " minChi2[itrack]=" << minChi2[itrack]);
1212  if (chi2 < minChi2[itrack]) {
1213  minChi2[itrack] = chi2;
1214  bestHit[itrack] = m_XHitArr.At(itrack, hit_cnt, 0);
1215  }
1216  }
1217  }
1218  } // end loop over hits
1219 
1220  //#pragma omp simd
1221  for (int itrack = 0; itrack < NN; ++itrack) {
1222  if (itrack >= N_proc) {
1223  continue;
1224  }
1225 
1226  if (m_XWsrResult[itrack].m_wsr == WSR_Outside) {
1227  // Why am I doing this?
1228  m_msErr.setDiagonal3x3(itrack, 666);
1229  m_msPar(itrack, 0, 0) = m_Par[iP](itrack, 0, 0);
1230  m_msPar(itrack, 1, 0) = m_Par[iP](itrack, 1, 0);
1231  m_msPar(itrack, 2, 0) = m_Par[iP](itrack, 2, 0);
1232 
1233  // XXXX If not in gap, should get back the old track params. But they are gone ...
1234  // Would actually have to do it right after SelectHitIndices where updated params are still ok.
1235  // Here they got screwed during hit matching.
1236  // So, I'd store them there (into propagated params) and retrieve them here.
1237  // Or we decide not to care ...
1238 
1239  continue;
1240  }
1241 
1242  //fixme decide what to do in case no hit found
1243  if (bestHit[itrack] >= 0) {
1244  const Hit &hit = layer_of_hits.refHit(bestHit[itrack]);
1245  const float chi2 = minChi2[itrack];
1246 
1247  dprint("ADD BEST HIT FOR TRACK #"
1248  << itrack << std::endl
1249  << "prop x=" << m_Par[iP].constAt(itrack, 0, 0) << " y=" << m_Par[iP].constAt(itrack, 1, 0) << std::endl
1250  << "copy in hit #" << bestHit[itrack] << " x=" << hit.position()[0] << " y=" << hit.position()[1]);
1251 
1252  m_msErr.copyIn(itrack, hit.errArray());
1253  m_msPar.copyIn(itrack, hit.posArray());
1254  m_Chi2(itrack, 0, 0) += chi2;
1255 
1256  add_hit(itrack, bestHit[itrack], layer_of_hits.layer_id());
1257  } else {
1258  int fake_hit_idx = Hit::kHitMissIdx;
1259 
1260  if (m_XWsrResult[itrack].m_wsr == WSR_Edge) {
1261  // YYYYYY Config::store_missed_layers
1262  fake_hit_idx = Hit::kHitEdgeIdx;
1263  } else if (num_all_minus_one_hits(itrack)) {
1264  fake_hit_idx = Hit::kHitStopIdx;
1265  }
1266 
1267  dprint("ADD FAKE HIT FOR TRACK #" << itrack << " withinBounds=" << (fake_hit_idx != Hit::kHitEdgeIdx)
1268  << " r=" << std::hypot(m_Par[iP](itrack, 0, 0), m_Par[iP](itrack, 1, 0)));
1269 
1270  m_msErr.setDiagonal3x3(itrack, 666);
1271  m_msPar(itrack, 0, 0) = m_Par[iP](itrack, 0, 0);
1272  m_msPar(itrack, 1, 0) = m_Par[iP](itrack, 1, 0);
1273  m_msPar(itrack, 2, 0) = m_Par[iP](itrack, 2, 0);
1274  // Don't update chi2
1275 
1276  add_hit(itrack, fake_hit_idx, layer_of_hits.layer_id());
1277  }
1278  }
1279 
1280  // Update the track parameters with this hit. (Note that some calculations
1281  // are already done when computing chi2. Not sure it's worth caching them?)
1282 
1283  dprint("update parameters");
1284  clearFailFlag();
1285  (*fnd_foos.m_update_param_foo)(m_Err[iP],
1286  m_Par[iP],
1287  m_Chg,
1288  m_msErr,
1289  m_msPar,
1290  m_Err[iC],
1291  m_Par[iC],
1292  m_FailFlag,
1293  N_proc,
1296 
1297  dprint("m_Par[iP](0,0,0)=" << m_Par[iP](0, 0, 0) << " m_Par[iC](0,0,0)=" << m_Par[iC](0, 0, 0));
1298  }
1299 
1300  //=======================================================
1301  // isStripQCompatible : check if prop is consistent with the barrel/endcap strip length
1302  //=======================================================
1304  int itrack, bool isBarrel, const MPlexLS &pErr, const MPlexLV &pPar, const MPlexHS &msErr, const MPlexHV &msPar) {
1305  //check module compatibility via long strip side = L/sqrt(12)
1306  if (isBarrel) { //check z direction only
1307  const float res = std::abs(msPar.constAt(itrack, 2, 0) - pPar.constAt(itrack, 2, 0));
1308  const float hitHL = sqrt(msErr.constAt(itrack, 2, 2) * 3.f); //half-length
1309  const float qErr = sqrt(pErr.constAt(itrack, 2, 2));
1310  dprint("qCompat " << hitHL << " + " << 3.f * qErr << " vs " << res);
1311  return hitHL + std::max(3.f * qErr, 0.5f) > res;
1312  } else { //project on xy, assuming the strip Length >> Width
1313  const float res[2]{msPar.constAt(itrack, 0, 0) - pPar.constAt(itrack, 0, 0),
1314  msPar.constAt(itrack, 1, 0) - pPar.constAt(itrack, 1, 0)};
1315  const float hitT2 = msErr.constAt(itrack, 0, 0) + msErr.constAt(itrack, 1, 1);
1316  const float hitT2inv = 1.f / hitT2;
1317  const float proj[3] = {msErr.constAt(itrack, 0, 0) * hitT2inv,
1318  msErr.constAt(itrack, 0, 1) * hitT2inv,
1319  msErr.constAt(itrack, 1, 1) * hitT2inv};
1320  const float qErr =
1321  sqrt(std::abs(pErr.constAt(itrack, 0, 0) * proj[0] + 2.f * pErr.constAt(itrack, 0, 1) * proj[1] +
1322  pErr.constAt(itrack, 1, 1) * proj[2])); //take abs to avoid non-pos-def cases
1323  const float resProj =
1324  sqrt(res[0] * proj[0] * res[0] + 2.f * res[1] * proj[1] * res[0] + res[1] * proj[2] * res[1]);
1325  dprint("qCompat " << sqrt(hitT2 * 3.f) << " + " << 3.f * qErr << " vs " << resProj);
1326  return sqrt(hitT2 * 3.f) + std::max(3.f * qErr, 0.5f) > resProj;
1327  }
1328  }
1329 
1330  //=======================================================
1331  // passStripChargePCMfromTrack : apply the slope correction to charge per cm and cut using hit err matrix
1332  // the raw pcm = charge/L_normal
1333  // the corrected qCorr = charge/L_path = charge/(L_normal*p/p_zLocal) = pcm*p_zLocal/p
1334  //=======================================================
1336  int itrack, bool isBarrel, unsigned int pcm, unsigned int pcmMin, const MPlexLV &pPar, const MPlexHS &msErr) {
1337  //skip the overflow case
1338  if (pcm >= Hit::maxChargePerCM())
1339  return true;
1340 
1341  float qSF;
1342  if (isBarrel) { //project in x,y, assuming zero-error direction is in this plane
1343  const float hitT2 = msErr.constAt(itrack, 0, 0) + msErr.constAt(itrack, 1, 1);
1344  const float hitT2inv = 1.f / hitT2;
1345  const float proj[3] = {msErr.constAt(itrack, 0, 0) * hitT2inv,
1346  msErr.constAt(itrack, 0, 1) * hitT2inv,
1347  msErr.constAt(itrack, 1, 1) * hitT2inv};
1348  const bool detXY_OK =
1349  std::abs(proj[0] * proj[2] - proj[1] * proj[1]) < 0.1f; //check that zero-direction is close
1350  const float cosP = cos(pPar.constAt(itrack, 4, 0));
1351  const float sinP = sin(pPar.constAt(itrack, 4, 0));
1352  const float sinT = std::abs(sin(pPar.constAt(itrack, 5, 0)));
1353  //qSF = sqrt[(px,py)*(1-proj)*(px,py)]/p = sinT*sqrt[(cosP,sinP)*(1-proj)*(cosP,sinP)].
1354  qSF = detXY_OK ? sinT * std::sqrt(std::abs(1.f + cosP * cosP * proj[0] + sinP * sinP * proj[2] -
1355  2.f * cosP * sinP * proj[1]))
1356  : 1.f;
1357  } else { //project on z
1358  // p_zLocal/p = p_z/p = cosT
1359  qSF = std::abs(cos(pPar.constAt(itrack, 5, 0)));
1360  }
1361 
1362  const float qCorr = pcm * qSF;
1363  dprint("pcm " << pcm << " * " << qSF << " = " << qCorr << " vs " << pcmMin);
1364  return qCorr > pcmMin;
1365  }
1366 
1367  //==============================================================================
1368  // FindCandidates - Standard Track Finding
1369  //==============================================================================
1370 
1371  void MkFinder::findCandidates(const LayerOfHits &layer_of_hits,
1372  std::vector<std::vector<TrackCand>> &tmp_candidates,
1373  const int offset,
1374  const int N_proc,
1375  const FindingFoos &fnd_foos) {
1376  // bool debug = true;
1377 
1378  MatriplexHitPacker mhp(layer_of_hits.hitArray());
1379 
1380  int maxSize = 0;
1381 
1382  // Determine maximum number of hits for tracks in the collection.
1383  for (int it = 0; it < NN; ++it) {
1384  if (it < N_proc) {
1385  if (m_XHitSize[it] > 0) {
1387  }
1388  }
1389  }
1390 
1391  dprintf("FindCandidates max hits to process=%d\n", maxSize);
1392 
1393  int nHitsAdded[NN]{};
1394  bool isTooLargeCluster[NN]{false};
1395 
1396  for (int hit_cnt = 0; hit_cnt < maxSize; ++hit_cnt) {
1397  mhp.reset();
1398 
1399  int charge_pcm[NN];
1400 
1401  //#pragma omp simd doesn't vectorize with current compilers
1402  for (int itrack = 0; itrack < NN; ++itrack) {
1403  if (itrack < N_proc && hit_cnt < m_XHitSize[itrack]) {
1404  const auto &hit = layer_of_hits.refHit(m_XHitArr.At(itrack, hit_cnt, 0));
1405  mhp.addInputAt(itrack, hit);
1406  charge_pcm[itrack] = hit.chargePerCM();
1407  }
1408  }
1409 
1410  mhp.pack(m_msErr, m_msPar);
1411 
1412  //now compute the chi2 of track state vs hit
1413  MPlexQF outChi2;
1414  MPlexLV propPar;
1415  clearFailFlag();
1416 
1417  if /*constexpr*/ (Config::usePropToPlane) {
1418  // Maybe could use 2 matriplex packers ... ModuleInfo has 3 * SVector3 and uint
1419  MPlexHV norm, dir, pnt;
1420  packModuleNormDirPnt(layer_of_hits, hit_cnt, norm, dir, pnt, N_proc);
1422  m_Par[iP],
1423  m_Chg,
1424  m_msErr,
1425  m_msPar,
1426  norm,
1427  dir,
1428  pnt,
1429  outChi2,
1430  propPar,
1431  m_FailFlag,
1432  N_proc,
1435  } else {
1436  (*fnd_foos.m_compute_chi2_foo)(m_Err[iP],
1437  m_Par[iP],
1438  m_Chg,
1439  m_msErr,
1440  m_msPar,
1441  outChi2,
1442  propPar,
1443  m_FailFlag,
1444  N_proc,
1447  }
1448 
1449  // Now update the track parameters with this hit (note that some
1450  // calculations are already done when computing chi2, to be optimized).
1451  // 1. This is not needed for candidates the hit is not added to, but it's
1452  // vectorized so doing it serially below should take the same time.
1453  // 2. Still it's a waste of time in case the hit is not added to any of the
1454  // candidates, so check beforehand that at least one cand needs update.
1455  bool oneCandPassCut = false;
1456  for (int itrack = 0; itrack < NN; ++itrack) {
1457  if (itrack >= N_proc) {
1458  continue;
1459  }
1460  float max_c2 = getHitSelDynamicChi2Cut(itrack, iP);
1461 
1462  if (hit_cnt < m_XHitSize[itrack]) {
1463  const float chi2 = std::abs(outChi2[itrack]); //fixme negative chi2 sometimes...
1464  dprint("chi2=" << chi2);
1465  if (chi2 < max_c2) {
1466  bool isCompatible = true;
1467  if (!layer_of_hits.is_pixel()) {
1468  //check module compatibility via long strip side = L/sqrt(12)
1469  isCompatible =
1470  isStripQCompatible(itrack, layer_of_hits.is_barrel(), m_Err[iP], propPar, m_msErr, m_msPar);
1471 
1472  //rescale strip charge to track parameters and reapply the cut
1473  if (isCompatible && layer_of_hits.layer_info().has_charge()) {
1474  isCompatible = passStripChargePCMfromTrack(
1475  itrack, layer_of_hits.is_barrel(), charge_pcm[itrack], Hit::minChargePerCM(), propPar, m_msErr);
1476  }
1477  }
1478  // Select only SiStrip hits with cluster size < maxClusterSize
1479  if (!layer_of_hits.is_pixel()) {
1480  if (layer_of_hits.refHit(m_XHitArr.At(itrack, hit_cnt, 0)).spanRows() >=
1482  isTooLargeCluster[itrack] = true;
1483  isCompatible = false;
1484  }
1485  }
1486 
1487  if (isCompatible) {
1488  oneCandPassCut = true;
1489  break;
1490  }
1491  }
1492  }
1493  }
1494 
1495  if (oneCandPassCut) {
1496  MPlexQI tmpChg = m_Chg;
1497  clearFailFlag();
1498  (*fnd_foos.m_update_param_foo)(m_Err[iP],
1499  m_Par[iP],
1500  tmpChg,
1501  m_msErr,
1502  m_msPar,
1503  m_Err[iC],
1504  m_Par[iC],
1505  m_FailFlag,
1506  N_proc,
1509 
1510  dprint("update parameters" << std::endl
1511  << "propagated track parameters x=" << m_Par[iP].constAt(0, 0, 0)
1512  << " y=" << m_Par[iP].constAt(0, 1, 0) << std::endl
1513  << " hit position x=" << m_msPar.constAt(0, 0, 0)
1514  << " y=" << m_msPar.constAt(0, 1, 0) << std::endl
1515  << " updated track parameters x=" << m_Par[iC].constAt(0, 0, 0)
1516  << " y=" << m_Par[iC].constAt(0, 1, 0));
1517 
1518  //create candidate with hit in case chi2 < max_c2
1519  //fixme: please vectorize me... (not sure it's possible in this case)
1520  for (int itrack = 0; itrack < NN; ++itrack) {
1521  if (itrack < N_proc && hit_cnt < m_XHitSize[itrack]) {
1522  const float max_c2 = getHitSelDynamicChi2Cut(itrack, iP);
1523  const float chi2 = std::abs(outChi2[itrack]); //fixme negative chi2 sometimes...
1524  dprint("chi2=" << chi2);
1525  if (chi2 < max_c2) {
1526  bool isCompatible = true;
1527  if (!layer_of_hits.is_pixel()) {
1528  // select only SiStrip hits with cluster size < maxClusterSize
1529  if (layer_of_hits.refHit(m_XHitArr.At(itrack, hit_cnt, 0)).spanRows() >=
1531  // isTooLargeCluster[itrack] = true; -- only in CloneEngine
1532  isCompatible = false;
1533  }
1534  // check module compatibility via long strip side = L/sqrt(12)
1535  if (isCompatible)
1536  isCompatible =
1537  isStripQCompatible(itrack, layer_of_hits.is_barrel(), m_Err[iP], propPar, m_msErr, m_msPar);
1538  // rescale strip charge to track parameters and reapply the cut
1539  if (isCompatible && layer_of_hits.layer_info().has_charge()) {
1540  isCompatible = passStripChargePCMfromTrack(
1541  itrack, layer_of_hits.is_barrel(), charge_pcm[itrack], Hit::minChargePerCM(), propPar, m_msErr);
1542  }
1543  }
1544 
1545  if (isCompatible) {
1546  bool hitExists = false;
1547  int maxHits = m_NFoundHits(itrack, 0, 0);
1548  if (layer_of_hits.is_pixel()) {
1549  for (int i = 0; i <= maxHits; ++i) {
1550  if (i > 2)
1551  break;
1552  if (m_HoTArrs[itrack][i].layer == layer_of_hits.layer_id()) {
1553  hitExists = true;
1554  break;
1555  }
1556  }
1557  }
1558  if (hitExists)
1559  continue;
1560 
1561  nHitsAdded[itrack]++;
1562  dprint("chi2 cut passed, creating new candidate");
1563  // Create a new candidate and fill the tmp_candidates output vector.
1564  // QQQ only instantiate if it will pass, be better than N_best
1565 
1566  const int hit_idx = m_XHitArr.At(itrack, hit_cnt, 0);
1567 
1568  TrackCand newcand;
1569  copy_out(newcand, itrack, iC);
1570  newcand.setCharge(tmpChg(itrack, 0, 0));
1571  newcand.addHitIdx(hit_idx, layer_of_hits.layer_id(), chi2);
1573  newcand,
1574  true /*penalizeTailMissHits*/,
1575  true /*inFindCandidates*/));
1576  newcand.setOriginIndex(m_CandIdx(itrack, 0, 0));
1577 
1578  // To apply a fixed cut instead of dynamic cut for overlap: m_iteration_params->chi2CutOverlap
1579  if (chi2 < max_c2) {
1580  CombCandidate &ccand = *newcand.combCandidate();
1581  ccand[m_CandIdx(itrack, 0, 0)].considerHitForOverlap(
1582  hit_idx, layer_of_hits.refHit(hit_idx).detIDinLayer(), chi2);
1583  }
1584 
1585  dprint("updated track parameters x=" << newcand.parameters()[0] << " y=" << newcand.parameters()[1]
1586  << " z=" << newcand.parameters()[2]
1587  << " pt=" << 1. / newcand.parameters()[3]);
1588 
1589  tmp_candidates[m_SeedIdx(itrack, 0, 0) - offset].emplace_back(newcand);
1590  }
1591  }
1592  }
1593  }
1594  } //end if (oneCandPassCut)
1595 
1596  } //end loop over hits
1597 
1598  //now add invalid hit
1599  //fixme: please vectorize me...
1600  for (int itrack = 0; itrack < NN; ++itrack) {
1601  // Cands that miss the layer are stashed away in MkBuilder(), before propagation,
1602  // and then merged back afterwards.
1603  if (itrack >= N_proc || m_XWsrResult[itrack].m_wsr == WSR_Outside) {
1604  continue;
1605  }
1606 
1607  int fake_hit_idx = ((num_all_minus_one_hits(itrack) < m_iteration_params->maxHolesPerCand) &&
1610  : Hit::kHitStopIdx;
1611 
1612  if (m_XWsrResult[itrack].m_wsr == WSR_Edge) {
1613  // YYYYYY m_iteration_params->store_missed_layers
1614  fake_hit_idx = Hit::kHitEdgeIdx;
1615  }
1616  //now add fake hit for tracks that passsed through inactive modules
1617  else if (m_XWsrResult[itrack].m_in_gap == true && nHitsAdded[itrack] == 0) {
1618  fake_hit_idx = Hit::kHitInGapIdx;
1619  }
1620  //now add fake hit for cases where hit cluster size is larger than maxClusterSize
1621  else if (isTooLargeCluster[itrack] == true && nHitsAdded[itrack] == 0) {
1622  fake_hit_idx = Hit::kHitMaxClusterIdx;
1623  }
1624 
1625  dprint("ADD FAKE HIT FOR TRACK #" << itrack << " withinBounds=" << (fake_hit_idx != Hit::kHitEdgeIdx)
1626  << " r=" << std::hypot(m_Par[iP](itrack, 0, 0), m_Par[iP](itrack, 1, 0)));
1627 
1628  // QQQ as above, only create and add if score better
1629  TrackCand newcand;
1630  copy_out(newcand, itrack, iP);
1631  newcand.addHitIdx(fake_hit_idx, layer_of_hits.layer_id(), 0.);
1632  newcand.setScore(getScoreCand(
1633  m_steering_params->m_track_scorer, newcand, true /*penalizeTailMissHits*/, true /*inFindCandidates*/));
1634  // Only relevant when we actually add a hit
1635  // newcand.setOriginIndex(m_CandIdx(itrack, 0, 0));
1636  tmp_candidates[m_SeedIdx(itrack, 0, 0) - offset].emplace_back(newcand);
1637  }
1638  }
1639 
1640  //==============================================================================
1641  // FindCandidatesCloneEngine - Clone Engine Track Finding
1642  //==============================================================================
1643 
1645  CandCloner &cloner,
1646  const int offset,
1647  const int N_proc,
1648  const FindingFoos &fnd_foos) {
1649  // bool debug = true;
1650 
1651  MatriplexHitPacker mhp(layer_of_hits.hitArray());
1652 
1653  int maxSize = 0;
1654 
1655  // Determine maximum number of hits for tracks in the collection.
1656 #pragma omp simd
1657  for (int it = 0; it < NN; ++it) {
1658  if (it < N_proc) {
1659  if (m_XHitSize[it] > 0) {
1661  }
1662  }
1663  }
1664 
1665  dprintf("FindCandidatesCloneEngine max hits to process=%d\n", maxSize);
1666 
1667  int nHitsAdded[NN]{};
1668  bool isTooLargeCluster[NN]{false};
1669 
1670  for (int hit_cnt = 0; hit_cnt < maxSize; ++hit_cnt) {
1671  mhp.reset();
1672 
1673  int charge_pcm[NN];
1674 
1675  //#pragma omp simd doesn't vectorize with current compilers
1676  for (int itrack = 0; itrack < NN; ++itrack) {
1677  if (itrack < N_proc && hit_cnt < m_XHitSize[itrack]) {
1678  const auto &hit = layer_of_hits.refHit(m_XHitArr.At(itrack, hit_cnt, 0));
1679  mhp.addInputAt(itrack, hit);
1680  charge_pcm[itrack] = hit.chargePerCM();
1681  }
1682  }
1683 
1684  mhp.pack(m_msErr, m_msPar);
1685 
1686  //now compute the chi2 of track state vs hit
1687  MPlexQF outChi2;
1688  MPlexLV propPar;
1689  clearFailFlag();
1690 
1691  if /*constexpr*/ (Config::usePropToPlane) {
1692  // Maybe could use 2 matriplex packers ... ModuleInfo has 3 * SVector3 and uint
1693  MPlexHV norm, dir, pnt;
1694  packModuleNormDirPnt(layer_of_hits, hit_cnt, norm, dir, pnt, N_proc);
1696  m_Par[iC],
1697  m_Chg,
1698  m_msErr,
1699  m_msPar,
1700  norm, dir, pnt,
1701  outChi2,
1702  propPar,
1703  m_FailFlag,
1704  N_proc,
1707  } else {
1708  (*fnd_foos.m_compute_chi2_foo)(m_Err[iP],
1709  m_Par[iP],
1710  m_Chg,
1711  m_msErr,
1712  m_msPar,
1713  outChi2,
1714  propPar,
1715  m_FailFlag,
1716  N_proc,
1719  }
1720 
1721  //#pragma omp simd // DOES NOT VECTORIZE AS IT IS NOW
1722  for (int itrack = 0; itrack < NN; ++itrack) {
1723  // We can be in failed state from the initial propagation before selectHitIndices
1724  // and there hit_count for track is set to -1 and WSR state to Failed, handled below.
1725  // Or we might have hit it here in propagate-to-hit.
1726  // PROP-FAIL-ENABLE FailFlag check to be enabled when propagation failure
1727  // detection is properly implemented in propagate-to-R/Z.
1728  if ( itrack < N_proc && hit_cnt < m_XHitSize[itrack]) {
1729  // make sure the hit was in the compatiblity window for the candidate
1730  const float max_c2 = getHitSelDynamicChi2Cut(itrack, iP);
1731  const float chi2 = std::abs(outChi2[itrack]); //fixme negative chi2 sometimes...
1732  // XXX-NUM-ERR assert(chi2 >= 0);
1733 
1734  dprintf(" chi2=%.3f (%.3f) trkIdx=%d hitIdx=%d\n", chi2, max_c2, itrack, m_XHitArr.At(itrack, hit_cnt, 0));
1735  if (chi2 < max_c2) {
1736  bool isCompatible = true;
1737  if (!layer_of_hits.is_pixel()) {
1738  // select only SiStrip hits with cluster size < maxClusterSize
1739  if (layer_of_hits.refHit(m_XHitArr.At(itrack, hit_cnt, 0)).spanRows() >=
1741  isTooLargeCluster[itrack] = true;
1742  isCompatible = false;
1743  }
1744  // check module compatibility via long strip side = L/sqrt(12)
1745  if (isCompatible)
1746  isCompatible =
1747  isStripQCompatible(itrack, layer_of_hits.is_barrel(), m_Err[iP], propPar, m_msErr, m_msPar);
1748  // rescale strip charge to track parameters and reapply the cut
1749  if (isCompatible && layer_of_hits.layer_info().has_charge()) {
1750  isCompatible = passStripChargePCMfromTrack(
1751  itrack, layer_of_hits.is_barrel(), charge_pcm[itrack], Hit::minChargePerCM(), propPar, m_msErr);
1752  }
1753  }
1754 
1755  if (isCompatible) {
1756  CombCandidate &ccand = cloner.combCandWithOriginalIndex(m_SeedIdx(itrack, 0, 0));
1757  bool hitExists = false;
1758  int maxHits = m_NFoundHits(itrack, 0, 0);
1759  if (layer_of_hits.is_pixel()) {
1760  for (int i = 0; i <= maxHits; ++i) {
1761  if (i > 2)
1762  break;
1763  if (ccand.hot(i).layer == layer_of_hits.layer_id()) {
1764  hitExists = true;
1765  break;
1766  }
1767  }
1768  }
1769  if (hitExists)
1770  continue;
1771 
1772  nHitsAdded[itrack]++;
1773  const int hit_idx = m_XHitArr.At(itrack, hit_cnt, 0);
1774 
1775  // Register hit for overlap consideration, if chi2 cut is passed
1776  // To apply a fixed cut instead of dynamic cut for overlap: m_iteration_params->chi2CutOverlap
1777  if (chi2 < max_c2) {
1778  ccand[m_CandIdx(itrack, 0, 0)].considerHitForOverlap(
1779  hit_idx, layer_of_hits.refHit(hit_idx).detIDinLayer(), chi2);
1780  }
1781 
1782  IdxChi2List tmpList;
1783  tmpList.trkIdx = m_CandIdx(itrack, 0, 0);
1784  tmpList.hitIdx = hit_idx;
1785  tmpList.module = layer_of_hits.refHit(hit_idx).detIDinLayer();
1786  tmpList.nhits = m_NFoundHits(itrack, 0, 0) + 1;
1787  tmpList.ntailholes = 0;
1788  tmpList.noverlaps = m_NOverlapHits(itrack, 0, 0);
1789  tmpList.nholes = num_all_minus_one_hits(itrack);
1790  tmpList.pt = std::abs(1.0f / m_Par[iP].At(itrack, 3, 0));
1791  tmpList.chi2 = m_Chi2(itrack, 0, 0) + chi2;
1792  tmpList.chi2_hit = chi2;
1794  cloner.add_cand(m_SeedIdx(itrack, 0, 0) - offset, tmpList);
1795 
1796  dprint(" adding hit with hit_cnt=" << hit_cnt << " for trkIdx=" << tmpList.trkIdx
1797  << " orig Seed=" << m_Label(itrack, 0, 0));
1798 
1799 #ifdef RNT_DUMP_MkF_SelHitIdcs
1800  if (rnt_shi.f_h_remap[itrack] >= 0) {
1801  CandInfo &ci = (*rnt_shi.ci)[rnt_shi.f_h_remap[itrack]];
1802  ci.assignIdxChi2List(tmpList);
1803  }
1804 #endif
1805  }
1806  }
1807  }
1808  }
1809 
1810  } //end loop over hits
1811 
1812  //now add invalid hit
1813  for (int itrack = 0; itrack < NN; ++itrack) {
1814  dprint("num_all_minus_one_hits(" << itrack << ")=" << num_all_minus_one_hits(itrack));
1815 
1816  // Cands that miss the layer are stashed away in MkBuilder(), before propagation,
1817  // and then merged back afterwards.
1818  if (itrack >= N_proc || m_XWsrResult[itrack].m_wsr == WSR_Outside) {
1819  continue;
1820  }
1821 
1822  // int fake_hit_idx = num_all_minus_one_hits(itrack) < m_iteration_params->maxHolesPerCand ? -1 : -2;
1823  int fake_hit_idx = ((num_all_minus_one_hits(itrack) < m_iteration_params->maxHolesPerCand) &&
1826  : Hit::kHitStopIdx;
1827 
1828  if (m_XWsrResult[itrack].m_wsr == WSR_Edge) {
1829  fake_hit_idx = Hit::kHitEdgeIdx;
1830  }
1831  //now add fake hit for tracks that passsed through inactive modules
1832  else if (m_XWsrResult[itrack].m_in_gap == true && nHitsAdded[itrack] == 0) {
1833  fake_hit_idx = Hit::kHitInGapIdx;
1834  }
1835  //now add fake hit for cases where hit cluster size is larger than maxClusterSize
1836  else if (isTooLargeCluster[itrack] == true && nHitsAdded[itrack] == 0) {
1837  fake_hit_idx = Hit::kHitMaxClusterIdx;
1838  }
1839 
1840  // PROP-FAIL-ENABLE The following to be enabled when propagation failure
1841  // detection is properly implemented in propagate-to-R/Z.
1842  // // Override for failed propagation, this trumps all other cases.
1843  // if (m_XWsrResult[itrack].m_wsr == WSR_Failed) {
1844  // fake_hit_idx = Hit::kHitStopIdx;
1845  // }
1846 
1847  IdxChi2List tmpList;
1848  tmpList.trkIdx = m_CandIdx(itrack, 0, 0);
1849  tmpList.hitIdx = fake_hit_idx;
1850  tmpList.module = -1;
1851  tmpList.nhits = m_NFoundHits(itrack, 0, 0);
1852  tmpList.ntailholes = (fake_hit_idx == Hit::kHitMissIdx ? m_NTailMinusOneHits(itrack, 0, 0) + 1
1853  : m_NTailMinusOneHits(itrack, 0, 0));
1854  tmpList.noverlaps = m_NOverlapHits(itrack, 0, 0);
1855  tmpList.nholes = num_inside_minus_one_hits(itrack);
1856  tmpList.pt = std::abs(1.0f / m_Par[iP].At(itrack, 3, 0));
1857  tmpList.chi2 = m_Chi2(itrack, 0, 0);
1858  tmpList.chi2_hit = 0;
1860  cloner.add_cand(m_SeedIdx(itrack, 0, 0) - offset, tmpList);
1861  dprint("adding invalid hit " << fake_hit_idx);
1862  }
1863  }
1864 
1865  //==============================================================================
1866  // UpdateWithLoadedHit
1867  //==============================================================================
1868 
1869  void MkFinder::updateWithLoadedHit(int N_proc, const LayerOfHits &layer_of_hits, const FindingFoos &fnd_foos) {
1870  // See comment in MkBuilder::find_tracks_in_layer() about intra / inter flags used here
1871  // for propagation to the hit.
1872  clearFailFlag();
1873  if /*constexpr*/ (Config::usePropToPlane) {
1874  MPlexHV norm, dir, pnt;
1875  packModuleNormDirPnt(layer_of_hits, 0, norm, dir, pnt, N_proc);
1877  m_Par[iP],
1878  m_Chg,
1879  m_msErr,
1880  m_msPar,
1881  norm, dir, pnt,
1882  m_Err[iC],
1883  m_Par[iC],
1884  m_FailFlag,
1885  N_proc,
1888  } else {
1889  (*fnd_foos.m_update_param_foo)(m_Err[iP],
1890  m_Par[iP],
1891  m_Chg,
1892  m_msErr,
1893  m_msPar,
1894  m_Err[iC],
1895  m_Par[iC],
1896  m_FailFlag,
1897  N_proc,
1900  }
1901 
1902  // PROP-FAIL-ENABLE The following to be enabled when propagation failure
1903  // detection is properly implemented in propagate-to-R/Z.
1904  // for (int i = 0; i < N_proc; ++i) {
1905  // if (m_FailFlag[i]) {
1906  // dprintf("MkFinder::updateWithLoadedHit fail in update, recovering.\n");
1907  // m_Err[iC].copySlot(i, m_Err[iP]);
1908  // m_Par[iC].copySlot(i, m_Par[iP]);
1909  // }
1910  // }
1911  }
1912 
1913  void MkFinder::chi2OfLoadedHit(int N_proc, const FindingFoos &fnd_foos) {
1914  // We expect input in iC slots from above function.
1915  // See comment in MkBuilder::find_tracks_in_layer() about intra / inter flags used here
1916  // for propagation to the hit.
1917  clearFailFlag();
1918  (*fnd_foos.m_compute_chi2_foo)(m_Err[iC],
1919  m_Par[iC],
1920  m_Chg,
1921  m_msErr,
1922  m_msPar,
1923  m_Chi2,
1924  m_Par[iP],
1925  m_FailFlag,
1926  N_proc,
1929 
1930  // PROP-FAIL-ENABLE .... removed here
1931  }
1932 
1933  //==============================================================================
1934  // CopyOutParErr
1935  //==============================================================================
1936 
1937  void MkFinder::copyOutParErr(std::vector<CombCandidate> &seed_cand_vec, int N_proc, bool outputProp) const {
1938  const int iO = outputProp ? iP : iC;
1939 
1940  for (int i = 0; i < NN; ++i) {
1941  if (i < N_proc) {
1942  TrackCand &cand = seed_cand_vec[m_SeedIdx(i, 0, 0)][m_CandIdx(i, 0, 0)];
1943 
1944  // Set the track state to the updated parameters
1945  m_Err[iO].copyOut(i, cand.errors_nc().Array());
1946  m_Par[iO].copyOut(i, cand.parameters_nc().Array());
1947  cand.setCharge(m_Chg(i, 0, 0));
1948 
1949  dprint((outputProp ? "propagated" : "updated")
1950  << " track parameters x=" << cand.parameters()[0] << " y=" << cand.parameters()[1]
1951  << " z=" << cand.parameters()[2] << " pt=" << 1. / cand.parameters()[3] << " posEta=" << cand.posEta());
1952  }
1953  }
1954  }
1955 
1956  //==============================================================================
1957  // Backward Fit hack
1958  //==============================================================================
1959 
1960  void MkFinder::bkFitInputTracks(TrackVec &cands, int beg, int end) {
1961  // Uses HitOnTrack vector from Track directly + a local cursor array to current hit.
1962 
1963  MatriplexTrackPacker mtp(&cands[beg]);
1964 
1965  int itrack = 0;
1966 
1967  for (int i = beg; i < end; ++i, ++itrack) {
1968  const Track &trk = cands[i];
1969 
1970  m_Chg(itrack, 0, 0) = trk.charge();
1971  m_CurHit[itrack] = trk.nTotalHits() - 1;
1972  m_HoTArr[itrack] = trk.getHitsOnTrackArray();
1973 
1974  mtp.addInput(trk);
1975  }
1976 
1977  m_Chi2.setVal(0);
1978 
1979  mtp.pack(m_Err[iC], m_Par[iC]);
1980 
1981  m_Err[iC].scale(100.0f);
1982  }
1983 
1984  void MkFinder::bkFitInputTracks(EventOfCombCandidates &eocss, int beg, int end) {
1985  // Could as well use HotArrays from tracks directly + a local cursor array to last hit.
1986 
1987  // XXXX - shall we assume only TrackCand-zero is needed and that we can freely
1988  // bork the HoTNode array?
1989 
1990  MatriplexTrackPacker mtp(&eocss[beg][0]);
1991 
1992  int itrack = 0;
1993 
1994  for (int i = beg; i < end; ++i, ++itrack) {
1995  const TrackCand &trk = eocss[i][0];
1996 
1997  m_Chg(itrack, 0, 0) = trk.charge();
1998  m_CurNode[itrack] = trk.lastCcIndex();
1999  m_HoTNodeArr[itrack] = trk.combCandidate()->hotsData();
2000 
2001  // XXXX Need TrackCand* to update num-hits. Unless I collect info elsewhere
2002  // and fix it in BkFitOutputTracks.
2003  m_TrkCand[itrack] = &eocss[i][0];
2004 
2005  mtp.addInput(trk);
2006  }
2007 
2008  m_Chi2.setVal(0);
2009 
2010  mtp.pack(m_Err[iC], m_Par[iC]);
2011 
2012  m_Err[iC].scale(100.0f);
2013  }
2014 
2015  //------------------------------------------------------------------------------
2016 
2017  void MkFinder::bkFitOutputTracks(TrackVec &cands, int beg, int end, bool outputProp) {
2018  // Only copy out track params / errors / chi2, all the rest is ok.
2019 
2020  const int iO = outputProp ? iP : iC;
2021 
2022  int itrack = 0;
2023  for (int i = beg; i < end; ++i, ++itrack) {
2024  Track &trk = cands[i];
2025 
2026  m_Err[iO].copyOut(itrack, trk.errors_nc().Array());
2027  m_Par[iO].copyOut(itrack, trk.parameters_nc().Array());
2028 
2029  trk.setChi2(m_Chi2(itrack, 0, 0));
2030  if (isFinite(trk.chi2())) {
2032  }
2033  }
2034  }
2035 
2036  void MkFinder::bkFitOutputTracks(EventOfCombCandidates &eocss, int beg, int end, bool outputProp) {
2037  // Only copy out track params / errors / chi2, all the rest is ok.
2038 
2039  // XXXX - where will rejected hits get removed?
2040 
2041  const int iO = outputProp ? iP : iC;
2042 
2043  int itrack = 0;
2044  for (int i = beg; i < end; ++i, ++itrack) {
2045  TrackCand &trk = eocss[i][0];
2046 
2047  m_Err[iO].copyOut(itrack, trk.errors_nc().Array());
2048  m_Par[iO].copyOut(itrack, trk.parameters_nc().Array());
2049 
2050  trk.setChi2(m_Chi2(itrack, 0, 0));
2051  if (isFinite(trk.chi2())) {
2053  }
2054  }
2055  }
2056 
2057  //------------------------------------------------------------------------------
2058 
2059 #if defined(DEBUG_BACKWARD_FIT) || defined(DEBUG_BACKWARD_FIT_BH)
2060  namespace {
2061  float e2s(float x) { return 1e4 * std::sqrt(x); }
2062  } // namespace
2063 #endif
2064 
2065  void MkFinder::bkFitFitTracksBH(const EventOfHits &eventofhits,
2066  const SteeringParams &st_par,
2067  const int N_proc,
2068  bool chiDebug) {
2069  // Prototyping final backward fit.
2070  // This works with track-finding indices, before remapping.
2071  //
2072  // Layers should be collected during track finding and list all layers that have actual hits.
2073  // Then we could avoid checking which layers actually do have hits.
2074 
2075  MPlexQF tmp_chi2;
2076  float tmp_err[6] = {666, 0, 666, 0, 0, 666};
2077  float tmp_pos[3];
2078 
2079  for (auto lp_iter = st_par.m_layer_plan.rbegin(); lp_iter != st_par.m_layer_plan.rend(); ++lp_iter) {
2080  const int layer = lp_iter->m_layer;
2081 
2082  const LayerOfHits &L = eventofhits[layer];
2083  const LayerInfo &LI = L.layer_info();
2084 
2085  int count = 0;
2086  for (int i = 0; i < N_proc; ++i) {
2087  while (m_CurHit[i] >= 0 && m_HoTArr[i][m_CurHit[i]].index < 0)
2088  --m_CurHit[i];
2089 
2090  if (m_CurHit[i] >= 0 && m_HoTArr[i][m_CurHit[i]].layer == layer) {
2091  // Skip the overlap hits -- if they exist.
2092  // 1. Overlap hit gets placed *after* the original hit in TrackCand::exportTrack()
2093  // which is *before* in the reverse iteration that we are doing here.
2094  // 2. Seed-hit merging can result in more than two hits per layer.
2095  while (m_CurHit[i] > 0 && m_HoTArr[i][m_CurHit[i] - 1].layer == layer)
2096  --m_CurHit[i];
2097 
2098  const Hit &hit = L.refHit(m_HoTArr[i][m_CurHit[i]].index);
2099  m_msErr.copyIn(i, hit.errArray());
2100  m_msPar.copyIn(i, hit.posArray());
2101  ++count;
2102  --m_CurHit[i];
2103  } else {
2104  tmp_pos[0] = m_Par[iC](i, 0, 0);
2105  tmp_pos[1] = m_Par[iC](i, 1, 0);
2106  tmp_pos[2] = m_Par[iC](i, 2, 0);
2107  m_msErr.copyIn(i, tmp_err);
2108  m_msPar.copyIn(i, tmp_pos);
2109  }
2110  }
2111 
2112  if (count == 0)
2113  continue;
2114 
2115  // ZZZ Could add missing hits here, only if there are any actual matches.
2116 
2117  if (LI.is_barrel()) {
2119 
2121  m_Err[iP],
2122  m_Par[iP],
2123  m_msErr,
2124  m_msPar,
2125  m_Err[iC],
2126  m_Par[iC],
2127  tmp_chi2,
2128  N_proc);
2129  } else {
2131 
2133  m_Err[iP],
2134  m_Par[iP],
2135  m_msErr,
2136  m_msPar,
2137  m_Err[iC],
2138  m_Par[iC],
2139  tmp_chi2,
2140  N_proc);
2141  }
2142 
2143  //fixup invpt sign and charge
2144  for (int n = 0; n < NN; ++n) {
2145  if (n < N_proc && m_Par[iC].At(n, 3, 0) < 0) {
2146  m_Chg.At(n, 0, 0) = -m_Chg.At(n, 0, 0);
2147  m_Par[iC].At(n, 3, 0) = -m_Par[iC].At(n, 3, 0);
2148  }
2149  }
2150 
2151 #ifdef DEBUG_BACKWARD_FIT_BH
2152  // Dump per hit chi2
2153  for (int i = 0; i < N_proc; ++i) {
2154  float r_h = std::hypot(m_msPar.At(i, 0, 0), m_msPar.At(i, 1, 0));
2155  float r_t = std::hypot(m_Par[iC].At(i, 0, 0), m_Par[iC].At(i, 1, 0));
2156 
2157  // if ((std::isnan(tmp_chi2[i]) || std::isnan(r_t)))
2158  // if ( ! std::isnan(tmp_chi2[i]) && tmp_chi2[i] > 0) // && tmp_chi2[i] > 30)
2159  if (chiDebug) {
2160  int ti = iP;
2161  printf(
2162  "CHIHIT %3d %10g %10g %10g %10g %10g %11.5g %11.5g %11.5g %10g %10g %10g %10g %11.5g %11.5g %11.5g %10g "
2163  "%10g %10g %10g %10g %11.5g %11.5g\n",
2164  layer,
2165  tmp_chi2[i],
2166  m_msPar.At(i, 0, 0),
2167  m_msPar.At(i, 1, 0),
2168  m_msPar.At(i, 2, 0),
2169  r_h, // x_h y_h z_h r_h -- hit pos
2170  e2s(m_msErr.At(i, 0, 0)),
2171  e2s(m_msErr.At(i, 1, 1)),
2172  e2s(m_msErr.At(i, 2, 2)), // ex_h ey_h ez_h -- hit errors
2173  m_Par[ti].At(i, 0, 0),
2174  m_Par[ti].At(i, 1, 0),
2175  m_Par[ti].At(i, 2, 0),
2176  r_t, // x_t y_t z_t r_t -- track pos
2177  e2s(m_Err[ti].At(i, 0, 0)),
2178  e2s(m_Err[ti].At(i, 1, 1)),
2179  e2s(m_Err[ti].At(i, 2, 2)), // ex_t ey_t ez_t -- track errors
2180  1.0f / m_Par[ti].At(i, 3, 0),
2181  m_Par[ti].At(i, 4, 0),
2182  m_Par[ti].At(i, 5, 0), // pt, phi, theta
2183  std::atan2(m_msPar.At(i, 1, 0), m_msPar.At(i, 0, 0)), // phi_h
2184  std::atan2(m_Par[ti].At(i, 1, 0), m_Par[ti].At(i, 0, 0)), // phi_t
2185  1e4f * std::hypot(m_msPar.At(i, 0, 0) - m_Par[ti].At(i, 0, 0),
2186  m_msPar.At(i, 1, 0) - m_Par[ti].At(i, 1, 0)), // d_xy
2187  1e4f * (m_msPar.At(i, 2, 0) - m_Par[ti].At(i, 2, 0)) // d_z
2188  // e2s((m_msErr.At(i,0,0) + m_msErr.At(i,1,1)) / (r_h * r_h)), // ephi_h
2189  // e2s((m_Err[ti].At(i,0,0) + m_Err[ti].At(i,1,1)) / (r_t * r_t)) // ephi_t
2190  );
2191  }
2192  }
2193 #endif
2194 
2195  // update chi2
2196  m_Chi2.add(tmp_chi2);
2197  }
2198  }
2199 
2200  //------------------------------------------------------------------------------
2201 
2202  void MkFinder::print_par_err(int corp, int mslot) const {
2203 #ifdef DEBUG
2204  printf("Parameters:\n");
2205  for (int i = 0; i < 6; ++i) {
2206  printf(" %12.4g", m_Par[corp].constAt(mslot, i, 0));
2207  }
2208  printf("\nError matrix\n");
2209  for (int i = 0; i < 6; ++i) {
2210  for (int j = 0; j < 6; ++j) {
2211  printf(" %12.4g", m_Err[corp].constAt(mslot, i, j));
2212  }
2213  printf("\n");
2214  }
2215 #endif
2216  }
2217 
2218  void MkFinder::bkFitFitTracks(const EventOfHits &eventofhits,
2219  const SteeringParams &st_par,
2220  const int N_proc,
2221  bool chiDebug) {
2222  // Prototyping final backward fit.
2223  // This works with track-finding indices, before remapping.
2224  //
2225  // Layers should be collected during track finding and list all layers that have actual hits.
2226  // Then we could avoid checking which layers actually do have hits.
2227 
2228  // bool debug = true;
2229 
2230  MPlexQF tmp_chi2;
2231  MPlexQI no_mat_effs;
2232  float tmp_err[6] = {666, 0, 666, 0, 0, 666};
2233  float tmp_pos[3];
2234 
2235 #if defined(DEBUG_PROP_UPDATE)
2236  const int DSLOT = 0;
2237  printf("bkfit entry, track in slot %d\n", DSLOT);
2238  print_par_err(iC, DSLOT);
2239 #endif
2240 
2241  for (auto lp_iter = st_par.make_iterator(SteeringParams::IT_BkwFit); lp_iter.is_valid(); ++lp_iter) {
2242  const int layer = lp_iter.layer();
2243 
2244  const LayerOfHits &L = eventofhits[layer];
2245  const LayerInfo &LI = L.layer_info();
2246 
2247 #if defined(DEBUG_BACKWARD_FIT)
2248  const Hit *last_hit_ptr[NN];
2249 #endif
2250 
2251  no_mat_effs.setVal(0);
2252  int done_count = 0;
2253  int here_count = 0;
2254  for (int i = 0; i < N_proc; ++i) {
2255  while (m_CurNode[i] >= 0 && m_HoTNodeArr[i][m_CurNode[i]].m_hot.index < 0) {
2257  }
2258 
2259  if (m_CurNode[i] < 0)
2260  ++done_count;
2261 
2262  if (m_CurNode[i] >= 0 && m_HoTNodeArr[i][m_CurNode[i]].m_hot.layer == layer) {
2263  // Skip the overlap hits -- if they exist.
2264  // 1. Overlap hit gets placed *after* the original hit in TrackCand::exportTrack()
2265  // which is *before* in the reverse iteration that we are doing here.
2266  // 2. Seed-hit merging can result in more than two hits per layer.
2267  // while (m_CurHit[i] > 0 && m_HoTArr[ i ][ m_CurHit[i] - 1 ].layer == layer) --m_CurHit[i];
2268  while (m_HoTNodeArr[i][m_CurNode[i]].m_prev_idx >= 0 &&
2269  m_HoTNodeArr[i][m_HoTNodeArr[i][m_CurNode[i]].m_prev_idx].m_hot.layer == layer)
2271 
2272  const Hit &hit = L.refHit(m_HoTNodeArr[i][m_CurNode[i]].m_hot.index);
2273 
2274 #ifdef DEBUG_BACKWARD_FIT
2275  last_hit_ptr[i] = &hit;
2276 #endif
2277  m_msErr.copyIn(i, hit.errArray());
2278  m_msPar.copyIn(i, hit.posArray());
2279  ++here_count;
2280 
2282  } else {
2283 #ifdef DEBUG_BACKWARD_FIT
2284  last_hit_ptr[i] = nullptr;
2285 #endif
2286  no_mat_effs[i] = 1;
2287  tmp_pos[0] = m_Par[iC](i, 0, 0);
2288  tmp_pos[1] = m_Par[iC](i, 1, 0);
2289  tmp_pos[2] = m_Par[iC](i, 2, 0);
2290  m_msErr.copyIn(i, tmp_err);
2291  m_msPar.copyIn(i, tmp_pos);
2292  }
2293  }
2294 
2295  if (done_count == N_proc)
2296  break;
2297  if (here_count == 0)
2298  continue;
2299 
2300  // ZZZ Could add missing hits here, only if there are any actual matches.
2301 
2302  clearFailFlag();
2303 
2304  // PROP-FAIL-ENABLE Once always "copy input to output on fail" is removed from
2305  // propagateToR one might want to enable this for barrel or endcap or both.
2306  if (LI.is_barrel()) {
2308 
2310  m_Err[iP],
2311  m_Par[iP],
2312  m_msErr,
2313  m_msPar,
2314  m_Err[iC],
2315  m_Par[iC],
2316  tmp_chi2,
2317  N_proc);
2318  } else {
2320 
2322  m_Err[iP],
2323  m_Par[iP],
2324  m_msErr,
2325  m_msPar,
2326  m_Err[iC],
2327  m_Par[iC],
2328  tmp_chi2,
2329  N_proc);
2330  }
2331 
2332 #if defined(DEBUG_PROP_UPDATE)
2333  printf("\nbkfit at layer %d, track in slot %d -- fail=%d, had hit=%d (%g, %g, %g)\n",
2334  LI.layer_id(),
2335  DSLOT,
2336  m_FailFlag[DSLOT],
2337  1 - no_mat_effs[DSLOT],
2338  m_msPar(DSLOT, 0, 0),
2339  m_msPar(DSLOT, 1, 0),
2340  m_msPar(DSLOT, 2, 0));
2341  printf("Propagated:\n");
2342  print_par_err(iP, DSLOT);
2343  printf("Updated:\n");
2344  print_par_err(iC, DSLOT);
2345 #endif
2346 
2347  // Fixup for failed propagation or invpt sign and charge.
2348  for (int i = 0; i < NN; ++i) {
2349  // PROP-FAIL-ENABLE The following to be enabled when propagation failure
2350  // detection is properly implemented in propagate-to-R/Z.
2351  // 1. The following code was only expecting barrel state to be restored.
2352  // auto barrel_pf(m_prop_config->backward_fit_pflags);
2353  // barrel_pf.copy_input_state_on_fail = true;
2354  // 2. There is also check on chi2, commented out to keep physics changes minimal.
2355  /*
2356  if (m_FailFlag[i] && LI.is_barrel()) {
2357  // Barrel pflags are set to include PF_copy_input_state_on_fail.
2358  // Endcap errors are immaterial here (relevant for fwd search), with prop error codes
2359  // one could do other things.
2360  // Are there also fail conditions in KalmanUpdate?
2361 #ifdef DEBUG
2362  if (debug && g_debug) {
2363  dprintf("MkFinder::bkFitFitTracks prop fail: chi2=%f, layer=%d, label=%d. Recovering.\n",
2364  tmp_chi2[i], LI.layer_id(), m_Label[i]);
2365  print_par_err(iC, i);
2366  }
2367 #endif
2368  m_Err[iC].copySlot(i, m_Err[iP]);
2369  m_Par[iC].copySlot(i, m_Par[iP]);
2370  } else if (tmp_chi2[i] > 200 || tmp_chi2[i] < 0) {
2371 #ifdef DEBUG
2372  if (debug && g_debug) {
2373  dprintf("MkFinder::bkFitFitTracks chi2 fail: chi2=%f, layer=%d, label=%d. Recovering.\n",
2374  tmp_chi2[i], LI.layer_id(), m_Label[i]);
2375  print_par_err(iC, i);
2376  }
2377 #endif
2378  // Go back to propagated state (at the current hit, the previous one is lost).
2379  m_Err[iC].copySlot(i, m_Err[iP]);
2380  m_Par[iC].copySlot(i, m_Par[iP]);
2381  }
2382  */
2383  // Fixup invpt sign and charge.
2384  if (i < N_proc && m_Par[iC].At(i, 3, 0) < 0) {
2385  m_Chg.At(i, 0, 0) = -m_Chg.At(i, 0, 0);
2386  m_Par[iC].At(i, 3, 0) = -m_Par[iC].At(i, 3, 0);
2387  }
2388  }
2389 
2390 #if defined(DEBUG_BACKWARD_FIT)
2391  // clang-format off
2392  bool debug = true;
2393  const char beg_cur_sep = '/'; // set to ' ' root parsable printouts
2394  for (int i = 0; i < N_proc; ++i) {
2395  if (chiDebug && last_hit_ptr[i]) {
2396  TrackCand &bb = *m_TrkCand[i];
2397  int ti = iP;
2398  float chi = tmp_chi2.At(i, 0, 0);
2399  float chi_prnt = std::isfinite(chi) ? chi : -9;
2400 
2401 #if defined(MKFIT_STANDALONE)
2402  const MCHitInfo &mchi = m_event->simHitsInfo_[last_hit_ptr[i]->mcHitID()];
2403 
2404  dprintf("BKF_OVERLAP %d %d %d %d %d %d %d "
2405  "%f%c%f %f %f%c%f %f %f %f %d %d %d %d "
2406  "%f %f %f %f %f\n",
2407  m_event->evtID(),
2408 #else
2409  dprintf("BKF_OVERLAP %d %d %d %d %d %d "
2410  "%f%c%f %f %f%c%f %f %f %f %d %d %d "
2411  "%f %f %f %f %f\n",
2412 #endif
2413  bb.label(), (int)bb.prodType(), bb.isFindable(),
2414  layer, L.is_stereo(), L.is_barrel(),
2415  bb.pT(), beg_cur_sep, 1.0f / m_Par[ti].At(i, 3, 0),
2416  bb.posEta(),
2417  bb.posPhi(), beg_cur_sep, std::atan2(m_Par[ti].At(i, 1, 0), m_Par[ti].At(i, 0, 0)),
2418  std::hypot(m_Par[ti].At(i, 0, 0), m_Par[ti].At(i, 1, 0)),
2419  m_Par[ti].At(i, 2, 0),
2420  chi_prnt,
2421  std::isnan(chi), std::isfinite(chi), chi > 0,
2422 #if defined(MKFIT_STANDALONE)
2423  mchi.mcTrackID(),
2424 #endif
2425  // The following three can get negative / prouce nans in e2s.
2426  // std::abs the args for FPE hunt.
2427  e2s(std::abs(m_Err[ti].At(i, 0, 0))),
2428  e2s(std::abs(m_Err[ti].At(i, 1, 1))),
2429  e2s(std::abs(m_Err[ti].At(i, 2, 2))), // sx_t sy_t sz_t -- track errors
2430  1e4f * std::hypot(m_msPar.At(i, 0, 0) - m_Par[ti].At(i, 0, 0),
2431  m_msPar.At(i, 1, 0) - m_Par[ti].At(i, 1, 0)), // d_xy
2432  1e4f * (m_msPar.At(i, 2, 0) - m_Par[ti].At(i, 2, 0)) // d_z
2433  );
2434  }
2435  }
2436  // clang-format on
2437 #endif
2438 
2439  // update chi2
2440  m_Chi2.add(tmp_chi2);
2441  }
2442  }
2443 
2444  //------------------------------------------------------------------------------
2445 
2446  void MkFinder::bkFitPropTracksToPCA(const int N_proc) {
2448  }
2449 
2450 } // end namespace mkfit
void(* m_compute_chi2_foo)(const MPlexLS &, const MPlexLV &, const MPlexQI &, const MPlexHS &, const MPlexHV &, MPlexQF &, MPlexLV &, MPlexQI &, const int, const PropagationFlags &, const bool)
Definition: FindingFoos.h:25
void setOriginIndex(int oi)
float getScoreCand(const track_score_func &score_func, const Track &cand1, bool penalizeTailMissHits=false, bool inFindCandidates=false)
Definition: Track.h:601
float x() const
Definition: Hit.h:162
void addHitIdx(int hitIdx, int hitLyr, float chi2)
int n_hits_match
Definition: RntStructs.h:106
def isnan(num)
MPlexQI m_Chg
Definition: MkBase.h:103
static constexpr int iC
Definition: MkBase.h:18
void copy_in(const Track &trk, const int mslot, const int tslot)
Definition: MkFinder.h:179
static constexpr int MPlexHitIdxMax
Definition: MkFinder.h:42
const SVector6 & parameters() const
Definition: Track.h:132
MPlex< T, D1, D2, N > hypot(const MPlex< T, D1, D2, N > &a, const MPlex< T, D1, D2, N > &b)
Definition: Matriplex.h:616
int charge() const
Definition: Track.h:171
MPlexQI m_NFoundHits
Definition: MkFinder.h:296
const IterationLayerConfig * m_iteration_layer_config
Definition: MkFinder.h:340
void chi2OfLoadedHit(int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1913
Definition: APVGainStruct.h:7
float dq_first_match
Definition: RntStructs.h:108
const HitOnTrack * m_HoTArr[NN]
Definition: MkFinder.h:349
static constexpr int iP
Definition: MkBase.h:19
void inputOverlapHits(const LayerOfHits &layer_of_hits, const std::vector< UpdateIndices > &idxs, int beg, int end)
Definition: MkFinder.cc:181
float rin() const
Definition: TrackerInfo.h:95
PropState ps_min
Definition: RntStructs.h:102
float q_bin() const
Definition: TrackerInfo.h:102
float good_frac() const
Definition: Event.h:56
void kalmanOperationEndcap(const int kfOp, const MPlexLS &psErr, const MPlexLV &psPar, const MPlexHS &msErr, const MPlexHV &msPar, MPlexLS &outErr, MPlexLV &outPar, MPlexQF &outChi2, const int N_proc)
void copy_out(Track &trk, const int mslot, const int tslot) const
Definition: MkFinder.h:196
void packModuleNormDirPnt(const LayerOfHits &layer_of_hits, int hit_cnt, MPlexHV &norm, MPlexHV &dir, MPlexHV &pnt, int N_proc) const
Definition: MkFinder.cc:240
void outputTracksAndHitIdx(std::vector< Track > &tracks, int beg, int end, bool outputProp) const
Definition: MkFinder.cc:217
const float chg[109]
Definition: CoreSimTrack.cc:5
float pT() const
Definition: Track.h:157
void propagateTracksToHitZ(const MPlexHV &par, const int N_proc, const PropagationFlags &pf, const MPlexQI *noMatEffPtr=nullptr)
Definition: MkBase.h:68
HitOnTrack m_HoTArrs[NN][Config::nMaxTrkHits]
Definition: MkFinder.h:298
bin_index_t qBinChecked(float q) const
Definition: HitStructures.h:75
const Hit * hitArray() const
void inputTracksAndHitIdx(const std::vector< Track > &tracks, int beg, int end, bool inputProp)
Definition: MkFinder.cc:99
void bkFitInputTracks(TrackVec &cands, int beg, int end)
Definition: MkFinder.cc:1960
const Event * m_event
Definition: MkFinder.h:343
for(int i=first, nt=offsets[nh];i< nt;i+=gridDim.x *blockDim.x)
Matriplex::Matriplex< float, HH, 1, NN > MPlexHV
Definition: Matrix.h:58
RVec state2mom(const miprops::State &s)
Matriplex::Matriplex< unsigned short, 1, 1, NN > MPlexQUH
Definition: Matrix.h:84
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
int n_hits_pass_match
Definition: RntStructs.h:106
MPlexLV m_Par[2]
Definition: MkBase.h:102
PropagationFlags backward_fit_pflags
MPlexQI m_FailFlag
Definition: MkBase.h:104
ProdType prodType() const
Definition: Track.h:258
Trktree trk
Definition: Trktree.cc:2
bool is_pixel() const
int label() const
Definition: Track.h:174
void selectHitIndices(const LayerOfHits &layer_of_hits, const int N_proc, bool fill_binsearch_only=false)
Definition: MkFinder.cc:320
void setup(const PropagationConfig &pc, const IterationConfig &ic, const IterationParams &ip, const IterationLayerConfig &ilc, const SteeringParams &sp, const std::vector< bool > *ihm, const Event *ev, int region, bool infwd)
Definition: MkFinder.cc:30
PropState statep2propstate(const miprops::StatePlex &s, int i)
void bkFitPropTracksToPCA(const int N_proc)
Definition: MkFinder.cc:2446
int evtID() const
Definition: Event.h:24
int mcTrackID() const
Definition: Hit.h:114
const IterationConfig * m_iteration_config
Definition: MkFinder.h:338
constexpr float PIOver2
Definition: Config.h:9
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:149
void release()
Definition: MkFinder.cc:56
void add_hit(const int mslot, int index, int layer)
Definition: MkFinder.h:248
int n_hits_pass
Definition: RntStructs.h:106
Matriplex::Matriplex< float, LL, 1, NN > MPlexLV
Definition: Matrix.h:54
float getEta(float r, float z)
Definition: Hit.h:38
assert(be >=bs)
constexpr float TwoPI
Definition: Config.h:8
int ord_first_match
Definition: RntStructs.h:107
float exx() const
Definition: Hit.h:165
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:112
Definition: Electron.h:6
const float * posArray() const
Definition: Hit.h:151
static unsigned int maxChargePerCM()
Definition: Hit.h:234
float zmax() const
Definition: TrackerInfo.h:99
static constexpr int kHitStopIdx
Definition: Hit.h:194
const IterationParams * m_iteration_params
Definition: MkFinder.h:339
MPlexLS m_Err[2]
Definition: MkBase.h:101
void kalmanOperation(const int kfOp, const MPlexLS &psErr, const MPlexLV &psPar, const MPlexHS &msErr, const MPlexHV &msPar, MPlexLS &outErr, MPlexLV &outPar, MPlexQF &outChi2, const int N_proc)
void findCandidates(const LayerOfHits &layer_of_hits, std::vector< std::vector< TrackCand >> &tmp_candidates, const int offset, const int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1371
static constexpr int kHitInGapIdx
Definition: Hit.h:197
const Double_t pi
track_score_func m_track_scorer
int m_current_region
Definition: MkFinder.h:344
float ezz() const
Definition: Hit.h:167
constexpr bool usePhiQArrays
Definition: Config.h:76
float momEta() const
Definition: Track.h:161
PropagationFlags finding_inter_layer_pflags
bool isStripQCompatible(int itrack, bool isBarrel, const MPlexLS &pErr, const MPlexLV &pPar, const MPlexHS &msErr, const MPlexHV &msPar)
Definition: MkFinder.cc:1303
void setScore(float s)
Definition: Track.h:178
RVec state2pos(const miprops::State &s)
float getScoreStruct(const track_score_func &score_func, const IdxChi2List &cand1)
Definition: Track.h:617
const PropagationConfig * m_prop_config
Definition: MkFinder.h:337
float zmin() const
Definition: TrackerInfo.h:98
float posR() const
Definition: Track.h:149
iterator make_iterator(IterationType_e type) const
unsigned int module
Definition: IdxChi2List.h:8
int np
Definition: AMPTWrapper.h:43
int num_all_minus_one_hits(const int mslot) const
Definition: MkFinder.h:282
unsigned int detIDinLayer() const
Definition: Hit.h:228
bin_index_t phiBinChecked(float phi) const
Definition: HitStructures.h:79
const ModuleInfo & module_info(unsigned int sid) const
Definition: TrackerInfo.h:160
constexpr float PI
Definition: Config.h:7
void(* m_update_param_foo)(const MPlexLS &, const MPlexLV &, MPlexQI &, const MPlexHS &, const MPlexHV &, MPlexLS &, MPlexLV &, MPlexQI &, const int, const PropagationFlags &, const bool)
Definition: FindingFoos.h:26
Definition: EPCuts.h:4
RVec hit2pos(const Hit &h)
tex
Definition: cuy.py:773
T sqrt(T t)
Definition: SSEVec.h:23
const float * errArray() const
Definition: Hit.h:152
constexpr Matriplex::idx_t NN
Definition: Matrix.h:48
unsigned int bin_content_t
Definition: HitStructures.h:29
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
void setup_bkfit(const PropagationConfig &pc, const SteeringParams &sp, const Event *ev)
Definition: MkFinder.cc:50
PropState ps_max
Definition: RntStructs.h:102
int layer_id() const
Definition: TrackerInfo.h:93
float eyy() const
Definition: Hit.h:166
CombCandidate * combCandidate() const
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
MPlexQI m_XHitSize
Definition: MkFinder.h:323
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
MPlexHV m_msPar
Definition: MkFinder.h:328
void propagateTracksToHitR(const MPlexHV &par, const int N_proc, const PropagationFlags &pf, const MPlexQI *noMatEffPtr=nullptr)
Definition: MkBase.h:42
MPlexQI m_NTailMinusOneHits
Definition: MkFinder.h:313
double f[11][100]
bool isFindable() const
Definition: Track.h:251
void clearFailFlag()
Definition: MkBase.h:96
void min_max(const MPlex< T, D1, D2, N > &a, const MPlex< T, D1, D2, N > &b, MPlex< T, D1, D2, N > &min, MPlex< T, D1, D2, N > &max)
Definition: Matriplex.h:703
float ephi() const
Definition: Hit.h:172
MPlexQI m_SeedOriginIdx
Definition: MkFinder.h:302
int m_CurNode[NN]
Definition: MkFinder.h:350
int n_all_hits
Definition: RntStructs.h:106
MCHitInfoVec simHitsInfo_
Definition: Event.h:73
PropagationFlags pca_prop_pflags
float posEta() const
Definition: Track.h:152
constexpr float nSigmaPhi
BinSearch bso
Definition: RntStructs.h:103
float cdist(float a)
Definition: Config.h:33
void begin_layer(const LayerOfHits &layer_of_hits)
Definition: MkFinder.cc:68
MPlexHS m_msErr
Definition: MkFinder.h:327
void propagateTracksToPCAZ(const int N_proc, const PropagationFlags &pf)
Definition: MkBase.h:82
Matriplex::Matriplex< int, 1, 1, NN > MPlexQI
Definition: Matrix.h:81
ii
Definition: cuy.py:589
TrackVec simTracks_
Definition: Event.h:75
TrackCand * m_TrkCand[NN]
Definition: MkFinder.h:319
void updateWithLoadedHit(int N_proc, const LayerOfHits &layer_of_hits, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1869
float y() const
Definition: Hit.h:163
void selectHitIndicesV2(const LayerOfHits &layer_of_hits, const int N_proc)
Definition: MkFinder.cc:760
std::vector< Track > TrackVec
SimLabelFromHits simLabelForCurrentSeed(int i) const
Definition: Event.cc:871
#define debug
Definition: HDRShower.cc:19
Matriplex::Matriplex< float, 1, 1, NN > MPlexQF
Definition: Matrix.h:80
WithinSensitiveRegion_e m_wsr
Definition: TrackerInfo.h:21
void pack(TMerr &err, TMpar &par)
void bkFitFitTracks(const EventOfHits &eventofhits, const SteeringParams &st_par, const int N_proc, bool chiDebug=false)
Definition: MkFinder.cc:2218
int m_CurHit[NN]
Definition: MkFinder.h:348
const SteeringParams * m_steering_params
Definition: MkFinder.h:341
static const FindingFoos & get_finding_foos(bool is_barrel)
Definition: FindingFoos.cc:18
float z() const
Definition: Track.h:148
std::vector< LayerControl > m_layer_plan
MPlexQI m_NOverlapHits
Definition: MkFinder.h:311
double b
Definition: hdecay.h:120
bool passStripChargePCMfromTrack(int itrack, bool isBarrel, unsigned int pcm, unsigned int pcmMin, const MPlexLV &pPar, const MPlexHS &msErr)
Definition: MkFinder.cc:1335
float getPhi(float x, float y)
Definition: Hit.h:34
bool has_charge() const
Definition: TrackerInfo.h:108
float rout() const
Definition: TrackerInfo.h:96
const Track & currentSeed(int i) const
Definition: Event.cc:869
int nTotalHits() const
Definition: Track.h:512
MPlexHitIdx m_XHitArr
Definition: MkFinder.h:324
Matriplex::MatriplexSym< float, HH, NN > MPlexHS
Definition: Matrix.h:59
#define dprint(x)
Definition: Debug.h:95
MPlexQF m_Chi2
Definition: MkFinder.h:292
static constexpr int kHitMaxClusterIdx
Definition: Hit.h:196
void bkFitOutputTracks(TrackVec &cands, int beg, int end, bool outputProp)
Definition: MkFinder.cc:2017
void bkFitFitTracksBH(const EventOfHits &eventofhits, const SteeringParams &st_par, const int N_proc, bool chiDebug=false)
Definition: MkFinder.cc:2065
std::vector< HitMatchInfo > hmi
Definition: RntStructs.h:105
float z() const
Definition: Hit.h:164
const std::vector< float > & get_window_params(bool forward, bool fallback_to_other) const
MPlexQI m_CandIdx
Definition: MkFinder.h:301
double a
Definition: hdecay.h:121
MPlexQI m_SeedIdx
Definition: MkFinder.h:300
HitOnTrack hot(int i) const
void copyOutParErr(std::vector< CombCandidate > &seed_cand_vec, int N_proc, bool outputProp) const
Definition: MkFinder.cc:1937
int num_inside_minus_one_hits(const int mslot) const
Definition: MkFinder.h:286
void findCandidatesCloneEngine(const LayerOfHits &layer_of_hits, CandCloner &cloner, const int offset, const int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1644
void kalmanPropagateAndComputeChi2Plane(const MPlexLS &psErr, const MPlexLV &psPar, const MPlexQI &inChg, const MPlexHS &msErr, const MPlexHV &msPar, const MPlexHV &plNrm, const MPlexHV &plDir, const MPlexHV &plPnt, MPlexQF &outChi2, MPlexLV &propPar, MPlexQI &outFailFlag, const int N_proc, const PropagationFlags &propFlags, const bool propToHit)
Matriplex::MatriplexSym< float, LL, NN > MPlexLS
Definition: Matrix.h:55
float x
const std::vector< bool > * m_iteration_hit_mask
Definition: MkFinder.h:342
bool is_barrel() const
PropagationFlags finding_intra_layer_pflags
int layer_id() const
void setCharge(int chg)
Definition: Track.h:176
BinSearch bsn
Definition: RntStructs.h:104
void add_cand(int idx, const IdxChi2List &cand_info)
Definition: CandCloner.h:35
float getHitSelDynamicChi2Cut(const int itrk, const int ipar)
Definition: MkFinder.cc:297
MPF fast_atan2(const MPF &y, const MPF &x)
static constexpr int kHitMissIdx
Definition: Hit.h:193
const HoTNode * m_HoTNodeArr[NN]
Definition: MkFinder.h:351
const LayerInfo & layer_info() const
unsigned short bin_index_t
Definition: HitStructures.h:28
float dphi_first_match
Definition: RntStructs.h:108
float momPhi() const
Definition: Track.h:160
WSR_Result m_XWsrResult[NN]
Definition: MkFinder.h:322
float posPhi() const
Definition: Track.h:151
void getHitSelDynamicWindows(const float invpt, const float theta, float &min_dq, float &max_dq, float &min_dphi, float &max_dphi)
Definition: MkFinder.cc:266
static constexpr int kHitEdgeIdx
Definition: Hit.h:195
bool assignIdxChi2List(const mkfit::IdxChi2List &ic2l)
Definition: RntStructs.h:120
CombCandidate & combCandWithOriginalIndex(int idx)
Definition: CandCloner.h:52
static unsigned int minChargePerCM()
Definition: Hit.h:233
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
#define dprintf(...)
Definition: Debug.h:98
int mcHitID() const
Definition: Hit.h:187
MPlexQI m_Label
Definition: MkFinder.h:293
bool is_barrel() const
Definition: TrackerInfo.h:105
bool usePropToPlane
Definition: Config.cc:7
void end_layer()
Definition: MkFinder.cc:88
const Hit & refHit(int i) const
MPlex< T, D1, D2, N > sqrt(const MPlex< T, D1, D2, N > &a)
Definition: Matriplex.h:610
void print_par_err(int corp, int mslot) const
Definition: MkFinder.cc:2202
MPlex< T, D1, D2, N > atan2(const MPlex< T, D1, D2, N > &y, const MPlex< T, D1, D2, N > &x)
Definition: Matriplex.h:648
void addBestHit(const LayerOfHits &layer_of_hits, const int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1155
constexpr bool isFinite(float x)
void kalmanPropagateAndUpdatePlane(const MPlexLS &psErr, const MPlexLV &psPar, MPlexQI &Chg, const MPlexHS &msErr, const MPlexHV &msPar, const MPlexHV &plNrm, const MPlexHV &plDir, const MPlexHV &plPnt, MPlexLS &outErr, MPlexLV &outPar, MPlexQI &outFailFlag, const int N_proc, const PropagationFlags &propFlags, const bool propToHit)