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"
32
33#include <algorithm>
34#include <cstdio>
35#include <fstream>
36#include <iostream>
37#include <list>
38#include <map>
39#include <sstream>
40
41// #include "CaToolsDebugger.h"
42
43namespace cbm::algo::ca
44{
45 // -------------------------------------------------------------------------------------------------------------------
47 const fscal mass, const ca::TrackingMode& mode,
48 ca::TrackingMonitorData& monitorData)
49 : fFramework(framework)
50 , fParameters(pars)
51 , fSetup(fParameters.GetActiveSetup())
52 , fField(fSetup.GetField())
53 , fDefaultMass(mass)
54 , fTrackingMode(mode)
55 , frMonitorData(monitorData)
56 , fTrackExtender(pars, mass)
57 , fCloneMerger(pars, mass)
58 , fTrackFitter(pars, mass, mode)
59 {
60 }
61
62 // -------------------------------------------------------------------------------------------------------------------
64 WindowData& wData) const
65 {
66 dchi2 = 1.e20;
67
68 if (r.GetMHit() != l.GetRHit()) return false;
69 if (r.GetLHit() != l.GetMHit()) return false;
70
71 if (r.GetMSta() != l.GetRSta()) return false;
72 if (r.GetLSta() != l.GetMSta()) return false;
73
74 const fscal tripletLinkChi2 = wData.CurrentIteration()->GetTripletLinkChi2();
75 if (r.IsMomentumFitted()) {
76 assert(l.IsMomentumFitted());
77
78 fscal dqp = l.GetQp() - r.GetQp();
79 fscal Cqp = l.GetCqp() + r.GetCqp();
80
81 if (!std::isfinite(dqp)) return false;
82 if (!std::isfinite(Cqp)) return false;
83
84 if (dqp * dqp > tripletLinkChi2 * Cqp) {
85 return false; // bad neighbour // CHECKME why do we need recheck it?? (it really change result)
86 }
87 dchi2 = dqp * dqp / Cqp;
88 }
89 else {
90 fscal dtx = l.GetTx() - r.GetTx();
91 fscal Ctx = l.GetCtx() + r.GetCtx();
92
93 fscal dty = l.GetTy() - r.GetTy();
94 fscal Cty = l.GetCty() + r.GetCty();
95
96 // it shouldn't happen, but happens sometimes
97
98 if (!std::isfinite(dtx)) return false;
99 if (!std::isfinite(dty)) return false;
100 if (!std::isfinite(Ctx)) return false;
101 if (!std::isfinite(Cty)) return false;
102
103 if (dty * dty > tripletLinkChi2 * Cty) return false;
104 if (dtx * dtx > tripletLinkChi2 * Ctx) return false;
105
106 //dchi2 = 0.5f * (dtx * dtx / Ctx + dty * dty / Cty);
107 dchi2 = 0.;
108 }
109
110 if (!std::isfinite(dchi2)) return false;
111
112 return true;
113 }
114
115
116 // **************************************************************************************************
117 // * *
118 // * ------ CATrackFinder procedure ------ *
119 // * *
120 // **************************************************************************************************
121
122 // -------------------------------------------------------------------------------------------------------------------
124 {
125 pwData = &wData;
126
127 // Init windows
129 ReadWindowData(input.GetHits(), wData);
131
132 // Init grids
134 PrepareGrid(input.GetHits(), wData);
136
137 // Run CA iterations
139 auto& caIterations = fParameters.GetCAIterations();
140 for (unsigned int iterInd = 0; iterInd < caIterations.size(); ++iterInd) {
141 auto& iter = caIterations[iterInd];
142
143 // ----- Prepare iteration
145 PrepareCAIteration(iterInd, iter, wData);
147
148 // ----- Triplets construction -----
150 ConstructTriplets(wData);
152
153 // ----- Search for neighbouring triplets -----
155 SearchNeighbors(wData);
157
158 // ----- Collect track candidates and create tracks
160 CreateTracks(wData, iter, std::get<2>(fTripletData));
162
163 // ----- Suppress strips of suppressed hits
165 for (unsigned int ih = 0; ih < wData.Hits().size(); ih++) {
166 if (wData.IsHitSuppressed(ih)) {
167 const ca::Hit& hit = wData.Hit(ih);
168 wData.IsHitKeyUsed(hit.FrontKey()) = 1;
169 wData.IsHitKeyUsed(hit.BackKey()) = 1;
170 }
171 }
173 } // ---- Loop over Track Finder iterations: END ----//
175
176 // Fit tracks
178 fTrackFitter.FitCaTracks(input, wData);
180
181 // Merge clones
183 fCloneMerger.Exec(input, wData);
185
186 // Fit tracks after the merge
187 if (!fParameters.GetConfig().DevUseParSearchWindows()) {
189 fTrackFitter.FitCaTracks(input, wData);
191 }
192 }
193
194 // -------------------------------------------------------------------------------------------------------------------
196 {
197 int nHits = 0;
198 for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
199 wData.HitStartIndexOnStation(iS) = nHits;
200 wData.NofHitsOnStation(iS) = wData.TsHitIndices(iS).size();
201 nHits += wData.NofHitsOnStation(iS);
202 }
203 wData.HitStartIndexOnStation(fParameters.GetNstationsActive()) = nHits;
204 wData.ResetHitData(nHits);
205
206 for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
207 int iFstHit = wData.HitStartIndexOnStation(iS);
208 for (ca::HitIndex_t ih = 0; ih < wData.TsHitIndices(iS).size(); ++ih) {
209 ca::Hit h = hits[wData.TsHitIndex(iS, ih)];
210 h.SetId(wData.TsHitIndex(iS, ih));
211 wData.Hit(iFstHit + ih) = h;
212 }
213 }
214
215 if constexpr (fDebug) {
216 LOG(info) << "===== Sliding Window hits: ";
217 for (int i = 0; i < nHits; ++i) {
218 LOG(info) << " " << wData.Hit(i).ToString();
219 }
220 LOG(info) << "===== ";
221 }
222
223 wData.RecoTracks().clear();
224 wData.RecoTracks().reserve(2 * nHits / fParameters.GetNstationsActive());
225
226 wData.RecoHitIndices().clear();
227 wData.RecoHitIndices().reserve(2 * nHits);
228 }
229
230 // -------------------------------------------------------------------------------------------------------------------
232 {
233 for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
234
235 fscal lasttime = std::numeric_limits<fscal>::infinity();
236 fscal starttime = -std::numeric_limits<fscal>::infinity();
237 fscal gridMinX = -0.1;
238 fscal gridMaxX = 0.1;
239 fscal gridMinY = -0.1;
240 fscal gridMaxY = 0.1;
241
242 for (ca::HitIndex_t ih = 0; ih < wData.TsHitIndices(iS).size(); ++ih) {
243 const ca::Hit& h = hits[wData.TsHitIndex(iS, ih)];
244
245 gridMinX = std::min(gridMinX, h.X());
246 gridMinY = std::min(gridMinY, h.Y());
247 gridMaxX = std::max(gridMaxX, h.X());
248 gridMaxY = std::max(gridMaxY, h.Y());
249
250 const fscal time = h.T();
251 assert(std::isfinite(time));
252 lasttime = std::min(lasttime, time);
253 starttime = std::max(starttime, time);
254 }
255
256 // TODO: changing the grid also changes the result. Investigate why it happens.
257 // TODO: find the optimal grid size
258
259 const int nSliceHits = wData.TsHitIndices(iS).size();
260 const fscal sizeY = gridMaxY - gridMinY;
261 const fscal sizeX = gridMaxX - gridMinX;
262 const int nBins2D = 1 + nSliceHits;
263
264 // TODO: SG: the coefficients should be removed
265 const fscal zRef = fParameters.GetActiveSetup().GetActiveLayer(iS).GetZref()[0];
266 const fscal scale = zRef - fSetup.GetTarget().GetZ()[0];
267 const fscal maxScale = 0.3 * scale;
268 const fscal minScale = 0.01 * scale;
269
270 fscal yStep = 0.3 * sizeY / sqrt(nBins2D);
271 fscal xStep = 0.8 * sizeX / sqrt(nBins2D);
272 yStep = std::clamp(yStep, minScale, maxScale);
273 xStep = std::clamp(xStep, minScale, maxScale);
274
275 auto& grid = wData.Grid(iS);
276 grid.BuildBins(gridMinX, gridMaxX, gridMinY, gridMaxY, xStep, yStep, zRef);
277 /* clang-format off */
278 grid.StoreHits(wData.Hits(),
279 wData.HitStartIndexOnStation(iS),
280 wData.NofHitsOnStation(iS),
281 wData.HitKeyFlags());
282 /* clang-format on */
283 }
284 }
285
286 // ---------------------------------------------------------------------------------------------------------------------
287 void TrackFinderWindow::PrepareCAIteration(int iterationIndex, const ca::Iteration& caIteration, WindowData& wData)
288 {
289 wData.SetCurrentIteration(iterationIndex, &caIteration);
290
291 // Check if it is not the first element
292 if (iterationIndex != 0) {
293 for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
294 wData.Grid(ista).RemoveUsedHits(wData.Hits(), wData.HitKeyFlags());
295 }
296 }
297
298 // --> frAlgo.fIsWindowHitSuppressed.reset(frAlgo.fWindowHits.size(), 0);
299 wData.ResetHitSuppressionFlags(); // TODO: ??? No effect?
300
301 // --- SET PARAMETERS FOR THE ITERATION ---
302 // define the target
303 const fscal SigmaTargetX = caIteration.GetTargetPosSigmaX();
304 const fscal SigmaTargetY = caIteration.GetTargetPosSigmaY(); // target constraint [cm]
305
306 // Select magnetic field. For primary tracks - fVtxFieldValue, for secondary tracks - st.fieldSlice
307 if (caIteration.GetPrimaryFlag()) {
308 const auto& trg = fSetup.GetTarget();
309 wData.TargB() = fField.GetPrimVertexField().Get(trg.GetX(), trg.GetY(), trg.GetZ());
310 }
311 else {
312 wData.TargB() = fField.GetFieldValue(0, 0., 0.);
313 } // NOTE: calculates field frAlgo.fTargB in the center of 0th station
314
315 wData.TargetMeasurement().SetX(fSetup.GetTarget().GetX());
316 wData.TargetMeasurement().SetY(fSetup.GetTarget().GetY());
317 wData.TargetMeasurement().SetDx2(SigmaTargetX * SigmaTargetX);
318 wData.TargetMeasurement().SetDxy(0);
319 wData.TargetMeasurement().SetDy2(SigmaTargetY * SigmaTargetY);
320 wData.TargetMeasurement().SetNdfX(1);
321 wData.TargetMeasurement().SetNdfY(1);
322 }
323
324 // -------------------------------------------------------------------------------------------------------------------
326 {
327 auto& [vHitFirstTriplet, vHitNofTriplets, vTriplets] = fTripletData;
328 vHitFirstTriplet.reset(wData.Hits().size(), 0);
329 vHitNofTriplets.reset(wData.Hits().size(), 0);
330
333
334 // prepare triplet storage
335 for (int j = 0; j < fParameters.GetNstationsActive(); j++) {
336 const size_t nHitsStation = wData.TsHitIndices(j).size();
337 vTriplets[j].clear();
338 vTriplets[j].reserve(2 * nHitsStation);
339 }
340
341 // indices of the two neighbouring station, taking into account allowed gaps
342 std::vector<std::pair<int, int>> staPattern;
343 for (int gap = 0; gap <= wData.CurrentIteration()->GetMaxStationGap(); gap++) {
344 for (int i = 0; i <= gap; i++) {
345 staPattern.push_back(std::make_pair(1 + i, 2 + gap));
346 }
347 }
348
349 for (int istal = fParameters.GetNstationsActive() - 2; istal >= wData.CurrentIteration()->GetFirstStationIndex();
350 istal--) {
351 // start with downstream chambers
352 const auto& grid = wData.Grid(istal);
353 for (auto& entry : grid.GetEntries()) {
354 ca::HitIndex_t ihitl = entry.GetObjectId();
355 const size_t oldSize = vTriplets[istal].size();
356 for (auto& pattern : staPattern) {
357 if (fParameters.GetConfig().DevUseParSearchWindows()) {
358 constructorSW.CreateTripletsForHit(fvTriplets, istal, istal + pattern.first, istal + pattern.second, ihitl);
359 }
360 else {
361 constructor.CreateTripletsForHit(fvTriplets, istal, istal + pattern.first, istal + pattern.second, ihitl);
362 }
363 vTriplets[istal].insert(vTriplets[istal].end(), fvTriplets.begin(), fvTriplets.end());
364 }
365 vHitFirstTriplet[ihitl] = PackTripletId(istal, oldSize);
366 vHitNofTriplets[ihitl] = vTriplets[istal].size() - oldSize;
367 }
368 } // istal
369 }
370
371 // -------------------------------------------------------------------------------------------------------------------
373 {
374 auto& [vHitFirstTriplet, vHitNofTriplets, vTriplets] = fTripletData;
375
376 for (int istal = fParameters.GetNstationsActive() - 2; istal >= wData.CurrentIteration()->GetFirstStationIndex();
377 istal--) {
378 // start with downstream chambers
379
380 for (ca::Triplet& tr : vTriplets[istal]) {
381 unsigned int nNeighbours = vHitNofTriplets[tr.GetMHit()];
382 unsigned int neighLocation = vHitFirstTriplet[tr.GetMHit()];
383 unsigned int neighStation = TripletId2Station(neighLocation);
384 unsigned int neighTriplet = TripletId2Triplet(neighLocation);
385
386 if (nNeighbours > 0) {
387 assert((int) neighStation >= istal + 1
388 && (int) neighStation <= istal + 1 + wData.CurrentIteration()->GetMaxStationGap());
389 }
390
391 unsigned char level = 0;
392
393 for (unsigned int iN = 0; iN < nNeighbours; ++iN, ++neighTriplet, ++neighLocation) {
394
395 ca::Triplet& neighbour = vTriplets[neighStation][neighTriplet];
396
397 fscal dchi2 = 0.;
398 if (!checkTripletMatch(tr, neighbour, dchi2, wData)) continue;
399
400 if (tr.GetFNeighbour() == 0) {
401 tr.SetFNeighbour(neighLocation);
402 }
403 tr.SetNNeighbours(neighLocation - tr.GetFNeighbour() + 1);
404
405 level = std::max(level, static_cast<unsigned char>(neighbour.GetLevel() + 1));
406 }
407 tr.SetLevel(level);
408 }
409 frMonitorData.IncrementCounter(ECounter::Triplet, vTriplets[istal].size());
410 }
411 }
412
413 // -------------------------------------------------------------------------------------------------------------------
414 void TrackFinderWindow::CreateTracks(WindowData& wData, const ca::Iteration& caIteration, TripletArray_t& vTriplets)
415 {
416 // min level to start triplet. So min track length = min_level+3.
417 const int min_level = wData.CurrentIteration()->GetTrackFromTripletsFlag()
418 ? 0
419 : std::min(caIteration.GetMinNhits(), caIteration.GetMinNhitsStation0()) - 3;
420
421 // collect consequtive: the longest tracks, shorter, more shorter and so on
422 for (int firstTripletLevel = fParameters.GetNstationsActive() - 3; firstTripletLevel >= min_level;
423 firstTripletLevel--) {
424 // choose length in triplets number - firstTripletLevel - the maximum possible triplet level among all triplets in the searched candidate
425 CreateTrackCandidates(wData, vTriplets, min_level, firstTripletLevel);
426 DoCompetitionLoop(wData);
427 SelectTracks(wData);
428 }
429 }
430
431 // -------------------------------------------------------------------------------------------------------------------
432 void TrackFinderWindow::CreateTrackCandidates(WindowData& wData, TripletArray_t& vTriplets, const int min_level,
433 const int firstTripletLevel)
434 {
435 // how many levels to check
436 int nlevel = (fParameters.GetNstationsActive() - 2) - firstTripletLevel + 1;
437
438 const unsigned char min_best_l =
439 (firstTripletLevel > min_level) ? firstTripletLevel + 2 : min_level + 3; // loose maximum
440
441 // Uses persistent field to save memory allocations.
442 // fNewTr is only used here!
444
445 fvTrackCandidates.clear();
446 fvTrackCandidates.reserve(wData.Hits().size() / 10);
447
448 for (const auto& h : wData.Hits()) {
449 fvHitKeyToTrack[h.FrontKey()] = -1;
450 fvHitKeyToTrack[h.BackKey()] = -1;
451 }
452
453 //== Loop over triplets with the required level, find and store track candidates
454 for (int istaF = wData.CurrentIteration()->GetFirstStationIndex();
455 istaF <= fParameters.GetNstationsActive() - 3 - firstTripletLevel; ++istaF) {
456
457 if (--nlevel == 0) break; //TODO: SG: this is not needed
458
459 for (ca::Triplet& first_trip : vTriplets[istaF]) {
460
461 const auto& fstTripLHit = wData.Hit(first_trip.GetLHit());
462 if (wData.IsHitKeyUsed(fstTripLHit.FrontKey()) || wData.IsHitKeyUsed(fstTripLHit.BackKey())) {
463 continue;
464 }
465
466 // skip track candidates that are too short
467
468 int minNhits = wData.CurrentIteration()->GetMinNhits();
469
470 if (fstTripLHit.Station() == 0) {
471 minNhits = wData.CurrentIteration()->GetMinNhitsStation0();
472 }
474 minNhits = 0;
475 }
476
477 if (3 + first_trip.GetLevel() < minNhits) {
478 continue;
479 }
480
481 // Collect triplets, which can start a track with length equal to firstTipletLevel + 3. This cut suppresses
482 // ghost tracks, but does not affect the efficiency
483 if (first_trip.GetLevel() < firstTripletLevel) {
484 continue;
485 }
486
487 ca::Branch curr_tr;
488 curr_tr.AddHit(first_trip.GetLHit());
489 curr_tr.SetChi2(first_trip.GetChi2());
490
491 ca::Branch best_tr = curr_tr;
492
494 CAFindTrack(istaF, best_tr, &first_trip, curr_tr, min_best_l, new_tr, wData, vTriplets);
495
496 if (best_tr.NofHits() < firstTripletLevel + 2) continue; // loose maximum one hit
497
498 if (best_tr.NofHits() < min_level + 3) continue; // should find all hits for min_level
499
500 if (best_tr.NofHits() < minNhits) {
501 continue;
502 }
503
504 int ndf = best_tr.NofHits() * 2 - 5;
505
506 // TODO: automatize the NDF calculation
507
509 ndf = best_tr.NofHits() * 2 - 4;
510 }
511
512 best_tr.SetChi2(best_tr.Chi2() / ndf);
513 if (fParameters.GetConfig().SuppressGhost()) {
514 if (3 == best_tr.NofHits()) {
515 if (!wData.CurrentIteration()->GetPrimaryFlag() && (istaF != 0)) continue; // too /*short*/ non-MAPS track
516 if (wData.CurrentIteration()->GetPrimaryFlag() && (best_tr.Chi2() > 5.0)) continue;
517 }
518 }
519 // NOTE: Temporarely disable the warnings, one has to provide more specific coefficient in the capacity
520 // reservation
521 fvTrackCandidates.push_back_no_warning(best_tr);
522 ca::Branch& tr = fvTrackCandidates.back();
523 tr.SetStation(istaF);
524 tr.SetId(fvTrackCandidates.size() - 1);
525 // Mark the candidate as dead. To became alive it should first pass the competition in DoCompetitionLoop
526 tr.SetAlive(false);
527 if constexpr (fDebug) {
528 std::stringstream s;
529 s << "iter " << wData.CurrentIteration()->GetName() << ", track candidate " << fvTrackCandidates.size() - 1
530 << " found, L = " << best_tr.NofHits() << " chi2= " << best_tr.Chi2() << " hits: ";
531 for (auto hitIdLoc : tr.Hits()) {
532 const auto hitId = wData.Hit(hitIdLoc).Id();
533 s << hitId << " (mc " << fFramework.GetBestMcTrackIdForCaHit(hitId) << ") ";
534 }
535 LOG(info) << s.str();
536 }
537 } // itrip
538 } // istaF
539 }
540
541 // -------------------------------------------------------------------------------------------------------------------
543 {
544
545 // look at the dead track candidates in fvTrackCandidates pool; select the best ones and make them alive
546
547 for (int iComp = 0; (iComp < 100); ++iComp) {
548
549 bool repeatCompetition = false;
550
551 // == Loop over track candidates and mark their strips
552 for (ca::Branch& tr : fvTrackCandidates) {
553 if (tr.IsAlive()) {
554 continue;
555 }
556 for (auto& hitId : tr.Hits()) {
557
558 auto updateStrip = [&](int& strip) {
559 if ((strip >= 0) && (strip != tr.Id())) { // strip is used by other candidate
560 const auto& other = fvTrackCandidates[strip];
561 if (!other.IsAlive() && tr.IsBetterThan(other)) {
562 strip = tr.Id();
563 }
564 else {
565 return false;
566 }
567 }
568 else {
569 strip = tr.Id();
570 }
571 return true;
572 };
573
574 const ca::Hit& h = wData.Hit(hitId);
575 if (!updateStrip(fvHitKeyToTrack[h.FrontKey()])) { // front strip
576 break;
577 }
578 if (!updateStrip(fvHitKeyToTrack[h.BackKey()])) { // back strip
579 break;
580 }
581 } // loop over hits
582 } // itrack
583
584 // == Check if some suppressed candidates are still alive
585
586 for (ca::Branch& tr : fvTrackCandidates) {
587 if (tr.IsAlive()) {
588 continue;
589 }
590
591 tr.SetAlive(true);
592 for (const auto& hitIndex : tr.Hits()) {
593 if (!tr.IsAlive()) break;
594 const ca::Hit& h = wData.Hit(hitIndex);
595 tr.SetAlive((fvHitKeyToTrack[h.FrontKey()] == tr.Id()) && (fvHitKeyToTrack[h.BackKey()] == tr.Id()));
596 }
597
598 if (!tr.IsAlive()) { // release strips
599 for (auto hitId : tr.Hits()) {
600 const ca::Hit& h = wData.Hit(hitId);
601 if (fvHitKeyToTrack[h.FrontKey()] == tr.Id()) {
602 fvHitKeyToTrack[h.FrontKey()] = -1;
603 }
604 if (fvHitKeyToTrack[h.BackKey()] == tr.Id()) {
605 fvHitKeyToTrack[h.BackKey()] = -1;
606 }
607 }
608 }
609 else {
610 repeatCompetition = true;
611 }
612 } // itrack
613
614 if (!repeatCompetition) break;
615 } // competitions
616 }
617
618 // -------------------------------------------------------------------------------------------------------------------
620 {
621 for (Tindex iCandidate = 0; iCandidate < (Tindex) fvTrackCandidates.size(); ++iCandidate) {
622 ca::Branch& tr = fvTrackCandidates[iCandidate];
623
624 if constexpr (fDebug) {
625 LOG(info) << "iter " << wData.CurrentIteration()->GetName() << ", track candidate " << iCandidate
626 << ": alive = " << tr.IsAlive();
627 }
628 if (!tr.IsAlive()) continue;
629
630 if (wData.CurrentIteration()->GetExtendTracksFlag()) {
631 if (tr.NofHits() < fParameters.GetNstationsActive()) {
632 fTrackExtender.ExtendBranch(tr, wData);
633 }
634 }
635
636 for (auto iHit : tr.Hits()) {
637 const ca::Hit& hit = wData.Hit(iHit);
639 wData.IsHitKeyUsed(hit.FrontKey()) = 1;
640 wData.IsHitKeyUsed(hit.BackKey()) = 1;
641 wData.RecoHitIndices().push_back(hit.Id());
642 }
643 Track t;
644 t.fNofHits = tr.NofHits();
645 wData.RecoTracks().push_back(t);
646 if (0) { // SG debug
647 std::stringstream s;
648 s << "store track " << iCandidate << " chi2= " << tr.Chi2() << "\n";
649 s << " hits: ";
650 for (auto hitLoc : tr.Hits()) {
651 auto hitId = wData.Hit(hitLoc).Id();
652 s << fFramework.GetBestMcTrackIdForCaHit(hitId) << " ";
653 }
654 LOG(info) << s.str();
655 }
656 } // tracks
657 }
658
667
668 // -------------------------------------------------------------------------------------------------------------------
669 void TrackFinderWindow::CAFindTrack(int ista, ca::Branch& best_tr, const ca::Triplet* curr_trip, ca::Branch& curr_tr,
670 unsigned char min_best_l, ca::Branch* new_tr, WindowData& wData,
671 TripletArray_t& vTriplets)
675 {
676
677 if (curr_trip->GetLevel() == 0) // the end of the track -> check and store
678 {
679 // -- finish with current track
680 // add rest of hits
681 const auto& hitM = wData.Hit(curr_trip->GetMHit());
682 const auto& hitR = wData.Hit(curr_trip->GetRHit());
683
684 if (!(wData.IsHitKeyUsed(hitM.FrontKey()) || wData.IsHitKeyUsed(hitM.BackKey()))) {
685 curr_tr.AddHit(curr_trip->GetMHit());
686 }
687 if (!(wData.IsHitKeyUsed(hitR.FrontKey()) || wData.IsHitKeyUsed(hitR.BackKey()))) {
688 curr_tr.AddHit(curr_trip->GetRHit());
689 }
690
691 //if( curr_tr.NofHits() < min_best_l - 1 ) return; // suppouse that only one hit can be added by extender
692 // TODO: SZh 21.08.2023: Replace hard-coded value with a parameter
693 int ndf = curr_tr.NofHits() * 2 - 5;
694
696 ndf = curr_tr.NofHits() * 2 - 4;
697 }
698 if (curr_tr.Chi2() > wData.CurrentIteration()->GetTrackChi2Cut() * ndf) {
699 return;
700 }
701
702 // -- select the best
703 if ((curr_tr.NofHits() > best_tr.NofHits())
704 || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
705 best_tr = curr_tr;
706 }
707 return;
708 }
709 else //MEANS level ! = 0
710 {
711 int N_neighbour = (curr_trip->GetNNeighbours());
712
713 for (Tindex in = 0; in < N_neighbour; in++) {
714
715 unsigned int ID = curr_trip->GetFNeighbour() + in;
716 unsigned int Station = TripletId2Station(ID);
717 unsigned int Triplet = TripletId2Triplet(ID);
718
719 const ca::Triplet& new_trip = vTriplets[Station][Triplet];
720
721 fscal dchi2 = 0.;
722 if (!checkTripletMatch(*curr_trip, new_trip, dchi2, wData)) continue;
723
724 const auto& hitL = wData.Hit(new_trip.GetLHit()); // left hit of new triplet
725 if (wData.IsHitKeyUsed(hitL.FrontKey()) || wData.IsHitKeyUsed(hitL.BackKey())) { //hits are used
726 // no used hits allowed -> compare and store track
727 if ((curr_tr.NofHits() > best_tr.NofHits())
728 || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
729 best_tr = curr_tr;
730 }
731 }
732 else { // hit is not used: add the left hit from the new triplet to the current track
733
734 unsigned char new_L = curr_tr.NofHits() + 1;
735 fscal new_chi2 = curr_tr.Chi2() + dchi2;
736
737 if constexpr (0) { //SGtrd2d debug!!
738
739 int mc01 = GetBestMcTrackIdForWindowHit(curr_trip->GetLHit());
740 int mc02 = GetBestMcTrackIdForWindowHit(curr_trip->GetMHit());
741 int mc03 = GetBestMcTrackIdForWindowHit(curr_trip->GetRHit());
742 int mc11 = GetBestMcTrackIdForWindowHit(new_trip.GetLHit());
743 int mc12 = GetBestMcTrackIdForWindowHit(new_trip.GetMHit());
744 int mc13 = GetBestMcTrackIdForWindowHit(new_trip.GetRHit());
745
746 if ((mc01 == mc02) && (mc02 == mc03)) {
747 LOG(info) << " sta " << ista << " mc0 " << mc01 << " " << mc02 << " " << mc03 << " mc1 " << mc11 << " "
748 << mc12 << " " << mc13 << " chi2 " << curr_tr.Chi2() / (2 * (curr_tr.NofHits() + 2) - 4)
749 << " new " << new_chi2 / (2 * (new_L + 2) - 4);
750 LOG(info) << " hits " << curr_trip->GetLHit() << " " << curr_trip->GetMHit() << " "
751 << curr_trip->GetRHit() << " " << new_trip.GetLHit();
752 }
753 }
754
755 int ndf = 2 * (new_L + 2) - 5;
756
757 if (ca::TrackingMode::kGlobal == fTrackingMode) { //SGtrd2d!!!
758 ndf = 2 * (new_L + 2) - 4;
759 }
761 ndf = 2 * (new_L + 2) - 4;
762 }
763 else {
764 ndf = new_L; // TODO: SG: 2 * (new_L + 2) - 5
765 }
766
767 if (new_chi2 > wData.CurrentIteration()->GetTrackChi2Cut() * ndf) continue;
768
769 // add new hit
770 new_tr[ista] = curr_tr;
771 new_tr[ista].AddHit(new_trip.GetLHit());
772
773 const int new_ista = ista + new_trip.GetMSta() - new_trip.GetLSta();
774 new_tr[ista].SetChi2(new_chi2);
775
776 CAFindTrack(new_ista, best_tr, &new_trip, new_tr[ista], min_best_l, new_tr, wData, vTriplets);
777 } // add triplet to track
778 } // for neighbours
779 } // level = 0
780 }
781
782
784 {
785 const Hit& hit = pwData->Hit(iHit);
786 return fFramework.GetBestMcTrackIdForCaHit(hit.Id());
787 }
788
790 {
791 const Hit& hit = pwData->Hit(iHit);
792 return fFramework.GetMcMatchForCaHit(hit.Id());
793 }
794
795} // 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.
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
Generates beam ions for transport simulation.
void push_back(Tinput value)
Pushes back a value to the vector.
Definition CaVector.h:190
void reserve(std::size_t count)
Reserves a new size for the vector.
Definition CaVector.h:176
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 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:113
void BuildBins(fscal xMin, fscal xMax, fscal yMin, fscal yMax, fscal binWidthX, fscal binWidthY, fscal zRef)
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.
Definition CaIteration.h:31
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
A container for all external parameters of the CA tracking algorithm.
TrackExtender fTrackExtender
Object of the track extender algorithm.
void PrepareCAIteration(int iterationIndex, const ca::Iteration &caIteration, WindowData &wData)
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.
const cbm::algo::kf::Field< fvec > & fField
Reference to magnetic field object.
static unsigned int TripletId2Triplet(unsigned int id)
void DoCompetitionLoop(const WindowData &wData)
fscal fDefaultMass
mass of the propagated particle [GeV/c2]
void ConstructTriplets(WindowData &wData)
int GetBestMcTrackIdForWindowHit(int iHit) const
Get mc track ID for a hit (debug tool)
McMatch GetMcMatchForWindowHit(int iHit) const
WindowData * pwData
Pointer to the window data object.
void PrepareGrid(const Vector< Hit > &hits, WindowData &wData)
const Framework & fFramework
Reference to the Framework object.
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)
TrackingMonitorData & frMonitorData
Reference to monitor data.
TrackFinderWindow(const ca::Framework &framework, const ca::Parameters< fvec > &pars, const fscal mass, const ca::TrackingMode &mode, ca::TrackingMonitorData &monitorData)
Default constructor.
const cbm::algo::kf::Setup< fvec > & fSetup
Reference to the setup.
void ReadWindowData(const Vector< Hit > &hits, WindowData &wData)
std::array< Vector< ca::Triplet >, constants::size::MaxNstations > TripletArray_t
static unsigned int TripletId2Station(unsigned int id)
Class representing an output track in the CA tracking algorithm.
Definition CaTrack.h:28
int fNofHits
Number of hits in track.
Definition CaTrack.h:46
void CreateTripletsForHit(Vector< ca::Triplet > &tripletsOut, int istal, int istam, int istar, ca::HitIndex_t ihl)
---— FUNCTIONAL PART ---—
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
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.
void SetCurrentIteration(int ind, const Iteration *ptr)
Accesses current iteration.
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.
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
MonitorData< ECounter, ETimer > TrackingMonitorData
kf::fscal fscal
Definition CaSimd.h:14
unsigned int HitIndex_t
Index of ca::Hit.
Definition CaHit.h:27
@ PrepareIteration
(iterations loop)