CbmRoot
Loading...
Searching...
No Matches
CaTrackFinder.cxx
Go to the documentation of this file.
1/* Copyright (C) 2009-2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Valentina Akishina, Ivan Kisel, Sergey Gorbunov [committer], Igor Kulakov, Sergei Zharko, 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#include "CaTrackFinder.h"
22
23#include "CaTimer.h"
24#include "CaTrack.h"
25#include "CaTriplet.h"
26
27#include <chrono>
28#include <fstream>
29#include <sstream>
30#include <thread>
31
32
33namespace cbm::algo::ca
34{
38
39 // -------------------------------------------------------------------------------------------------------------------
40 //
41 TrackFinder::TrackFinder(const ca::Framework& framework, const ca::Parameters<fvec>& pars, const fscal mass,
42 const ca::TrackingMode& mode, TrackingMonitorData& monitorData, int nThreads,
43 double& recoTime)
44 : fFramework(framework)
45 , fParameters(pars)
46 , fDefaultMass(mass)
47 , fTrackingMode(mode)
48 , fMonitorData(monitorData)
49 , fvMonitorDataThread(nThreads)
50 , fvWData(nThreads)
51 , fNofThreads(nThreads)
52 , fCaRecoTime(recoTime)
53 , fvRecoTracks(nThreads)
54 , fvRecoHitIndices(nThreads)
55 , fWindowLength((ca::TrackingMode::kMcbm == mode) ? 500 : 10000)
56 {
57 assert(fNofThreads > 0);
58
59 for (int iThread = 0; iThread < fNofThreads; ++iThread) {
60 fvRecoTracks[iThread].SetName(std::string("TrackFinder::fvRecoTracks_") + std::to_string(iThread));
61 fvRecoHitIndices[iThread].SetName(std::string("TrackFinder::fvRecoHitIndices_") + std::to_string(iThread));
62 }
63 }
64
65 // -------------------------------------------------------------------------------------------------------------------
66 //CBM Level 1 4D Reconstruction
67 //Finds tracks using the Cellular Automaton algorithm
68 //
70 {
71 Output_t output;
72 Vector<Track>& recoTracks = output.first; //reconstructed tracks
73 Vector<ca::HitIndex_t>& recoHits = output.second; //packed hits of reconstructed tracks
74
75 if (input.GetNhits() < 1) {
76 LOG(debug) << "No hits were passed to the ca::TrackFinder. Stopping the routine";
77 return output;
78 }
79
80 //
81 // The main CaTrackFinder routine
82 // It splits the input data into sub-timeslices
83 // and runs the track finder over the sub-slices
84 //
87 fMonitorData.IncrementCounter(ECounter::TrackingCall);
88 fMonitorData.IncrementCounter(ECounter::RecoHit, input.GetNhits());
89
90 auto timerStart = std::chrono::high_resolution_clock::now();
91
92 auto& wDataThread0 = fvWData[0]; // NOTE: Thread 0 must be always defined
93
94 // ----- Reset data arrays -----------------------------------------------------------------------------------------
95
96 wDataThread0.HitKeyFlags().reset(input.GetNhitKeys(), 0);
97
98 fHitTimeInfo.reset(input.GetNhits());
99
100 // TODO: move these values to Parameters namespace (S.Zharko)
101
102 // length of sub-TS
103 const kf::Target<fscal> trg(fParameters.GetActiveSetup().GetTarget());
104 const fscal minProtonMomentum = 0.1;
105 const fscal preFactor = sqrt(1. + ProtonMassD * ProtonMassD / (minProtonMomentum * minProtonMomentum));
106 const fscal targX = trg.GetX();
107 const fscal targY = trg.GetY();
108 const fscal targZ = trg.GetZ();
109
110 fStatTsStart = std::numeric_limits<fscal>::max(); // end time of the TS
111 fStatTsEnd = 0.; // end time of the TS
112 fStatNhitsTotal = 0;
113
114 // calculate possible event time for the hits (fHitTimeInfo array)
115 for (int iStream = 0; iStream < input.GetNdataStreams(); ++iStream) {
116
117 fscal maxTimeBeforeHit = std::numeric_limits<fscal>::lowest();
118 const int nStreamHits = input.GetStreamNhits(iStream);
119 fStatNhitsTotal += nStreamHits;
120
121 for (int ih = 0; ih < nStreamHits; ++ih) {
122
123 ca::HitIndex_t caHitId = input.GetStreamStartIndex(iStream) + ih;
124 const ca::Hit& h = input.GetHit(caHitId);
125 const auto& st = fParameters.GetActiveSetup().GetActiveLayer(h.Station());
126 const fscal dx = h.X() - targX;
127 const fscal dy = h.Y() - targY;
128 const fscal dz = h.Z() - targZ;
129 const fscal l = sqrt(dx * dx + dy * dy + dz * dz);
130 const fscal timeOfFlightMin = l * SpeedOfLightInv;
131 const fscal timeOfFlightMax = 1.5 * l * preFactor * SpeedOfLightInvD;
132 const fscal dt = h.RangeT();
133 // TODO: Is it possible, that the proton mass selection affects the search of heavier particles?
134
135 CaHitTimeInfo& info = fHitTimeInfo[caHitId];
136 info.fEventTimeMin = st.IsTimeMeasured() ? (h.T() - dt - timeOfFlightMax) : -1.e10;
137 info.fEventTimeMax = st.IsTimeMeasured() ? (h.T() + dt - timeOfFlightMin) : 1.e10;
138
139 // NOTE: if not a MT part, use wDataThread0.IsHitKeyUsed, it will be later copied to other threads
140 if (info.fEventTimeMin > 500.e6 || info.fEventTimeMax < -500.) { // cut hits with bogus start time > 500 ms
141 wDataThread0.IsHitKeyUsed(h.FrontKey()) = 1;
142 wDataThread0.IsHitKeyUsed(h.BackKey()) = 1;
143 LOG(error) << "CATrackFinder: skip bogus hit " << h.ToString();
144 continue;
145 }
146 maxTimeBeforeHit = std::max(maxTimeBeforeHit, info.fEventTimeMax);
147 info.fMaxTimeBeforeHit = maxTimeBeforeHit;
148 fStatTsStart = std::min(fStatTsStart, info.fEventTimeMax);
149 fStatTsEnd = std::max(fStatTsEnd, info.fEventTimeMin);
150 }
151
152 fscal minTimeAfterHit = std::numeric_limits<fscal>::max();
153 // loop in the reverse order to fill CaHitTimeInfo::fMinTimeAfterHit fields
154
155 for (int ih = nStreamHits - 1; ih >= 0; --ih) {
156 ca::HitIndex_t caHitId = input.GetStreamStartIndex(iStream) + ih;
157 const ca::Hit& h = input.GetHit(caHitId);
158 if (wDataThread0.IsHitKeyUsed(h.FrontKey()) || wDataThread0.IsHitKeyUsed(h.BackKey())) {
159 continue;
160 } // the hit is skipped
161 CaHitTimeInfo& info = fHitTimeInfo[caHitId];
162 minTimeAfterHit = std::min(minTimeAfterHit, info.fEventTimeMin);
163 info.fMinTimeAfterHit = minTimeAfterHit;
164 }
165
166 if (0) {
167 static int tmp = 0;
168 if (tmp < 10000) {
169 tmp++;
170 LOG(warning) << "\n\n stream " << iStream << " hits " << nStreamHits << "\n\n";
171 for (int ih = 0; (ih < nStreamHits) && (tmp < 10000); ++ih) {
172 ca::HitIndex_t caHitId = input.GetStreamStartIndex(iStream) + ih;
173 const ca::Hit& h = input.GetHit(caHitId);
174 if (wDataThread0.IsHitKeyUsed(h.FrontKey()) || wDataThread0.IsHitKeyUsed(h.BackKey())) {
175 continue;
176 } // the hit is skipped
177 CaHitTimeInfo& info = fHitTimeInfo[caHitId];
178 if (h.Station() < 4) {
179 tmp++;
180 LOG(warning) << " hit sta " << h.Station() << " stream " << iStream << " time " << h.T() << " event time "
181 << info.fEventTimeMin << " .. " << info.fEventTimeMax << " max time before hit "
182 << info.fMaxTimeBeforeHit << " min time after hit " << info.fMinTimeAfterHit;
183 }
184 }
185 }
186 }
187 }
188 // all hits belong to one sub-timeslice; 1 s is the maximal length of the TS
189 fStatTsEnd = std::clamp(fStatTsEnd, fStatTsStart, fStatTsStart + 1.e9f);
190
191 LOG(debug) << "CA tracker process time slice " << fStatTsStart * 1.e-6 << " -- " << fStatTsEnd * 1.e-6
192 << " [ms] with " << fStatNhitsTotal << " hits";
193
194 int nWindows = static_cast<int>((fStatTsEnd - fStatTsStart) / fWindowLength) + 1;
195 if (nWindows < 1) { // Situation, when fStatTsEnd == fStatTsStart
196 nWindows = 1;
197 }
198
199 // int nWindowsThread = nWindows / fNofThreads;
200 // LOG(info) << "CA: estimated number of time windows: " << nWindows;
201
202 std::vector<std::pair<fscal, fscal>> vWindowRangeThread(fNofThreads);
203 { // Estimation of number of hits in time windows
204 //Timer time;
205 //time.Start();
206 const HitIndex_t nHitsTot = input.GetNhits();
207 const int nSt = fParameters.GetNstationsActive();
208
209 // Count number of hits per window and station
210 std::vector<HitIndex_t> nHitsWindowSta(nWindows * nSt, 0);
211
212 for (HitIndex_t iHit = 0; iHit < nHitsTot; ++iHit) {
213 const auto& hit = input.GetHit(iHit);
214 const auto& info = fHitTimeInfo[iHit];
215 int iWindow = static_cast<int>((info.fEventTimeMin - fStatTsStart) / fWindowLength);
216 if (iWindow < 0) {
217 iWindow = 0;
218 }
219 if (iWindow >= nWindows) {
220 LOG(error) << "ca: Hit out of range: iHit = " << iHit << ", min. event time = " << info.fEventTimeMin * 1.e-6
221 << " ms, window = " << iWindow;
222 continue;
223 }
224 ++nHitsWindowSta[hit.Station() + iWindow * nSt];
225 }
226
227 // Remove hits from the "monster events"
229 const auto maxNofHitsSta = static_cast<HitIndex_t>(50 * fWindowLength / 1.e3);
230 for (auto& content : nHitsWindowSta) {
231 if (content > maxNofHitsSta) {
232 content = 0;
233 }
234 }
235 }
236
237 // Integrate number of hits per window
238 std::vector<HitIndex_t> nHitsWindow;
239 nHitsWindow.reserve(nWindows);
240 HitIndex_t nHitsCollected = 0;
241 for (auto it = nHitsWindowSta.begin(); it != nHitsWindowSta.end(); it += nSt) {
242 nHitsCollected = nHitsWindow.emplace_back(std::accumulate(it, it + nSt, nHitsCollected));
243 }
244
245 // Get time range for threads
246 const HitIndex_t nHitsPerThread = nHitsCollected / fNofThreads;
247 auto windowIt = nHitsWindow.begin();
248 vWindowRangeThread[0].first = fStatTsStart;
249 for (int iTh = 1; iTh < fNofThreads; ++iTh) {
250 windowIt = std::lower_bound(windowIt, nHitsWindow.end(), iTh * nHitsPerThread);
251 const size_t iWbegin = std::distance(nHitsWindow.begin(), windowIt) + 1;
252 vWindowRangeThread[iTh].first = fStatTsStart + iWbegin * fWindowLength;
253 vWindowRangeThread[iTh - 1].second = vWindowRangeThread[iTh].first;
254 }
255 vWindowRangeThread[fNofThreads - 1].second = fStatTsEnd;
256
257 //time.Stop();
258 //LOG(info) << "Thread boarders estimation time: " << time.GetTotalMs() << " ms";
259 LOG(debug) << "Fraction of hits from monster events: "
260 << static_cast<double>(nHitsTot - nHitsCollected) / nHitsTot;
261 }
262
263 // cut data into sub-timeslices and process them one by one
264 //for (int iThread = 0; iThread < fNofThreads; ++iThread) {
265 // vWindowStartThread[iThread] = fStatTsStart + iThread * nWindowsThread * fWindowLength;
266 // vWindowEndThread[iThread] =
267 // vWindowStartThread[iThread] + nWindowsThread * fWindowLength;
268 //}
269
270 for (int iThread = 0; iThread < fNofThreads; ++iThread) {
271 auto& entry = vWindowRangeThread[iThread];
272 double start = entry.first * 1.e-6;
273 double end = entry.second * 1.e-6;
274 LOG(debug) << "Thread: " << iThread << " from " << start << " ms to " << end << " ms (delta = " << end - start
275 << " ms)";
276 }
277
278 // Statistics for monitoring
279 std::vector<int> vStatNwindows(fNofThreads), vStatNhitsProcessed(fNofThreads);
280
282 // Save tracks
283 if (fNofThreads == 1) {
284 this->FindTracksThread(input, 0, std::ref(vWindowRangeThread[0]), std::ref(vStatNwindows[0]),
285 std::ref(vStatNhitsProcessed[0]));
287 recoTracks = std::move(fvRecoTracks[0]);
288 recoHits = std::move(fvRecoHitIndices[0]);
290 }
291 else {
292 std::vector<std::thread> vThreadList;
293 vThreadList.reserve(fNofThreads);
294 for (int iTh = 0; iTh < fNofThreads; ++iTh) {
295 vThreadList.emplace_back(&TrackFinder::FindTracksThread, this, std::ref(input), iTh,
296 std::ref(vWindowRangeThread[iTh]), std::ref(vStatNwindows[iTh]),
297 std::ref(vStatNhitsProcessed[iTh]));
298 }
299 for (auto& th : vThreadList) {
300 if (th.joinable()) {
301 th.join();
302 }
303 }
305 auto Operation = [](size_t acc, const auto& v) { return acc + v.size(); };
306 int nRecoTracks = std::accumulate(fvRecoTracks.begin(), fvRecoTracks.end(), 0, Operation);
307 int nRecoHits = std::accumulate(fvRecoHitIndices.begin(), fvRecoHitIndices.end(), 0, Operation);
308 recoTracks.reserve(nRecoTracks);
309 recoHits.reserve(nRecoHits);
310 for (int iTh = 0; iTh < fNofThreads; ++iTh) {
311 recoTracks.insert(recoTracks.end(), fvRecoTracks[iTh].begin(), fvRecoTracks[iTh].end());
312 recoHits.insert(recoHits.end(), fvRecoHitIndices[iTh].begin(), fvRecoHitIndices[iTh].end());
313 }
315 }
316
317 fMonitorData.IncrementCounter(ECounter::RecoTrack, recoTracks.size());
318 fMonitorData.IncrementCounter(ECounter::RecoHitUsed, recoHits.size());
319
320 auto timerEnd = std::chrono::high_resolution_clock::now();
321 fCaRecoTime = (double) (std::chrono::duration<double>(timerEnd - timerStart).count());
322
323 // Add thread monitors to the main monitor
324 for (auto& monitor : fvMonitorDataThread) {
325 fMonitorData.AddMonitorData(monitor, true);
326 //fMonitorData.AddMonitorData(monitor);
327 monitor.Reset();
328 }
329
330 const int statNhitsProcessedTotal = std::accumulate(vStatNhitsProcessed.begin(), vStatNhitsProcessed.end(), 0);
331 const int statNwindowsTotal = std::accumulate(vStatNwindows.begin(), vStatNwindows.end(), 0);
332
333 // Filling TS headear
334 tsHeader.Start() = fStatTsStart;
335 tsHeader.End() = fStatTsEnd;
336
338
339 LOG(debug) << "CA tracker: time slice finished. Reconstructed " << recoTracks.size() << " tracks with "
340 << recoHits.size() << " hits. Processed " << statNhitsProcessedTotal << " hits in " << statNwindowsTotal
341 << " time windows. Reco time " << fCaRecoTime / 1.e9 << " s";
342 return output;
343 }
344
345 // -------------------------------------------------------------------------------------------------------------------
346 //
347 void TrackFinder::FindTracksThread(const InputData& input, int iThread, std::pair<fscal, fscal>& windowRange,
348 int& statNwindows, int& statNhitsProcessed)
349 {
350 //std::stringstream filename;
351 //filename << "./dbg_caTrackFinder::FindTracksThread_" << iThread << ".txt";
352 //std::ofstream out(filename.str());
353 Timer timer;
354 timer.Start();
355
356 auto& monitor = fvMonitorDataThread[iThread];
357 monitor.StartTimer(ETimer::TrackingThread);
358 monitor.StartTimer(ETimer::PrepareThread);
359
360 // Init vectors
361 auto& tracks = fvRecoTracks[iThread];
362 auto& hitIndices = fvRecoHitIndices[iThread];
363 auto& wData = fvWData[iThread];
364 {
365 const int nStations = fParameters.GetNstationsActive();
366 const size_t nHitsTot = input.GetNhits();
367 const size_t nHitsExpected = 2 * nHitsTot;
368 const size_t nTracksExpected = 2 * nHitsTot / nStations;
369 tracks.clear();
370 tracks.reserve(nTracksExpected / fNofThreads);
371 hitIndices.clear();
372 hitIndices.reserve(nHitsExpected / fNofThreads);
373 if (iThread != 0) {
374 wData.HitKeyFlags() = fvWData[0].HitKeyFlags();
375 }
376 for (int iS = 0; iS < nStations; ++iS) {
377 wData.TsHitIndices(iS).clear();
378 wData.TsHitIndices(iS).reserve(nHitsTot);
379 }
380 }
381
382 // Begin and end index of hit-range for streams
383 std::vector<std::pair<HitIndex_t, HitIndex_t>> streamHitRanges(input.GetNdataStreams(), {0, 0});
384
385 // Define first hit, skip all the hits, which are before the first window
386 for (size_t iStream = 0; iStream < streamHitRanges.size(); ++iStream) {
387 auto& range = streamHitRanges[iStream];
388 range.first = input.GetStreamStartIndex(iStream);
389 range.second = input.GetStreamStopIndex(iStream);
390
391 for (HitIndex_t caHitId = range.first; caHitId < range.second; ++caHitId) {
392 const ca::Hit& h = input.GetHit(caHitId);
393 if (wData.IsHitKeyUsed(h.FrontKey()) || wData.IsHitKeyUsed(h.BackKey())) {
394 continue;
395 }
396 const CaHitTimeInfo& info = fHitTimeInfo[caHitId];
397 if (info.fMaxTimeBeforeHit < windowRange.first) {
398 range.first = caHitId + 1;
399 }
400 if (info.fMinTimeAfterHit > windowRange.second) {
401 range.second = caHitId;
402 }
403 }
404 }
405
406 int statLastLogTimeChunk = -1;
407
408 // Track finder algorithm for the time window
410 trackFinderWindow.InitTimeslice(input.GetNhitKeys());
411
412 monitor.StopTimer(ETimer::PrepareThread);
413
414 while (true) {
415 monitor.IncrementCounter(ECounter::SubTS);
416 // select the sub-slice hits
417 for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
418 wData.TsHitIndices(iS).clear();
419 }
420 bool areUntouchedDataLeft = false; // is the whole TS processed
421
422 // TODO: SG: skip empty regions and start the subslice with the earliest hit
423
424 statNwindows++;
425 //out << statNwindows << ' ';
426
427 monitor.StartTimer(ETimer::PrepareWindow);
428
429 for (auto& range : streamHitRanges) {
430 for (HitIndex_t caHitId = range.first; caHitId < range.second; ++caHitId) {
431 const ca::Hit& h = input.GetHit(caHitId);
432 if (wData.IsHitKeyUsed(h.FrontKey()) || wData.IsHitKeyUsed(h.BackKey())) {
433 // the hit is already reconstructed
434 continue;
435 }
436 const CaHitTimeInfo& info = fHitTimeInfo[caHitId];
437 if (info.fEventTimeMax < windowRange.first) {
438 // the hit belongs to previous sub-slices
439 continue;
440 }
441 if (info.fMinTimeAfterHit > windowRange.first + fWindowLength) {
442 // this hit and all later hits are out of the sub-slice
443 areUntouchedDataLeft = true;
444 break;
445 }
446 if (info.fEventTimeMin > windowRange.first + fWindowLength) {
447 // the hit is too late for the sub slice
448 areUntouchedDataLeft = true;
449 continue;
450 }
451
452 // the hit belongs to the sub-slice
453 wData.TsHitIndices(h.Station()).push_back(caHitId);
454 if (info.fMaxTimeBeforeHit < windowRange.first + fWindowLength) {
455 range.first = caHitId + 1; // this hit and all hits before are before the overlap
456 }
457 }
458 }
459
460 //out << statNwindowHits << ' ';
461 //if (statNwindowHits == 0) { // Empty window
462 // monitor.StopTimer(ETimer::PrepareWindow);
463 // out << 0 << ' ' << 0 << ' ' << 0 << '\n';
464 // continue;
465 //}
466
468 // cut at 50 hits per station per 1 us.
469 int maxStationHits = (int) (50 * fWindowLength / 1.e3);
470 for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
471 int nHitsSta = static_cast<int>(wData.TsHitIndices(ista).size());
472 if (nHitsSta > maxStationHits) {
473 wData.TsHitIndices(ista).clear();
474 }
475 }
476 }
477
478 int statNwindowHits = 0;
479 for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
480 statNwindowHits += wData.TsHitIndices(ista).size();
481 }
482 statNhitsProcessed += statNwindowHits;
483
484 // print the LOG for every 10 ms of data processed
485 if constexpr (0) {
486 int currentChunk = (int) ((windowRange.first - fStatTsStart) / 10.e6);
487 if (!areUntouchedDataLeft || currentChunk > statLastLogTimeChunk) {
488 statLastLogTimeChunk = currentChunk;
489 double dataRead = 100. * (windowRange.first + fWindowLength - fStatTsStart) / (fStatTsEnd - fStatTsStart);
490 if (dataRead > 100.) {
491 dataRead = 100.;
492 }
493 LOG(debug) << "CA tracker process sliding window N " << statNwindows << ": time " << windowRange.first / 1.e6
494 << " ms + " << fWindowLength / 1.e3 << " us) with " << statNwindowHits << " hits. "
495 << " Processing " << dataRead << " % of the TS time and "
496 << 100. * statNhitsProcessed / fStatNhitsTotal << " % of TS hits."
497 << " Already reconstructed " << tracks.size() << " tracks on thread #" << iThread;
498 }
499 }
500
501 //out << statNwindowHits << ' ';
502 monitor.StopTimer(ETimer::PrepareWindow);
503
504 //Timer trackingInWindow; //DBG
505 //trackingInWindow.Start();
506 monitor.StartTimer(ETimer::TrackingWindow);
507 trackFinderWindow.CaTrackFinderSlice(input, wData);
508 monitor.StopTimer(ETimer::TrackingWindow);
509 //trackingInWindow.Stop();
510 //out << trackingInWindow.GetTotalMs() << ' ';
511
512 // save reconstructed tracks with no hits in the overlap region
513 //if (windowRange.first > 13.23e6 && windowRange.first < 13.26e6) {
514 windowRange.first += fWindowLength;
515 // we should add hits from reconstructed but not stored tracks to the new sub-timeslice
516 // we do it in a simple way by extending the tsStartNew
517 // TODO: only add those hits from the region before tsStartNew that belong to the not stored tracks
518 //out << fvWData[iThread].RecoHitIndices().size() << ' ';
519 //out << fvWData[iThread].RecoTracks().size() << '\n';
520
521 monitor.StartTimer(ETimer::StoreTracksWindow);
522 auto trackFirstHit = wData.RecoHitIndices().begin();
523
524 for (const auto& track : wData.RecoTracks()) {
525
526 const bool isTrackCompletelyInOverlap =
527 std::all_of(trackFirstHit, trackFirstHit + track.fNofHits, [&](int caHitId) {
528 CaHitTimeInfo& info = fHitTimeInfo[caHitId];
529 return info.fEventTimeMax >= windowRange.first;
530 });
531
532 // Don't save tracks from the overlap region, since they might have additional hits in the next subslice.
533 // Don't reject tracks in the overlap when no more data are left
534 const bool useFlag = !isTrackCompletelyInOverlap || !areUntouchedDataLeft;
535
536 for (int i = 0; i < track.fNofHits; i++) {
537 const int caHitId = *(trackFirstHit + i);
538 const auto& h = input.GetHit(caHitId);
539 wData.IsHitKeyUsed(h.FrontKey()) = static_cast<int>(useFlag);
540 wData.IsHitKeyUsed(h.BackKey()) = static_cast<int>(useFlag);
541
542 if (useFlag) {
543 hitIndices.push_back(caHitId);
544 }
545 }
546 if (useFlag) {
547 tracks.push_back(track);
548 }
549
550 trackFirstHit += track.fNofHits;
551 } // sub-timeslice tracks
552 monitor.StopTimer(ETimer::StoreTracksWindow);
553
554 if (windowRange.first > windowRange.second) {
555 break;
556 }
557 if (!areUntouchedDataLeft) {
558 break;
559 }
560 } // while(true)
561 monitor.StopTimer(ETimer::TrackingThread);
562 //timer.Stop();
563 //LOG(info) << "CA: finishing tracking on thread " << iThread << " (time: " << timer.GetTotalMs() << " ms, "
564 // << "hits processed: " << statNhitsProcessed << ", "
565 // << "hits used: " << hitIndices.size() << ')';
566 }
567} // namespace cbm::algo::ca
TClonesArray * tracks
Timer class for CA tracking (header)
source file for the ca::Track class
friend fvec sqrt(const fvec &a)
static constexpr size_t size()
Definition KfSimdPseudo.h:2
fscal v[fmask::Size]
Definition KfSimdPseudo.h:4
Data class with information on a STS local track.
ca::Hit class describes a generic hit for the CA tracker
Definition CaHit.h:32
HitIndex_t GetNhits() const
Gets number of hits in the hits vector.
Definition CaInputData.h:61
const Hit & GetHit(HitIndex_t index) const
Gets reference to hit by its index.
Definition CaInputData.h:55
int GetNdataStreams() const
Gets number of data streams.
Definition CaInputData.h:51
HitIndex_t GetStreamNhits(int iStream) const
Gets n hits for the data stream.
Definition CaInputData.h:76
int GetNhitKeys() const
Gets total number of stored keys.
Definition CaInputData.h:64
HitIndex_t GetStreamStartIndex(int iStream) const
Gets index of the first hit in the sorted hits vector.
Definition CaInputData.h:68
HitIndex_t GetStreamStopIndex(int iStream) const
Gets index of (the last + 1) hit in the sorted hits vector.
Definition CaInputData.h:72
A container for all external parameters of the CA tracking algorithm.
A timer class for the monitor.
Definition CaTimer.h:25
void Start()
Starts the timer.
Definition CaTimer.h:86
Structure for keeping the current information on the timeslice.
float & End()
Accesses the end of timeslice [ns].
float & Start()
Accesses the start of timeslice [ns].
void CaTrackFinderSlice(const ca::InputData &input, WindowData &wData)
const Framework & fFramework
Reference to the Framework object.
const Parameters< fvec > & fParameters
Object of Framework parameters class.
std::pair< Vector< Track >, Vector< ca::HitIndex_t > > Output_t
TrackFinder(const ca::Framework &framework, const ca::Parameters< fvec > &pars, const fscal mass, const ca::TrackingMode &mode, TrackingMonitorData &monitorData, int nThreads, double &recoTime)
Default constructor.
ca::TrackingMode fTrackingMode
Output_t FindTracks(const InputData &input, TimesliceHeader &tsHeader)
std::vector< ca::WindowData > fvWData
Intrnal data processed in a time-window.
Vector< CaHitTimeInfo > fHitTimeInfo
int fNofThreads
Number of threads to execute the track-finder.
void FindTracksThread(const InputData &input, int iThread, std::pair< fscal, fscal > &windowRange, int &statNwindows, int &statNhitsProcessed)
std::vector< TrackingMonitorData > fvMonitorDataThread
Tracking monitor data per thread.
fscal fWindowLength
Time window length [ns].
TrackingMonitorData & fMonitorData
Tracking monitor data (statistics per call)
fscal fDefaultMass
mass of the propagated particle [GeV/c2]
std::vector< Vector< Track > > fvRecoTracks
reconstructed tracks
std::vector< Vector< HitIndex_t > > fvRecoHitIndices
packed hits of reconstructed tracks
void reserve(std::size_t count)
Reserves a new size for the vector.
Definition CaVector.h:176
A geometry layer in the target region.
Definition KfTarget.h:25
T GetZ() const
Gets z-coordinate of the nominal target center.
Definition KfTarget.h:67
T GetY() const
Gets y-coordinate of the nominal target center.
Definition KfTarget.h:64
T GetX() const
Gets x-coordinate of the nominal target center.
Definition KfTarget.h:61
constexpr double ProtonMassD
Proton mass [GeV/c2] (PDG 11.08.2022)
Definition CaDefs.h:85
constexpr fscal SpeedOfLightInv
Inverse speed of light [ns/cm].
Definition CaDefs.h:96
constexpr double SpeedOfLightInvD
Inverse speed of light [ns/cm].
Definition CaDefs.h:87
TODO: SZh 8.11.2022: add selection of parameterisation.
Definition CaBranch.h:14
@ RecoHit
number of reconstructed hits
@ RecoTrack
number of reconstructed tracks
@ TrackingCall
number of the routine calls
@ SubTS
number of sub time-slices
@ RecoHitUsed
number of used reconstructed hits
MonitorData< ECounter, ETimer > TrackingMonitorData
kf::fscal fscal
Definition CaSimd.h:14
constexpr double ProtonMassD
Proton mass [GeV/c2] (PDG 11.08.2022)
Definition CaDefs.h:85
constexpr fscal SpeedOfLightInv
Inverse speed of light [ns/cm].
Definition CaDefs.h:96
unsigned int HitIndex_t
Index of ca::Hit.
Definition CaHit.h:27
constexpr double SpeedOfLightInvD
Inverse speed of light [ns/cm].
Definition CaDefs.h:87