76 LOG(debug) <<
"No hits were passed to the ca::TrackFinder. Stopping the routine";
90 auto timerStart = std::chrono::high_resolution_clock::now();
92 auto& wDataThread0 =
fvWData[0];
96 wDataThread0.HitKeyFlags().reset(input.
GetNhitKeys(), 0);
104 const fscal minProtonMomentum = 0.1;
117 fscal maxTimeBeforeHit = std::numeric_limits<fscal>::lowest();
121 for (
int ih = 0; ih < nStreamHits; ++ih) {
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);
132 const fscal dt =
h.RangeT();
136 info.
fEventTimeMin = st.IsTimeMeasured() ? (
h.T() - dt - timeOfFlightMax) : -1.e10;
137 info.
fEventTimeMax = st.IsTimeMeasured() ? (
h.T() + dt - timeOfFlightMin) : 1.e10;
141 wDataThread0.IsHitKeyUsed(
h.FrontKey()) = 1;
142 wDataThread0.IsHitKeyUsed(
h.BackKey()) = 1;
143 LOG(error) <<
"CATrackFinder: skip bogus hit " <<
h.ToString();
146 maxTimeBeforeHit = std::max(maxTimeBeforeHit, info.
fEventTimeMax);
152 fscal minTimeAfterHit = std::numeric_limits<fscal>::max();
155 for (
int ih = nStreamHits - 1; ih >= 0; --ih) {
158 if (wDataThread0.IsHitKeyUsed(
h.FrontKey()) || wDataThread0.IsHitKeyUsed(
h.BackKey())) {
162 minTimeAfterHit = std::min(minTimeAfterHit, info.
fEventTimeMin);
170 LOG(warning) <<
"\n\n stream " << iStream <<
" hits " << nStreamHits <<
"\n\n";
171 for (
int ih = 0; (ih < nStreamHits) && (tmp < 10000); ++ih) {
174 if (wDataThread0.IsHitKeyUsed(
h.FrontKey()) || wDataThread0.IsHitKeyUsed(
h.BackKey())) {
178 if (
h.Station() < 4) {
180 LOG(warning) <<
" hit sta " <<
h.Station() <<
" stream " << iStream <<
" time " <<
h.T() <<
" event time "
202 std::vector<std::pair<fscal, fscal>> vWindowRangeThread(
fNofThreads);
210 std::vector<HitIndex_t> nHitsWindowSta(nWindows * nSt, 0);
212 for (
HitIndex_t iHit = 0; iHit < nHitsTot; ++iHit) {
213 const auto& hit = input.
GetHit(iHit);
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;
224 ++nHitsWindowSta[hit.Station() + iWindow * nSt];
230 for (
auto& content : nHitsWindowSta) {
231 if (content > maxNofHitsSta) {
238 std::vector<HitIndex_t> nHitsWindow;
239 nHitsWindow.reserve(nWindows);
241 for (
auto it = nHitsWindowSta.begin(); it != nHitsWindowSta.end(); it += nSt) {
242 nHitsCollected = nHitsWindow.emplace_back(std::accumulate(it, it + nSt, nHitsCollected));
247 auto windowIt = nHitsWindow.begin();
250 windowIt = std::lower_bound(windowIt, nHitsWindow.end(), iTh * nHitsPerThread);
251 const size_t iWbegin = std::distance(nHitsWindow.begin(), windowIt) + 1;
253 vWindowRangeThread[iTh - 1].second = vWindowRangeThread[iTh].first;
259 LOG(debug) <<
"Fraction of hits from monster events: "
260 <<
static_cast<double>(nHitsTot - nHitsCollected) / nHitsTot;
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
284 this->
FindTracksThread(input, 0, std::ref(vWindowRangeThread[0]), std::ref(vStatNwindows[0]),
285 std::ref(vStatNhitsProcessed[0]));
292 std::vector<std::thread> vThreadList;
296 std::ref(vWindowRangeThread[iTh]), std::ref(vStatNwindows[iTh]),
297 std::ref(vStatNhitsProcessed[iTh]));
299 for (
auto& th : vThreadList) {
305 auto Operation = [](
size_t acc,
const auto&
v) {
return acc +
v.size(); };
308 recoTracks.
reserve(nRecoTracks);
320 auto timerEnd = std::chrono::high_resolution_clock::now();
321 fCaRecoTime = (double) (std::chrono::duration<double>(timerEnd - timerStart).count());
330 const int statNhitsProcessedTotal = std::accumulate(vStatNhitsProcessed.begin(), vStatNhitsProcessed.end(), 0);
331 const int statNwindowsTotal = std::accumulate(vStatNwindows.begin(), vStatNwindows.end(), 0);
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";
348 int& statNwindows,
int& statNhitsProcessed)
363 auto& wData =
fvWData[iThread];
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;
374 wData.HitKeyFlags() =
fvWData[0].HitKeyFlags();
376 for (
int iS = 0; iS < nStations; ++iS) {
377 wData.TsHitIndices(iS).clear();
378 wData.TsHitIndices(iS).reserve(nHitsTot);
383 std::vector<std::pair<HitIndex_t, HitIndex_t>> streamHitRanges(input.
GetNdataStreams(), {0, 0});
386 for (
size_t iStream = 0; iStream < streamHitRanges.size(); ++iStream) {
387 auto& range = streamHitRanges[iStream];
391 for (
HitIndex_t caHitId = range.first; caHitId < range.second; ++caHitId) {
393 if (wData.IsHitKeyUsed(
h.FrontKey()) || wData.IsHitKeyUsed(
h.BackKey())) {
398 range.first = caHitId + 1;
401 range.second = caHitId;
406 int statLastLogTimeChunk = -1;
417 for (
int iS = 0; iS <
fParameters.GetNstationsActive(); ++iS) {
418 wData.TsHitIndices(iS).clear();
420 bool areUntouchedDataLeft =
false;
429 for (
auto& range : streamHitRanges) {
430 for (
HitIndex_t caHitId = range.first; caHitId < range.second; ++caHitId) {
432 if (wData.IsHitKeyUsed(
h.FrontKey()) || wData.IsHitKeyUsed(
h.BackKey())) {
443 areUntouchedDataLeft =
true;
448 areUntouchedDataLeft =
true;
453 wData.TsHitIndices(
h.Station()).push_back(caHitId);
455 range.first = caHitId + 1;
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();
478 int statNwindowHits = 0;
479 for (
int ista = 0; ista <
fParameters.GetNstationsActive(); ++ista) {
480 statNwindowHits += wData.TsHitIndices(ista).size();
482 statNhitsProcessed += statNwindowHits;
486 int currentChunk = (int) ((windowRange.first -
fStatTsStart) / 10.e6);
487 if (!areUntouchedDataLeft || currentChunk > statLastLogTimeChunk) {
488 statLastLogTimeChunk = currentChunk;
490 if (dataRead > 100.) {
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 "
497 <<
" Already reconstructed " <<
tracks.size() <<
" tracks on thread #" << iThread;
522 auto trackFirstHit = wData.RecoHitIndices().begin();
524 for (
const auto& track : wData.RecoTracks()) {
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;
534 const bool useFlag = !isTrackCompletelyInOverlap || !areUntouchedDataLeft;
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);
543 hitIndices.push_back(caHitId);
550 trackFirstHit += track.fNofHits;
554 if (windowRange.first > windowRange.second) {
557 if (!areUntouchedDataLeft) {