74 LOG(warn) <<
"No hits were passed to the ca::TrackFinder. Stopping the routine";
88 auto timerStart = std::chrono::high_resolution_clock::now();
90 auto& wDataThread0 =
fvWData[0];
94 wDataThread0.HitKeyFlags().reset(input.
GetNhitKeys(), 0);
101 const fscal minProtonMomentum = 0.1;
102 const fscal preFactor =
sqrt(1. + ProtonMassD * ProtonMassD / (minProtonMomentum * minProtonMomentum));
114 fscal maxTimeBeforeHit = std::numeric_limits<fscal>::lowest();
118 for (
int ih = 0; ih < nStreamHits; ++ih) {
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();
138 wDataThread0.IsHitKeyUsed(
h.FrontKey()) = 1;
139 wDataThread0.IsHitKeyUsed(
h.BackKey()) = 1;
140 LOG(error) <<
"CATrackFinder: skip bogus hit " <<
h.ToString();
143 maxTimeBeforeHit = std::max(maxTimeBeforeHit, info.
fEventTimeMax);
149 fscal minTimeAfterHit = std::numeric_limits<fscal>::max();
152 for (
int ih = nStreamHits - 1; ih >= 0; --ih) {
155 if (wDataThread0.IsHitKeyUsed(
h.FrontKey()) || wDataThread0.IsHitKeyUsed(
h.BackKey())) {
159 minTimeAfterHit = std::min(minTimeAfterHit, info.
fEventTimeMin);
167 LOG(warning) <<
"\n\n stream " << iStream <<
" hits " << nStreamHits <<
"\n\n";
168 for (
int ih = 0; (ih < nStreamHits) && (tmp < 10000); ++ih) {
171 if (wDataThread0.IsHitKeyUsed(
h.FrontKey()) || wDataThread0.IsHitKeyUsed(
h.BackKey())) {
175 if (
h.Station() < 4) {
177 LOG(warning) <<
" hit sta " <<
h.Station() <<
" stream " << iStream <<
" time " <<
h.T() <<
" event time "
199 std::vector<std::pair<fscal, fscal>> vWindowRangeThread(
fNofThreads);
207 std::vector<HitIndex_t> nHitsWindowSta(nWindows * nSt, 0);
209 for (
HitIndex_t iHit = 0; iHit < nHitsTot; ++iHit) {
210 const auto& hit = input.
GetHit(iHit);
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;
221 ++nHitsWindowSta[hit.Station() + iWindow * nSt];
227 for (
auto& content : nHitsWindowSta) {
228 if (content > maxNofHitsSta) {
235 std::vector<HitIndex_t> nHitsWindow;
236 nHitsWindow.reserve(nWindows);
238 for (
auto it = nHitsWindowSta.begin(); it != nHitsWindowSta.end(); it += nSt) {
239 nHitsCollected = nHitsWindow.emplace_back(std::accumulate(it, it + nSt, nHitsCollected));
244 auto windowIt = nHitsWindow.begin();
247 windowIt = std::lower_bound(windowIt, nHitsWindow.end(), iTh * nHitsPerThread);
248 const size_t iWbegin = std::distance(nHitsWindow.begin(), windowIt) + 1;
250 vWindowRangeThread[iTh - 1].second = vWindowRangeThread[iTh].first;
256 LOG(debug) <<
"Fraction of hits from monster events: "
257 <<
static_cast<double>(nHitsTot - nHitsCollected) / nHitsTot;
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
281 this->
FindTracksThread(input, 0, std::ref(vWindowRangeThread[0]), std::ref(vStatNwindows[0]),
282 std::ref(vStatNhitsProcessed[0]));
289 std::vector<std::thread> vThreadList;
293 std::ref(vWindowRangeThread[iTh]), std::ref(vStatNwindows[iTh]),
294 std::ref(vStatNhitsProcessed[iTh]));
296 for (
auto& th : vThreadList) {
302 auto Operation = [](
size_t acc,
const auto&
v) {
return acc +
v.size(); };
305 recoTracks.
reserve(nRecoTracks);
317 auto timerEnd = std::chrono::high_resolution_clock::now();
318 fCaRecoTime = (double) (std::chrono::duration<double>(timerEnd - timerStart).count());
327 const int statNhitsProcessedTotal = std::accumulate(vStatNhitsProcessed.begin(), vStatNhitsProcessed.end(), 0);
328 const int statNwindowsTotal = std::accumulate(vStatNwindows.begin(), vStatNwindows.end(), 0);
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";
345 int& statNwindows,
int& statNhitsProcessed)
360 auto& wData =
fvWData[iThread];
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;
371 wData.HitKeyFlags() =
fvWData[0].HitKeyFlags();
373 for (
int iS = 0; iS < nStations; ++iS) {
374 wData.TsHitIndices(iS).clear();
375 wData.TsHitIndices(iS).reserve(nHitsTot);
380 std::vector<std::pair<HitIndex_t, HitIndex_t>> streamHitRanges(input.
GetNdataStreams(), {0, 0});
383 for (
size_t iStream = 0; iStream < streamHitRanges.size(); ++iStream) {
384 auto& range = streamHitRanges[iStream];
388 for (
HitIndex_t caHitId = range.first; caHitId < range.second; ++caHitId) {
390 if (wData.IsHitKeyUsed(
h.FrontKey()) || wData.IsHitKeyUsed(
h.BackKey())) {
395 range.first = caHitId + 1;
398 range.second = caHitId;
403 int statLastLogTimeChunk = -1;
414 for (
int iS = 0; iS <
fParameters.GetNstationsActive(); ++iS) {
415 wData.TsHitIndices(iS).clear();
417 bool areUntouchedDataLeft =
false;
426 for (
auto& range : streamHitRanges) {
427 for (
HitIndex_t caHitId = range.first; caHitId < range.second; ++caHitId) {
429 if (wData.IsHitKeyUsed(
h.FrontKey()) || wData.IsHitKeyUsed(
h.BackKey())) {
440 areUntouchedDataLeft =
true;
445 areUntouchedDataLeft =
true;
450 wData.TsHitIndices(
h.Station()).push_back(caHitId);
452 range.first = caHitId + 1;
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();
475 int statNwindowHits = 0;
476 for (
int ista = 0; ista <
fParameters.GetNstationsActive(); ++ista) {
477 statNwindowHits += wData.TsHitIndices(ista).size();
479 statNhitsProcessed += statNwindowHits;
483 int currentChunk = (int) ((windowRange.first -
fStatTsStart) / 10.e6);
484 if (!areUntouchedDataLeft || currentChunk > statLastLogTimeChunk) {
485 statLastLogTimeChunk = currentChunk;
487 if (dataRead > 100.) {
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 "
494 <<
" Already reconstructed " <<
tracks.size() <<
" tracks on thread #" << iThread;
519 auto trackFirstHit = wData.RecoHitIndices().begin();
521 for (
const auto& track : wData.RecoTracks()) {
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;
531 const bool useFlag = !isTrackCompletelyInOverlap || !areUntouchedDataLeft;
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);
540 hitIndices.push_back(caHitId);
547 trackFirstHit += track.fNofHits;
551 if (windowRange.first > windowRange.second) {
554 if (!areUntouchedDataLeft) {