diff --git a/RecoTracker/MkFitCMS/standalone/Shell.cc b/RecoTracker/MkFitCMS/standalone/Shell.cc index ad4fa12c00827..4f378ec0adf82 100644 --- a/RecoTracker/MkFitCMS/standalone/Shell.cc +++ b/RecoTracker/MkFitCMS/standalone/Shell.cc @@ -325,7 +325,9 @@ namespace mkfit { reco tracks labels are seed indices. seed labels are sim track indices -- - mkfit labels are seed indices in given iteration after cleaning (at seed load-time) + mkfit labels are seed indices in given iteration after cleaning (at seed load-time). + This is no longer true -- was done like that in branch where this code originated from. + It seems the label is the same as seed label. */ int Shell::LabelFromHits(Track &t, bool replace, float good_frac) { diff --git a/RecoTracker/MkFitCore/interface/IterationConfig.h b/RecoTracker/MkFitCore/interface/IterationConfig.h index 33bc8dabf658d..5504d2476e504 100644 --- a/RecoTracker/MkFitCore/interface/IterationConfig.h +++ b/RecoTracker/MkFitCore/interface/IterationConfig.h @@ -90,6 +90,8 @@ namespace mkfit { float chi2Cut_min = 15.0; float chi2CutOverlap = 3.5; float pTCutOverlap = 0.0; + bool recheckOverlap = false; + bool useHitSelectionV2 = false; //quality filter params int minHitsQF = 4; diff --git a/RecoTracker/MkFitCore/interface/TrackStructures.h b/RecoTracker/MkFitCore/interface/TrackStructures.h index 736fbe8847e55..5c7912b8ea7c1 100644 --- a/RecoTracker/MkFitCore/interface/TrackStructures.h +++ b/RecoTracker/MkFitCore/interface/TrackStructures.h @@ -224,6 +224,7 @@ namespace mkfit { } void addHitIdx(int hitIdx, int hitLyr, float chi2); + bool popOverlap(); HoTNode& refLastHoTNode(); // for filling up overlap info const HoTNode& refLastHoTNode() const; // for dump traversal @@ -564,6 +565,25 @@ namespace mkfit { } } + inline bool TrackCand::popOverlap() { + auto popHitIdx = getLastHitIdx(); + auto popHitLyr = getLastHitLyr(); + auto popPrev = refLastHoTNode().m_prev_idx; + auto popChi2 = refLastHoTNode().m_chi2; + // sanity checks first, then just shift lastHitIdx_ to popPrev + if (lastHitIdx_ == 0 || popHitIdx < 0) + return false; + auto prevHitLyr = m_comb_candidate->hot(popPrev).layer; + auto prevHitIdx = m_comb_candidate->hot(popPrev).index; + if (popHitLyr != prevHitLyr || prevHitIdx < 0) + return false; + lastHitIdx_ = popPrev; + + --nFoundHits_; + chi2_ -= popChi2; + --nOverlapHits_; + return true; + } //============================================================================== class EventOfCombCandidates { diff --git a/RecoTracker/MkFitCore/src/CandCloner.cc b/RecoTracker/MkFitCore/src/CandCloner.cc index 253e639a20b2e..78d2ead9495d3 100644 --- a/RecoTracker/MkFitCore/src/CandCloner.cc +++ b/RecoTracker/MkFitCore/src/CandCloner.cc @@ -24,11 +24,13 @@ namespace mkfit { void CandCloner::begin_eta_bin(EventOfCombCandidates *e_o_ccs, std::vector *update_list, + std::vector *overlap_list, std::vector> *extra_cands, int start_seed, int n_seeds) { mp_event_of_comb_candidates = e_o_ccs; mp_kalman_update_list = update_list; + mp_kalman_overlap_list = overlap_list; mp_extra_cands = extra_cands; m_start_seed = start_seed; m_n_seeds = n_seeds; @@ -50,6 +52,7 @@ namespace mkfit { m_idx_max_prev = 0; mp_kalman_update_list->clear(); + mp_kalman_overlap_list->clear(); #ifdef CC_TIME_LAYER t_lay = dtime(); @@ -193,14 +196,21 @@ namespace mkfit { break; if (h2a.hitIdx >= 0) { - mp_kalman_update_list->emplace_back(UpdateIndices(m_start_seed + is, n_pushed, h2a.hitIdx)); - - // set the overlap if we have it and and pT > pTCutOverlap + // set the overlap if we have it and pT > pTCutOverlap HitMatch *hm; if (tc.pT() > mp_iteration_params->pTCutOverlap && (hm = ccand[h2a.trkIdx].findOverlap(h2a.hitIdx, h2a.module))) { - tc.addHitIdx(hm->m_hit_idx, m_layer, 0); - tc.incOverlapCount(); + if (mp_iteration_params->recheckOverlap) { + // Special overlap_list if the overlap hit needs to be re-checked after primary update. + mp_kalman_overlap_list->emplace_back( + UpdateIndices(m_start_seed + is, n_pushed, h2a.hitIdx, hm->m_hit_idx)); + } else { + tc.addHitIdx(hm->m_hit_idx, m_layer, 0); + tc.incOverlapCount(); + mp_kalman_update_list->emplace_back(UpdateIndices(m_start_seed + is, n_pushed, h2a.hitIdx, -1)); + } + } else { + mp_kalman_update_list->emplace_back(UpdateIndices(m_start_seed + is, n_pushed, h2a.hitIdx, -1)); } } diff --git a/RecoTracker/MkFitCore/src/CandCloner.h b/RecoTracker/MkFitCore/src/CandCloner.h index 0466811aa0520..fbb4a29bf69fd 100644 --- a/RecoTracker/MkFitCore/src/CandCloner.h +++ b/RecoTracker/MkFitCore/src/CandCloner.h @@ -25,6 +25,7 @@ namespace mkfit { void begin_eta_bin(EventOfCombCandidates *e_o_ccs, std::vector *update_list, + std::vector *overlap_list, std::vector> *extra_cands, int start_seed, int n_seeds); @@ -56,7 +57,7 @@ namespace mkfit { const IterationParams *mp_iteration_params = nullptr; EventOfCombCandidates *mp_event_of_comb_candidates; - std::vector *mp_kalman_update_list; + std::vector *mp_kalman_update_list, *mp_kalman_overlap_list; std::vector> *mp_extra_cands; #if defined(CC_TIME_ETA) or defined(CC_TIME_LAYER) diff --git a/RecoTracker/MkFitCore/src/FindingFoos.h b/RecoTracker/MkFitCore/src/FindingFoos.h index 939d141947b12..a02bff4e2c541 100644 --- a/RecoTracker/MkFitCore/src/FindingFoos.h +++ b/RecoTracker/MkFitCore/src/FindingFoos.h @@ -16,6 +16,10 @@ namespace mkfit { const MPlexLS &, const MPlexLV &, MPlexQI &, const MPlexHS &, const MPlexHV &, MPlexLS &, MPlexLV &, MPlexQI &, \ const int, const PropagationFlags &, const bool +#define COMPUTE_CHI2_AND_UPDATE_ARGS \ + const MPlexLS &, const MPlexLV &, MPlexQI &, const MPlexHS &, const MPlexHV &, MPlexQF &, MPlexLS &, MPlexLV &, \ + MPlexQI &, const int, const PropagationFlags, const bool + class FindingFoos { public: void (*m_compute_chi2_foo)(COMPUTE_CHI2_ARGS); diff --git a/RecoTracker/MkFitCore/src/HitStructures.cc b/RecoTracker/MkFitCore/src/HitStructures.cc index da2afc2f60b0f..91d9cebdeb60a 100644 --- a/RecoTracker/MkFitCore/src/HitStructures.cc +++ b/RecoTracker/MkFitCore/src/HitStructures.cc @@ -91,6 +91,9 @@ namespace mkfit { m_hit_infos.reserve(m_n_hits); } + // Factor to get from hit sigma to half-length in q direction. + const float hl_fac = is_pixel() ? 3.0f : std::sqrt(3.0f); + for (unsigned int i = 0; i < m_n_hits; ++i) { const Hit &h = hitv[i]; @@ -100,13 +103,12 @@ namespace mkfit { m_binnor.register_entry_safe(phi, q); if (Config::usePhiQArrays) { - const float sqrt3 = std::sqrt(3); float half_length, qbar; if (m_is_barrel) { - half_length = sqrt3 * std::sqrt(h.ezz()); + half_length = hl_fac * std::sqrt(h.ezz()); qbar = h.r(); } else { - half_length = sqrt3 * std::sqrt(h.exx() + h.eyy()); + half_length = hl_fac * std::sqrt(h.exx() + h.eyy()); qbar = h.z(); } hinfos.emplace_back(HitInfo({phi, q, half_length, qbar})); @@ -168,13 +170,14 @@ namespace mkfit { m_binnor.register_entry_safe(phi, q); if (Config::usePhiQArrays) { - const float sqrt3 = std::sqrt(3); + // Factor to get from hit sigma to half-length in q direction. + const float hl_fac = is_pixel() ? 3.0f : std::sqrt(3.0f); float half_length, qbar; if (m_is_barrel) { - half_length = sqrt3 * std::sqrt(h.ezz()); + half_length = hl_fac * std::sqrt(h.ezz()); qbar = h.r(); } else { - half_length = sqrt3 * std::sqrt(h.exx() + h.eyy()); + half_length = hl_fac * std::sqrt(h.exx() + h.eyy()); qbar = h.z(); } m_hit_infos.emplace_back(HitInfo({phi, q, half_length, qbar})); diff --git a/RecoTracker/MkFitCore/src/IterationConfig.cc b/RecoTracker/MkFitCore/src/IterationConfig.cc index 60e9066d89da0..b4b5e612584a9 100644 --- a/RecoTracker/MkFitCore/src/IterationConfig.cc +++ b/RecoTracker/MkFitCore/src/IterationConfig.cc @@ -61,6 +61,8 @@ namespace mkfit { /* float */ chi2Cut_min, /* float */ chi2CutOverlap, /* float */ pTCutOverlap, + /* bool */ recheckOverlap, + /* bool */ useHitSelectionV2, /* int */ minHitsQF, /* float */ minPtCut, /* unsigned int */ maxClusterSize) diff --git a/RecoTracker/MkFitCore/src/Matriplex/Matriplex.h b/RecoTracker/MkFitCore/src/Matriplex/Matriplex.h index 712afd240789b..2eff5e7bbecc6 100644 --- a/RecoTracker/MkFitCore/src/Matriplex/Matriplex.h +++ b/RecoTracker/MkFitCore/src/Matriplex/Matriplex.h @@ -115,6 +115,24 @@ namespace Matriplex { return *this; } + Matriplex operator-() { + Matriplex t; + for (idx_t i = 0; i < kTotSize; ++i) + t.fArray[i] = -fArray[i]; + return t; + } + + Matriplex& abs(const Matriplex& a) { + for (idx_t i = 0; i < kTotSize; ++i) + fArray[i] = std::abs(a.fArray[i]); + return *this; + } + Matriplex& abs() { + for (idx_t i = 0; i < kTotSize; ++i) + fArray[i] = std::abs(fArray[i]); + return *this; + } + Matriplex& sqrt(const Matriplex& a) { for (idx_t i = 0; i < kTotSize; ++i) fArray[i] = std::sqrt(a.fArray[i]); @@ -401,6 +419,12 @@ namespace Matriplex { return t; } + template + MPlex abs(const MPlex& a) { + MPlex t; + return t.abs(a); + } + template MPlex sqrt(const MPlex& a) { MPlex t; @@ -410,7 +434,7 @@ namespace Matriplex { template MPlex sqr(const MPlex& a) { MPlex t; - return t.sqrt(a); + return t.sqr(a); } template diff --git a/RecoTracker/MkFitCore/src/Matriplex/MatriplexSym.h b/RecoTracker/MkFitCore/src/Matriplex/MatriplexSym.h index 151f616402440..4a746d2c972c4 100644 --- a/RecoTracker/MkFitCore/src/Matriplex/MatriplexSym.h +++ b/RecoTracker/MkFitCore/src/Matriplex/MatriplexSym.h @@ -263,6 +263,14 @@ namespace Matriplex { a[5 * N + n] = s * c22; } } + + Matriplex ReduceFixedIJ(idx_t i, idx_t j) const { + Matriplex t; + for (idx_t n = 0; n < N; ++n) { + t[n] = constAt(n, i, j); + } + return t; + } }; template diff --git a/RecoTracker/MkFitCore/src/MkBuilder.cc b/RecoTracker/MkFitCore/src/MkBuilder.cc index 2c984991519b8..4d4e3a30d1675 100644 --- a/RecoTracker/MkFitCore/src/MkBuilder.cc +++ b/RecoTracker/MkFitCore/src/MkBuilder.cc @@ -979,15 +979,16 @@ namespace mkfit { const int n_seeds = end_seed - start_seed; std::vector> seed_cand_idx; - std::vector seed_cand_update_idx; + std::vector seed_cand_update_idx, seed_cand_overlap_idx; seed_cand_idx.reserve(n_seeds * params.maxCandsPerSeed); seed_cand_update_idx.reserve(n_seeds * params.maxCandsPerSeed); + seed_cand_overlap_idx.reserve(n_seeds * params.maxCandsPerSeed); std::vector> extra_cands(n_seeds); for (int ii = 0; ii < n_seeds; ++ii) extra_cands[ii].reserve(params.maxCandsPerSeed); - cloner.begin_eta_bin(&eoccs, &seed_cand_update_idx, &extra_cands, start_seed, n_seeds); + cloner.begin_eta_bin(&eoccs, &seed_cand_update_idx, &seed_cand_overlap_idx, &extra_cands, start_seed, n_seeds); // Loop over layers, starting from after the seed. @@ -1087,7 +1088,10 @@ namespace mkfit { dprint("now get hit range"); - mkfndr->selectHitIndices(layer_of_hits, end - itrack); + if (iter_params.useHitSelectionV2) + mkfndr->selectHitIndicesV2(layer_of_hits, end - itrack); + else + mkfndr->selectHitIndices(layer_of_hits, end - itrack); find_tracks_handle_missed_layers( mkfndr, layer_info, extra_cands, seed_cand_idx, region, start_seed, itrack, end); @@ -1115,6 +1119,9 @@ namespace mkfit { // Update loop of best candidates. CandCloner prepares the list of those // that need update (excluding all those with negative last hit index). + // This is split into two sections - candidates without overlaps and with overlaps. + // On CMS PU-50 the ratio of those is ~ 65 : 35 over all iterations. + // Note, overlap recheck is only enabled for some iterations, e.g. pixelLess. const int theEndUpdater = seed_cand_update_idx.size(); @@ -1129,6 +1136,43 @@ namespace mkfit { mkfndr->copyOutParErr(eoccs.refCandidates_nc(), end - itrack, false); } + const int theEndOverlapper = seed_cand_overlap_idx.size(); + + for (int itrack = 0; itrack < theEndOverlapper; itrack += NN) { + const int end = std::min(itrack + NN, theEndOverlapper); + + mkfndr->inputTracksAndHits(eoccs.refCandidates(), layer_of_hits, seed_cand_overlap_idx, itrack, end, true); + + mkfndr->updateWithLoadedHit(end - itrack, layer_of_hits, fnd_foos); + + mkfndr->copyOutParErr(eoccs.refCandidates_nc(), end - itrack, false); + + mkfndr->inputOverlapHits(layer_of_hits, seed_cand_overlap_idx, itrack, end); + + // XXXX Could also be calcChi2AndUpdate(), then copy-out would have to be done + // below, choosing appropriate slot (with or without the overlap hit). + // Probably in a dedicated MkFinder copyOutXyzz function. + mkfndr->chi2OfLoadedHit(end - itrack, fnd_foos); + + for (int ii = itrack; ii < end; ++ii) { + const int fi = ii - itrack; + TrackCand &tc = eoccs[seed_cand_overlap_idx[ii].seed_idx][seed_cand_overlap_idx[ii].cand_idx]; + + // XXXX For now we DO NOT use chi2 as this was how things were done before the post-update + // chi2 check. To use it we should retune scoring function (might be even simpler). + auto chi2Ovlp = mkfndr->m_Chi2[fi]; + if (mkfndr->m_FailFlag[fi] == 0 && chi2Ovlp >= 0.0f && chi2Ovlp <= 60.0f) { + auto scoreCand = + getScoreCand(st_par.m_track_scorer, tc, true /*penalizeTailMissHits*/, true /*inFindCandidates*/); + tc.addHitIdx(seed_cand_overlap_idx[ii].ovlp_idx, curr_layer, chi2Ovlp); + tc.incOverlapCount(); + auto scoreCandOvlp = getScoreCand(st_par.m_track_scorer, tc, true, true); + if (scoreCand > scoreCandOvlp) + tc.popOverlap(); + } + } + } + // Check if cands are sorted, as expected. #ifdef DEBUG for (int iseed = start_seed; iseed < end_seed; ++iseed) { diff --git a/RecoTracker/MkFitCore/src/MkFinder.cc b/RecoTracker/MkFitCore/src/MkFinder.cc index ee9726a8eb485..d15ae47c4b7da 100644 --- a/RecoTracker/MkFitCore/src/MkFinder.cc +++ b/RecoTracker/MkFitCore/src/MkFinder.cc @@ -178,6 +178,19 @@ namespace mkfit { } } + void MkFinder::inputOverlapHits(const LayerOfHits &layer_of_hits, + const std::vector &idxs, + int beg, + int end) { + // Copy overlap hit values in. + + for (int i = beg, imp = 0; i < end; ++i, ++imp) { + const Hit &hit = layer_of_hits.refHit(idxs[i].ovlp_idx); + m_msErr.copyIn(imp, hit.errArray()); + m_msPar.copyIn(imp, hit.posArray()); + } + } + void MkFinder::inputTracksAndHitIdx(const std::vector &tracks, const std::vector> &idxs, int beg, @@ -776,6 +789,8 @@ namespace mkfit { mp::StatePlex sp1, sp2; int n_proc; + MPlexQF dphi_track, dq_track; // 3 sigma track errors at initial state + // debug & ntuple dump -- to be local in functions MPlexQF phi_c, dphi; MPlexQF q_c, qmin, qmax; @@ -795,10 +810,10 @@ namespace mkfit { } } - void find_bin_ranges(const LayerInfo &li, const LayerOfHits &loh) { + void find_bin_ranges(const LayerInfo &li, const LayerOfHits &loh, const MPlexLS &err) { // Below made members for debugging // MPlexQF phi_c, dphi_min, dphi_max; - phi_c = mp::fast_atan2(isp.y, isp.x); + // phi_c = mp::fast_atan2(isp.y, isp.x); // calculated below as difference // Matriplex::min_max(sp1.dphi, sp2.dphi, dphi_min, dphi_max); // the above is wrong: dalpha is not dphi --> renamed variable in State @@ -820,13 +835,27 @@ namespace mkfit { // phi_c[ii], xp1[ii], xp2[ii], pmin[ii], pmax[ii], dphi[ii]); } + const auto calc_err_xy = [&](const MPlexQF &x, const MPlexQF &y) { + return x * x * err.ReduceFixedIJ(0, 0) + y * y * err.ReduceFixedIJ(1, 1) + + 2.0f * x * y * err.ReduceFixedIJ(0, 1); + }; + + // Calculate dphi_track, dq_track differs for barrel/endcap + MPlexQF r2_c = isp.x * isp.x + isp.y * isp.y; + MPlexQF r2inv_c = 1.0f / r2_c; + MPlexQF dphidx_c = -isp.y * r2inv_c; + MPlexQF dphidy_c = isp.x * r2inv_c; + dphi_track = 3.0f * calc_err_xy(dphidx_c, dphidy_c).abs().sqrt(); + // MPlexQF qmin, qmax; if (li.is_barrel()) { Matriplex::min_max(sp1.z, sp2.z, qmin, qmax); q_c = isp.z; + dq_track = 3.0f * err.ReduceFixedIJ(2, 2).abs().sqrt(); } else { Matriplex::min_max(Matriplex::hypot(sp1.x, sp1.y), Matriplex::hypot(sp2.x, sp2.y), qmin, qmax); - q_c = Matriplex::hypot(isp.x, isp.y); + q_c = Matriplex::sqrt(r2_c); + dq_track = 3.0f * (r2inv_c * calc_err_xy(isp.x, isp.y).abs()).sqrt(); } for (int i = 0; i < p1.kTotSize; ++i) { @@ -834,19 +863,19 @@ namespace mkfit { // const float dphi_clamp = 0.1; // if (dphi_min[i] > 0.0f || dphi_min[i] < -dphi_clamp) dphi_min[i] = -dphi_clamp; // if (dphi_max[i] < 0.0f || dphi_max[i] > dphi_clampf) dphi_max[i] = dphi_clamp; - p1[i] = loh.phiBinChecked(pmin[i] - PHI_BIN_EXTRA_FAC * 0.0123f); - p2[i] = loh.phiBinChecked(pmax[i] + PHI_BIN_EXTRA_FAC * 0.0123f); + p1[i] = loh.phiBinChecked(pmin[i] - dphi_track[i] - PHI_BIN_EXTRA_FAC * 0.0123f); + p2[i] = loh.phiBinChecked(pmax[i] + dphi_track[i] + PHI_BIN_EXTRA_FAC * 0.0123f); q0[i] = loh.qBinChecked(q_c[i]); - q1[i] = loh.qBinChecked(qmin[i] - Q_BIN_EXTRA_FAC * 0.5f * li.q_bin()); - q2[i] = loh.qBinChecked(qmax[i] + Q_BIN_EXTRA_FAC * 0.5f * li.q_bin()) + 1; + q1[i] = loh.qBinChecked(qmin[i] - dq_track[i] - Q_BIN_EXTRA_FAC * 0.5f * li.q_bin()); + q2[i] = loh.qBinChecked(qmax[i] + dq_track[i] + Q_BIN_EXTRA_FAC * 0.5f * li.q_bin()) + 1; } } }; Bins B(m_Par[iI], m_Chg, N_proc); B.prop_to_limits(LI); - B.find_bin_ranges(LI, L); + B.find_bin_ranges(LI, L, m_Err[iI]); for (int i = 0; i < N_proc; ++i) { m_XHitSize[i] = 0; @@ -969,8 +998,8 @@ namespace mkfit { new_ddphi = cdist(std::abs(new_phi - L.hit_phi(hi))); new_ddq = std::abs(new_q - L.hit_q(hi)); - bool dqdphi_presel = - new_ddq < DDQ_PRESEL_FAC * L.hit_q_half_length(hi) && new_ddphi < DDPHI_PRESEL_FAC * 0.0123f; + bool dqdphi_presel = new_ddq < B.dq_track[itrack] + DDQ_PRESEL_FAC * L.hit_q_half_length(hi) && + new_ddphi < B.dphi_track[itrack] + DDPHI_PRESEL_FAC * 0.0123f; // clang-format off dprintf(" SHI %3u %4u %5u %6.3f %6.3f %6.4f %7.5f PROP-%s %s\n", @@ -1752,6 +1781,26 @@ namespace mkfit { // } } + void MkFinder::chi2OfLoadedHit(int N_proc, const FindingFoos &fnd_foos) { + // We expect input in iC slots from above function. + // See comment in MkBuilder::find_tracks_in_layer() about intra / inter flags used here + // for propagation to the hit. + clearFailFlag(); + (*fnd_foos.m_compute_chi2_foo)(m_Err[iC], + m_Par[iC], + m_Chg, + m_msErr, + m_msPar, + m_Chi2, + m_Par[iP], + m_FailFlag, + N_proc, + m_prop_config->finding_inter_layer_pflags, + m_prop_config->finding_requires_propagation_to_hit_pos); + + // PROP-FAIL-ENABLE .... removed here + } + //============================================================================== // CopyOutParErr //============================================================================== diff --git a/RecoTracker/MkFitCore/src/MkFinder.h b/RecoTracker/MkFitCore/src/MkFinder.h index 7a9e0f3c96500..13a6df7a2e1f6 100644 --- a/RecoTracker/MkFitCore/src/MkFinder.h +++ b/RecoTracker/MkFitCore/src/MkFinder.h @@ -30,8 +30,9 @@ namespace mkfit { int seed_idx; int cand_idx; int hit_idx; + int ovlp_idx; - UpdateIndices(int si, int ci, int hi) : seed_idx(si), cand_idx(ci), hit_idx(hi) {} + UpdateIndices(int si, int ci, int hi, int oi) : seed_idx(si), cand_idx(ci), hit_idx(hi), ovlp_idx(oi) {} }; class MkFinder : public MkBase { @@ -85,6 +86,7 @@ namespace mkfit { int beg, int end, bool inputProp); + void inputOverlapHits(const LayerOfHits &layer_of_hits, const std::vector &idxs, int beg, int end); void inputTracksAndHitIdx(const std::vector &tracks, const std::vector> &idxs, @@ -145,6 +147,8 @@ namespace mkfit { void updateWithLoadedHit(int N_proc, const LayerOfHits &layer_of_hits, const FindingFoos &fnd_foos); + void chi2OfLoadedHit(int N_proc, const FindingFoos &fnd_foos); + void copyOutParErr(std::vector &seed_cand_vec, int N_proc, bool outputProp) const; //----------------------------------------------------------------------------