File indexing completed on 2022-05-01 22:52:20
0001 #ifndef RecoTracker_MkFitCore_interface_TrackStructures_h
0002 #define RecoTracker_MkFitCore_interface_TrackStructures_h
0003
0004 #include "RecoTracker/MkFitCore/interface/Config.h"
0005 #include "RecoTracker/MkFitCore/interface/Hit.h"
0006 #include "RecoTracker/MkFitCore/interface/Track.h"
0007 #include "RecoTracker/MkFitCore/interface/TrackerInfo.h"
0008
0009 #include <algorithm>
0010 #include <array>
0011
0012 namespace mkfit {
0013
0014 class IterationParams;
0015
0016
0017
0018
0019
0020 struct HoTNode {
0021 HitOnTrack m_hot;
0022 float m_chi2;
0023 int m_prev_idx;
0024 };
0025
0026 struct HitMatch {
0027 int m_hit_idx = -1;
0028 int m_module_id = -1;
0029 float m_chi2 = 1e9;
0030
0031 void reset() {
0032 m_hit_idx = -1;
0033 m_module_id = -1;
0034 m_chi2 = 1e9;
0035 }
0036 };
0037
0038 struct HitMatchPair {
0039 HitMatch M[2];
0040
0041 void reset() {
0042 M[0].reset();
0043 M[1].reset();
0044 }
0045
0046 void consider_hit_for_overlap(int hit_idx, int module_id, float chi2) {
0047 if (module_id == M[0].m_module_id) {
0048 if (chi2 < M[0].m_chi2) {
0049 M[0].m_chi2 = chi2;
0050 M[0].m_hit_idx = hit_idx;
0051 }
0052 } else if (module_id == M[1].m_module_id) {
0053 if (chi2 < M[1].m_chi2) {
0054 M[1].m_chi2 = chi2;
0055 M[1].m_hit_idx = hit_idx;
0056 }
0057 } else {
0058 if (M[0].m_chi2 > M[1].m_chi2) {
0059 if (chi2 < M[0].m_chi2) {
0060 M[0] = {hit_idx, module_id, chi2};
0061 }
0062 } else {
0063 if (chi2 < M[1].m_chi2) {
0064 M[1] = {hit_idx, module_id, chi2};
0065 }
0066 }
0067 }
0068 }
0069
0070 HitMatch* find_overlap(int hit_idx, int module_id) {
0071 if (module_id == M[0].m_module_id) {
0072 if (M[1].m_hit_idx >= 0)
0073 return &M[1];
0074 } else if (module_id == M[1].m_module_id) {
0075 if (M[0].m_hit_idx >= 0)
0076 return &M[0];
0077 } else {
0078 if (M[0].m_chi2 <= M[1].m_chi2) {
0079 if (M[0].m_hit_idx >= 0)
0080 return &M[0];
0081 } else {
0082 if (M[1].m_hit_idx >= 0)
0083 return &M[1];
0084 }
0085 }
0086
0087 return nullptr;
0088 }
0089 };
0090
0091
0092
0093 template <class T>
0094 class CcPool {
0095 public:
0096 void reset(std::size_t size) {
0097 if (size > m_mem.size())
0098 m_mem.resize(size);
0099 m_pos = 0;
0100 m_size = size;
0101 }
0102
0103 void release() {
0104 std::vector<T> tmp;
0105 m_mem.swap(tmp);
0106 m_pos = 0;
0107 m_size = 0;
0108 }
0109
0110 CcPool(std::size_t size = 0) {
0111 if (size)
0112 reset(size);
0113 }
0114
0115 T* allocate(std::size_t n) {
0116 if (m_pos + n > m_size)
0117 throw std::bad_alloc();
0118 T* ret = &m_mem[m_pos];
0119 m_pos += n;
0120 return ret;
0121 }
0122
0123 void deallocate(T* p, std::size_t n) noexcept {
0124
0125 }
0126
0127 private:
0128 std::vector<T> m_mem;
0129 std::size_t m_pos = 0;
0130 std::size_t m_size = 0;
0131 };
0132
0133 template <class T>
0134 class CcAlloc {
0135 public:
0136 typedef T value_type;
0137
0138 CcAlloc(CcPool<T>* p) : m_pool(p) {}
0139
0140 const void* pool_id() const { return m_pool; }
0141
0142 T* allocate(std::size_t n) { return m_pool->allocate(n); }
0143
0144 void deallocate(T* p, std::size_t n) noexcept { m_pool->deallocate(p, n); }
0145
0146 private:
0147 CcPool<T>* m_pool;
0148 };
0149
0150 template <class T, class U>
0151 bool operator==(const CcAlloc<T>& a, const CcAlloc<U>& b) {
0152 return a.pool_id() == b.pool_id();
0153 }
0154
0155
0156
0157 class CombCandidate;
0158
0159 class TrackCand : public TrackBase {
0160 public:
0161 TrackCand() = default;
0162
0163 explicit TrackCand(const TrackBase& base, CombCandidate* ccand) : TrackBase(base), m_comb_candidate(ccand) {
0164
0165 lastHitIdx_ = -1;
0166 nFoundHits_ = 0;
0167 }
0168
0169
0170
0171
0172
0173
0174
0175 CombCandidate* combCandidate() const { return m_comb_candidate; }
0176 void setCombCandidate(CombCandidate* cc) { m_comb_candidate = cc; }
0177
0178 int lastCcIndex() const { return lastHitIdx_; }
0179 int nFoundHits() const { return nFoundHits_; }
0180 int nMissingHits() const { return nMissingHits_; }
0181 int nOverlapHits() const { return nOverlapHits_; }
0182 int nTotalHits() const { return nFoundHits_ + nMissingHits_; }
0183
0184 void setLastCcIndex(int i) { lastHitIdx_ = i; }
0185 void setNFoundHits(int n) { nFoundHits_ = n; }
0186 void setNMissingHits(int n) { nMissingHits_ = n; }
0187 void setNOverlapHits(int n) { nOverlapHits_ = n; }
0188
0189 int nInsideMinusOneHits() const { return nInsideMinusOneHits_; }
0190 int nTailMinusOneHits() const { return nTailMinusOneHits_; }
0191
0192 void setNInsideMinusOneHits(int n) { nInsideMinusOneHits_ = n; }
0193 void setNTailMinusOneHits(int n) { nTailMinusOneHits_ = n; }
0194
0195 int originIndex() const { return m_origin_index; }
0196 void setOriginIndex(int oi) { m_origin_index = oi; }
0197
0198 void resetOverlaps() { m_overlap_hits.reset(); }
0199 void considerHitForOverlap(int hit_idx, int module_id, float chi2) {
0200 m_overlap_hits.consider_hit_for_overlap(hit_idx, module_id, chi2);
0201 }
0202 HitMatch* findOverlap(int hit_idx, int module_id) { return m_overlap_hits.find_overlap(hit_idx, module_id); }
0203
0204
0205
0206 HitOnTrack getLastHitOnTrack() const;
0207 int getLastHitIdx() const;
0208 int getLastHitLyr() const;
0209
0210
0211 int getLastFoundPixelHitLyr() const;
0212 int getLastFoundHitLyr() const;
0213 int nUniqueLayers() const;
0214
0215 int nLayersByTypeEncoded(const TrackerInfo& trk_inf) const;
0216 int nHitsByTypeEncoded(const TrackerInfo& trk_inf) const;
0217
0218 int nPixelDecoded(const int& encoded) const { return encoded % 100; }
0219 int nStereoDecoded(const int& encoded) const { return (encoded / 100) % 100; }
0220 int nMonoDecoded(const int& encoded) const { return (encoded / 10000) % 100; }
0221 int nMatchedDecoded(const int& encoded) const { return encoded / 1000000; }
0222 int nTotMatchDecoded(const int& encoded) const {
0223 return encoded % 100 + (encoded / 100) % 100 + (encoded / 10000) % 100 - encoded / 1000000;
0224 }
0225
0226 void addHitIdx(int hitIdx, int hitLyr, float chi2);
0227
0228 HoTNode& refLastHoTNode();
0229 const HoTNode& refLastHoTNode() const;
0230
0231 void incOverlapCount() { ++nOverlapHits_; }
0232
0233 Track exportTrack(bool remove_missing_hits = false) const;
0234
0235 void resetShortTrack() {
0236 score_ = getScoreWorstPossible();
0237 m_comb_candidate = nullptr;
0238 }
0239
0240 private:
0241 CombCandidate* m_comb_candidate = nullptr;
0242 HitMatchPair m_overlap_hits;
0243
0244
0245 short int nMissingHits_ = 0;
0246 short int nOverlapHits_ = 0;
0247
0248 short int nInsideMinusOneHits_ = 0;
0249 short int nTailMinusOneHits_ = 0;
0250
0251 short int m_origin_index = -1;
0252 };
0253
0254 inline bool sortByScoreTrackCand(const TrackCand& cand1, const TrackCand& cand2) {
0255 return cand1.score() > cand2.score();
0256 }
0257
0258 inline float getScoreCand(const TrackCand& cand1, bool penalizeTailMissHits = false, bool inFindCandidates = false) {
0259 int nfoundhits = cand1.nFoundHits();
0260 int noverlaphits = cand1.nOverlapHits();
0261 int nmisshits = cand1.nInsideMinusOneHits();
0262 int ntailmisshits = penalizeTailMissHits ? cand1.nTailMinusOneHits() : 0;
0263 float pt = cand1.pT();
0264 float chi2 = cand1.chi2();
0265
0266 if (chi2 < 0)
0267 chi2 = 0.f;
0268 return getScoreCalc(nfoundhits, ntailmisshits, noverlaphits, nmisshits, chi2, pt, inFindCandidates);
0269 }
0270
0271
0272
0273 class CombCandidate {
0274 public:
0275 using trk_cand_vec_type = std::vector<TrackCand, CcAlloc<TrackCand>>;
0276 using allocator_type = CcAlloc<TrackCand>;
0277
0278 enum SeedState_e { Dormant = 0, Finding, Finished };
0279
0280 CombCandidate(const allocator_type& alloc) : m_trk_cands(alloc), m_state(Dormant), m_pickup_layer(-1) {}
0281
0282
0283 CombCandidate(const CombCandidate& o)
0284 : m_trk_cands(o.m_trk_cands),
0285 m_state(o.m_state),
0286 m_pickup_layer(o.m_pickup_layer),
0287 m_lastHitIdx_before_bkwsearch(o.m_lastHitIdx_before_bkwsearch),
0288 m_nInsideMinusOneHits_before_bkwsearch(o.m_nInsideMinusOneHits_before_bkwsearch),
0289 m_nTailMinusOneHits_before_bkwsearch(o.m_nTailMinusOneHits_before_bkwsearch),
0290 #ifdef DUMPHITWINDOW
0291 m_seed_algo(o.m_seed_algo),
0292 m_seed_label(o.m_seed_label),
0293 #endif
0294 m_hots_size(o.m_hots_size),
0295 m_hots(o.m_hots) {
0296 }
0297
0298
0299 CombCandidate(CombCandidate&& o)
0300 : m_trk_cands(std::move(o.m_trk_cands)),
0301 m_best_short_cand(std::move(o.m_best_short_cand)),
0302 m_state(o.m_state),
0303 m_pickup_layer(o.m_pickup_layer),
0304 m_lastHitIdx_before_bkwsearch(o.m_lastHitIdx_before_bkwsearch),
0305 m_nInsideMinusOneHits_before_bkwsearch(o.m_nInsideMinusOneHits_before_bkwsearch),
0306 m_nTailMinusOneHits_before_bkwsearch(o.m_nTailMinusOneHits_before_bkwsearch),
0307 #ifdef DUMPHITWINDOW
0308 m_seed_algo(o.m_seed_algo),
0309 m_seed_label(o.m_seed_label),
0310 #endif
0311 m_hots_size(o.m_hots_size),
0312 m_hots(std::move(o.m_hots)) {
0313
0314
0315
0316
0317
0318 }
0319
0320
0321
0322
0323
0324 CombCandidate& operator=(CombCandidate&& o) {
0325 m_trk_cands = (std::move(o.m_trk_cands));
0326 m_best_short_cand = std::move(o.m_best_short_cand);
0327 m_state = o.m_state;
0328 m_pickup_layer = o.m_pickup_layer;
0329 m_lastHitIdx_before_bkwsearch = o.m_lastHitIdx_before_bkwsearch;
0330 m_nInsideMinusOneHits_before_bkwsearch = o.m_nInsideMinusOneHits_before_bkwsearch;
0331 m_nTailMinusOneHits_before_bkwsearch = o.m_nTailMinusOneHits_before_bkwsearch;
0332 #ifdef DUMPHITWINDOW
0333 m_seed_algo = o.m_seed_algo;
0334 m_seed_label = o.m_seed_label;
0335 #endif
0336 m_hots_size = o.m_hots_size;
0337 m_hots = std::move(o.m_hots);
0338
0339 for (auto& tc : m_trk_cands)
0340 tc.setCombCandidate(this);
0341
0342 return *this;
0343 }
0344
0345
0346 bool empty() const { return m_trk_cands.empty(); }
0347 trk_cand_vec_type::size_type size() const { return m_trk_cands.size(); }
0348 void resize(trk_cand_vec_type::size_type count) { m_trk_cands.resize(count); }
0349 TrackCand& operator[](int i) { return m_trk_cands[i]; }
0350 const TrackCand& operator[](int i) const { return m_trk_cands[i]; }
0351 TrackCand& front() { return m_trk_cands.front(); }
0352 const TrackCand& front() const { return m_trk_cands.front(); }
0353 trk_cand_vec_type::reference emplace_back(TrackCand& tc) { return m_trk_cands.emplace_back(tc); }
0354 void clear() { m_trk_cands.clear(); }
0355
0356 void reset(int max_cands_per_seed, int expected_num_hots) {
0357 std::vector<TrackCand, CcAlloc<TrackCand>> tmp(m_trk_cands.get_allocator());
0358 m_trk_cands.swap(tmp);
0359 m_trk_cands.reserve(max_cands_per_seed);
0360
0361 m_best_short_cand.setScore(getScoreWorstPossible());
0362
0363
0364
0365
0366
0367
0368
0369 m_hots.reserve(expected_num_hots);
0370 m_hots_size = 0;
0371 m_hots.clear();
0372 }
0373
0374 void importSeed(const Track& seed, int region);
0375
0376 int addHit(const HitOnTrack& hot, float chi2, int prev_idx) {
0377 m_hots.push_back({hot, chi2, prev_idx});
0378 return m_hots_size++;
0379 }
0380
0381 void mergeCandsAndBestShortOne(const IterationParams& params, bool update_score, bool sort_cands);
0382
0383 void compactifyHitStorageForBestCand(bool remove_seed_hits, int backward_fit_min_hits);
0384 void beginBkwSearch();
0385 void endBkwSearch();
0386
0387
0388
0389 int hotsSize() const { return m_hots_size; }
0390 const HoTNode& hot_node(int i) const { return m_hots[i]; }
0391 HoTNode& hot_node_nc(int i) { return m_hots[i]; }
0392 HitOnTrack hot(int i) const { return m_hots[i].m_hot; }
0393
0394 const HoTNode* hotsData() const { return m_hots.data(); }
0395
0396 const TrackCand& refBestShortCand() const { return m_best_short_cand; }
0397 void setBestShortCand(const TrackCand& tc) { m_best_short_cand = tc; }
0398
0399 SeedState_e state() const { return m_state; }
0400 void setState(SeedState_e ss) { m_state = ss; }
0401
0402 int pickupLayer() const { return m_pickup_layer; }
0403
0404 #ifdef DUMPHITWINDOW
0405 int seed_algo() const { return m_seed_algo; }
0406 int seed_label() const { return m_seed_label; }
0407 #endif
0408
0409 private:
0410 trk_cand_vec_type m_trk_cands;
0411 TrackCand m_best_short_cand;
0412 SeedState_e m_state : 8;
0413 int m_pickup_layer : 16;
0414 short int m_lastHitIdx_before_bkwsearch = -1;
0415 short int m_nInsideMinusOneHits_before_bkwsearch = -1;
0416 short int m_nTailMinusOneHits_before_bkwsearch = -1;
0417
0418 #ifdef DUMPHITWINDOW
0419 int m_seed_algo = 0;
0420 int m_seed_label = 0;
0421 #endif
0422 int m_hots_size = 0;
0423 std::vector<HoTNode> m_hots;
0424 };
0425
0426
0427
0428 inline HitOnTrack TrackCand::getLastHitOnTrack() const { return m_comb_candidate->hot(lastHitIdx_); }
0429
0430 inline int TrackCand::getLastHitIdx() const { return m_comb_candidate->hot(lastHitIdx_).index; }
0431
0432 inline int TrackCand::getLastHitLyr() const { return m_comb_candidate->hot(lastHitIdx_).layer; }
0433
0434 inline int TrackCand::getLastFoundHitLyr() const {
0435 int nh = nTotalHits();
0436 int ch = lastHitIdx_;
0437 int ll = -1;
0438 while (--nh >= 0) {
0439 const HoTNode& hot_node = m_comb_candidate->hot_node(ch);
0440 if (hot_node.m_hot.index < 0) {
0441 ch = hot_node.m_prev_idx;
0442 } else {
0443 ll = hot_node.m_hot.layer;
0444 break;
0445 }
0446 }
0447 return ll;
0448 }
0449
0450 inline int TrackCand::getLastFoundPixelHitLyr() const {
0451 int nh = nTotalHits();
0452 int ch = lastHitIdx_;
0453 int ll = -1;
0454 while (--nh >= 0) {
0455 const HoTNode& hot_node = m_comb_candidate->hot_node(ch);
0456 int tl = hot_node.m_hot.layer;
0457 if (hot_node.m_hot.index < 0 || !((0 <= tl && tl <= 3) || (18 <= tl && tl <= 20) || (45 <= tl && tl <= 47))) {
0458 ch = hot_node.m_prev_idx;
0459 } else if ((0 <= tl && tl <= 3) || (18 <= tl && tl <= 20) || (45 <= tl && tl <= 47)) {
0460 ll = hot_node.m_hot.layer;
0461 break;
0462 }
0463 }
0464 return ll;
0465 }
0466
0467 inline int TrackCand::nUniqueLayers() const {
0468 int nUL = 0;
0469 int prevL = -1;
0470 int nh = nTotalHits();
0471 int ch = lastHitIdx_;
0472
0473 while (--nh >= 0) {
0474 const HoTNode& hot_node = m_comb_candidate->hot_node(ch);
0475 int thisL = hot_node.m_hot.layer;
0476 if (thisL >= 0 && (hot_node.m_hot.index >= 0 || hot_node.m_hot.index == Hit::kHitCCCFilterIdx) &&
0477 thisL != prevL) {
0478 ++nUL;
0479 prevL = thisL;
0480 }
0481 ch = hot_node.m_prev_idx;
0482 }
0483 return nUL;
0484 }
0485
0486 inline int TrackCand::nHitsByTypeEncoded(const TrackerInfo& trk_inf) const {
0487 int prevL = -1;
0488 bool prevStereo = false;
0489 int nh = nTotalHits();
0490 int ch = lastHitIdx_;
0491 int pix = 0, stereo = 0, mono = 0, matched = 0;
0492 int doubleStereo = -1;
0493 while (--nh >= 0) {
0494 const HoTNode& hot_node = m_comb_candidate->hot_node(ch);
0495 int thisL = hot_node.m_hot.layer;
0496 if (thisL >= 0 && (hot_node.m_hot.index >= 0 || hot_node.m_hot.index == Hit::kHitCCCFilterIdx)) {
0497 if (trk_inf[thisL].is_pixel())
0498 ++pix;
0499 else if (trk_inf[thisL].is_stereo()) {
0500 ++stereo;
0501 if (thisL == prevL)
0502 doubleStereo = thisL;
0503 } else {
0504
0505 ++mono;
0506 if (prevStereo && thisL == prevL - 1)
0507 ++matched;
0508 else if (thisL == prevL && thisL == doubleStereo - 1)
0509 ++matched;
0510 }
0511 prevL = thisL;
0512 prevStereo = stereo;
0513 }
0514 ch = hot_node.m_prev_idx;
0515 }
0516 return pix + 100 * stereo + 10000 * mono + 1000000 * matched;
0517 }
0518
0519 inline int TrackCand::nLayersByTypeEncoded(const TrackerInfo& trk_inf) const {
0520 int prevL = -1;
0521 bool prevStereo = false;
0522 int nh = nTotalHits();
0523 int ch = lastHitIdx_;
0524 int pix = 0, stereo = 0, mono = 0, matched = 0;
0525 while (--nh >= 0) {
0526 const HoTNode& hot_node = m_comb_candidate->hot_node(ch);
0527 int thisL = hot_node.m_hot.layer;
0528 if (thisL >= 0 && (hot_node.m_hot.index >= 0 || hot_node.m_hot.index == Hit::kHitCCCFilterIdx) &&
0529 thisL != prevL) {
0530 if (trk_inf[thisL].is_pixel())
0531 ++pix;
0532 else if (trk_inf[thisL].is_stereo())
0533 ++stereo;
0534 else {
0535
0536 ++mono;
0537 if (prevStereo && thisL == prevL - 1)
0538 ++matched;
0539 }
0540 prevL = thisL;
0541 prevStereo = stereo;
0542 }
0543 ch = hot_node.m_prev_idx;
0544 }
0545 return pix + 100 * stereo + 10000 * mono + 1000000 * matched;
0546 }
0547
0548 inline HoTNode& TrackCand::refLastHoTNode() { return m_comb_candidate->hot_node_nc(lastHitIdx_); }
0549
0550 inline const HoTNode& TrackCand::refLastHoTNode() const { return m_comb_candidate->hot_node(lastHitIdx_); }
0551
0552
0553
0554 inline void TrackCand::addHitIdx(int hitIdx, int hitLyr, float chi2) {
0555 lastHitIdx_ = m_comb_candidate->addHit({hitIdx, hitLyr}, chi2, lastHitIdx_);
0556
0557 if (hitIdx >= 0 || hitIdx == Hit::kHitCCCFilterIdx) {
0558 ++nFoundHits_;
0559 chi2_ += chi2;
0560 nInsideMinusOneHits_ += nTailMinusOneHits_;
0561 nTailMinusOneHits_ = 0;
0562 }
0563
0564 else {
0565 ++nMissingHits_;
0566 if (hitIdx == Hit::kHitMissIdx)
0567 ++nTailMinusOneHits_;
0568 }
0569 }
0570
0571
0572
0573 class EventOfCombCandidates {
0574 public:
0575 EventOfCombCandidates(int size = 0) : m_cc_pool(), m_candidates() {}
0576
0577 void releaseMemory() {
0578 {
0579 std::vector<CombCandidate> tmp;
0580 m_candidates.swap(tmp);
0581 }
0582 m_capacity = 0;
0583 m_size = 0;
0584 m_n_seeds_inserted = 0;
0585 m_cc_pool.release();
0586 }
0587
0588 void reset(int new_capacity, int max_cands_per_seed, int expected_num_hots = 128) {
0589 m_cc_pool.reset(new_capacity * max_cands_per_seed);
0590 if (new_capacity > m_capacity) {
0591 CcAlloc<TrackCand> alloc(&m_cc_pool);
0592 std::vector<CombCandidate> tmp(new_capacity, alloc);
0593 m_candidates.swap(tmp);
0594 m_capacity = new_capacity;
0595 }
0596 for (int s = 0; s < new_capacity; ++s) {
0597 m_candidates[s].reset(max_cands_per_seed, expected_num_hots);
0598 }
0599 for (int s = new_capacity; s < m_capacity; ++s) {
0600 m_candidates[s].reset(0, 0);
0601 }
0602
0603 m_size = new_capacity;
0604 m_n_seeds_inserted = 0;
0605 }
0606
0607 void resizeAfterFiltering(int n_removed) {
0608 assert(n_removed <= m_size);
0609 m_size -= n_removed;
0610 m_n_seeds_inserted -= n_removed;
0611 }
0612
0613 void insertSeed(const Track& seed, int region, int pos) {
0614 assert(pos < m_size);
0615
0616 m_candidates[pos].importSeed(seed, region);
0617
0618 ++m_n_seeds_inserted;
0619 }
0620
0621 void compactifyHitStorageForBestCand(bool remove_seed_hits, int backward_fit_min_hits) {
0622 for (int i = 0; i < m_size; ++i)
0623 m_candidates[i].compactifyHitStorageForBestCand(remove_seed_hits, backward_fit_min_hits);
0624 }
0625
0626 void beginBkwSearch() {
0627 for (int i = 0; i < m_size; ++i)
0628 m_candidates[i].beginBkwSearch();
0629 }
0630 void endBkwSearch() {
0631 for (int i = 0; i < m_size; ++i)
0632 m_candidates[i].endBkwSearch();
0633 }
0634
0635
0636 int size() const { return m_size; }
0637
0638 const CombCandidate& operator[](int i) const { return m_candidates[i]; }
0639 CombCandidate& operator[](int i) { return m_candidates[i]; }
0640 CombCandidate& cand(int i) { return m_candidates[i]; }
0641
0642
0643 const std::vector<CombCandidate>& refCandidates() const { return m_candidates; }
0644 std::vector<CombCandidate>& refCandidates_nc() { return m_candidates; }
0645
0646 private:
0647 CcPool<TrackCand> m_cc_pool;
0648
0649 std::vector<CombCandidate> m_candidates;
0650
0651 int m_capacity = 0;
0652 int m_size = 0;
0653 int m_n_seeds_inserted = 0;
0654 };
0655
0656 }
0657
0658 #endif