CbmRoot
Loading...
Searching...
No Matches
CaTrackFinderWindow.cxx
Go to the documentation of this file.
1/* Copyright (C) 2009-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Valentina Akishina, Ivan Kisel, Sergey Gorbunov [committer], Igor Kulakov, Maksym Zyzak */
4
5/*
6 *=====================================================
7 *
8 * CBM Level 1 4D Reconstruction
9 *
10 * Authors: V.Akishina, I.Kisel, S.Gorbunov, I.Kulakov, M.Zyzak
11 * Documentation: V.Akishina
12 *
13 * e-mail : v.akishina@gsi.de
14 *
15 *=====================================================
16 *
17 * Finds tracks using the Cellular Automaton algorithm
18 *
19 */
20
21
22#include "CaTrackFinderWindow.h"
23
25#include "CaBranch.h"
26#include "CaFramework.h"
27#include "CaGrid.h"
28#include "CaGridEntry.h"
29#include "CaTrack.h"
31
32#include <algorithm>
33#include <cstdio>
34#include <fstream>
35#include <iostream>
36#include <list>
37#include <map>
38#include <sstream>
39
40// #include "CaToolsDebugger.h"
41
42namespace cbm::algo::ca
43{
44 // -------------------------------------------------------------------------------------------------------------------
46 ca::TrackingMonitorData& monitorData)
47 : fParameters(pars)
48 , fDefaultMass(mass)
49 , fTrackingMode(mode)
50 , frMonitorData(monitorData)
51 , fTrackExtender(pars, mass)
52 , fCloneMerger(pars, mass)
53 , fTrackFitter(pars, mass, mode)
54 {
55 }
56
57 // -------------------------------------------------------------------------------------------------------------------
59 WindowData& wData) const
60 {
61 dchi2 = 1.e20;
62
63 if (r.GetMHit() != l.GetRHit()) return false;
64 if (r.GetLHit() != l.GetMHit()) return false;
65
66 if (r.GetMSta() != l.GetRSta()) return false;
67 if (r.GetLSta() != l.GetMSta()) return false;
68
69 const fscal tripletLinkChi2 = wData.CurrentIteration()->GetTripletLinkChi2();
70 if (r.IsMomentumFitted()) {
71 assert(l.IsMomentumFitted());
72
73 fscal dqp = l.GetQp() - r.GetQp();
74 fscal Cqp = l.GetCqp() + r.GetCqp();
75
76 if (!std::isfinite(dqp)) return false;
77 if (!std::isfinite(Cqp)) return false;
78
79 if (dqp * dqp > tripletLinkChi2 * Cqp) {
80 return false; // bad neighbour // CHECKME why do we need recheck it?? (it really change result)
81 }
82 dchi2 = dqp * dqp / Cqp;
83 }
84 else {
85 fscal dtx = l.GetTx() - r.GetTx();
86 fscal Ctx = l.GetCtx() + r.GetCtx();
87
88 fscal dty = l.GetTy() - r.GetTy();
89 fscal Cty = l.GetCty() + r.GetCty();
90
91 // it shouldn't happen, but happens sometimes
92
93 if (!std::isfinite(dtx)) return false;
94 if (!std::isfinite(dty)) return false;
95 if (!std::isfinite(Ctx)) return false;
96 if (!std::isfinite(Cty)) return false;
97
98 if (dty * dty > tripletLinkChi2 * Cty) return false;
99 if (dtx * dtx > tripletLinkChi2 * Ctx) return false;
100
101 //dchi2 = 0.5f * (dtx * dtx / Ctx + dty * dty / Cty);
102 dchi2 = 0.;
103 }
104
105 if (!std::isfinite(dchi2)) return false;
106
107 return true;
108 }
109
110
111 // **************************************************************************************************
112 // * *
113 // * ------ CATrackFinder procedure ------ *
114 // * *
115 // **************************************************************************************************
116
117 // -------------------------------------------------------------------------------------------------------------------
119 {
120 // Init windows
122 ReadWindowData(input.GetHits(), wData);
124
125 // Init grids
127 PrepareGrid(input.GetHits(), wData);
129
130 // Run CA iterations
132 auto& caIterations = fParameters.GetCAIterations();
133 for (auto iter = caIterations.begin(); iter != caIterations.end(); ++iter) {
134
135 // ----- Prepare iteration
137 PrepareCAIteration(*iter, wData, iter == caIterations.begin());
139
140 // ----- Triplets construction -----
142 ConstructTriplets(wData);
144
145 // ----- Search for neighbouring triplets -----
147 SearchNeighbors(wData);
149
150 // ----- Collect track candidates and create tracks
152 CreateTracks(wData, *iter, std::get<2>(fTripletData));
154
155 // ----- Suppress strips of suppressed hits
157 for (unsigned int ih = 0; ih < wData.Hits().size(); ih++) {
158 if (wData.IsHitSuppressed(ih)) {
159 const ca::Hit& hit = wData.Hit(ih);
160 wData.IsHitKeyUsed(hit.FrontKey()) = 1;
161 wData.IsHitKeyUsed(hit.BackKey()) = 1;
162 }
163 }
165 } // ---- Loop over Track Finder iterations: END ----//
167
168 // Fit tracks
170 fTrackFitter.FitCaTracks(input, wData);
172
173 // Merge clones
175 fCloneMerger.Exec(input, wData);
177
178 // Fit tracks
180 fTrackFitter.FitCaTracks(input, wData);
182 }
183
184 // -------------------------------------------------------------------------------------------------------------------
186 {
187 int nHits = 0;
188 for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
189 wData.HitStartIndexOnStation(iS) = nHits;
190 wData.NofHitsOnStation(iS) = wData.TsHitIndices(iS).size();
191 nHits += wData.NofHitsOnStation(iS);
192 }
193 wData.HitStartIndexOnStation(fParameters.GetNstationsActive()) = nHits;
194 wData.ResetHitData(nHits);
195
196 for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
197 int iFstHit = wData.HitStartIndexOnStation(iS);
198 for (ca::HitIndex_t ih = 0; ih < wData.TsHitIndices(iS).size(); ++ih) {
199 ca::Hit h = hits[wData.TsHitIndex(iS, ih)];
200 h.SetId(wData.TsHitIndex(iS, ih));
201 wData.Hit(iFstHit + ih) = h;
202 }
203 }
204
205 if constexpr (fDebug) {
206 LOG(info) << "===== Sliding Window hits: ";
207 for (int i = 0; i < nHits; ++i) {
208 LOG(info) << " " << wData.Hit(i).ToString();
209 }
210 LOG(info) << "===== ";
211 }
212
213 wData.RecoTracks().clear();
214 wData.RecoTracks().reserve(2 * nHits / fParameters.GetNstationsActive());
215
216 wData.RecoHitIndices().clear();
217 wData.RecoHitIndices().reserve(2 * nHits);
218 }
219
220 // -------------------------------------------------------------------------------------------------------------------
222 {
223 for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
224
225 fscal lasttime = std::numeric_limits<fscal>::infinity();
226 fscal starttime = -std::numeric_limits<fscal>::infinity();
227 fscal gridMinX = -0.1;
228 fscal gridMaxX = 0.1;
229 fscal gridMinY = -0.1;
230 fscal gridMaxY = 0.1;
231
232 for (ca::HitIndex_t ih = 0; ih < wData.TsHitIndices(iS).size(); ++ih) {
233 const ca::Hit& h = hits[wData.TsHitIndex(iS, ih)];
234
235 gridMinX = std::min(gridMinX, h.X());
236 gridMinY = std::min(gridMinY, h.Y());
237 gridMaxX = std::max(gridMaxX, h.X());
238 gridMaxY = std::max(gridMaxY, h.Y());
239
240 const fscal time = h.T();
241 assert(std::isfinite(time));
242 lasttime = std::min(lasttime, time);
243 starttime = std::max(starttime, time);
244 }
245
246 // TODO: changing the grid also changes the result. Investigate why it happens.
247 // TODO: find the optimal grid size
248
249 const int nSliceHits = wData.TsHitIndices(iS).size();
250 const fscal sizeY = gridMaxY - gridMinY;
251 const fscal sizeX = gridMaxX - gridMinX;
252 const int nBins2D = 1 + nSliceHits;
253
254 // TODO: SG: the coefficients should be removed
255 const fscal scale = fParameters.GetStation(iS).GetZ<fscal>() - fParameters.GetTargetPositionZ()[0];
256 const fscal maxScale = 0.3 * scale;
257 const fscal minScale = 0.01 * scale;
258
259 fscal yStep = 0.3 * sizeY / sqrt(nBins2D);
260 fscal xStep = 0.8 * sizeX / sqrt(nBins2D);
261 yStep = std::clamp(yStep, minScale, maxScale);
262 xStep = std::clamp(xStep, minScale, maxScale);
263
264 auto& grid = wData.Grid(iS);
265 grid.BuildBins(gridMinX, gridMaxX, gridMinY, gridMaxY, xStep, yStep);
266 /* clang-format off */
267 grid.StoreHits(wData.Hits(),
268 wData.HitStartIndexOnStation(iS),
269 wData.NofHitsOnStation(iS),
270 wData.HitKeyFlags());
271 /* clang-format on */
272 }
273 }
274
275 // -------------------------------------------------------------------------------------------------------------------
276 void TrackFinderWindow::PrepareCAIteration(const ca::Iteration& caIteration, WindowData& wData, const bool isFirst)
277 {
278 wData.SetCurrentIteration(&caIteration);
279
280 // Check if it is not the first element
281 if (!isFirst) {
282 for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
283 wData.Grid(ista).RemoveUsedHits(wData.Hits(), wData.HitKeyFlags());
284 }
285 }
286
287 // --> frAlgo.fIsWindowHitSuppressed.reset(frAlgo.fWindowHits.size(), 0);
288 wData.ResetHitSuppressionFlags(); // TODO: ??? No effect?
289
290 // --- SET PARAMETERS FOR THE ITERATION ---
291 // define the target
292 const fscal SigmaTargetX = caIteration.GetTargetPosSigmaX();
293 const fscal SigmaTargetY = caIteration.GetTargetPosSigmaY(); // target constraint [cm]
294
295 // Select magnetic field. For primary tracks - fVtxFieldValue, for secondary tracks - st.fieldSlice
296 if (caIteration.GetPrimaryFlag()) {
297 wData.TargB() = fParameters.GetVertexFieldValue();
298 }
299 else {
300 wData.TargB() = fParameters.GetStation(0).fieldSlice.GetFieldValue(0, 0);
301 } // NOTE: calculates field frAlgo.fTargB in the center of 0th station
302
303 wData.TargetMeasurement().SetX(fParameters.GetTargetPositionX());
304 wData.TargetMeasurement().SetY(fParameters.GetTargetPositionY());
305 wData.TargetMeasurement().SetDx2(SigmaTargetX * SigmaTargetX);
306 wData.TargetMeasurement().SetDxy(0);
307 wData.TargetMeasurement().SetDy2(SigmaTargetY * SigmaTargetY);
308 wData.TargetMeasurement().SetNdfX(1);
309 wData.TargetMeasurement().SetNdfY(1);
310 }
311
312 // -------------------------------------------------------------------------------------------------------------------
314 {
315 auto& [vHitFirstTriplet, vHitNofTriplets, vTriplets] = fTripletData;
316 vHitFirstTriplet.reset(wData.Hits().size(), 0);
317 vHitNofTriplets.reset(wData.Hits().size(), 0);
318
320
321 // prepare triplet storage
322 for (int j = 0; j < fParameters.GetNstationsActive(); j++) {
323 const size_t nHitsStation = wData.TsHitIndices(j).size();
324 vTriplets[j].clear();
325 vTriplets[j].reserve(2 * nHitsStation);
326 }
327
328 // indices of the two neighbouring station, taking into account allowed gaps
329 std::vector<std::pair<int, int>> staPattern;
330 for (int gap = 0; gap <= wData.CurrentIteration()->GetMaxStationGap(); gap++) {
331 for (int i = 0; i <= gap; i++) {
332 staPattern.push_back(std::make_pair(1 + i, 2 + gap));
333 }
334 }
335
336 for (int istal = fParameters.GetNstationsActive() - 2; istal >= wData.CurrentIteration()->GetFirstStationIndex();
337 istal--) {
338 // start with downstream chambers
339 const auto& grid = wData.Grid(istal);
340 for (auto& entry : grid.GetEntries()) {
341 ca::HitIndex_t ihitl = entry.GetObjectId();
342 const size_t oldSize = vTriplets[istal].size();
343 for (auto& pattern : staPattern) {
344 constructor.CreateTripletsForHit(fvTriplets, istal, istal + pattern.first, istal + pattern.second, ihitl);
345 vTriplets[istal].insert(vTriplets[istal].end(), fvTriplets.begin(), fvTriplets.end());
346 }
347 vHitFirstTriplet[ihitl] = PackTripletId(istal, oldSize);
348 vHitNofTriplets[ihitl] = vTriplets[istal].size() - oldSize;
349 }
350 } // istal
351 }
352
353 // -------------------------------------------------------------------------------------------------------------------
355 {
356 auto& [vHitFirstTriplet, vHitNofTriplets, vTriplets] = fTripletData;
357
358 for (int istal = fParameters.GetNstationsActive() - 2; istal >= wData.CurrentIteration()->GetFirstStationIndex();
359 istal--) {
360 // start with downstream chambers
361
362 for (ca::Triplet& tr : vTriplets[istal]) {
363 unsigned int nNeighbours = vHitNofTriplets[tr.GetMHit()];
364 unsigned int neighLocation = vHitFirstTriplet[tr.GetMHit()];
365 unsigned int neighStation = TripletId2Station(neighLocation);
366 unsigned int neighTriplet = TripletId2Triplet(neighLocation);
367
368 if (nNeighbours > 0) {
369 assert((int) neighStation >= istal + 1
370 && (int) neighStation <= istal + 1 + wData.CurrentIteration()->GetMaxStationGap());
371 }
372
373 unsigned char level = 0;
374
375 for (unsigned int iN = 0; iN < nNeighbours; ++iN, ++neighTriplet, ++neighLocation) {
376
377 ca::Triplet& neighbour = vTriplets[neighStation][neighTriplet];
378
379 fscal dchi2 = 0.;
380 if (!checkTripletMatch(tr, neighbour, dchi2, wData)) continue;
381
382 if (tr.GetFNeighbour() == 0) {
383 tr.SetFNeighbour(neighLocation);
384 }
385 tr.SetNNeighbours(neighLocation - tr.GetFNeighbour() + 1);
386
387 level = std::max(level, static_cast<unsigned char>(neighbour.GetLevel() + 1));
388 }
389 tr.SetLevel(level);
390 }
392 }
393 }
394
395 // -------------------------------------------------------------------------------------------------------------------
396 void TrackFinderWindow::CreateTracks(WindowData& wData, const ca::Iteration& caIteration, TripletArray_t& vTriplets)
397 {
398 // min level to start triplet. So min track length = min_level+3.
399 const int min_level = wData.CurrentIteration()->GetTrackFromTripletsFlag()
400 ? 0
401 : std::min(caIteration.GetMinNhits(), caIteration.GetMinNhitsStation0()) - 3;
402
403 // collect consequtive: the longest tracks, shorter, more shorter and so on
404 for (int firstTripletLevel = fParameters.GetNstationsActive() - 3; firstTripletLevel >= min_level;
405 firstTripletLevel--) {
406 // choose length in triplets number - firstTripletLevel - the maximum possible triplet level among all triplets in the searched candidate
407 CreateTrackCandidates(wData, vTriplets, min_level, firstTripletLevel);
408 DoCompetitionLoop(wData);
409 SelectTracks(wData);
410 }
411 }
412
413 // -------------------------------------------------------------------------------------------------------------------
414 void TrackFinderWindow::CreateTrackCandidates(WindowData& wData, TripletArray_t& vTriplets, const int min_level,
415 const int firstTripletLevel)
416 {
417 // how many levels to check
418 int nlevel = (fParameters.GetNstationsActive() - 2) - firstTripletLevel + 1;
419
420 const unsigned char min_best_l =
421 (firstTripletLevel > min_level) ? firstTripletLevel + 2 : min_level + 3; // loose maximum
422
423 // Uses persistent field to save memory allocations.
424 // fNewTr is only used here!
426
427 fvTrackCandidates.clear();
428 fvTrackCandidates.reserve(wData.Hits().size() / 10);
429
430 for (const auto& h : wData.Hits()) {
431 fvHitKeyToTrack[h.FrontKey()] = -1;
432 fvHitKeyToTrack[h.BackKey()] = -1;
433 }
434
435 //== Loop over triplets with the required level, find and store track candidates
436 for (int istaF = wData.CurrentIteration()->GetFirstStationIndex();
437 istaF <= fParameters.GetNstationsActive() - 3 - firstTripletLevel; ++istaF) {
438
439 if (--nlevel == 0) break; //TODO: SG: this is not needed
440
441 for (ca::Triplet& first_trip : vTriplets[istaF]) {
442
443 const auto& fstTripLHit = wData.Hit(first_trip.GetLHit());
444 if (wData.IsHitKeyUsed(fstTripLHit.FrontKey()) || wData.IsHitKeyUsed(fstTripLHit.BackKey())) {
445 continue;
446 }
447
448 // skip track candidates that are too short
449
450 int minNhits = wData.CurrentIteration()->GetMinNhits();
451
452 if (fstTripLHit.Station() == 0) {
453 minNhits = wData.CurrentIteration()->GetMinNhitsStation0();
454 }
456 minNhits = 0;
457 }
458
459 if (3 + first_trip.GetLevel() < minNhits) {
460 continue;
461 }
462
463 // Collect triplets, which can start a track with length equal to firstTipletLevel + 3. This cut suppresses
464 // ghost tracks, but does not affect the efficiency
465 if (first_trip.GetLevel() < firstTripletLevel) {
466 continue;
467 }
468
469 ca::Branch curr_tr;
470 curr_tr.AddHit(first_trip.GetLHit());
471 curr_tr.SetChi2(first_trip.GetChi2());
472
473 ca::Branch best_tr = curr_tr;
474
476 CAFindTrack(istaF, best_tr, &first_trip, curr_tr, min_best_l, new_tr, wData, vTriplets);
477
478 if (best_tr.NofHits() < firstTripletLevel + 2) continue; // loose maximum one hit
479
480 if (best_tr.NofHits() < min_level + 3) continue; // should find all hits for min_level
481
482 if (best_tr.NofHits() < minNhits) {
483 continue;
484 }
485
486 int ndf = best_tr.NofHits() * 2 - 5;
487
488 // TODO: automatize the NDF calculation
489
491 ndf = best_tr.NofHits() * 2 - 4;
492 }
493
494 best_tr.SetChi2(best_tr.Chi2() / ndf);
495 if (fParameters.GetGhostSuppression()) {
496 if (3 == best_tr.NofHits()) {
497 if (!wData.CurrentIteration()->GetPrimaryFlag() && (istaF != 0)) continue; // too /*short*/ non-MAPS track
498 if (wData.CurrentIteration()->GetPrimaryFlag() && (best_tr.Chi2() > 5.0)) continue;
499 }
500 }
501 fvTrackCandidates.push_back(best_tr);
502 ca::Branch& tr = fvTrackCandidates.back();
503 tr.SetStation(istaF);
504 tr.SetId(fvTrackCandidates.size() - 1);
505 // Mark the candidate as dead. To became alive it should first pass the competition in DoCompetitionLoop
506 tr.SetAlive(false);
507 if constexpr (fDebug) {
508 std::stringstream s;
509 s << "iter " << wData.CurrentIteration()->GetName() << ", track candidate " << fvTrackCandidates.size() - 1
510 << " found, L = " << best_tr.NofHits() << " chi2= " << best_tr.Chi2() << " hits: ";
511 for (auto hitIdLoc : tr.Hits()) {
512 const auto hitId = wData.Hit(hitIdLoc).Id();
513 s << hitId << " (mc " << ca::Framework::GetMcTrackIdForCaHit(hitId) << ") ";
514 }
515 LOG(info) << s.str();
516 }
517 } // itrip
518 } // istaF
519 }
520
521 // -------------------------------------------------------------------------------------------------------------------
523 {
524
525 // look at the dead track candidates in fvTrackCandidates pool; select the best ones and make them alive
526
527 for (int iComp = 0; (iComp < 100); ++iComp) {
528
529 bool repeatCompetition = false;
530
531 // == Loop over track candidates and mark their strips
532 for (ca::Branch& tr : fvTrackCandidates) {
533 if (tr.IsAlive()) {
534 continue;
535 }
536 for (auto& hitId : tr.Hits()) {
537
538 auto updateStrip = [&](int& strip) {
539 if ((strip >= 0) && (strip != tr.Id())) { // strip is used by other candidate
540 const auto& other = fvTrackCandidates[strip];
541 if (!other.IsAlive() && tr.IsBetterThan(other)) {
542 strip = tr.Id();
543 }
544 else {
545 return false;
546 }
547 }
548 else {
549 strip = tr.Id();
550 }
551 return true;
552 };
553
554 const ca::Hit& h = wData.Hit(hitId);
555 if (!updateStrip(fvHitKeyToTrack[h.FrontKey()])) { // front strip
556 break;
557 }
558 if (!updateStrip(fvHitKeyToTrack[h.BackKey()])) { // back strip
559 break;
560 }
561 } // loop over hits
562 } // itrack
563
564 // == Check if some suppressed candidates are still alive
565
566 for (ca::Branch& tr : fvTrackCandidates) {
567 if (tr.IsAlive()) {
568 continue;
569 }
570
571 tr.SetAlive(true);
572 for (const auto& hitIndex : tr.Hits()) {
573 if (!tr.IsAlive()) break;
574 const ca::Hit& h = wData.Hit(hitIndex);
575 tr.SetAlive((fvHitKeyToTrack[h.FrontKey()] == tr.Id()) && (fvHitKeyToTrack[h.BackKey()] == tr.Id()));
576 }
577
578 if (!tr.IsAlive()) { // release strips
579 for (auto hitId : tr.Hits()) {
580 const ca::Hit& h = wData.Hit(hitId);
581 if (fvHitKeyToTrack[h.FrontKey()] == tr.Id()) {
582 fvHitKeyToTrack[h.FrontKey()] = -1;
583 }
584 if (fvHitKeyToTrack[h.BackKey()] == tr.Id()) {
585 fvHitKeyToTrack[h.BackKey()] = -1;
586 }
587 }
588 }
589 else {
590 repeatCompetition = true;
591 }
592 } // itrack
593
594 if (!repeatCompetition) break;
595 } // competitions
596 }
597
598 // -------------------------------------------------------------------------------------------------------------------
600 {
601 for (Tindex iCandidate = 0; iCandidate < (Tindex) fvTrackCandidates.size(); ++iCandidate) {
602 ca::Branch& tr = fvTrackCandidates[iCandidate];
603
604 if constexpr (fDebug) {
605 LOG(info) << "iter " << wData.CurrentIteration()->GetName() << ", track candidate " << iCandidate
606 << ": alive = " << tr.IsAlive();
607 }
608 if (!tr.IsAlive()) continue;
609
610 if (wData.CurrentIteration()->GetExtendTracksFlag()) {
611 if (tr.NofHits() < fParameters.GetNstationsActive()) {
612 fTrackExtender.ExtendBranch(tr, wData);
613 }
614 }
615
616 for (auto iHit : tr.Hits()) {
617 const ca::Hit& hit = wData.Hit(iHit);
619 wData.IsHitKeyUsed(hit.FrontKey()) = 1;
620 wData.IsHitKeyUsed(hit.BackKey()) = 1;
621 wData.RecoHitIndices().push_back(hit.Id());
622 }
623 Track t;
624 t.fNofHits = tr.NofHits();
625 wData.RecoTracks().push_back(t);
626 if (0) { // SG debug
627 std::stringstream s;
628 s << "store track " << iCandidate << " chi2= " << tr.Chi2() << "\n";
629 s << " hits: ";
630 for (auto hitLoc : tr.Hits()) {
631 auto hitId = wData.Hit(hitLoc).Id();
632 s << ca::Framework::GetMcTrackIdForCaHit(hitId) << " ";
633 }
634 LOG(info) << s.str();
635 }
636 } // tracks
637 }
638
648 // -------------------------------------------------------------------------------------------------------------------
649 void TrackFinderWindow::CAFindTrack(int ista, ca::Branch& best_tr, const ca::Triplet* curr_trip, ca::Branch& curr_tr,
650 unsigned char min_best_l, ca::Branch* new_tr, WindowData& wData,
651 TripletArray_t& vTriplets)
655 {
656
657 if (curr_trip->GetLevel() == 0) // the end of the track -> check and store
658 {
659 // -- finish with current track
660 // add rest of hits
661 const auto& hitM = wData.Hit(curr_trip->GetMHit());
662 const auto& hitR = wData.Hit(curr_trip->GetRHit());
663
664 if (!(wData.IsHitKeyUsed(hitM.FrontKey()) || wData.IsHitKeyUsed(hitM.BackKey()))) {
665 curr_tr.AddHit(curr_trip->GetMHit());
666 }
667 if (!(wData.IsHitKeyUsed(hitR.FrontKey()) || wData.IsHitKeyUsed(hitR.BackKey()))) {
668 curr_tr.AddHit(curr_trip->GetRHit());
669 }
670
671 //if( curr_tr.NofHits() < min_best_l - 1 ) return; // suppouse that only one hit can be added by extender
672 // TODO: SZh 21.08.2023: Replace hard-coded value with a parameter
673 int ndf = curr_tr.NofHits() * 2 - 5;
674
676 ndf = curr_tr.NofHits() * 2 - 4;
677 }
678 if (curr_tr.Chi2() > wData.CurrentIteration()->GetTrackChi2Cut() * ndf) {
679 return;
680 }
681
682 // -- select the best
683 if ((curr_tr.NofHits() > best_tr.NofHits())
684 || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
685 best_tr = curr_tr;
686 }
687 return;
688 }
689 else //MEANS level ! = 0
690 {
691 int N_neighbour = (curr_trip->GetNNeighbours());
692
693 for (Tindex in = 0; in < N_neighbour; in++) {
694
695 unsigned int ID = curr_trip->GetFNeighbour() + in;
696 unsigned int Station = TripletId2Station(ID);
697 unsigned int Triplet = TripletId2Triplet(ID);
698
699 const ca::Triplet& new_trip = vTriplets[Station][Triplet];
700
701 fscal dchi2 = 0.;
702 if (!checkTripletMatch(*curr_trip, new_trip, dchi2, wData)) continue;
703
704 const auto& hitL = wData.Hit(new_trip.GetLHit()); // left hit of new triplet
705 if (wData.IsHitKeyUsed(hitL.FrontKey()) || wData.IsHitKeyUsed(hitL.BackKey())) { //hits are used
706 // no used hits allowed -> compare and store track
707 if ((curr_tr.NofHits() > best_tr.NofHits())
708 || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
709 best_tr = curr_tr;
710 }
711 }
712 else { // hit is not used: add the left hit from the new triplet to the current track
713
714 unsigned char new_L = curr_tr.NofHits() + 1;
715 fscal new_chi2 = curr_tr.Chi2() + dchi2;
716
717 if constexpr (0) { //SGtrd2d debug!!
718 int mc01 = ca::Framework::GetMcTrackIdForWindowHit(curr_trip->GetLHit());
719 int mc02 = ca::Framework::GetMcTrackIdForWindowHit(curr_trip->GetMHit());
720 int mc03 = ca::Framework::GetMcTrackIdForWindowHit(curr_trip->GetRHit());
724
725 if ((mc01 == mc02) && (mc02 == mc03)) {
726 LOG(info) << " sta " << ista << " mc0 " << mc01 << " " << mc02 << " " << mc03 << " mc1 " << mc11 << " "
727 << mc12 << " " << mc13 << " chi2 " << curr_tr.Chi2() / (2 * (curr_tr.NofHits() + 2) - 4)
728 << " new " << new_chi2 / (2 * (new_L + 2) - 4);
729 LOG(info) << " hits " << curr_trip->GetLHit() << " " << curr_trip->GetMHit() << " "
730 << curr_trip->GetRHit() << " " << new_trip.GetLHit();
731 }
732 }
733
734 int ndf = 2 * (new_L + 2) - 5;
735
736 if (ca::TrackingMode::kGlobal == fTrackingMode) { //SGtrd2d!!!
737 ndf = 2 * (new_L + 2) - 4;
738 }
740 ndf = 2 * (new_L + 2) - 4;
741 }
742 else {
743 ndf = new_L; // TODO: SG: 2 * (new_L + 2) - 5
744 }
745
746 if (new_chi2 > wData.CurrentIteration()->GetTrackChi2Cut() * ndf) continue;
747
748 // add new hit
749 new_tr[ista] = curr_tr;
750 new_tr[ista].AddHit(new_trip.GetLHit());
751
752 const int new_ista = ista + new_trip.GetMSta() - new_trip.GetLSta();
753 new_tr[ista].SetChi2(new_chi2);
754
755 CAFindTrack(new_ista, best_tr, &new_trip, new_tr[ista], min_best_l, new_tr, wData, vTriplets);
756 } // add triplet to track
757 } // for neighbours
758 } // level = 0
759 }
760
761} // namespace cbm::algo::ca
A class to store hit information in a backet-sorted way on 2D grid.
A class wrapper over clones merger algorithm for the CA track finder (declaration)
source file for the ca::Track class
Triplet constructor for the CA tracker.
static vector< vector< QAHit > > hits
friend fvec sqrt(const fvec &a)
static constexpr size_t size()
Definition KfSimdPseudo.h:2
Data class with information on a STS local track.
fscal Chi2() const
Definition CaBranch.h:36
void AddHit(ca::HitIndex_t hitIndex)
Definition CaBranch.h:31
void SetId(int Id)
Definition CaBranch.h:28
void SetStation(int iStation)
Definition CaBranch.h:26
const Vector< ca::HitIndex_t > & Hits() const
Definition CaBranch.h:39
void SetAlive(bool isAlive)
Definition CaBranch.h:29
void SetChi2(fscal chi2)
Definition CaBranch.h:27
int NofHits() const
Definition CaBranch.h:34
bool IsAlive() const
Definition CaBranch.h:38
void Exec(const ca::InputData &input, WindowData &wData)
Registers.
static int GetMcTrackIdForCaHit(int iHit)
Gets number of stations before the pipe (MVD stations in CBM)
static int GetMcTrackIdForWindowHit(int iGridHit)
Get mc track ID for a hit (debug tool)
void RemoveUsedHits(const ca::Vector< ca::Hit > &hits, const ca::Vector< unsigned char > &hitKeyFlags)
Remove grid entries that correspond to the used hits.
Definition CaGrid.cxx:96
void BuildBins(fscal xMin, fscal xMax, fscal yMin, fscal yMax, fscal binWidthX, fscal binWidthY)
Build the grid.
Definition CaGrid.cxx:19
ca::Hit class describes a generic hit for the CA tracker
Definition CaHit.h:32
HitKeyIndex_t BackKey() const
Get the back key index.
Definition CaHit.h:99
std::string ToString() const
Simple string representation of the hit class.
Definition CaHit.cxx:17
HitKeyIndex_t FrontKey() const
Get the front key index.
Definition CaHit.h:96
HitIndex_t Id() const
Get the hit id.
Definition CaHit.h:135
const Vector< Hit > & GetHits() const
Gets reference to hits vector.
Definition CaInputData.h:58
A set of parameters for the CA Track finder iteration.
int GetMinNhits() const
Gets min n hits.
Definition CaIteration.h:88
float GetTrackChi2Cut() const
Gets track chi2 upper cut.
int GetMaxStationGap() const
Gets flag: true - triplets are also built with skipping <= GetMaxStationGap stations.
Definition CaIteration.h:73
int GetMinNhitsStation0() const
Gets min n hits for tracks that start on station 0.
Definition CaIteration.h:91
float GetTargetPosSigmaX() const
Gets sigma target position in X direction [cm].
bool GetTrackFromTripletsFlag() const
float GetTripletLinkChi2() const
Gets min value of dp/dp_error, for which two tiplets are neighbours.
bool GetPrimaryFlag() const
Checks flag: true - only primary tracks are searched, false - [all or only secondary?...
const std::string & GetName() const
Gets the name of the iteration.
Definition CaIteration.h:94
float GetTargetPosSigmaY() const
Gets sigma target position in Y direction [cm].
int GetFirstStationIndex() const
Gets station index of the first station used in tracking.
Definition CaIteration.h:70
bool GetExtendTracksFlag() const
Sets flag: true - extends track candidates with unused hits.
Definition CaIteration.h:67
void StopTimer(ETimerKey key)
Stops timer.
void IncrementCounter(ECounterKey key)
Increments key counter by 1.
void StartTimer(ETimerKey key)
Starts timer.
A container for all external parameters of the CA tracking algorithm.
fscal ExtendBranch(ca::Branch &t, WindowData &wData)
Try to extrapolate and find additional hits on other stations.
TrackExtender fTrackExtender
Object of the track extender algorithm.
void CreateTracks(WindowData &wData, const ca::Iteration &caIteration, TripletArray_t &vTriplets)
TrackFitter fTrackFitter
Object of the track extender algorithm.
CloneMerger fCloneMerger
Object of the clone merger algorithm.
void CAFindTrack(int ista, ca::Branch &best_tr, const ca::Triplet *curr_trip, ca::Branch &curr_tr, unsigned char min_best_l, ca::Branch *new_tr, WindowData &wData, TripletArray_t &vTriplets)
void CreateTrackCandidates(WindowData &wData, TripletArray_t &vTriplets, const int min_level, const int firstTripletLevel)
ca::Branch fNewTr[constants::size::MaxNstations]
const Parameters< fvec > & fParameters
Object of Framework parameters class.
static unsigned int TripletId2Triplet(unsigned int id)
void DoCompetitionLoop(const WindowData &wData)
std::array< Vector< ca::Triplet >, constants::size::MaxNstations > TripletArray_t
fscal fDefaultMass
mass of the propagated particle [GeV/c2]
TrackFinderWindow(const ca::Parameters< fvec > &pars, const fscal mass, const ca::TrackingMode &mode, ca::TrackingMonitorData &monitorData)
Default constructor.
void ConstructTriplets(WindowData &wData)
void PrepareGrid(const Vector< Hit > &hits, WindowData &wData)
bool checkTripletMatch(const ca::Triplet &l, const ca::Triplet &r, fscal &dchi2, WindowData &wData) const
static unsigned int PackTripletId(unsigned int iStation, unsigned int iTriplet)
void CaTrackFinderSlice(const ca::InputData &input, WindowData &wData)
void PrepareCAIteration(const ca::Iteration &caIteration, WindowData &wData, const bool isFirst)
TrackingMonitorData & frMonitorData
Reference to monitor data.
void ReadWindowData(const Vector< Hit > &hits, WindowData &wData)
static unsigned int TripletId2Station(unsigned int id)
void FitCaTracks(const ca::InputData &input, WindowData &wData)
Fit tracks, found by the CA tracker.
Class representing an output track in the CA tracking algorithm.
int fNofHits
Number of hits in track.
Definition CaTrack.h:44
void CreateTripletsForHit(Vector< ca::Triplet > &tripletsOut, int istal, int istam, int istar, ca::HitIndex_t ihl)
---— FUNCTIONAL PART ---—
Triplet class represents a short 3-hits track segment called a "triplet".
Definition CaTriplet.h:22
fscal GetTx() const
Definition CaTriplet.h:73
fscal GetQp() const
Definition CaTriplet.h:64
bool IsMomentumFitted() const
Definition CaTriplet.h:78
int GetMSta() const
Definition CaTriplet.h:69
unsigned char GetLevel() const
Definition CaTriplet.h:52
fscal GetCty() const
Definition CaTriplet.h:76
ca::HitIndex_t GetRHit() const
Definition CaTriplet.h:56
ca::HitIndex_t GetMHit() const
Definition CaTriplet.h:55
ca::HitIndex_t GetLHit() const
Definition CaTriplet.h:54
fscal GetTy() const
Definition CaTriplet.h:75
unsigned int GetFNeighbour() const
Definition CaTriplet.h:62
int GetNNeighbours() const
Definition CaTriplet.h:59
fscal GetCqp() const
Definition CaTriplet.h:72
int GetLSta() const
Definition CaTriplet.h:68
fscal GetCtx() const
Definition CaTriplet.h:74
int GetRSta() const
Definition CaTriplet.h:70
void SetNNeighbours(int n)
Definition CaTriplet.h:58
void push_back(Tinput value)
Pushes back a value to the vector.
Definition CaVector.h:176
void reserve(std::size_t count)
Reserves a new size for the vector.
Definition CaVector.h:162
Container for internal data, processed on a single time window.
HitIndex_t & HitStartIndexOnStation(int iStation)
Index of the first hit on the station.
HitIndex_t & NofHitsOnStation(int iStation)
Number of hits on station.
Vector< Track > & RecoTracks()
Accesses reconstructed track container.
void ResetHitData(int nHits)
Resets hit data.
void ResetHitSuppressionFlags()
Reset suppressed hit flags.
ca::Grid & Grid(int iStation)
Gets grid for station index.
HitIndex_t TsHitIndex(int iSt, int iHit) const
Maps hit index from the time window to the time slice.
void SetCurrentIteration(const Iteration *ptr)
Accesses current iteration.
const Iteration * CurrentIteration() const
Accesses current iteration.
Vector< unsigned char > & HitKeyFlags()
Access to the hit key flags container.
kf::FieldValue< fvec > & TargB()
Accesses magnetic field in starting point (target or first station)
uint8_t IsHitSuppressed(int iHit) const
Gets hit suppression flag.
Vector< HitIndex_t > & TsHitIndices(int iSt)
Accesses container of hit index map from the time window to the time slice.
Vector< ca::Hit > & Hits()
Gets hit vector.
kf::MeasurementXy< fvec > & TargetMeasurement()
Measurement of the target with the uncertainty.
unsigned char IsHitKeyUsed(HitKeyIndex_t iKey) const
Hit key flag: if this hit or cluster was already used.
ca::Hit & Hit(int iHit)
Gets hit by index.
Vector< HitIndex_t > & RecoHitIndices()
Accesses indices of hits, used by reconstructed tracks.
constexpr int MaxNstations
Max number of stations, 2^6 = 64.
Definition CaDefs.h:44
TODO: SZh 8.11.2022: add selection of parameterisation.
Definition CaBranch.h:14
@ Triplet
number of triplets
kf::fscal fscal
Definition CaSimd.h:14
unsigned int HitIndex_t
Index of ca::Hit.
Definition CaHit.h:27
@ PrepareIteration
(iterations loop)