50 for (
int iLayer = 0; iLayer < mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) {
51 mTimeFrame->getTracklets()[iLayer].clear();
52 mTimeFrame->getTrackletsLabel(iLayer).clear();
54 std::fill(mTimeFrame->getTrackletsLookupTable()[iLayer - 1].begin(), mTimeFrame->getTrackletsLookupTable()[iLayer - 1].end(), 0);
58 const Vertex diamondVert(mTrkParams[iteration].Diamond, mTrkParams[iteration].DiamondCov, 1, 1.f);
59 gsl::span<const Vertex> diamondSpan(&diamondVert, 1);
61 mTaskArena->execute([&] {
62 auto forTracklets = [&](
auto Tag,
int iLayer,
int pivotROF,
int base,
int&
offset) ->
int {
63 if (!mTimeFrame->getROFMaskView().isROFEnabled(iLayer, pivotROF)) {
66 gsl::span<const Vertex> primaryVertices = mTrkParams[iteration].UseDiamond ? diamondSpan : mTimeFrame->getPrimaryVertices(iLayer, pivotROF);
67 if (primaryVertices.empty()) {
70 const int startVtx = iVertex >= 0 ? iVertex : 0;
71 const int endVtx = iVertex >= 0 ? o2::gpu::CAMath::Min(iVertex + 1,
int(primaryVertices.size())) :
int(primaryVertices.size());
72 if (endVtx <= startVtx || (iVertex + 1) > primaryVertices.size()) {
77 const auto& rofOverlap = mTimeFrame->getROFOverlapTableView().getOverlap(iLayer, iLayer + 1, pivotROF);
78 if (!rofOverlap.getEntries()) {
83 auto&
tracklets = mTimeFrame->getTracklets()[iLayer];
84 auto layer0 = mTimeFrame->getClustersOnLayer(pivotROF, iLayer);
89 const float meanDeltaR = mTrkParams[iteration].LayerRadii[iLayer + 1] - mTrkParams[iteration].LayerRadii[iLayer];
91 for (
int iCluster = 0; iCluster <
int(layer0.size()); ++iCluster) {
92 const Cluster& currentCluster = layer0[iCluster];
93 const int currentSortedIndex = mTimeFrame->getSortedIndex(pivotROF, iLayer, iCluster);
94 if (mTimeFrame->isClusterUsed(iLayer, currentCluster.
clusterId)) {
97 const float inverseR0 = 1.f / currentCluster.
radius;
99 for (
int iV = startVtx; iV < endVtx; ++iV) {
100 const auto& pv = primaryVertices[iV];
101 if (!mTimeFrame->getROFVertexLookupTableView().isVertexCompatible(iLayer, pivotROF, pv)) {
107 const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(mTimeFrame->getPositionResolution(iLayer)) + math_utils::Sq(mTrkParams[iteration].PVres) /
float(pv.getNContributors()));
108 const float tanLambda = (currentCluster.
zCoordinate - pv.getZ()) * inverseR0;
109 const float zAtRmin = tanLambda * (mTimeFrame->getMinR(iLayer + 1) - currentCluster.
radius) + currentCluster.
zCoordinate;
110 const float zAtRmax = tanLambda * (mTimeFrame->getMaxR(iLayer + 1) - currentCluster.
radius) + currentCluster.
zCoordinate;
112 const float sigmaZ = o2::gpu::CAMath::Sqrt(
113 math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInvDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * mTimeFrame->getMSangle(iLayer)));
114 const auto bins = o2::its::getBinsRect(currentCluster, iLayer + 1, zAtRmin, zAtRmax,
115 sigmaZ * mTrkParams[iteration].NSigmaCut, mTimeFrame->getPhiCut(iLayer),
116 mTimeFrame->getIndexTableUtils());
120 int phiBinsNum =
bins.w -
bins.y + 1;
121 if (phiBinsNum < 0) {
122 phiBinsNum += mTrkParams[iteration].PhiBins;
125 for (
int targetROF = rofOverlap.getFirstEntry(); targetROF < rofOverlap.getEntriesBound(); ++targetROF) {
126 if (!mTimeFrame->getROFMaskView().isROFEnabled(iLayer + 1, targetROF)) {
129 auto layer1 = mTimeFrame->getClustersOnLayer(targetROF, iLayer + 1);
130 if (layer1.empty()) {
133 const auto ts = mTimeFrame->getROFOverlapTableView().getTimeStamp(iLayer, pivotROF, iLayer + 1, targetROF);
134 if (!ts.isCompatible(pv.getTimeStamp())) {
137 const auto& targetIndexTable = mTimeFrame->getIndexTable(targetROF, iLayer + 1);
138 const int zBinRange = (
bins.z -
bins.x) + 1;
139 for (
int iPhi = 0; iPhi < phiBinsNum; ++iPhi) {
140 const int iPhiBin = (
bins.y + iPhi) % mTrkParams[iteration].PhiBins;
141 const int firstBinIdx = mTimeFrame->getIndexTableUtils().getBinIndex(
bins.x, iPhiBin);
142 const int maxBinIdx = firstBinIdx + zBinRange;
143 const int firstRow = targetIndexTable[firstBinIdx];
144 const int lastRow = targetIndexTable[maxBinIdx];
145 for (
int iNext = firstRow; iNext <
lastRow; ++iNext) {
146 if (iNext >=
int(layer1.size())) {
149 const Cluster& nextCluster = layer1[iNext];
150 if (mTimeFrame->isClusterUsed(iLayer + 1, nextCluster.
clusterId)) {
155 if (deltaZ / sigmaZ < mTrkParams[iteration].NSigmaCut &&
156 math_utils::isPhiDifferenceBelow(currentCluster.
phi, nextCluster.
phi, mTimeFrame->getPhiCut(iLayer))) {
159 if constexpr (
decltype(Tag)
::value == PassMode::OnePass::value) {
160 tracklets.emplace_back(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF, iLayer + 1, iNext), tanL, phi, ts);
161 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassCount::value) {
163 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassInsert::value) {
164 const int idx = base +
offset++;
165 tracklets[idx] =
Tracklet(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF, iLayer + 1, iNext), tanL, phi, ts);
177 if (mTaskArena->max_concurrency() <= 1) {
178 for (
int iLayer{0}; iLayer < mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) {
179 const int startROF = 0, endROF = mTimeFrame->getROFOverlapTableView().getLayer(iLayer).mNROFsTF;
180 for (
int pivotROF{startROF}; pivotROF < endROF; ++pivotROF) {
185 tbb::parallel_for(0, mTrkParams[iteration].TrackletsPerRoad(), [&](
const int iLayer) {
186 const int startROF = 0, endROF = mTimeFrame->getROFOverlapTableView().getLayer(iLayer).mNROFsTF;
188 tbb::parallel_for(startROF, endROF, [&](
const int pivotROF) {
191 std::exclusive_scan(perROFCount.begin(), perROFCount.end(), perROFCount.begin(), 0);
192 const int nTracklets = perROFCount.back();
193 mTimeFrame->getTracklets()[iLayer].resize(nTracklets);
194 if (nTracklets == 0) {
197 tbb::parallel_for(startROF, endROF, [&](
const int pivotROF) {
198 int baseIdx = perROFCount[pivotROF - startROF];
199 if (baseIdx == perROFCount[pivotROF + 1 - startROF]) {
208 tbb::parallel_for(0, mTrkParams[iteration].TrackletsPerRoad(), [&](
const int iLayer) {
211 auto& trkl{mTimeFrame->getTracklets()[iLayer]};
212 std::sort(trkl.begin(), trkl.end());
213 trkl.erase(std::unique(trkl.begin(), trkl.end()), trkl.end());
214 trkl.shrink_to_fit();
216 auto& lut{mTimeFrame->getTrackletsLookupTable()[iLayer - 1]};
218 for (
const auto& tkl : trkl) {
219 lut[tkl.firstClusterIndex + 1]++;
221 std::inclusive_scan(lut.begin(), lut.end(), lut.begin());
227 if (mTimeFrame->hasMCinformation() && mTrkParams[iteration].createArtefactLabels) {
228 tbb::parallel_for(0, mTrkParams[iteration].TrackletsPerRoad(), [&](
const int iLayer) {
229 for (
auto& trk : mTimeFrame->getTracklets()[iLayer]) {
231 int currentId{mTimeFrame->getClusters()[iLayer][trk.firstClusterIndex].clusterId};
232 int nextId{mTimeFrame->getClusters()[iLayer + 1][trk.secondClusterIndex].clusterId};
233 for (
const auto& lab1 : mTimeFrame->getClusterLabels(iLayer, currentId)) {
234 for (
const auto& lab2 : mTimeFrame->getClusterLabels(iLayer + 1, nextId)) {
235 if (lab1 == lab2 && lab1.isValid()) {
240 if (
label.isValid()) {
244 mTimeFrame->getTrackletsLabel(iLayer).emplace_back(
label);
254 for (
int iLayer = 0; iLayer < mTrkParams[iteration].CellsPerRoad(); ++iLayer) {
259 if (mTimeFrame->hasMCinformation() && mTrkParams[iteration].createArtefactLabels) {
264 mTaskArena->execute([&] {
266 const Tracklet& currentTracklet{mTimeFrame->getTracklets()[iLayer][iTracklet]};
268 const int nextLayerFirstTrackletIndex{mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex]};
269 const int nextLayerLastTrackletIndex{mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex + 1]};
271 for (
int iNextTracklet{nextLayerFirstTrackletIndex}; iNextTracklet < nextLayerLastTrackletIndex; ++iNextTracklet) {
272 const Tracklet& nextTracklet{mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet]};
273 if (mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet].firstClusterIndex != nextLayerClusterIndex) {
276 if (!currentTracklet.getTimeStamp().isCompatible(nextTracklet.getTimeStamp())) {
280 const float deltaTanLambdaSigma = std::abs(currentTracklet.tanLambda - nextTracklet.tanLambda) / mTrkParams[iteration].CellDeltaTanLambdaSigma;
281 if (deltaTanLambdaSigma < mTrkParams[iteration].NSigmaCut) {
285 mTimeFrame->getClusters()[iLayer][currentTracklet.firstClusterIndex].clusterId,
286 mTimeFrame->getClusters()[iLayer + 1][nextTracklet.firstClusterIndex].clusterId,
287 mTimeFrame->getClusters()[iLayer + 2][nextTracklet.secondClusterIndex].clusterId};
288 const auto& cluster1_glo = mTimeFrame->getUnsortedClusters()[iLayer][clusId[0]];
289 const auto& cluster2_glo = mTimeFrame->getUnsortedClusters()[iLayer + 1][clusId[1]];
290 const auto& cluster3_tf = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer + 2)[clusId[2]];
291 auto track{o2::its::track::buildTrackSeed(cluster1_glo, cluster2_glo, cluster3_tf, mBz)};
295 for (
int iC{2}; iC--;) {
296 const TrackingFrameInfo& trackingHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer + iC)[clusId[iC]];
306 if (!track.correctForMaterial(mTrkParams[iteration].LayerxX0[iLayer + iC], mTrkParams[iteration].LayerxX0[iLayer + iC] *
constants::Radl *
constants::Rho,
true)) {
311 if (!iC && predChi2 > mTrkParams[iteration].MaxChi2ClusterAttachment) {
323 TimeEstBC ts = currentTracklet.getTimeStamp();
324 ts += nextTracklet.getTimeStamp();
325 if constexpr (
decltype(Tag)
::value == PassMode::OnePass::value) {
326 layerCells.emplace_back(iLayer, clusId[0], clusId[1], clusId[2], iTracklet, iNextTracklet, track, chi2, ts);
328 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassCount::value) {
330 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassInsert::value) {
331 layerCells[
offset++] =
CellSeed(iLayer, clusId[0], clusId[1], clusId[2], iTracklet, iNextTracklet, track, chi2, ts);
333 static_assert(
false,
"Unknown mode!");
341 for (
int iLayer = 0; iLayer < mTrkParams[iteration].CellsPerRoad(); ++iLayer) {
342 if (mTimeFrame->getTracklets()[iLayer + 1].empty() ||
343 mTimeFrame->getTracklets()[iLayer].empty()) {
344 if (iLayer < mTrkParams[iteration].TrackletsPerRoad()) {
351 auto& layerCells = mTimeFrame->getCells()[iLayer];
352 const int currentLayerTrackletsNum{
static_cast<int>(mTimeFrame->getTracklets()[iLayer].size())};
354 if (mTaskArena->max_concurrency() <= 1) {
355 for (
int iTracklet{0}; iTracklet < currentLayerTrackletsNum; ++iTracklet) {
356 perTrackletCount[iTracklet] = forTrackletCells(
PassMode::OnePass{}, iLayer, layerCells, iTracklet);
358 std::exclusive_scan(perTrackletCount.begin(), perTrackletCount.end(), perTrackletCount.begin(), 0);
360 tbb::parallel_for(0, currentLayerTrackletsNum, [&](
const int iTracklet) {
364 std::exclusive_scan(perTrackletCount.begin(), perTrackletCount.end(), perTrackletCount.begin(), 0);
365 auto totalCells{perTrackletCount.back()};
366 if (totalCells == 0) {
368 auto& lut = mTimeFrame->getCellsLookupTable()[iLayer - 1];
369 lut.resize(currentLayerTrackletsNum + 1);
370 std::fill(lut.begin(), lut.end(), 0);
376 layerCells.resize(totalCells);
378 tbb::parallel_for(0, currentLayerTrackletsNum, [&](
const int iTracklet) {
379 int offset = perTrackletCount[iTracklet];
380 if (
offset == perTrackletCount[iTracklet + 1]) {
388 auto& lut = mTimeFrame->getCellsLookupTable()[iLayer - 1];
389 lut.resize(currentLayerTrackletsNum + 1);
390 std::copy_n(perTrackletCount.begin(), currentLayerTrackletsNum + 1, lut.begin());
393 if (mTimeFrame->hasMCinformation() && mTrkParams[iteration].createArtefactLabels) {
394 auto&
labels = mTimeFrame->getCellsLabel(iLayer);
395 labels.reserve(layerCells.size());
396 for (
const auto& cell : layerCells) {
397 MCCompLabel currentLab{mTimeFrame->getTrackletsLabel(iLayer)[cell.getFirstTrackletIndex()]};
398 MCCompLabel nextLab{mTimeFrame->getTrackletsLabel(iLayer + 1)[cell.getSecondTrackletIndex()]};
410 for (
int iLayer = mTrkParams[iteration].CellsPerRoad(); iLayer < mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) {
420 int cell{-1}, nextCell{-1},
level{-1};
423 mTaskArena->execute([&] {
424 for (
int iLayer{0}; iLayer < mTrkParams[iteration].NeighboursPerRoad(); ++iLayer) {
427 if (mTimeFrame->getCells()[iLayer + 1].empty() ||
428 mTimeFrame->getCellsLookupTable()[iLayer].empty()) {
432 int nCells{
static_cast<int>(mTimeFrame->getCells()[iLayer].size())};
435 auto forCellNeighbour = [&](
auto Tag,
int iCell,
int offset = 0) ->
int {
436 const auto& currentCellSeed{mTimeFrame->getCells()[iLayer][iCell]};
437 const int nextLayerTrackletIndex{currentCellSeed.getSecondTrackletIndex()};
438 const int nextLayerFirstCellIndex{mTimeFrame->getCellsLookupTable()[iLayer][nextLayerTrackletIndex]};
439 const int nextLayerLastCellIndex{mTimeFrame->getCellsLookupTable()[iLayer][nextLayerTrackletIndex + 1]};
440 int foundNextCells{0};
441 for (
int iNextCell{nextLayerFirstCellIndex}; iNextCell < nextLayerLastCellIndex; ++iNextCell) {
442 auto nextCellSeed{mTimeFrame->getCells()[iLayer + 1][iNextCell]};
443 if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex || !currentCellSeed.getTimeStamp().isCompatible(nextCellSeed.getTimeStamp())) {
447 if (!nextCellSeed.rotate(currentCellSeed.getAlpha()) ||
448 !nextCellSeed.propagateTo(currentCellSeed.getX(), getBz())) {
452 float chi2 = currentCellSeed.getPredictedChi2(nextCellSeed);
453 if (chi2 > mTrkParams[iteration].MaxChi2ClusterAttachment) {
457 if constexpr (
decltype(Tag)
::value == PassMode::OnePass::value) {
458 cellsNeighbours.emplace_back(iCell, iNextCell, currentCellSeed.getLevel() + 1);
459 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassCount::value) {
461 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassInsert::value) {
462 cellsNeighbours[
offset++] = {iCell, iNextCell, currentCellSeed.getLevel() + 1};
464 static_assert(
false,
"Unknown mode!");
467 return foundNextCells;
470 if (mTaskArena->max_concurrency() <= 1) {
471 for (
int iCell{0}; iCell < nCells; ++iCell) {
476 tbb::parallel_for(0, nCells, [&](
const int iCell) {
480 std::exclusive_scan(perCellCount.begin(), perCellCount.end(), perCellCount.begin(), 0);
481 int totalCellNeighbours = perCellCount.back();
482 if (totalCellNeighbours == 0) {
486 cellsNeighbours.resize(totalCellNeighbours);
488 tbb::parallel_for(0, nCells, [&](
const int iCell) {
489 int offset = perCellCount[iCell];
490 if (
offset == perCellCount[iCell + 1]) {
497 if (cellsNeighbours.empty()) {
501 tbb::parallel_sort(cellsNeighbours.begin(), cellsNeighbours.end(), [](
const auto&
a,
const auto&
b) {
502 return a.nextCell < b.nextCell;
505 auto& cellsNeighbourLUT = mTimeFrame->getCellsNeighboursLUT()[iLayer];
506 cellsNeighbourLUT.assign(mTimeFrame->getCells()[iLayer + 1].size(), 0);
507 for (
const auto& neigh : cellsNeighbours) {
508 ++cellsNeighbourLUT[neigh.nextCell];
510 std::inclusive_scan(cellsNeighbourLUT.begin(), cellsNeighbourLUT.end(), cellsNeighbourLUT.begin());
512 mTimeFrame->getCellsNeighbours()[iLayer].reserve(cellsNeighbours.size());
513 std::ranges::transform(cellsNeighbours, std::back_inserter(mTimeFrame->getCellsNeighbours()[iLayer]), [](
const auto& neigh) { return neigh.cell; });
515 for (
auto it = cellsNeighbours.begin(); it != cellsNeighbours.end();) {
516 int cellIdx = it->nextCell;
517 int maxLvl = it->level;
518 while (++it != cellsNeighbours.end() && it->nextCell == cellIdx) {
519 maxLvl = std::max(maxLvl, it->level);
521 mTimeFrame->getCells()[iLayer + 1][cellIdx].setLevel(maxLvl);
536 mTaskArena->execute([&] {
537 auto forCellNeighbours = [&](
auto Tag,
int iCell,
int offset = 0) ->
int {
538 const auto& currentCell{currentCellSeed[iCell]};
540 if constexpr (
decltype(Tag)
::value != PassMode::TwoPassInsert::value) {
541 if (currentCell.getLevel() != iLevel) {
544 if (currentCellId.empty() && (mTimeFrame->isClusterUsed(iLayer, currentCell.getFirstClusterIndex()) ||
545 mTimeFrame->isClusterUsed(iLayer + 1, currentCell.getSecondClusterIndex()) ||
546 mTimeFrame->isClusterUsed(iLayer + 2, currentCell.getThirdClusterIndex()))) {
551 const int cellId = currentCellId.empty() ? iCell : currentCellId[iCell];
552 const int startNeighbourId{cellId ? mTimeFrame->getCellsNeighboursLUT()[iLayer - 1][cellId - 1] : 0};
553 const int endNeighbourId{mTimeFrame->getCellsNeighboursLUT()[iLayer - 1][cellId]};
555 for (
int iNeighbourCell{startNeighbourId}; iNeighbourCell < endNeighbourId; ++iNeighbourCell) {
556 const int neighbourCellId = mTimeFrame->getCellsNeighbours()[iLayer - 1][iNeighbourCell];
557 const auto& neighbourCell = mTimeFrame->getCells()[iLayer - 1][neighbourCellId];
558 if (neighbourCell.getSecondTrackletIndex() != currentCell.getFirstTrackletIndex()) {
561 if (!currentCell.getTimeStamp().isCompatible(neighbourCell.getTimeStamp())) {
564 if (currentCell.getLevel() - 1 != neighbourCell.getLevel()) {
567 if (mTimeFrame->isClusterUsed(iLayer - 1, neighbourCell.getFirstClusterIndex())) {
573 seed.getTimeStamp() = currentCell.getTimeStamp();
574 seed.getTimeStamp() += neighbourCell.getTimeStamp();
575 const auto& trHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer - 1)[neighbourCell.getFirstClusterIndex()];
577 if (!seed.rotate(trHit.alphaTrackingFrame)) {
585 if (mTrkParams[iteration].CorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) {
586 if (!seed.correctForMaterial(mTrkParams[iteration].LayerxX0[iLayer - 1], mTrkParams[iteration].LayerxX0[iLayer - 1] *
constants::Radl *
constants::Rho,
true)) {
591 auto predChi2{seed.getPredictedChi2Quiet(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)};
592 if ((predChi2 > mTrkParams[iteration].MaxChi2ClusterAttachment) || predChi2 < 0.f) {
595 seed.setChi2(seed.getChi2() + predChi2);
596 if (!seed.o2::track::TrackParCov::update(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)) {
600 if constexpr (
decltype(Tag)
::value != PassMode::TwoPassCount::value) {
601 seed.getClusters()[iLayer - 1] = neighbourCell.getFirstClusterIndex();
602 seed.setLevel(neighbourCell.getLevel());
603 seed.setFirstTrackletIndex(neighbourCell.getFirstTrackletIndex());
604 seed.setSecondTrackletIndex(neighbourCell.getSecondTrackletIndex());
607 if constexpr (
decltype(Tag)
::value == PassMode::OnePass::value) {
608 updatedCellSeeds.push_back(seed);
609 updatedCellsIds.push_back(neighbourCellId);
610 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassCount::value) {
612 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassInsert::value) {
613 updatedCellSeeds[
offset] = seed;
614 updatedCellsIds[
offset++] = neighbourCellId;
616 static_assert(
false,
"Unknown mode!");
622 const int nCells =
static_cast<int>(currentCellSeed.size());
623 if (mTaskArena->max_concurrency() <= 1) {
624 for (
int iCell{0}; iCell < nCells; ++iCell) {
629 tbb::parallel_for(0, nCells, [&](
const int iCell) {
633 std::exclusive_scan(perCellCount.begin(), perCellCount.end(), perCellCount.begin(), 0);
634 auto totalNeighbours{perCellCount.back()};
635 if (totalNeighbours == 0) {
638 updatedCellSeeds.resize(totalNeighbours);
639 updatedCellsIds.resize(totalNeighbours);
641 tbb::parallel_for(0, nCells, [&](
const int iCell) {
642 int offset = perCellCount[iCell];
643 if (
offset == perCellCount[iCell + 1]) {
657 firstClusters.resize(mTrkParams[iteration].NLayers);
658 sharedFirstClusters.resize(mTrkParams[iteration].NLayers);
661 const Cluster* unsortedClusters[NLayers]{};
662 for (
int iLayer = 0; iLayer < NLayers; ++iLayer) {
663 tfInfos[iLayer] = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer).data();
664 unsortedClusters[iLayer] = mTimeFrame->getUnsortedClusters()[iLayer].data();
666 for (
int startLevel{mTrkParams[iteration].CellsPerRoad()}; startLevel >= mTrkParams[iteration].CellMinimumLevel(); --startLevel) {
668 auto seedFilter = [&](
const auto& seed) {
669 return seed.getQ2Pt() <= 1.e3 && seed.getChi2() <= mTrkParams[iteration].MaxChi2NDF * ((startLevel + 2) * 2 - 5);
673 for (
int startLayer{mTrkParams[iteration].NeighboursPerRoad()}; startLayer >= startLevel - 1; --startLayer) {
674 if ((mTrkParams[iteration].StartLayerMask & (1 << (startLayer + 2))) == 0) {
681 processNeighbours(iteration, startLayer, startLevel, mTimeFrame->getCells()[startLayer], lastCellId, updatedCellSeed, updatedCellId);
683 int level = startLevel;
684 for (
int iLayer{startLayer - 1}; iLayer > 0 &&
level > 2; --iLayer) {
685 lastCellSeed.swap(updatedCellSeed);
686 lastCellId.swap(updatedCellId);
689 processNeighbours(iteration, iLayer, --
level, lastCellSeed, lastCellId, updatedCellSeed, updatedCellId);
694 if (!updatedCellSeed.empty()) {
695 trackSeeds.reserve(trackSeeds.size() + std::count_if(updatedCellSeed.begin(), updatedCellSeed.end(), seedFilter));
696 std::copy_if(updatedCellSeed.begin(), updatedCellSeed.end(), std::back_inserter(trackSeeds), seedFilter);
700 if (trackSeeds.empty()) {
705 mTaskArena->execute([&] {
706 auto forSeed = [&](
auto Tag,
int iSeed,
int offset = 0) {
708 bool refitSuccess = track::refitTrack<NLayers>(trackSeeds[iSeed],
710 mTrkParams[iteration].MaxChi2ClusterAttachment,
711 mTrkParams[iteration].MaxChi2NDF,
715 mTrkParams[iteration].LayerxX0.data(),
716 mTrkParams[iteration].LayerRadii.data(),
717 mTrkParams[iteration].MinPt.data(),
719 mTrkParams[iteration].CorrType,
720 mTrkParams[iteration].ReseedIfShorter,
721 mTrkParams[iteration].ShiftRefToCluster,
722 mTrkParams[iteration].RepeatRefitOut);
725 if constexpr (
decltype(Tag)
::value == PassMode::OnePass::value) {
726 tracks.push_back(temporaryTrack);
727 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassCount::value) {
729 }
else if constexpr (
decltype(Tag)
::value == PassMode::TwoPassInsert::value) {
730 tracks[
offset] = temporaryTrack;
732 static_assert(
false,
"Unknown mode!");
739 const int nSeeds =
static_cast<int>(trackSeeds.size());
740 if (mTaskArena->max_concurrency() <= 1) {
741 for (
int iSeed{0}; iSeed < nSeeds; ++iSeed) {
747 tbb::parallel_for(0, nSeeds, [&](
const int iSeed) {
751 std::exclusive_scan(perSeedCount.begin(), perSeedCount.end(), perSeedCount.begin(), 0);
752 auto totalTracks{perSeedCount.back()};
753 if (totalTracks == 0) {
756 tracks.resize(totalTracks);
758 tbb::parallel_for(0, nSeeds, [&](
const int iSeed) {
759 if (perSeedCount[iSeed] == perSeedCount[iSeed + 1]) {
769 std::sort(tracks.begin(), tracks.end(), [](
const auto&
a,
const auto&
b) {
770 return a.getChi2() < b.getChi2();
773 acceptTracks(iteration, tracks, firstClusters, sharedFirstClusters);
775 markTracks(iteration, sharedFirstClusters);
781 const float smallestROFHalf = mTimeFrame->getROFOverlapTableView().getClockLayer().mROFLength * 0.5f;
782 for (
auto& track : tracks) {
784 bool isFirstShared{
false};
785 int firstLayer{-1}, firstCluster{-1};
786 for (
int iLayer{0}; iLayer < mTrkParams[iteration].NLayers; ++iLayer) {
790 bool isShared = mTimeFrame->isClusterUsed(iLayer, track.getClusterIndex(iLayer));
791 nShared +=
int(isShared);
792 if (firstLayer < 0) {
793 firstCluster = track.getClusterIndex(iLayer);
794 isFirstShared = isShared && mTrkParams[iteration].AllowSharingFirstCluster && std::find(firstClusters[iLayer].begin(), firstClusters[iLayer].
end(), firstCluster) != firstClusters[iLayer].end();
800 if (nShared -
int(isFirstShared && mTrkParams[iteration].AllowSharingFirstCluster) > mTrkParams[iteration].ClusterSharing) {
804 bool firstCls{
true}, nominalCompatible{
true};
806 for (
int iLayer{0}; iLayer < mTrkParams[iteration].NLayers; ++iLayer) {
810 mTimeFrame->markUsedCluster(iLayer, track.getClusterIndex(iLayer));
811 int currentROF = mTimeFrame->getClusterROF(iLayer, track.getClusterIndex(iLayer));
812 const auto nominalROFTS = mTimeFrame->getROFOverlapTableView().getLayer(iLayer).getROFTimeBounds(currentROF);
813 const auto expandedROFTS = mTimeFrame->getROFOverlapTableView().getLayer(iLayer).getROFTimeBounds(currentROF,
true);
816 nominalTS = nominalROFTS;
817 expandedTS = expandedROFTS;
819 if (nominalCompatible) {
820 if (nominalTS.isCompatible(nominalROFTS)) {
821 nominalTS += nominalROFTS;
823 nominalCompatible =
false;
826 if (!expandedTS.isCompatible(expandedROFTS)) {
827 LOGP(fatal,
"TS {}+/-{} are incompatible with {}+/-{}, this should not happen!", expandedROFTS.getTimeStamp(), expandedROFTS.getTimeStampError(), expandedTS.getTimeStamp(), expandedTS.getTimeStampError());
829 expandedTS += expandedROFTS;
832 track.getTimeStamp() = (nominalCompatible ? nominalTS : expandedTS).makeSymmetrical();
835 if (track.getTimeStamp().getTimeStampError() > smallestROFHalf) {
836 track.getTimeStamp().setTimeStampError(smallestROFHalf);
838 track.setUserField(0);
839 track.getParamOut().setUserField(0);
840 mTimeFrame->getTracks().emplace_back(track);
842 if (mTrkParams[iteration].AllowSharingFirstCluster) {
843 firstClusters[firstLayer].push_back(firstCluster);
845 sharedFirstClusters[firstLayer].push_back(firstCluster);