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