CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
MkFinder.cc
Go to the documentation of this file.
1 #include "MkFinder.h"
2 
3 #include "CandCloner.h"
6 #include "FindingFoos.h"
7 
8 #include "KalmanUtilsMPlex.h"
9 
10 #include "MatriplexPackers.h"
11 
12 //#define DEBUG
13 #include "Debug.h"
14 
15 #if (defined(DUMPHITWINDOW) || defined(DEBUG_BACKWARD_FIT)) && defined(MKFIT_STANDALONE)
17 #endif
18 
19 #ifndef MKFIT_STANDALONE
21 #endif
22 
23 #include <algorithm>
24 
25 namespace {
26  bool isFinite(float x) {
27 #ifndef MKFIT_STANDALONE
28  return edm::isFinite(x);
29 #else
30  return std::isfinite(x);
31 #endif
32  }
33 } // namespace
34 
35 namespace mkfit {
36 
38  const IterationParams &ip,
39  const IterationLayerConfig &ilc,
40  const std::vector<bool> *ihm) {
41  m_prop_config = &pc;
42  m_iteration_params = &ip;
45  }
46 
48 
50  m_prop_config = nullptr;
51  m_iteration_params = nullptr;
52  m_iteration_layer_config = nullptr;
53  m_iteration_hit_mask = nullptr;
54  }
55 
56  //==============================================================================
57  // Input / Output TracksAndHitIdx
58  //==============================================================================
59 
60  void MkFinder::inputTracksAndHitIdx(const std::vector<Track> &tracks, int beg, int end, bool inputProp) {
61  // Assign track parameters to initial state and copy hit values in.
62 
63  // This might not be true for the last chunk!
64  // assert(end - beg == NN);
65 
66  const int iI = inputProp ? iP : iC;
67 
68  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
69  copy_in(tracks[i], imp, iI);
70  }
71  }
72 
74  const std::vector<Track> &tracks, const std::vector<int> &idxs, int beg, int end, bool inputProp, int mp_offset) {
75  // Assign track parameters to initial state and copy hit values in.
76 
77  // This might not be true for the last chunk!
78  // assert(end - beg == NN);
79 
80  const int iI = inputProp ? iP : iC;
81 
82  for (int i = beg, imp = mp_offset; i < end; ++i, ++imp) {
83  copy_in(tracks[idxs[i]], imp, iI);
84  }
85  }
86 
87  void MkFinder::inputTracksAndHitIdx(const std::vector<CombCandidate> &tracks,
88  const std::vector<std::pair<int, int>> &idxs,
89  int beg,
90  int end,
91  bool inputProp) {
92  // Assign track parameters to initial state and copy hit values in.
93 
94  // This might not be true for the last chunk!
95  // assert(end - beg == NN);
96 
97  const int iI = inputProp ? iP : iC;
98 
99  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
100  const TrackCand &trk = tracks[idxs[i].first][idxs[i].second];
101 
102  copy_in(trk, imp, iI);
103 
104 #ifdef DUMPHITWINDOW
105  m_SeedAlgo(imp, 0, 0) = tracks[idxs[i].first].seed_algo();
106  m_SeedLabel(imp, 0, 0) = tracks[idxs[i].first].seed_label();
107 #endif
108 
109  m_SeedIdx(imp, 0, 0) = idxs[i].first;
110  m_CandIdx(imp, 0, 0) = idxs[i].second;
111  }
112  }
113 
114  void MkFinder::inputTracksAndHitIdx(const std::vector<CombCandidate> &tracks,
115  const std::vector<std::pair<int, IdxChi2List>> &idxs,
116  int beg,
117  int end,
118  bool inputProp) {
119  // Assign track parameters to initial state and copy hit values in.
120 
121  // This might not be true for the last chunk!
122  // assert(end - beg == NN);
123 
124  const int iI = inputProp ? iP : iC;
125 
126  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
127  const TrackCand &trk = tracks[idxs[i].first][idxs[i].second.trkIdx];
128 
129  copy_in(trk, imp, iI);
130 
131 #ifdef DUMPHITWINDOW
132  m_SeedAlgo(imp, 0, 0) = tracks[idxs[i].first].seed_algo();
133  m_SeedLabel(imp, 0, 0) = tracks[idxs[i].first].seed_label();
134 #endif
135 
136  m_SeedIdx(imp, 0, 0) = idxs[i].first;
137  m_CandIdx(imp, 0, 0) = idxs[i].second.trkIdx;
138  }
139  }
140 
141  void MkFinder::outputTracksAndHitIdx(std::vector<Track> &tracks, int beg, int end, bool outputProp) const {
142  // Copies requested track parameters into Track objects.
143  // The tracks vector should be resized to allow direct copying.
144 
145  const int iO = outputProp ? iP : iC;
146 
147  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
148  copy_out(tracks[i], imp, iO);
149  }
150  }
151 
153  std::vector<Track> &tracks, const std::vector<int> &idxs, int beg, int end, bool outputProp) const {
154  // Copies requested track parameters into Track objects.
155  // The tracks vector should be resized to allow direct copying.
156 
157  const int iO = outputProp ? iP : iC;
158 
159  for (int i = beg, imp = 0; i < end; ++i, ++imp) {
160  copy_out(tracks[idxs[i]], imp, iO);
161  }
162  }
163 
164  //==============================================================================
165  // getHitSelDynamicWindows
166  //==============================================================================
167  // From HitSelectionWindows.h: track-related config on hit selection windows
168 
170  const float invpt, const float theta, float &min_dq, float &max_dq, float &min_dphi, float &max_dphi) {
172 
173  float max_invpt = invpt;
174  if (invpt > 10.0)
175  max_invpt = 10.0; // => pT>0.1 GeV
176 
177  // dq hit selection window
178  float this_dq = (ILC.c_dq_0) * max_invpt + (ILC.c_dq_1) * theta + (ILC.c_dq_2);
179  // In case layer is missing (e.g., seeding layers, or too low stats for training), leave original limits
180  if ((ILC.c_dq_sf) * this_dq > 0.f) {
181  min_dq = (ILC.c_dq_sf) * this_dq;
182  max_dq = 2.0f * min_dq;
183  }
184 
185  // dphi hit selection window
186  float this_dphi = (ILC.c_dp_0) * max_invpt + (ILC.c_dp_1) * theta + (ILC.c_dp_2);
187  // In case layer is missing (e.g., seeding layers, or too low stats for training), leave original limits
188  if ((ILC.c_dp_sf) * this_dphi > min_dphi) {
189  min_dphi = (ILC.c_dp_sf) * this_dphi;
190  max_dphi = 2.0f * min_dphi;
191  }
192 
194  //float this_c2 = (ILC.c_c2_0)*invpt+(ILC.c_c2_1)*theta+(ILC.c_c2_2);
196  //if(this_c2>0.f){
197  // max_c2 = (ILC.c_c2_sf)*this_c2;
198  //}
199  }
200 
201  //==============================================================================
202  // getHitSelDynamicChi2Cut
203  //==============================================================================
204  // From HitSelectionWindows.h: track-related config on hit selection windows
205 
206  inline float MkFinder::getHitSelDynamicChi2Cut(const int itrk, const int ipar) {
208 
209  const float minChi2Cut = m_iteration_params->chi2Cut_min;
210  const float invpt = m_Par[ipar].At(itrk, 3, 0);
211  const float theta = std::abs(m_Par[ipar].At(itrk, 5, 0) - Const::PIOver2);
212 
213  float max_invpt = invpt;
214  if (invpt > 10.0)
215  max_invpt = 10.0;
216 
217  float this_c2 = ILC.c_c2_0 * max_invpt + ILC.c_c2_1 * theta + ILC.c_c2_2;
218  // In case layer is missing (e.g., seeding layers, or too low stats for training), leave original limits
219  if ((ILC.c_c2_sf) * this_c2 > minChi2Cut)
220  return ILC.c_c2_sf * this_c2;
221  else
222  return minChi2Cut;
223  }
224 
225  //==============================================================================
226  // SelectHitIndices
227  //==============================================================================
228 
229  void MkFinder::selectHitIndices(const LayerOfHits &layer_of_hits, const int N_proc) {
230  // bool debug = true;
231 
232  const LayerOfHits &L = layer_of_hits;
234 
235  const int iI = iP;
236  const float nSigmaPhi = 3;
237  const float nSigmaZ = 3;
238  const float nSigmaR = 3;
239 
240  dprintf("LayerOfHits::SelectHitIndices %s layer=%d N_proc=%d\n",
241  L.is_barrel() ? "barrel" : "endcap",
242  L.layer_id(),
243  N_proc);
244 
245  float dqv[NN], dphiv[NN], qv[NN], phiv[NN];
246  int qb1v[NN], qb2v[NN], qbv[NN], pb1v[NN], pb2v[NN];
247 
248  const auto assignbins = [&](int itrack,
249  float q,
250  float dq,
251  float phi,
252  float dphi,
253  float min_dq,
254  float max_dq,
255  float min_dphi,
256  float max_dphi) {
257  dphi = std::clamp(std::abs(dphi), min_dphi, max_dphi);
258  dq = std::clamp(dq, min_dq, max_dq);
259  //
260  qv[itrack] = q;
261  phiv[itrack] = phi;
262  dphiv[itrack] = dphi;
263  dqv[itrack] = dq;
264  //
265  qbv[itrack] = L.qBinChecked(q);
266  qb1v[itrack] = L.qBinChecked(q - dq);
267  qb2v[itrack] = L.qBinChecked(q + dq) + 1;
268  pb1v[itrack] = L.phiBin(phi - dphi);
269  pb2v[itrack] = L.phiBin(phi + dphi) + 1;
270  };
271 
272  const auto calcdphi2 = [&](int itrack, float dphidx, float dphidy) {
273  return dphidx * dphidx * m_Err[iI].constAt(itrack, 0, 0) + dphidy * dphidy * m_Err[iI].constAt(itrack, 1, 1) +
274  2 * dphidx * dphidy * m_Err[iI].constAt(itrack, 0, 1);
275  };
276 
277  const auto calcdphi = [&](float dphi2, float min_dphi) {
278  return std::max(nSigmaPhi * std::sqrt(std::abs(dphi2)), min_dphi);
279  };
280 
281  if (L.is_barrel()) {
282  // Pull out the part of the loop that vectorizes
283 #pragma omp simd
284  for (int itrack = 0; itrack < NN; ++itrack) {
285  m_XHitSize[itrack] = 0;
286 
287  float min_dq = ILC.min_dq();
288  float max_dq = ILC.max_dq();
289  float min_dphi = ILC.min_dphi();
290  float max_dphi = ILC.max_dphi();
291 
292  const float invpt = m_Par[iI].At(itrack, 3, 0);
293  const float theta = std::fabs(m_Par[iI].At(itrack, 5, 0) - Const::PIOver2);
294  getHitSelDynamicWindows(invpt, theta, min_dq, max_dq, min_dphi, max_dphi);
295 
296  const float x = m_Par[iI].constAt(itrack, 0, 0);
297  const float y = m_Par[iI].constAt(itrack, 1, 0);
298  const float r2 = x * x + y * y;
299  const float dphidx = -y / r2, dphidy = x / r2;
300  const float dphi2 = calcdphi2(itrack, dphidx, dphidy);
301 #ifdef HARD_CHECK
302  assert(dphi2 >= 0);
303 #endif
304 
305  const float phi = getPhi(x, y);
306  float dphi = calcdphi(dphi2, min_dphi);
307 
308  const float z = m_Par[iI].constAt(itrack, 2, 0);
309  const float dz = std::abs(nSigmaZ * std::sqrt(m_Err[iI].constAt(itrack, 2, 2)));
310  const float edgeCorr = std::abs(0.5f * (L.layer_info()->rout() - L.layer_info()->rin()) /
311  std::tan(m_Par[iI].constAt(itrack, 5, 0)));
312  // XXX-NUM-ERR above, m_Err(2,2) gets negative!
313 
314  m_XWsrResult[itrack] = L.is_within_z_sensitive_region(z, std::sqrt(dz * dz + edgeCorr * edgeCorr));
315  assignbins(itrack, z, dz, phi, dphi, min_dq, max_dq, min_dphi, max_dphi);
316  }
317  } else // endcap
318  {
319  // Pull out the part of the loop that vectorizes
320 #pragma omp simd
321  for (int itrack = 0; itrack < NN; ++itrack) {
322  m_XHitSize[itrack] = 0;
323 
324  float min_dq = ILC.min_dq();
325  float max_dq = ILC.max_dq();
326  float min_dphi = ILC.min_dphi();
327  float max_dphi = ILC.max_dphi();
328 
329  const float invpt = m_Par[iI].At(itrack, 3, 0);
330  const float theta = std::fabs(m_Par[iI].At(itrack, 5, 0) - Const::PIOver2);
331  getHitSelDynamicWindows(invpt, theta, min_dq, max_dq, min_dphi, max_dphi);
332 
333  const float x = m_Par[iI].constAt(itrack, 0, 0);
334  const float y = m_Par[iI].constAt(itrack, 1, 0);
335  const float r2 = x * x + y * y;
336  const float dphidx = -y / r2, dphidy = x / r2;
337  const float dphi2 = calcdphi2(itrack, dphidx, dphidy);
338 #ifdef HARD_CHECK
339  assert(dphi2 >= 0);
340 #endif
341 
342  const float phi = getPhi(x, y);
343  float dphi = calcdphi(dphi2, min_dphi);
344 
345  const float r = std::sqrt(r2);
346  const float dr = nSigmaR * std::sqrt(std::abs(x * x * m_Err[iI].constAt(itrack, 0, 0) +
347  y * y * m_Err[iI].constAt(itrack, 1, 1) +
348  2 * x * y * m_Err[iI].constAt(itrack, 0, 1)) /
349  r2);
350  const float edgeCorr = std::abs(0.5f * (L.layer_info()->zmax() - L.layer_info()->zmin()) *
351  std::tan(m_Par[iI].constAt(itrack, 5, 0)));
352 
353  m_XWsrResult[itrack] = L.is_within_r_sensitive_region(r, std::sqrt(dr * dr + edgeCorr * edgeCorr));
354  assignbins(itrack, r, dr, phi, dphi, min_dq, max_dq, min_dphi, max_dphi);
355  }
356  }
357 
358  // Vectorizing this makes it run slower!
359  //#pragma omp simd
360  for (int itrack = 0; itrack < N_proc; ++itrack) {
361  if (m_XWsrResult[itrack].m_wsr == WSR_Outside) {
362  m_XHitSize[itrack] = -1;
363  continue;
364  }
365 
366  const int qb = qbv[itrack];
367  const int qb1 = qb1v[itrack];
368  const int qb2 = qb2v[itrack];
369  const int pb1 = pb1v[itrack];
370  const int pb2 = pb2v[itrack];
371 
372  // Used only by usePhiQArrays
373  const float q = qv[itrack];
374  const float phi = phiv[itrack];
375  const float dphi = dphiv[itrack];
376  const float dq = dqv[itrack];
377 
378  dprintf(" %2d/%2d: %6.3f %6.3f %6.6f %7.5f %3d %3d %4d %4d\n",
379  L.layer_id(),
380  itrack,
381  q,
382  phi,
383  dq,
384  dphi,
385  qb1,
386  qb2,
387  pb1,
388  pb2);
389 
390  // MT: One could iterate in "spiral" order, to pick hits close to the center.
391  // http://stackoverflow.com/questions/398299/looping-in-a-spiral
392  // This would then work best with relatively small bin sizes.
393  // Or, set them up so I can always take 3x3 array around the intersection.
394 
395 #if defined(DUMPHITWINDOW) && defined(MKFIT_STANDALONE)
396  int thisseedmcid = -999999;
397  {
398  int seedlabel = m_SeedLabel(itrack, 0, 0);
399  TrackVec &seedtracks = m_event->seedTracks_;
400  int thisidx = -999999;
401  for (int i = 0; i < int(seedtracks.size()); ++i) {
402  auto &thisseed = seedtracks[i];
403  if (thisseed.label() == seedlabel) {
404  thisidx = i;
405  break;
406  }
407  }
408  if (thisidx > -999999) {
409  auto &seedtrack = m_event->seedTracks_[thisidx];
410  std::vector<int> thismcHitIDs;
411  seedtrack.mcHitIDsVec(m_event->layerHits_, m_event->simHitsInfo_, thismcHitIDs);
412  if (std::adjacent_find(thismcHitIDs.begin(), thismcHitIDs.end(), std::not_equal_to<>()) ==
413  thismcHitIDs.end()) {
414  thisseedmcid = thismcHitIDs.at(0);
415  }
416  }
417  }
418 #endif
419 
420  for (int qi = qb1; qi < qb2; ++qi) {
421  for (int pi = pb1; pi < pb2; ++pi) {
422  const int pb = L.phiMaskApply(pi);
423 
424  // Limit to central Q-bin
425  if (qi == qb && L.phi_bin_dead(qi, pb) == true) {
426  dprint("dead module for track in layer=" << L.layer_id() << " qb=" << qi << " pb=" << pb << " q=" << q
427  << " phi=" << phi);
428  m_XWsrResult[itrack].m_in_gap = true;
429  }
430 
431  // MT: The following line is the biggest hog (4% total run time).
432  // This comes from cache misses, I presume.
433  // It might make sense to make first loop to extract bin indices
434  // and issue prefetches at the same time.
435  // Then enter vectorized loop to actually collect the hits in proper order.
436 
437  //SK: ~20x1024 bin sizes give mostly 1 hit per bin. Commented out for 128 bins or less
438  // #pragma nounroll
439  auto pbi = L.phi_bin_info(qi, pb);
440  for (uint16_t hi = pbi.first; hi < pbi.second; ++hi) {
441  // MT: Access into m_hit_zs and m_hit_phis is 1% run-time each.
442 
443  int hi_orig = L.getOriginalHitIndex(hi);
444 
445  if (m_iteration_hit_mask && (*m_iteration_hit_mask)[hi_orig]) {
446  dprintf(
447  "Yay, denying masked hit on layer %d, hi %d, orig idx %d\n", L.layer_info()->layer_id(), hi, hi_orig);
448  continue;
449  }
450 
451  if (Config::usePhiQArrays) {
452  if (m_XHitSize[itrack] >= MPlexHitIdxMax)
453  break;
454 
455  const float ddq = std::abs(q - L.hit_q(hi));
456  const float ddphi = cdist(std::abs(phi - L.hit_phi(hi)));
457 
458 #if defined(DUMPHITWINDOW) && defined(MKFIT_STANDALONE)
459  {
460  const MCHitInfo &mchinfo = m_event->simHitsInfo_[L.refHit(hi).mcHitID()];
461  int mchid = mchinfo.mcTrackID();
462  int st_isfindable = 0;
463  int st_label = -999999;
464  int st_prodtype = 0;
465  int st_nhits = -1;
466  int st_charge = 0;
467  float st_r = -999.;
468  float st_z = -999.;
469  float st_pt = -999.;
470  float st_eta = -999.;
471  float st_phi = -999.;
472  if (mchid >= 0) {
473  Track simtrack = m_event->simTracks_[mchid];
474  st_isfindable = (int)simtrack.isFindable();
475  st_label = simtrack.label();
476  st_prodtype = (int)simtrack.prodType();
477  st_pt = simtrack.pT();
478  st_eta = simtrack.momEta();
479  st_phi = simtrack.momPhi();
480  st_nhits = simtrack.nTotalHits();
481  st_charge = simtrack.charge();
482  st_r = simtrack.posR();
483  st_z = simtrack.z();
484  }
485 
486  const Hit &thishit = L.refHit(hi);
487  m_msErr.copyIn(itrack, thishit.errArray());
488  m_msPar.copyIn(itrack, thishit.posArray());
489 
490  MPlexQF thisOutChi2;
491  MPlexLV tmpPropPar;
492  const FindingFoos &fnd_foos = FindingFoos::get_finding_foos(L.is_barrel());
493  (*fnd_foos.m_compute_chi2_foo)(m_Err[iI],
494  m_Par[iI],
495  m_Chg,
496  m_msErr,
497  m_msPar,
498  thisOutChi2,
499  tmpPropPar,
500  N_proc,
503 
504  float hx = thishit.x();
505  float hy = thishit.y();
506  float hz = thishit.z();
507  float hr = std::hypot(hx, hy);
508  float hphi = std::atan2(hy, hx);
509  float hex = std::sqrt(thishit.exx());
510  if (std::isnan(hex))
511  hex = -999.;
512  float hey = std::sqrt(thishit.eyy());
513  if (std::isnan(hey))
514  hey = -999.;
515  float hez = std::sqrt(thishit.ezz());
516  if (std::isnan(hez))
517  hez = -999.;
518  float her = std::sqrt(
519  (hx * hx * thishit.exx() + hy * hy * thishit.eyy() + 2.0f * hx * hy * m_msErr.At(itrack, 0, 1)) /
520  (hr * hr));
521  if (std::isnan(her))
522  her = -999.;
523  float hephi = std::sqrt(thishit.ephi());
524  if (std::isnan(hephi))
525  hephi = -999.;
526  float hchi2 = thisOutChi2[itrack];
527  if (std::isnan(hchi2))
528  hchi2 = -999.;
529  float tx = m_Par[iI].At(itrack, 0, 0);
530  float ty = m_Par[iI].At(itrack, 1, 0);
531  float tz = m_Par[iI].At(itrack, 2, 0);
532  float tr = std::hypot(tx, ty);
533  float tphi = std::atan2(ty, tx);
534  float tchi2 = m_Chi2(itrack, 0, 0);
535  if (std::isnan(tchi2))
536  tchi2 = -999.;
537  float tex = std::sqrt(m_Err[iI].At(itrack, 0, 0));
538  if (std::isnan(tex))
539  tex = -999.;
540  float tey = std::sqrt(m_Err[iI].At(itrack, 1, 1));
541  if (std::isnan(tey))
542  tey = -999.;
543  float tez = std::sqrt(m_Err[iI].At(itrack, 2, 2));
544  if (std::isnan(tez))
545  tez = -999.;
546  float ter = std::sqrt(
547  (tx * tx * tex * tex + ty * ty * tey * tey + 2.0f * tx * ty * m_Err[iI].At(itrack, 0, 1)) /
548  (tr * tr));
549  if (std::isnan(ter))
550  ter = -999.;
551  float tephi = std::sqrt(
552  (ty * ty * tex * tex + tx * tx * tey * tey - 2.0f * tx * ty * m_Err[iI].At(itrack, 0, 1)) /
553  (tr * tr * tr * tr));
554  if (std::isnan(tephi))
555  tephi = -999.;
556  float ht_dxy = std::hypot(hx - tx, hy - ty);
557  float ht_dz = hz - tz;
558  float ht_dphi = cdist(std::abs(hphi - tphi));
559 
560  static bool first = true;
561  if (first) {
562  printf(
563  "HITWINDOWSEL "
564  "evt_id/I:"
565  "lyr_id/I:lyr_isbrl/I:hit_idx/I:"
566  "trk_cnt/I:trk_idx/I:trk_label/I:"
567  "trk_pt/F:trk_eta/F:trk_mphi/F:trk_chi2/F:"
568  "nhits/I:"
569  "seed_idx/I:seed_label/I:seed_algo/I:seed_mcid/I:"
570  "hit_mcid/I:"
571  "st_isfindable/I:st_prodtype/I:st_label/I:"
572  "st_pt/F:st_eta/F:st_phi/F:"
573  "st_nhits/I:st_charge/I:st_r/F:st_z/F:"
574  "trk_q/F:hit_q/F:dq_trkhit/F:dq_cut/F:trk_phi/F:hit_phi/F:dphi_trkhit/F:dphi_cut/F:"
575  "t_x/F:t_y/F:t_r/F:t_phi/F:t_z/F:"
576  "t_ex/F:t_ey/F:t_er/F:t_ephi/F:t_ez/F:"
577  "h_x/F:h_y/F:h_r/F:h_phi/F:h_z/F:"
578  "h_ex/F:h_ey/F:h_er/F:h_ephi/F:h_ez/F:"
579  "ht_dxy/F:ht_dz/F:ht_dphi/F:"
580  "h_chi2/F"
581  "\n");
582  first = false;
583  }
584 
585  if (!(std::isnan(phi)) && !(std::isnan(getEta(m_Par[iI].At(itrack, 5, 0))))) {
586  //|| std::isnan(ter) || std::isnan(her) || std::isnan(m_Chi2(itrack, 0, 0)) || std::isnan(hchi2)))
587  printf(
588  "HITWINDOWSEL "
589  "%d "
590  "%d %d %d "
591  "%d %d %d "
592  "%6.3f %6.3f %6.3f %6.3f "
593  "%d "
594  "%d %d %d %d "
595  "%d "
596  "%d %d %d "
597  "%6.3f %6.3f %6.3f "
598  "%d %d %6.3f %6.3f "
599  "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f "
600  "%6.3f %6.3f %6.3f %6.3f %6.3f "
601  "%6.6f %6.6f %6.6f %6.6f %6.6f "
602  "%6.3f %6.3f %6.3f %6.3f %6.3f "
603  "%6.6f %6.6f %6.6f %6.6f %6.6f "
604  "%6.3f %6.3f %6.3f "
605  "%6.3f"
606  "\n",
607  m_event->evtID(),
608  L.layer_id(),
609  L.is_barrel(),
610  L.getOriginalHitIndex(hi),
611  itrack,
612  m_CandIdx(itrack, 0, 0),
613  m_Label(itrack, 0, 0),
614  1.0f / m_Par[iI].At(itrack, 3, 0),
615  getEta(m_Par[iI].At(itrack, 5, 0)),
616  m_Par[iI].At(itrack, 4, 0),
617  m_Chi2(itrack, 0, 0),
618  m_NFoundHits(itrack, 0, 0),
619  m_SeedIdx(itrack, 0, 0),
620  m_SeedLabel(itrack, 0, 0),
621  m_SeedAlgo(itrack, 0, 0),
622  thisseedmcid,
623  mchid,
624  st_isfindable,
625  st_prodtype,
626  st_label,
627  st_pt,
628  st_eta,
629  st_phi,
630  st_nhits,
631  st_charge,
632  st_r,
633  st_z,
634  q,
635  L.hit_q(hi),
636  ddq,
637  dq,
638  phi,
639  L.hit_phi(hi),
640  ddphi,
641  dphi,
642  tx,
643  ty,
644  tr,
645  tphi,
646  tz,
647  tex,
648  tey,
649  ter,
650  tephi,
651  tez,
652  hx,
653  hy,
654  hr,
655  hphi,
656  hz,
657  hex,
658  hey,
659  her,
660  hephi,
661  hez,
662  ht_dxy,
663  ht_dz,
664  ht_dphi,
665  hchi2);
666  }
667  }
668 #endif
669 
670  if (ddq >= dq)
671  continue;
672  if (ddphi >= dphi)
673  continue;
674 
675  dprintf(" SHI %3d %4d %4d %5d %6.3f %6.3f %6.4f %7.5f %s\n",
676  qi,
677  pi,
678  pb,
679  hi,
680  L.hit_q(hi),
681  L.hit_phi(hi),
682  ddq,
683  ddphi,
684  (ddq < dq && ddphi < dphi) ? "PASS" : "FAIL");
685 
686  // MT: Removing extra check gives full efficiency ...
687  // and means our error estimations are wrong!
688  // Avi says we should have *minimal* search windows per layer.
689  // Also ... if bins are sufficiently small, we do not need the extra
690  // checks, see above.
691  m_XHitArr.At(itrack, m_XHitSize[itrack]++, 0) = hi_orig;
692  } else {
693  // MT: The following check alone makes more sense with spiral traversal,
694  // we'd be taking in closest hits first.
695 
696  // Hmmh -- there used to be some more checks here.
697  // Or, at least, the phi binning was much smaller and no further checks were done.
698  assert(false && "this code has not been used in a while -- see comments in code");
699 
700  if (m_XHitSize[itrack] < MPlexHitIdxMax) {
701  m_XHitArr.At(itrack, m_XHitSize[itrack]++, 0) = hi_orig;
702  }
703  }
704  } //hi
705  } //pi
706  } //qi
707  } //itrack
708  }
709 
710  //==============================================================================
711  // AddBestHit - Best Hit Track Finding
712  //==============================================================================
713 
714  void MkFinder::addBestHit(const LayerOfHits &layer_of_hits, const int N_proc, const FindingFoos &fnd_foos) {
715  // debug = true;
716 
717  MatriplexHitPacker mhp(layer_of_hits.hitArray());
718 
719  float minChi2[NN];
720  int bestHit[NN];
721  int maxSize = 0;
722 
723  // Determine maximum number of hits for tracks in the collection.
724  for (int it = 0; it < NN; ++it) {
725  if (it < N_proc) {
726  if (m_XHitSize[it] > 0) {
727  maxSize = std::max(maxSize, m_XHitSize[it]);
728  }
729  }
730 
731  bestHit[it] = -1;
732  minChi2[it] = getHitSelDynamicChi2Cut(it, iP);
733  }
734 
735  for (int hit_cnt = 0; hit_cnt < maxSize; ++hit_cnt) {
736  //fixme what if size is zero???
737 
738  mhp.reset();
739 
740 #pragma omp simd
741  for (int itrack = 0; itrack < N_proc; ++itrack) {
742  if (hit_cnt < m_XHitSize[itrack]) {
743  mhp.addInputAt(itrack, layer_of_hits.refHit(m_XHitArr.At(itrack, hit_cnt, 0)));
744  }
745  }
746 
747  mhp.pack(m_msErr, m_msPar);
748 
749  //now compute the chi2 of track state vs hit
750  MPlexQF outChi2;
751  MPlexLV tmpPropPar;
752  (*fnd_foos.m_compute_chi2_foo)(m_Err[iP],
753  m_Par[iP],
754  m_Chg,
755  m_msErr,
756  m_msPar,
757  outChi2,
758  tmpPropPar,
759  N_proc,
762 
763  //update best hit in case chi2<minChi2
764 #pragma omp simd
765  for (int itrack = 0; itrack < N_proc; ++itrack) {
766  if (hit_cnt < m_XHitSize[itrack]) {
767  const float chi2 = std::abs(outChi2[itrack]); //fixme negative chi2 sometimes...
768  dprint("chi2=" << chi2 << " minChi2[itrack]=" << minChi2[itrack]);
769  if (chi2 < minChi2[itrack]) {
770  minChi2[itrack] = chi2;
771  bestHit[itrack] = m_XHitArr.At(itrack, hit_cnt, 0);
772  }
773  }
774  }
775  } // end loop over hits
776 
777  //#pragma omp simd
778  for (int itrack = 0; itrack < N_proc; ++itrack) {
779  if (m_XWsrResult[itrack].m_wsr == WSR_Outside) {
780  // Why am I doing this?
781  m_msErr.setDiagonal3x3(itrack, 666);
782  m_msPar(itrack, 0, 0) = m_Par[iP](itrack, 0, 0);
783  m_msPar(itrack, 1, 0) = m_Par[iP](itrack, 1, 0);
784  m_msPar(itrack, 2, 0) = m_Par[iP](itrack, 2, 0);
785 
786  // XXXX If not in gap, should get back the old track params. But they are gone ...
787  // Would actually have to do it right after SelectHitIndices where updated params are still ok.
788  // Here they got screwed during hit matching.
789  // So, I'd store them there (into propagated params) and retrieve them here.
790  // Or we decide not to care ...
791 
792  continue;
793  }
794 
795  //fixme decide what to do in case no hit found
796  if (bestHit[itrack] >= 0) {
797  const Hit &hit = layer_of_hits.refHit(bestHit[itrack]);
798  const float chi2 = minChi2[itrack];
799 
800  dprint("ADD BEST HIT FOR TRACK #"
801  << itrack << std::endl
802  << "prop x=" << m_Par[iP].constAt(itrack, 0, 0) << " y=" << m_Par[iP].constAt(itrack, 1, 0) << std::endl
803  << "copy in hit #" << bestHit[itrack] << " x=" << hit.position()[0] << " y=" << hit.position()[1]);
804 
805  m_msErr.copyIn(itrack, hit.errArray());
806  m_msPar.copyIn(itrack, hit.posArray());
807  m_Chi2(itrack, 0, 0) += chi2;
808 
809  add_hit(itrack, bestHit[itrack], layer_of_hits.layer_id());
810  } else {
811  int fake_hit_idx = -1;
812 
813  if (m_XWsrResult[itrack].m_wsr == WSR_Edge) {
814  // YYYYYY Config::store_missed_layers
815  fake_hit_idx = -3;
816  } else if (num_all_minus_one_hits(itrack)) {
817  fake_hit_idx = -2;
818  }
819 
820  dprint("ADD FAKE HIT FOR TRACK #" << itrack << " withinBounds=" << (fake_hit_idx != -3)
821  << " r=" << std::hypot(m_Par[iP](itrack, 0, 0), m_Par[iP](itrack, 1, 0)));
822 
823  m_msErr.setDiagonal3x3(itrack, 666);
824  m_msPar(itrack, 0, 0) = m_Par[iP](itrack, 0, 0);
825  m_msPar(itrack, 1, 0) = m_Par[iP](itrack, 1, 0);
826  m_msPar(itrack, 2, 0) = m_Par[iP](itrack, 2, 0);
827  // Don't update chi2
828 
829  add_hit(itrack, fake_hit_idx, layer_of_hits.layer_id());
830  }
831  }
832 
833  // Update the track parameters with this hit. (Note that some calculations
834  // are already done when computing chi2. Not sure it's worth caching them?)
835 
836  dprint("update parameters");
837  (*fnd_foos.m_update_param_foo)(m_Err[iP],
838  m_Par[iP],
839  m_Chg,
840  m_msErr,
841  m_msPar,
842  m_Err[iC],
843  m_Par[iC],
844  N_proc,
847 
848  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));
849  }
850 
851  //=======================================================
852  // isStripQCompatible : check if prop is consistent with the barrel/endcap strip length
853  //=======================================================
855  int itrack, bool isBarrel, const MPlexLS &pErr, const MPlexLV &pPar, const MPlexHS &msErr, const MPlexHV &msPar) {
856  //check module compatibility via long strip side = L/sqrt(12)
857  if (isBarrel) { //check z direction only
858  const float res = std::abs(msPar.constAt(itrack, 2, 0) - pPar.constAt(itrack, 2, 0));
859  const float hitHL = sqrt(msErr.constAt(itrack, 2, 2) * 3.f); //half-length
860  const float qErr = sqrt(pErr.constAt(itrack, 2, 2));
861  dprint("qCompat " << hitHL << " + " << 3.f * qErr << " vs " << res);
862  return hitHL + std::max(3.f * qErr, 0.5f) > res;
863  } else { //project on xy, assuming the strip Length >> Width
864  const float res[2]{msPar.constAt(itrack, 0, 0) - pPar.constAt(itrack, 0, 0),
865  msPar.constAt(itrack, 1, 0) - pPar.constAt(itrack, 1, 0)};
866  const float hitT2 = msErr.constAt(itrack, 0, 0) + msErr.constAt(itrack, 1, 1);
867  const float hitT2inv = 1.f / hitT2;
868  const float proj[3] = {msErr.constAt(itrack, 0, 0) * hitT2inv,
869  msErr.constAt(itrack, 0, 1) * hitT2inv,
870  msErr.constAt(itrack, 1, 1) * hitT2inv};
871  const float qErr =
872  sqrt(std::abs(pErr.constAt(itrack, 0, 0) * proj[0] + 2.f * pErr.constAt(itrack, 0, 1) * proj[1] +
873  pErr.constAt(itrack, 1, 1) * proj[2])); //take abs to avoid non-pos-def cases
874  const float resProj =
875  sqrt(res[0] * proj[0] * res[0] + 2.f * res[1] * proj[1] * res[0] + res[1] * proj[2] * res[1]);
876  dprint("qCompat " << sqrt(hitT2 * 3.f) << " + " << 3.f * qErr << " vs " << resProj);
877  return sqrt(hitT2 * 3.f) + std::max(3.f * qErr, 0.5f) > resProj;
878  }
879  }
880 
881  //=======================================================
882  // passStripChargePCMfromTrack : apply the slope correction to charge per cm and cut using hit err matrix
883  // the raw pcm = charge/L_normal
884  // the corrected qCorr = charge/L_path = charge/(L_normal*p/p_zLocal) = pcm*p_zLocal/p
885  //=======================================================
887  int itrack, bool isBarrel, unsigned int pcm, unsigned int pcmMin, const MPlexLV &pPar, const MPlexHS &msErr) {
888  //skip the overflow case
889  if (pcm >= Hit::maxChargePerCM())
890  return true;
891 
892  float qSF;
893  if (isBarrel) { //project in x,y, assuming zero-error direction is in this plane
894  const float hitT2 = msErr.constAt(itrack, 0, 0) + msErr.constAt(itrack, 1, 1);
895  const float hitT2inv = 1.f / hitT2;
896  const float proj[3] = {msErr.constAt(itrack, 0, 0) * hitT2inv,
897  msErr.constAt(itrack, 0, 1) * hitT2inv,
898  msErr.constAt(itrack, 1, 1) * hitT2inv};
899  const bool detXY_OK =
900  std::abs(proj[0] * proj[2] - proj[1] * proj[1]) < 0.1f; //check that zero-direction is close
901  const float cosP = cos(pPar.constAt(itrack, 4, 0));
902  const float sinP = sin(pPar.constAt(itrack, 4, 0));
903  const float sinT = std::abs(sin(pPar.constAt(itrack, 5, 0)));
904  //qSF = sqrt[(px,py)*(1-proj)*(px,py)]/p = sinT*sqrt[(cosP,sinP)*(1-proj)*(cosP,sinP)].
905  qSF = detXY_OK ? sinT * std::sqrt(std::abs(1.f + cosP * cosP * proj[0] + sinP * sinP * proj[2] -
906  2.f * cosP * sinP * proj[1]))
907  : 1.f;
908  } else { //project on z
909  // p_zLocal/p = p_z/p = cosT
910  qSF = std::abs(cos(pPar.constAt(itrack, 5, 0)));
911  }
912 
913  const float qCorr = pcm * qSF;
914  dprint("pcm " << pcm << " * " << qSF << " = " << qCorr << " vs " << pcmMin);
915  return qCorr > pcmMin;
916  }
917 
918  //==============================================================================
919  // FindCandidates - Standard Track Finding
920  //==============================================================================
921 
922  void MkFinder::findCandidates(const LayerOfHits &layer_of_hits,
923  std::vector<std::vector<TrackCand>> &tmp_candidates,
924  const int offset,
925  const int N_proc,
926  const FindingFoos &fnd_foos) {
927  // bool debug = true;
928 
929  MatriplexHitPacker mhp(layer_of_hits.hitArray());
930 
931  int maxSize = 0;
932 
933  // Determine maximum number of hits for tracks in the collection.
934  for (int it = 0; it < NN; ++it) {
935  if (it < N_proc) {
936  if (m_XHitSize[it] > 0) {
937  maxSize = std::max(maxSize, m_XHitSize[it]);
938  }
939  }
940  }
941 
942  dprintf("FindCandidates max hits to process=%d\n", maxSize);
943  int nHitsAdded[NN]{};
944 
945  for (int hit_cnt = 0; hit_cnt < maxSize; ++hit_cnt) {
946  mhp.reset();
947 
948  int charge_pcm[NN];
949 
950 #pragma omp simd
951  for (int itrack = 0; itrack < N_proc; ++itrack) {
952  if (hit_cnt < m_XHitSize[itrack]) {
953  const auto &hit = layer_of_hits.refHit(m_XHitArr.At(itrack, hit_cnt, 0));
954  mhp.addInputAt(itrack, hit);
955  charge_pcm[itrack] = hit.chargePerCM();
956  }
957  }
958 
959  mhp.pack(m_msErr, m_msPar);
960 
961  //now compute the chi2 of track state vs hit
962  MPlexQF outChi2;
963  MPlexLV propPar;
964  (*fnd_foos.m_compute_chi2_foo)(m_Err[iP],
965  m_Par[iP],
966  m_Chg,
967  m_msErr,
968  m_msPar,
969  outChi2,
970  propPar,
971  N_proc,
974 
975  // Now update the track parameters with this hit (note that some
976  // calculations are already done when computing chi2, to be optimized).
977  // 1. This is not needed for candidates the hit is not added to, but it's
978  // vectorized so doing it serially below should take the same time.
979  // 2. Still it's a waste of time in case the hit is not added to any of the
980  // candidates, so check beforehand that at least one cand needs update.
981  bool oneCandPassCut = false;
982  for (int itrack = 0; itrack < N_proc; ++itrack) {
983  float max_c2 = getHitSelDynamicChi2Cut(itrack, iP);
984 
985  if (hit_cnt < m_XHitSize[itrack]) {
986  const float chi2 = std::abs(outChi2[itrack]); //fixme negative chi2 sometimes...
987  dprint("chi2=" << chi2);
988  if (chi2 < max_c2) {
989  bool isCompatible = true;
990  if (!layer_of_hits.is_pix_lyr()) {
991  //check module compatibility via long strip side = L/sqrt(12)
992  isCompatible =
993  isStripQCompatible(itrack, layer_of_hits.is_barrel(), m_Err[iP], propPar, m_msErr, m_msPar);
994 
995  //rescale strip charge to track parameters and reapply the cut
996  isCompatible &= passStripChargePCMfromTrack(
997  itrack, layer_of_hits.is_barrel(), charge_pcm[itrack], Hit::minChargePerCM(), propPar, m_msErr);
998  }
999  if (isCompatible) {
1000  oneCandPassCut = true;
1001  break;
1002  }
1003  }
1004  }
1005  }
1006 
1007  if (oneCandPassCut) {
1008  MPlexQI tmpChg = m_Chg;
1009  (*fnd_foos.m_update_param_foo)(m_Err[iP],
1010  m_Par[iP],
1011  tmpChg,
1012  m_msErr,
1013  m_msPar,
1014  m_Err[iC],
1015  m_Par[iC],
1016  N_proc,
1019 
1020  dprint("update parameters" << std::endl
1021  << "propagated track parameters x=" << m_Par[iP].constAt(0, 0, 0)
1022  << " y=" << m_Par[iP].constAt(0, 1, 0) << std::endl
1023  << " hit position x=" << m_msPar.constAt(0, 0, 0)
1024  << " y=" << m_msPar.constAt(0, 1, 0) << std::endl
1025  << " updated track parameters x=" << m_Par[iC].constAt(0, 0, 0)
1026  << " y=" << m_Par[iC].constAt(0, 1, 0));
1027 
1028  //create candidate with hit in case chi2 < m_iteration_params->chi2Cut_min
1029  //fixme: please vectorize me... (not sure it's possible in this case)
1030  for (int itrack = 0; itrack < N_proc; ++itrack) {
1031  float max_c2 = getHitSelDynamicChi2Cut(itrack, iP);
1032 
1033  if (hit_cnt < m_XHitSize[itrack]) {
1034  const float chi2 = std::abs(outChi2[itrack]); //fixme negative chi2 sometimes...
1035  dprint("chi2=" << chi2);
1036  if (chi2 < max_c2) {
1037  bool isCompatible = true;
1038  if (!layer_of_hits.is_pix_lyr()) {
1039  //check module compatibility via long strip side = L/sqrt(12)
1040  isCompatible =
1041  isStripQCompatible(itrack, layer_of_hits.is_barrel(), m_Err[iP], propPar, m_msErr, m_msPar);
1042 
1043  //rescale strip charge to track parameters and reapply the cut
1044  isCompatible &= passStripChargePCMfromTrack(
1045  itrack, layer_of_hits.is_barrel(), charge_pcm[itrack], Hit::minChargePerCM(), propPar, m_msErr);
1046  }
1047  if (isCompatible) {
1048  bool hitExists = false;
1049  int maxHits = m_NFoundHits(itrack, 0, 0);
1050  if (layer_of_hits.is_pix_lyr()) {
1051  for (int i = 0; i <= maxHits; ++i) {
1052  if (i > 2)
1053  break;
1054  if (m_HoTArrs[itrack][i].layer == layer_of_hits.layer_id()) {
1055  hitExists = true;
1056  break;
1057  }
1058  }
1059  }
1060  if (hitExists)
1061  continue;
1062 
1063  nHitsAdded[itrack]++;
1064  dprint("chi2 cut passed, creating new candidate");
1065  // Create a new candidate and fill the tmp_candidates output vector.
1066  // QQQ only instantiate if it will pass, be better than N_best
1067 
1068  const int hit_idx = m_XHitArr.At(itrack, hit_cnt, 0);
1069 
1070  TrackCand newcand;
1071  copy_out(newcand, itrack, iC);
1072  newcand.setCharge(tmpChg(itrack, 0, 0));
1073  newcand.addHitIdx(hit_idx, layer_of_hits.layer_id(), chi2);
1074  newcand.setScore(getScoreCand(newcand, true /*penalizeTailMissHits*/, true /*inFindCandidates*/));
1075  newcand.setOriginIndex(m_CandIdx(itrack, 0, 0));
1076 
1077  if (chi2 < m_iteration_params->chi2CutOverlap) {
1078  CombCandidate &ccand = *newcand.combCandidate();
1079  ccand[m_CandIdx(itrack, 0, 0)].considerHitForOverlap(
1080  hit_idx, layer_of_hits.refHit(hit_idx).detIDinLayer(), chi2);
1081  }
1082 
1083  dprint("updated track parameters x=" << newcand.parameters()[0] << " y=" << newcand.parameters()[1]
1084  << " z=" << newcand.parameters()[2]
1085  << " pt=" << 1. / newcand.parameters()[3]);
1086 
1087  tmp_candidates[m_SeedIdx(itrack, 0, 0) - offset].emplace_back(newcand);
1088  }
1089  }
1090  }
1091  }
1092  } //end if (oneCandPassCut)
1093 
1094  } //end loop over hits
1095 
1096  //now add invalid hit
1097  //fixme: please vectorize me...
1098  for (int itrack = 0; itrack < N_proc; ++itrack) {
1099  // Cands that miss the layer are stashed away in MkBuilder(), before propagation,
1100  // and then merged back afterwards.
1101  if (m_XWsrResult[itrack].m_wsr == WSR_Outside) {
1102  continue;
1103  }
1104 
1105  int fake_hit_idx = ((num_all_minus_one_hits(itrack) < m_iteration_params->maxHolesPerCand) &&
1107  ? -1
1108  : -2;
1109 
1110  if (m_XWsrResult[itrack].m_wsr == WSR_Edge) {
1111  // YYYYYY m_iteration_params->store_missed_layers
1112  fake_hit_idx = -3;
1113  }
1114  //now add fake hit for tracks that passsed through inactive modules
1115  else if (m_XWsrResult[itrack].m_in_gap == true && nHitsAdded[itrack] == 0) {
1116  fake_hit_idx = -7;
1117  }
1118 
1119  dprint("ADD FAKE HIT FOR TRACK #" << itrack << " withinBounds=" << (fake_hit_idx != -3)
1120  << " r=" << std::hypot(m_Par[iP](itrack, 0, 0), m_Par[iP](itrack, 1, 0)));
1121 
1122  // QQQ as above, only create and add if score better
1123  TrackCand newcand;
1124  copy_out(newcand, itrack, iP);
1125  newcand.addHitIdx(fake_hit_idx, layer_of_hits.layer_id(), 0.);
1126  newcand.setScore(getScoreCand(newcand, true /*penalizeTailMissHits*/, true /*inFindCandidates*/));
1127  // Only relevant when we actually add a hit
1128  // newcand.setOriginIndex(m_CandIdx(itrack, 0, 0));
1129  tmp_candidates[m_SeedIdx(itrack, 0, 0) - offset].emplace_back(newcand);
1130  }
1131  }
1132 
1133  //==============================================================================
1134  // FindCandidatesCloneEngine - Clone Engine Track Finding
1135  //==============================================================================
1136 
1138  CandCloner &cloner,
1139  const int offset,
1140  const int N_proc,
1141  const FindingFoos &fnd_foos) {
1142  // bool debug = true;
1143 
1144  MatriplexHitPacker mhp(layer_of_hits.hitArray());
1145 
1146  int maxSize = 0;
1147 
1148  // Determine maximum number of hits for tracks in the collection.
1149 #pragma omp simd
1150  for (int it = 0; it < NN; ++it) {
1151  if (it < N_proc) {
1152  if (m_XHitSize[it] > 0) {
1153  maxSize = std::max(maxSize, m_XHitSize[it]);
1154  }
1155  }
1156  }
1157 
1158  dprintf("FindCandidatesCloneEngine max hits to process=%d\n", maxSize);
1159  int nHitsAdded[NN]{};
1160 
1161  for (int hit_cnt = 0; hit_cnt < maxSize; ++hit_cnt) {
1162  mhp.reset();
1163 
1164  int charge_pcm[NN];
1165 
1166 #pragma omp simd
1167  for (int itrack = 0; itrack < N_proc; ++itrack) {
1168  if (hit_cnt < m_XHitSize[itrack]) {
1169  const auto &hit = layer_of_hits.refHit(m_XHitArr.At(itrack, hit_cnt, 0));
1170  mhp.addInputAt(itrack, hit);
1171  charge_pcm[itrack] = hit.chargePerCM();
1172  }
1173  }
1174 
1175  mhp.pack(m_msErr, m_msPar);
1176 
1177  //now compute the chi2 of track state vs hit
1178  MPlexQF outChi2;
1179  MPlexLV propPar;
1180  (*fnd_foos.m_compute_chi2_foo)(m_Err[iP],
1181  m_Par[iP],
1182  m_Chg,
1183  m_msErr,
1184  m_msPar,
1185  outChi2,
1186  propPar,
1187  N_proc,
1190 
1191 #pragma omp simd // DOES NOT VECTORIZE AS IT IS NOW
1192  for (int itrack = 0; itrack < N_proc; ++itrack) {
1193  // make sure the hit was in the compatiblity window for the candidate
1194 
1195  float max_c2 = getHitSelDynamicChi2Cut(itrack, iP);
1196 
1197  if (hit_cnt < m_XHitSize[itrack]) {
1198  // XXX-NUM-ERR assert(chi2 >= 0);
1199  const float chi2 = std::abs(outChi2[itrack]); //fixme negative chi2 sometimes...
1200 
1201  dprint("chi2=" << chi2 << " for trkIdx=" << itrack << " hitIdx=" << m_XHitArr.At(itrack, hit_cnt, 0));
1202  if (chi2 < max_c2) {
1203  bool isCompatible = true;
1204  if (!layer_of_hits.is_pix_lyr()) {
1205  //check module compatibility via long strip side = L/sqrt(12)
1206  isCompatible =
1207  isStripQCompatible(itrack, layer_of_hits.is_barrel(), m_Err[iP], propPar, m_msErr, m_msPar);
1208 
1209  //rescale strip charge to track parameters and reapply the cut
1210  isCompatible &= passStripChargePCMfromTrack(
1211  itrack, layer_of_hits.is_barrel(), charge_pcm[itrack], Hit::minChargePerCM(), propPar, m_msErr);
1212  }
1213 
1214  if (isCompatible) {
1215  CombCandidate &ccand = cloner.combCandWithOriginalIndex(m_SeedIdx(itrack, 0, 0));
1216  bool hitExists = false;
1217  int maxHits = m_NFoundHits(itrack, 0, 0);
1218  if (layer_of_hits.is_pix_lyr()) {
1219  for (int i = 0; i <= maxHits; ++i) {
1220  if (i > 2)
1221  break;
1222  if (ccand.hot(i).layer == layer_of_hits.layer_id()) {
1223  hitExists = true;
1224  break;
1225  }
1226  }
1227  }
1228  if (hitExists)
1229  continue;
1230 
1231  nHitsAdded[itrack]++;
1232  const int hit_idx = m_XHitArr.At(itrack, hit_cnt, 0);
1233 
1234  // Register hit for overlap consideration, here we apply chi2 cut
1235  if (chi2 < m_iteration_params->chi2CutOverlap) {
1236  ccand[m_CandIdx(itrack, 0, 0)].considerHitForOverlap(
1237  hit_idx, layer_of_hits.refHit(hit_idx).detIDinLayer(), chi2);
1238  }
1239 
1240  IdxChi2List tmpList;
1241  tmpList.trkIdx = m_CandIdx(itrack, 0, 0);
1242  tmpList.hitIdx = hit_idx;
1243  tmpList.module = layer_of_hits.refHit(hit_idx).detIDinLayer();
1244  tmpList.nhits = m_NFoundHits(itrack, 0, 0) + 1;
1245  tmpList.ntailholes = 0;
1246  tmpList.noverlaps = m_NOverlapHits(itrack, 0, 0);
1247  tmpList.nholes = num_all_minus_one_hits(itrack);
1248  tmpList.pt = std::abs(1.0f / m_Par[iP].At(itrack, 3, 0));
1249  tmpList.chi2 = m_Chi2(itrack, 0, 0) + chi2;
1250  tmpList.chi2_hit = chi2;
1251  tmpList.score = getScoreStruct(tmpList);
1252  cloner.add_cand(m_SeedIdx(itrack, 0, 0) - offset, tmpList);
1253 
1254  dprint(" adding hit with hit_cnt=" << hit_cnt << " for trkIdx=" << tmpList.trkIdx
1255  << " orig Seed=" << m_Label(itrack, 0, 0));
1256  }
1257  }
1258  }
1259  }
1260 
1261  } //end loop over hits
1262 
1263  //now add invalid hit
1264  for (int itrack = 0; itrack < N_proc; ++itrack) {
1265  dprint("num_all_minus_one_hits(" << itrack << ")=" << num_all_minus_one_hits(itrack));
1266 
1267  // Cands that miss the layer are stashed away in MkBuilder(), before propagation,
1268  // and then merged back afterwards.
1269  if (m_XWsrResult[itrack].m_wsr == WSR_Outside) {
1270  continue;
1271  }
1272 
1273  // int fake_hit_idx = num_all_minus_one_hits(itrack) < m_iteration_params->maxHolesPerCand ? -1 : -2;
1274  int fake_hit_idx = ((num_all_minus_one_hits(itrack) < m_iteration_params->maxHolesPerCand) &&
1276  ? -1
1277  : -2;
1278 
1279  if (m_XWsrResult[itrack].m_wsr == WSR_Edge) {
1280  fake_hit_idx = -3;
1281  }
1282  //now add fake hit for tracks that passsed through inactive modules
1283  else if (m_XWsrResult[itrack].m_in_gap == true && nHitsAdded[itrack] == 0) {
1284  fake_hit_idx = -7;
1285  }
1286 
1287  IdxChi2List tmpList;
1288  tmpList.trkIdx = m_CandIdx(itrack, 0, 0);
1289  tmpList.hitIdx = fake_hit_idx;
1290  tmpList.module = -1;
1291  tmpList.nhits = m_NFoundHits(itrack, 0, 0);
1292  tmpList.ntailholes =
1293  (fake_hit_idx == -1 ? m_NTailMinusOneHits(itrack, 0, 0) + 1 : m_NTailMinusOneHits(itrack, 0, 0));
1294  tmpList.noverlaps = m_NOverlapHits(itrack, 0, 0);
1295  tmpList.nholes = num_inside_minus_one_hits(itrack);
1296  tmpList.pt = std::abs(1.0f / m_Par[iP].At(itrack, 3, 0));
1297  tmpList.chi2 = m_Chi2(itrack, 0, 0);
1298  tmpList.chi2_hit = 0;
1299  tmpList.score = getScoreStruct(tmpList);
1300  cloner.add_cand(m_SeedIdx(itrack, 0, 0) - offset, tmpList);
1301  dprint("adding invalid hit " << fake_hit_idx);
1302  }
1303  }
1304 
1305  //==============================================================================
1306  // UpdateWithLastHit
1307  //==============================================================================
1308 
1309  void MkFinder::updateWithLastHit(const LayerOfHits &layer_of_hits, int N_proc, const FindingFoos &fnd_foos) {
1310  for (int i = 0; i < N_proc; ++i) {
1311  const HitOnTrack &hot = m_LastHoT[i];
1312 
1313  const Hit &hit = layer_of_hits.refHit(hot.index);
1314 
1315  m_msErr.copyIn(i, hit.errArray());
1316  m_msPar.copyIn(i, hit.posArray());
1317  }
1318 
1319  // See comment in MkBuilder::find_tracks_in_layer() about intra / inter flags used here
1320  // for propagation to the hit.
1321  (*fnd_foos.m_update_param_foo)(m_Err[iP],
1322  m_Par[iP],
1323  m_Chg,
1324  m_msErr,
1325  m_msPar,
1326  m_Err[iC],
1327  m_Par[iC],
1328  N_proc,
1331  }
1332 
1333  //==============================================================================
1334  // CopyOutParErr
1335  //==============================================================================
1336 
1337  void MkFinder::copyOutParErr(std::vector<CombCandidate> &seed_cand_vec, int N_proc, bool outputProp) const {
1338  const int iO = outputProp ? iP : iC;
1339 
1340  for (int i = 0; i < N_proc; ++i) {
1341  TrackCand &cand = seed_cand_vec[m_SeedIdx(i, 0, 0)][m_CandIdx(i, 0, 0)];
1342 
1343  // Set the track state to the updated parameters
1344  m_Err[iO].copyOut(i, cand.errors_nc().Array());
1345  m_Par[iO].copyOut(i, cand.parameters_nc().Array());
1346  cand.setCharge(m_Chg(i, 0, 0));
1347 
1348  dprint((outputProp ? "propagated" : "updated")
1349  << " track parameters x=" << cand.parameters()[0] << " y=" << cand.parameters()[1]
1350  << " z=" << cand.parameters()[2] << " pt=" << 1. / cand.parameters()[3] << " posEta=" << cand.posEta());
1351  }
1352  }
1353 
1354  //==============================================================================
1355  // Backward Fit hack
1356  //==============================================================================
1357 
1359  // Uses HitOnTrack vector from Track directly + a local cursor array to current hit.
1360 
1361  MatriplexTrackPacker mtp(&cands[beg]);
1362 
1363  int itrack = 0;
1364 
1365  for (int i = beg; i < end; ++i, ++itrack) {
1366  const Track &trk = cands[i];
1367 
1368  m_Chg(itrack, 0, 0) = trk.charge();
1369  m_CurHit[itrack] = trk.nTotalHits() - 1;
1370  m_HoTArr[itrack] = trk.getHitsOnTrackArray();
1371 
1372  mtp.addInput(trk);
1373  }
1374 
1375  m_Chi2.setVal(0);
1376 
1377  mtp.pack(m_Err[iC], m_Par[iC]);
1378 
1379  m_Err[iC].scale(100.0f);
1380  }
1381 
1383  // Could as well use HotArrays from tracks directly + a local cursor array to last hit.
1384 
1385  // XXXX - shall we assume only TrackCand-zero is needed and that we can freely
1386  // bork the HoTNode array?
1387 
1388  MatriplexTrackPacker mtp(&eocss[beg][0]);
1389 
1390  int itrack = 0;
1391 
1392  for (int i = beg; i < end; ++i, ++itrack) {
1393  const TrackCand &trk = eocss[i][0];
1394 
1395  m_Chg(itrack, 0, 0) = trk.charge();
1396  m_CurNode[itrack] = trk.lastCcIndex();
1397  m_HoTNodeArr[itrack] = trk.combCandidate()->hotsData();
1398 
1399  // XXXX Need TrackCand* to update num-hits. Unless I collect info elsewhere
1400  // and fix it in BkFitOutputTracks.
1401  m_TrkCand[itrack] = &eocss[i][0];
1402 
1403  mtp.addInput(trk);
1404  }
1405 
1406  m_Chi2.setVal(0);
1407 
1408  mtp.pack(m_Err[iC], m_Par[iC]);
1409 
1410  m_Err[iC].scale(100.0f);
1411  }
1412 
1413  //------------------------------------------------------------------------------
1414 
1415  void MkFinder::bkFitOutputTracks(TrackVec &cands, int beg, int end, bool outputProp) {
1416  // Only copy out track params / errors / chi2, all the rest is ok.
1417 
1418  const int iO = outputProp ? iP : iC;
1419 
1420  int itrack = 0;
1421  for (int i = beg; i < end; ++i, ++itrack) {
1422  Track &trk = cands[i];
1423 
1424  m_Err[iO].copyOut(itrack, trk.errors_nc().Array());
1425  m_Par[iO].copyOut(itrack, trk.parameters_nc().Array());
1426 
1427  trk.setChi2(m_Chi2(itrack, 0, 0));
1428  if (isFinite(trk.chi2())) {
1429  trk.setScore(getScoreCand(trk));
1430  }
1431  }
1432  }
1433 
1434  void MkFinder::bkFitOutputTracks(EventOfCombCandidates &eocss, int beg, int end, bool outputProp) {
1435  // Only copy out track params / errors / chi2, all the rest is ok.
1436 
1437  // XXXX - where will rejected hits get removed?
1438 
1439  const int iO = outputProp ? iP : iC;
1440 
1441  int itrack = 0;
1442  for (int i = beg; i < end; ++i, ++itrack) {
1443  TrackCand &trk = eocss[i][0];
1444 
1445  m_Err[iO].copyOut(itrack, trk.errors_nc().Array());
1446  m_Par[iO].copyOut(itrack, trk.parameters_nc().Array());
1447 
1448  trk.setChi2(m_Chi2(itrack, 0, 0));
1449  if (isFinite(trk.chi2())) {
1450  trk.setScore(getScoreCand(trk));
1451  }
1452  }
1453  }
1454 
1455  //------------------------------------------------------------------------------
1456 
1457 #if defined(DEBUG_BACKWARD_FIT) || defined(DEBUG_BACKWARD_FIT_BH)
1458  namespace {
1459  float e2s(float x) { return 1e4 * std::sqrt(x); }
1460  } // namespace
1461 #endif
1462 
1463  void MkFinder::bkFitFitTracksBH(const EventOfHits &eventofhits,
1464  const SteeringParams &st_par,
1465  const int N_proc,
1466  bool chiDebug) {
1467  // Prototyping final backward fit.
1468  // This works with track-finding indices, before remapping.
1469  //
1470  // Layers should be collected during track finding and list all layers that have actual hits.
1471  // Then we could avoid checking which layers actually do have hits.
1472 
1473  MPlexQF tmp_chi2;
1474  float tmp_err[6] = {666, 0, 666, 0, 0, 666};
1475  float tmp_pos[3];
1476 
1477  for (auto lp_iter = st_par.m_layer_plan.rbegin(); lp_iter != st_par.m_layer_plan.rend(); ++lp_iter) {
1478  const int layer = lp_iter->m_layer;
1479 
1480  const LayerOfHits &L = eventofhits[layer];
1481  const LayerInfo &LI = *L.layer_info();
1482 
1483  int count = 0;
1484  for (int i = 0; i < N_proc; ++i) {
1485  while (m_CurHit[i] >= 0 && m_HoTArr[i][m_CurHit[i]].index < 0)
1486  --m_CurHit[i];
1487 
1488  if (m_CurHit[i] >= 0 && m_HoTArr[i][m_CurHit[i]].layer == layer) {
1489  // Skip the overlap hits -- if they exist.
1490  // 1. Overlap hit gets placed *after* the original hit in TrackCand::exportTrack()
1491  // which is *before* in the reverse iteration that we are doing here.
1492  // 2. Seed-hit merging can result in more than two hits per layer.
1493  while (m_CurHit[i] > 0 && m_HoTArr[i][m_CurHit[i] - 1].layer == layer)
1494  --m_CurHit[i];
1495 
1496  const Hit &hit = L.refHit(m_HoTArr[i][m_CurHit[i]].index);
1497  m_msErr.copyIn(i, hit.errArray());
1498  m_msPar.copyIn(i, hit.posArray());
1499  ++count;
1500  --m_CurHit[i];
1501  } else {
1502  tmp_pos[0] = m_Par[iC](i, 0, 0);
1503  tmp_pos[1] = m_Par[iC](i, 1, 0);
1504  tmp_pos[2] = m_Par[iC](i, 2, 0);
1505  m_msErr.copyIn(i, tmp_err);
1506  m_msPar.copyIn(i, tmp_pos);
1507  }
1508  }
1509 
1510  if (count == 0)
1511  continue;
1512 
1513  // ZZZ Could add missing hits here, only if there are any actual matches.
1514 
1515  if (LI.is_barrel()) {
1517 
1519  m_Err[iP],
1520  m_Par[iP],
1521  m_msErr,
1522  m_msPar,
1523  m_Err[iC],
1524  m_Par[iC],
1525  tmp_chi2,
1526  N_proc);
1527  } else {
1529 
1531  m_Err[iP],
1532  m_Par[iP],
1533  m_msErr,
1534  m_msPar,
1535  m_Err[iC],
1536  m_Par[iC],
1537  tmp_chi2,
1538  N_proc);
1539  }
1540 
1541  //fixup invpt sign and charge
1542  for (int n = 0; n < N_proc; ++n) {
1543  if (m_Par[iC].At(n, 3, 0) < 0) {
1544  m_Chg.At(n, 0, 0) = -m_Chg.At(n, 0, 0);
1545  m_Par[iC].At(n, 3, 0) = -m_Par[iC].At(n, 3, 0);
1546  }
1547  }
1548 
1549 #ifdef DEBUG_BACKWARD_FIT_BH
1550  // Dump per hit chi2
1551  for (int i = 0; i < N_proc; ++i) {
1552  float r_h = std::hypot(m_msPar.At(i, 0, 0), m_msPar.At(i, 1, 0));
1553  float r_t = std::hypot(m_Par[iC].At(i, 0, 0), m_Par[iC].At(i, 1, 0));
1554 
1555  // if ((std::isnan(tmp_chi2[i]) || std::isnan(r_t)))
1556  // if ( ! std::isnan(tmp_chi2[i]) && tmp_chi2[i] > 0) // && tmp_chi2[i] > 30)
1557  if (chiDebug) {
1558  int ti = iP;
1559  printf(
1560  "CHIHIT %3d %10g %10g %10g %10g %10g %11.5g %11.5g %11.5g %10g %10g %10g %10g %11.5g %11.5g %11.5g %10g "
1561  "%10g %10g %10g %10g %11.5g %11.5g\n",
1562  layer,
1563  tmp_chi2[i],
1564  m_msPar.At(i, 0, 0),
1565  m_msPar.At(i, 1, 0),
1566  m_msPar.At(i, 2, 0),
1567  r_h, // x_h y_h z_h r_h -- hit pos
1568  e2s(m_msErr.At(i, 0, 0)),
1569  e2s(m_msErr.At(i, 1, 1)),
1570  e2s(m_msErr.At(i, 2, 2)), // ex_h ey_h ez_h -- hit errors
1571  m_Par[ti].At(i, 0, 0),
1572  m_Par[ti].At(i, 1, 0),
1573  m_Par[ti].At(i, 2, 0),
1574  r_t, // x_t y_t z_t r_t -- track pos
1575  e2s(m_Err[ti].At(i, 0, 0)),
1576  e2s(m_Err[ti].At(i, 1, 1)),
1577  e2s(m_Err[ti].At(i, 2, 2)), // ex_t ey_t ez_t -- track errors
1578  1.0f / m_Par[ti].At(i, 3, 0),
1579  m_Par[ti].At(i, 4, 0),
1580  m_Par[ti].At(i, 5, 0), // pt, phi, theta
1581  std::atan2(m_msPar.At(i, 1, 0), m_msPar.At(i, 0, 0)), // phi_h
1582  std::atan2(m_Par[ti].At(i, 1, 0), m_Par[ti].At(i, 0, 0)), // phi_t
1583  1e4f * std::hypot(m_msPar.At(i, 0, 0) - m_Par[ti].At(i, 0, 0),
1584  m_msPar.At(i, 1, 0) - m_Par[ti].At(i, 1, 0)), // d_xy
1585  1e4f * (m_msPar.At(i, 2, 0) - m_Par[ti].At(i, 2, 0)) // d_z
1586  // e2s((m_msErr.At(i,0,0) + m_msErr.At(i,1,1)) / (r_h * r_h)), // ephi_h
1587  // e2s((m_Err[ti].At(i,0,0) + m_Err[ti].At(i,1,1)) / (r_t * r_t)) // ephi_t
1588  );
1589  }
1590  }
1591 #endif
1592 
1593  // update chi2
1594  m_Chi2.add(tmp_chi2);
1595  }
1596  }
1597 
1598  //------------------------------------------------------------------------------
1599 
1600  void MkFinder::bkFitFitTracks(const EventOfHits &eventofhits,
1601  const SteeringParams &st_par,
1602  const int N_proc,
1603  bool chiDebug) {
1604  // Prototyping final backward fit.
1605  // This works with track-finding indices, before remapping.
1606  //
1607  // Layers should be collected during track finding and list all layers that have actual hits.
1608  // Then we could avoid checking which layers actually do have hits.
1609 
1610  MPlexQF tmp_chi2;
1611  MPlexQI no_mat_effs;
1612  float tmp_err[6] = {666, 0, 666, 0, 0, 666};
1613  float tmp_pos[3];
1614 
1615  for (auto lp_iter = st_par.make_iterator(SteeringParams::IT_BkwFit); lp_iter.is_valid(); ++lp_iter) {
1616  const int layer = lp_iter.layer();
1617 
1618  const LayerOfHits &L = eventofhits[layer];
1619  const LayerInfo &LI = *L.layer_info();
1620 
1621  // XXXX
1622 #if defined(DEBUG_BACKWARD_FIT)
1623  const Hit *last_hit_ptr[NN];
1624 #endif
1625 
1626  no_mat_effs.setVal(0);
1627  int done_count = 0;
1628  int here_count = 0;
1629  for (int i = 0; i < N_proc; ++i) {
1630  while (m_CurNode[i] >= 0 && m_HoTNodeArr[i][m_CurNode[i]].m_hot.index < 0) {
1632  }
1633 
1634  if (m_CurNode[i] < 0)
1635  ++done_count;
1636 
1637  if (m_CurNode[i] >= 0 && m_HoTNodeArr[i][m_CurNode[i]].m_hot.layer == layer) {
1638  // Skip the overlap hits -- if they exist.
1639  // 1. Overlap hit gets placed *after* the original hit in TrackCand::exportTrack()
1640  // which is *before* in the reverse iteration that we are doing here.
1641  // 2. Seed-hit merging can result in more than two hits per layer.
1642  // while (m_CurHit[i] > 0 && m_HoTArr[ i ][ m_CurHit[i] - 1 ].layer == layer) --m_CurHit[i];
1643  while (m_HoTNodeArr[i][m_CurNode[i]].m_prev_idx >= 0 &&
1644  m_HoTNodeArr[i][m_HoTNodeArr[i][m_CurNode[i]].m_prev_idx].m_hot.layer == layer)
1646 
1647  const Hit &hit = L.refHit(m_HoTNodeArr[i][m_CurNode[i]].m_hot.index);
1648 
1649 #ifdef DEBUG_BACKWARD_FIT
1650  last_hit_ptr[i] = &hit;
1651 #endif
1652  m_msErr.copyIn(i, hit.errArray());
1653  m_msPar.copyIn(i, hit.posArray());
1654  ++here_count;
1655 
1657  } else {
1658 #ifdef DEBUG_BACKWARD_FIT
1659  last_hit_ptr[i] = nullptr;
1660 #endif
1661  no_mat_effs[i] = 1;
1662  tmp_pos[0] = m_Par[iC](i, 0, 0);
1663  tmp_pos[1] = m_Par[iC](i, 1, 0);
1664  tmp_pos[2] = m_Par[iC](i, 2, 0);
1665  m_msErr.copyIn(i, tmp_err);
1666  m_msPar.copyIn(i, tmp_pos);
1667  }
1668  }
1669 
1670  if (done_count == N_proc)
1671  break;
1672  if (here_count == 0)
1673  continue;
1674 
1675  // ZZZ Could add missing hits here, only if there are any actual matches.
1676 
1677  if (LI.is_barrel()) {
1679 
1681  m_Err[iP],
1682  m_Par[iP],
1683  m_msErr,
1684  m_msPar,
1685  m_Err[iC],
1686  m_Par[iC],
1687  tmp_chi2,
1688  N_proc);
1689  } else {
1691 
1693  m_Err[iP],
1694  m_Par[iP],
1695  m_msErr,
1696  m_msPar,
1697  m_Err[iC],
1698  m_Par[iC],
1699  tmp_chi2,
1700  N_proc);
1701  }
1702 
1703  //fixup invpt sign and charge
1704  for (int n = 0; n < N_proc; ++n) {
1705  if (m_Par[iC].At(n, 3, 0) < 0) {
1706  m_Chg.At(n, 0, 0) = -m_Chg.At(n, 0, 0);
1707  m_Par[iC].At(n, 3, 0) = -m_Par[iC].At(n, 3, 0);
1708  }
1709  }
1710 
1711  for (int i = 0; i < N_proc; ++i) {
1712 #if defined(DEBUG_BACKWARD_FIT)
1713  if (chiDebug && last_hit_ptr[i]) {
1714  TrackCand &bb = *m_TrkCand[i];
1715  int ti = iP;
1716  float chi = tmp_chi2.At(i, 0, 0);
1717  float chi_prnt = std::isfinite(chi) ? chi : -9;
1718 
1719 #if defined(MKFIT_STANDALONE)
1720  const MCHitInfo &mchi = m_event->simHitsInfo_[last_hit_ptr[i]->mcHitID()];
1721 
1722  printf(
1723  "BKF_OVERLAP %d %d %d %d %d %d %d "
1724  "%f %f %f %f %d %d %d %d "
1725  "%f %f %f %f %f\n",
1726  m_event->evtID(),
1727 #else
1728  printf(
1729  "BKF_OVERLAP %d %d %d %d %d %d "
1730  "%f %f %f %f %d %d %d "
1731  "%f %f %f %f %f\n",
1732 #endif
1733  bb.label(),
1734  (int)bb.prodType(),
1735  bb.isFindable(),
1736  layer,
1737  L.is_stereo(),
1738  L.is_barrel(),
1739  bb.pT(),
1740  bb.posEta(),
1741  bb.posPhi(),
1742  chi_prnt,
1743  std::isnan(chi),
1744  std::isfinite(chi),
1745  chi > 0,
1746 #if defined(MKFIT_STANDALONE)
1747  mchi.mcTrackID(),
1748 #endif
1749  e2s(m_Err[ti].At(i, 0, 0)),
1750  e2s(m_Err[ti].At(i, 1, 1)),
1751  e2s(m_Err[ti].At(i, 2, 2)), // sx_t sy_t sz_t -- track errors
1752  1e4f * std::hypot(m_msPar.At(i, 0, 0) - m_Par[ti].At(i, 0, 0),
1753  m_msPar.At(i, 1, 0) - m_Par[ti].At(i, 1, 0)), // d_xy
1754  1e4f * (m_msPar.At(i, 2, 0) - m_Par[ti].At(i, 2, 0)) // d_z
1755  );
1756  }
1757 #endif
1758  }
1759 
1760  // update chi2
1761  m_Chi2.add(tmp_chi2);
1762  }
1763  }
1764 
1765  //------------------------------------------------------------------------------
1766 
1767  void MkFinder::bkFitPropTracksToPCA(const int N_proc) {
1769  }
1770 
1771 } // end namespace mkfit
float chi2_hit
Definition: Track.h:42
void setOriginIndex(int oi)
float hit_phi(int i) const
Definition: HitStructures.h:92
void addHitIdx(int hitIdx, int hitLyr, float chi2)
const SVector6 & parameters() const
Definition: Track.h:144
MPlexQI m_Chg
Definition: MkBase.h:96
static constexpr int iC
Definition: MkBase.h:16
void copy_in(const Track &trk, const int mslot, const int tslot)
Definition: MkFinder.h:149
static constexpr int MPlexHitIdxMax
Definition: MkFinder.h:34
MPlexQI m_NFoundHits
Definition: MkFinder.h:265
const IterationLayerConfig * m_iteration_layer_config
Definition: MkFinder.h:314
int qBinChecked(float q) const
Definition: HitStructures.h:74
float eyy() const
Definition: Hit.h:165
void setDiagonal3x3(idx_t n, T d)
Definition: MatriplexSym.h:201
const HitOnTrack * m_HoTArr[NN]
Definition: MkFinder.h:319
int getOriginalHitIndex(int i) const
Definition: HitStructures.h:97
static constexpr int iP
Definition: MkBase.h:17
int layer_id() const
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 copyIn(idx_t n, const T *arr)
Definition: Matriplex.h:70
float chi2() const
Definition: Track.h:184
HitOnTrack m_HoTArrs[NN][Config::nMaxTrkHits]
Definition: MkFinder.h:267
void inputTracksAndHitIdx(const std::vector< Track > &tracks, int beg, int end, bool inputProp)
Definition: MkFinder.cc:60
void bkFitInputTracks(TrackVec &cands, int beg, int end)
Definition: MkFinder.cc:1358
void setChi2(float chi2)
Definition: Track.h:189
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
void copyOut(idx_t n, T *arr) const
Definition: MatriplexSym.h:195
const Hit * hitArray() const
void outputTracksAndHitIdx(std::vector< Track > &tracks, int beg, int end, bool outputProp) const
Definition: MkFinder.cc:141
MPlexLV m_Par[2]
Definition: MkBase.h:95
PropagationFlags backward_fit_pflags
Definition: Config.h:26
Geom::Theta< T > theta() const
T & At(idx_t n, idx_t i, idx_t j)
Definition: MatriplexSym.h:71
bool phi_bin_dead(int qi, int pi) const
Definition: HitStructures.h:89
void selectHitIndices(const LayerOfHits &layer_of_hits, const int N_proc)
Definition: MkFinder.cc:229
float y() const
Definition: Hit.h:162
auto const & tracks
cannot be loose
void(* m_compute_chi2_foo)(const MPlexLS &, const MPlexLV &, const MPlexQI &, const MPlexHS &, const MPlexHV &, MPlexQF &, MPlexLV &, const int, const PropagationFlags, const bool)
Definition: FindingFoos.h:20
void bkFitPropTracksToPCA(const int N_proc)
Definition: MkFinder.cc:1767
SMatrixSym66 & errors_nc()
Definition: Track.h:152
WSR_Result is_within_z_sensitive_region(float z, float dz) const
constexpr float PIOver2
Definition: Config.h:44
int phiMaskApply(int in) const
Definition: HitStructures.h:82
void release()
Definition: MkFinder.cc:49
void add_hit(const int mslot, int index, int layer)
Definition: MkFinder.h:219
float getEta(float r, float z)
Definition: Hit.h:37
assert(be >=bs)
constexpr bool isFinite(T x)
const float * errArray() const
Definition: Hit.h:151
static unsigned int maxChargePerCM()
Definition: Hit.h:220
const LayerInfo * layer_info() const
const IterationParams * m_iteration_params
Definition: MkFinder.h:313
constexpr std::array< uint8_t, layerIndexSize > layer
iterator make_iterator(IterationType_e type) const
float zmin() const
Definition: TrackerInfo.h:45
MPlexLS m_Err[2]
Definition: MkBase.h:94
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:922
void(* m_update_param_foo)(const MPlexLS &, const MPlexLV &, MPlexQI &, const MPlexHS &, const MPlexHV &, MPlexLS &, MPlexLV &, const int, const PropagationFlags, const bool)
Definition: FindingFoos.h:21
const Double_t pi
float ephi() const
Definition: Hit.h:171
float exx() const
Definition: Hit.h:164
constexpr bool usePhiQArrays
Definition: Config.h:104
int charge() const
Definition: Track.h:183
PropagationFlags finding_inter_layer_pflags
Definition: Config.h:24
bool isStripQCompatible(int itrack, bool isBarrel, const MPlexLS &pErr, const MPlexLV &pPar, const MPlexHS &msErr, const MPlexHV &msPar)
Definition: MkFinder.cc:854
void setScore(float s)
Definition: Track.h:190
void add(const Matriplex &v)
Definition: Matriplex.h:37
float z() const
Definition: Hit.h:163
const PropagationConfig * m_prop_config
Definition: MkFinder.h:312
const T & constAt(idx_t n, idx_t i, idx_t j) const
Definition: Matriplex.h:52
void setup_bkfit(const PropagationConfig &pc)
Definition: MkFinder.cc:47
unsigned int module
Definition: Track.h:35
int layer_id() const
Definition: TrackerInfo.h:40
float getScoreStruct(const IdxChi2List &cand1)
Definition: Track.h:643
const float * posArray() const
Definition: Hit.h:150
tuple maxSize
&#39;/store/data/Commissioning08/BeamHalo/RECO/StuffAlmostToP5_v1/000/061/642/10A0FE34-A67D-DD11-AD05-000...
float rin() const
Definition: TrackerInfo.h:42
T sqrt(T t)
Definition: SSEVec.h:19
bool is_pix_lyr() const
printf("params %d %f %f %f\n", minT, eps, errmax, chi2max)
constexpr Matriplex::idx_t NN
Definition: Matrix.h:43
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
int mcHitID() const
Definition: Hit.h:186
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
MPlexQI m_XHitSize
Definition: MkFinder.h:298
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const HoTNode * hotsData() const
MPlexHV m_msPar
Definition: MkFinder.h:303
void propagateTracksToHitR(const MPlexHV &par, const int N_proc, const PropagationFlags pf, const MPlexQI *noMatEffPtr=nullptr)
Definition: MkBase.h:39
MPlexQI m_NTailMinusOneHits
Definition: MkFinder.h:287
uint16_t const *__restrict__ x
Definition: gpuClustering.h:43
int phiBin(float phi) const
Definition: HitStructures.h:78
HitOnTrack hot(int i) const
ProdType prodType() const
Definition: Track.h:261
PhiBinInfo_t phi_bin_info(int qi, int pi) const
Definition: HitStructures.h:88
int m_CurNode[NN]
Definition: MkFinder.h:320
void setup(const PropagationConfig &pc, const IterationParams &ip, const IterationLayerConfig &ilc, const std::vector< bool > *ihm)
Definition: MkFinder.cc:37
bool is_barrel() const
Definition: TrackerInfo.h:52
PropagationFlags pca_prop_pflags
Definition: Config.h:29
bool finding_requires_propagation_to_hit_pos
Definition: Config.h:23
constexpr float nSigmaPhi
float cdist(float a)
Definition: Config.h:67
MPlexHS m_msErr
Definition: MkFinder.h:302
CombCandidate * combCandidate() const
float pT() const
Definition: Track.h:169
bool isFindable() const
Definition: Track.h:254
float rout() const
Definition: TrackerInfo.h:43
void updateWithLastHit(const LayerOfHits &layer_of_hits, int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1309
int lastCcIndex() const
TrackCand * m_TrkCand[NN]
Definition: MkFinder.h:294
float momEta() const
Definition: Track.h:173
std::vector< Track > TrackVec
float getScoreCand(const TrackCand &cand1, bool penalizeTailMissHits=false, bool inFindCandidates=false)
const SVector3 & position() const
Definition: Hit.h:146
float x() const
Definition: Hit.h:161
const HitOnTrack * getHitsOnTrackArray() const
Definition: Track.h:498
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:1600
int m_CurHit[NN]
Definition: MkFinder.h:318
static const FindingFoos & get_finding_foos(bool is_barrel)
Definition: FindingFoos.cc:18
HitOnTrack m_LastHoT[NN]
Definition: MkFinder.h:290
std::vector< LayerControl > m_layer_plan
MPlexQI m_NOverlapHits
Definition: MkFinder.h:285
void copyOutParErr(std::vector< CombCandidate > &seed_cand_vec, int N_proc, bool outputProp) const
Definition: MkFinder.cc:1337
bool passStripChargePCMfromTrack(int itrack, bool isBarrel, unsigned int pcm, unsigned int pcmMin, const MPlexLV &pPar, const MPlexHS &msErr)
Definition: MkFinder.cc:886
float getPhi(float x, float y)
Definition: Hit.h:33
const T & constAt(idx_t n, idx_t i, idx_t j) const
Definition: MatriplexSym.h:69
float hit_q(int i) const
Definition: HitStructures.h:91
float z() const
Definition: Track.h:160
MPlexHitIdx m_XHitArr
Definition: MkFinder.h:299
#define dprint(x)
Definition: Debug.h:90
MPlexQF m_Chi2
Definition: MkFinder.h:261
bool is_stereo() const
int label() const
Definition: Track.h:186
bool is_barrel() const
const Hit & refHit(int i) const
void bkFitOutputTracks(TrackVec &cands, int beg, int end, bool outputProp)
Definition: MkFinder.cc:1415
void bkFitFitTracksBH(const EventOfHits &eventofhits, const SteeringParams &st_par, const int N_proc, bool chiDebug=false)
Definition: MkFinder.cc:1463
int mcTrackID() const
Definition: Hit.h:113
void copyIn(idx_t n, const T *arr)
Definition: MatriplexSym.h:87
MPlexQI m_CandIdx
Definition: MkFinder.h:276
MPlexQI m_SeedIdx
Definition: MkFinder.h:275
void findCandidatesCloneEngine(const LayerOfHits &layer_of_hits, CandCloner &cloner, const int offset, const int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1137
string end
Definition: dataset.py:937
unsigned int detIDinLayer() const
Definition: Hit.h:214
const std::vector< bool > * m_iteration_hit_mask
Definition: MkFinder.h:315
PropagationFlags finding_intra_layer_pflags
Definition: Config.h:25
float posPhi() const
Definition: Track.h:163
int num_inside_minus_one_hits(const int mslot) const
Definition: MkFinder.h:257
void setCharge(int chg)
Definition: Track.h:188
void add_cand(int idx, const IdxChi2List &cand_info)
Definition: CandCloner.h:34
float getHitSelDynamicChi2Cut(const int itrk, const int ipar)
Definition: MkFinder.cc:206
float zmax() const
Definition: TrackerInfo.h:46
float posEta() const
Definition: Track.h:164
void setVal(T v)
Definition: Matriplex.h:31
WSR_Result is_within_r_sensitive_region(float r, float dr) const
const HoTNode * m_HoTNodeArr[NN]
Definition: MkFinder.h:321
int num_all_minus_one_hits(const int mslot) const
Definition: MkFinder.h:253
int nTotalHits() const
Definition: Track.h:517
WSR_Result m_XWsrResult[NN]
Definition: MkFinder.h:297
tuple tex
Definition: cuy.py:773
void getHitSelDynamicWindows(const float invpt, const float theta, float &min_dq, float &max_dq, float &min_dphi, float &max_dphi)
Definition: MkFinder.cc:169
void copy_out(Track &trk, const int mslot, const int tslot) const
Definition: MkFinder.h:166
float momPhi() const
Definition: Track.h:172
float posR() const
Definition: Track.h:161
T & At(idx_t n, idx_t i, idx_t j)
Definition: Matriplex.h:54
CombCandidate & combCandWithOriginalIndex(int idx)
Definition: CandCloner.h:51
static unsigned int minChargePerCM()
Definition: Hit.h:219
SVector6 & parameters_nc()
Definition: Track.h:151
#define dprintf(...)
Definition: Debug.h:93
void copyOut(idx_t n, T *arr) const
Definition: Matriplex.h:180
MPlexQI m_Label
Definition: MkFinder.h:262
void propagateTracksToHitZ(const MPlexHV &par, const int N_proc, const PropagationFlags pf, const MPlexQI *noMatEffPtr=nullptr)
Definition: MkBase.h:64
void propagateTracksToPCAZ(const int N_proc, const PropagationFlags pf)
Definition: MkBase.h:77
void addBestHit(const LayerOfHits &layer_of_hits, const int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:714
float ezz() const
Definition: Hit.h:166