58#ifdef OPTIMISATION_OUTPUT
60 std::ofstream off(fmt::format(
"tracklets{}.txt", iter++));
63 for (
int iLayer = 0; iLayer <
mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) {
64 tf->getTracklets()[iLayer].clear();
65 tf->getTrackletsLabel(iLayer).clear();
67 std::fill(
tf->getTrackletsLookupTable()[iLayer - 1].begin(),
tf->getTrackletsLookupTable()[iLayer - 1].end(), 0);
71 const Vertex diamondVert({
mTrkParams[iteration].Diamond[0],
mTrkParams[iteration].Diamond[1],
mTrkParams[iteration].Diamond[2]}, {25.e-6f, 0.f, 0.f, 25.e-6f, 0.f, 36.f}, 1, 1.f);
72 gsl::span<const Vertex> diamondSpan(&diamondVert, 1);
73 int startROF{
mTrkParams[iteration].nROFsPerIterations > 0 ? iROFslice *
mTrkParams[iteration].nROFsPerIterations : 0};
74 int endROF{gpu::GPUCommonMath::Min(
mTrkParams[iteration].nROFsPerIterations > 0 ? (iROFslice + 1) *
mTrkParams[iteration].nROFsPerIterations +
mTrkParams[iteration].DeltaROF :
tf->getNrof(),
tf->getNrof())};
75 for (
int rof0{startROF}; rof0 < endROF; ++rof0) {
76 gsl::span<const Vertex> primaryVertices =
mTrkParams[iteration].UseDiamond ? diamondSpan :
tf->getPrimaryVertices(rof0);
77 const int startVtx{iVertex >= 0 ? iVertex : 0};
78 const int endVtx{iVertex >= 0 ? o2::gpu::CAMath::Min(iVertex + 1,
static_cast<int>(primaryVertices.size())) :
static_cast<int>(primaryVertices.size())};
79 int minRof = o2::gpu::CAMath::Max(startROF, rof0 -
mTrkParams[iteration].DeltaROF);
80 int maxRof = o2::gpu::CAMath::Min(endROF - 1, rof0 +
mTrkParams[iteration].DeltaROF);
81#pragma omp parallel for num_threads(mNThreads)
82 for (
int iLayer = 0; iLayer <
mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) {
83 gsl::span<const Cluster> layer0 =
tf->getClustersOnLayer(rof0, iLayer);
87 float meanDeltaR{
mTrkParams[iteration].LayerRadii[iLayer + 1] -
mTrkParams[iteration].LayerRadii[iLayer]};
89 const int currentLayerClustersNum{
static_cast<int>(layer0.size())};
90 for (
int iCluster{0}; iCluster < currentLayerClustersNum; ++iCluster) {
91 const Cluster& currentCluster{layer0[iCluster]};
92 const int currentSortedIndex{
tf->getSortedIndex(rof0, iLayer, iCluster)};
94 if (
tf->isClusterUsed(iLayer, currentCluster.clusterId)) {
97 const float inverseR0{1.f / currentCluster.
radius};
99 for (
int iV{startVtx}; iV < endVtx; ++iV) {
100 auto& primaryVertex{primaryVertices[iV]};
101 if (primaryVertex.isFlagSet(2) && iteration != 3) {
104 const float resolution = o2::gpu::CAMath::Sqrt(Sq(
mTrkParams[iteration].PVres) / primaryVertex.getNContributors() + Sq(
tf->getPositionResolution(iLayer)));
106 const float tanLambda{(currentCluster.zCoordinate - primaryVertex.getZ()) * inverseR0};
108 const float zAtRmin{tanLambda * (
tf->getMinR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate};
109 const float zAtRmax{tanLambda * (
tf->getMaxR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate};
111 const float sqInverseDeltaZ0{1.f / (Sq(currentCluster.zCoordinate - primaryVertex.getZ()) + 2.e-8f)};
112 const float sigmaZ{o2::gpu::CAMath::Sqrt(Sq(resolution) * Sq(tanLambda) * ((Sq(inverseR0) + sqInverseDeltaZ0) * Sq(meanDeltaR) + 1.f) + Sq(meanDeltaR *
tf->getMSangle(iLayer)))};
114 const int4 selectedBinsRect{
getBinsRect(currentCluster, iLayer + 1, zAtRmin, zAtRmax,
115 sigmaZ *
mTrkParams[iteration].NSigmaCut,
tf->getPhiCut(iLayer))};
116 if (selectedBinsRect.x == 0 && selectedBinsRect.y == 0 && selectedBinsRect.z == 0 && selectedBinsRect.w == 0) {
120 int phiBinsNum{selectedBinsRect.
w - selectedBinsRect.y + 1};
122 if (phiBinsNum < 0) {
126 for (
int rof1{minRof}; rof1 <= maxRof; ++rof1) {
127 gsl::span<const Cluster> layer1 =
tf->getClustersOnLayer(rof1, iLayer + 1);
128 if (layer1.empty()) {
131 for (
int iPhiCount{0}; iPhiCount < phiBinsNum; iPhiCount++) {
132 int iPhiBin = (selectedBinsRect.y + iPhiCount) %
mTrkParams[iteration].PhiBins;
133 const int firstBinIndex{
tf->mIndexTableUtils.getBinIndex(selectedBinsRect.x, iPhiBin)};
134 const int maxBinIndex{firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1};
136 if (firstBinIndex < 0 || firstBinIndex >
tf->getIndexTable(rof1, iLayer + 1).size() ||
137 maxBinIndex < 0 || maxBinIndex >
tf->getIndexTable(rof1, iLayer + 1).size()) {
138 std::cout << iLayer <<
"\t" << iCluster <<
"\t" << zAtRmin <<
"\t" << zAtRmax <<
"\t" << sigmaZ *
mTrkParams[iteration].NSigmaCut <<
"\t" <<
tf->getPhiCut(iLayer) << std::endl;
139 std::cout << currentCluster.zCoordinate <<
"\t" << primaryVertex.getZ() <<
"\t" << currentCluster.radius << std::endl;
140 std::cout <<
tf->getMinR(iLayer + 1) <<
"\t" << currentCluster.radius <<
"\t" << currentCluster.zCoordinate << std::endl;
141 std::cout <<
"Illegal access to IndexTable " << firstBinIndex <<
"\t" << maxBinIndex <<
"\t" << selectedBinsRect.z <<
"\t" << selectedBinsRect.x << std::endl;
145 const int firstRowClusterIndex =
tf->getIndexTable(rof1, iLayer + 1)[firstBinIndex];
146 const int maxRowClusterIndex =
tf->getIndexTable(rof1, iLayer + 1)[maxBinIndex];
147 for (
int iNextCluster{firstRowClusterIndex}; iNextCluster < maxRowClusterIndex; ++iNextCluster) {
148 if (iNextCluster >= (
int)layer1.size()) {
152 const Cluster& nextCluster{layer1[iNextCluster]};
153 if (
tf->isClusterUsed(iLayer + 1, nextCluster.clusterId)) {
157 const float deltaPhi{gpu::GPUCommonMath::Abs(currentCluster.phi - nextCluster.phi)};
158 const float deltaZ{gpu::GPUCommonMath::Abs(tanLambda * (nextCluster.radius - currentCluster.radius) +
159 currentCluster.zCoordinate - nextCluster.zCoordinate)};
161#ifdef OPTIMISATION_OUTPUT
163 int currentId{currentCluster.clusterId};
164 int nextId{nextCluster.clusterId};
165 for (
auto& lab1 :
tf->getClusterLabels(iLayer, currentId)) {
166 for (
auto& lab2 :
tf->getClusterLabels(iLayer + 1, nextId)) {
167 if (lab1 == lab2 && lab1.isValid()) {
172 if (
label.isValid()) {
176 off << fmt::format(
"{}\t{:d}\t{}\t{}\t{}\t{}", iLayer,
label.isValid(), (tanLambda * (nextCluster.radius - currentCluster.radius) + currentCluster.zCoordinate - nextCluster.zCoordinate) / sigmaZ, tanLambda, resolution, sigmaZ) << std::endl;
179 if (deltaZ / sigmaZ <
mTrkParams[iteration].NSigmaCut &&
180 (deltaPhi < tf->getPhiCut(iLayer) ||
183 tf->getTrackletsLookupTable()[iLayer - 1][currentSortedIndex]++;
185 const float phi{o2::gpu::GPUCommonMath::ATan2(currentCluster.yCoordinate - nextCluster.yCoordinate,
186 currentCluster.xCoordinate - nextCluster.xCoordinate)};
187 const float tanL{(currentCluster.zCoordinate - nextCluster.zCoordinate) /
188 (currentCluster.radius - nextCluster.radius)};
189 tf->getTracklets()[iLayer].emplace_back(currentSortedIndex,
tf->getSortedIndex(rof1, iLayer + 1, iNextCluster), tanL, phi, rof0, rof1);
198 if (!
tf->checkMemory(
mTrkParams[iteration].MaxMemory)) {
202#pragma omp parallel for num_threads(mNThreads)
203 for (
int iLayer = 0; iLayer <
mTrkParams[iteration].CellsPerRoad(); ++iLayer) {
205 auto& trkl{
tf->getTracklets()[iLayer + 1]};
207 return a.firstClusterIndex < b.firstClusterIndex || (a.firstClusterIndex == b.firstClusterIndex && a.secondClusterIndex < b.secondClusterIndex);
210 auto& lut{
tf->getTrackletsLookupTable()[iLayer]};
211 int id0{-1}, id1{-1};
212 std::vector<Tracklet> newTrk;
213 newTrk.reserve(trkl.size());
214 for (
auto& trk : trkl) {
215 if (trk.firstClusterIndex == id0 && trk.secondClusterIndex == id1) {
218 id0 = trk.firstClusterIndex;
219 id1 = trk.secondClusterIndex;
220 newTrk.push_back(trk);
226 std::exclusive_scan(lut.begin(), lut.end(), lut.begin(), 0);
227 lut.push_back(trkl.size());
230 std::sort(
tf->getTracklets()[0].begin(),
tf->getTracklets()[0].end(), [](
const Tracklet&
a,
const Tracklet&
b) {
231 return a.firstClusterIndex < b.firstClusterIndex || (a.firstClusterIndex == b.firstClusterIndex && a.secondClusterIndex < b.secondClusterIndex);
233 int id0{-1}, id1{-1};
234 std::vector<Tracklet> newTrk;
235 newTrk.reserve(
tf->getTracklets()[0].size());
236 for (
auto& trk :
tf->getTracklets()[0]) {
237 if (trk.firstClusterIndex != id0 || trk.secondClusterIndex != id1) {
238 id0 = trk.firstClusterIndex;
239 id1 = trk.secondClusterIndex;
240 newTrk.push_back(trk);
243 tf->getTracklets()[0].swap(newTrk);
246 if (
tf->hasMCinformation()) {
247 for (
int iLayer{0}; iLayer <
mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) {
248 for (
auto& trk :
tf->getTracklets()[iLayer]) {
250 int currentId{
tf->getClusters()[iLayer][trk.firstClusterIndex].clusterId};
251 int nextId{
tf->getClusters()[iLayer + 1][trk.secondClusterIndex].clusterId};
252 for (
auto& lab1 :
tf->getClusterLabels(iLayer, currentId)) {
253 for (
auto& lab2 :
tf->getClusterLabels(iLayer + 1, nextId)) {
254 if (lab1 == lab2 && lab1.isValid()) {
259 if (
label.isValid()) {
263 tf->getTrackletsLabel(iLayer).emplace_back(
label);
271#ifdef OPTIMISATION_OUTPUT
273 std::ofstream off(fmt::format(
"cells{}.txt", iter++));
276 for (
int iLayer = 0; iLayer <
mTrkParams[iteration].CellsPerRoad(); ++iLayer) {
285#pragma omp parallel for num_threads(mNThreads)
286 for (
int iLayer = 0; iLayer <
mTrkParams[iteration].CellsPerRoad(); ++iLayer) {
288 if (
tf->getTracklets()[iLayer + 1].empty() ||
289 tf->getTracklets()[iLayer].empty()) {
293#ifdef OPTIMISATION_OUTPUT
294 float resolution{o2::gpu::CAMath::Sqrt(0.5f * (
mTrkParams[iteration].SystErrorZ2[iLayer] +
mTrkParams[iteration].SystErrorZ2[iLayer + 1] +
mTrkParams[iteration].SystErrorZ2[iLayer + 2] +
mTrkParams[iteration].SystErrorY2[iLayer] +
mTrkParams[iteration].SystErrorY2[iLayer + 1] +
mTrkParams[iteration].SystErrorY2[iLayer + 2])) /
mTrkParams[iteration].LayerResolution[iLayer]};
295 resolution = resolution > 1.e-12 ? resolution : 1.f;
297 const int currentLayerTrackletsNum{
static_cast<int>(
tf->getTracklets()[iLayer].size())};
298 for (
int iTracklet{0}; iTracklet < currentLayerTrackletsNum; ++iTracklet) {
300 const Tracklet& currentTracklet{
tf->getTracklets()[iLayer][iTracklet]};
302 const int nextLayerFirstTrackletIndex{
303 tf->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex]};
304 const int nextLayerLastTrackletIndex{
305 tf->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex + 1]};
307 if (nextLayerFirstTrackletIndex == nextLayerLastTrackletIndex) {
311 for (
int iNextTracklet{nextLayerFirstTrackletIndex}; iNextTracklet < nextLayerLastTrackletIndex; ++iNextTracklet) {
312 if (
tf->getTracklets()[iLayer + 1][iNextTracklet].firstClusterIndex != nextLayerClusterIndex) {
315 const Tracklet& nextTracklet{
tf->getTracklets()[iLayer + 1][iNextTracklet]};
316 const float deltaTanLambda{std::abs(currentTracklet.tanLambda - nextTracklet.tanLambda)};
318#ifdef OPTIMISATION_OUTPUT
319 bool good{
tf->getTrackletsLabel(iLayer)[iTracklet] ==
tf->getTrackletsLabel(iLayer + 1)[iNextTracklet]};
320 float signedDelta{currentTracklet.
tanLambda - nextTracklet.tanLambda};
321 off << fmt::format(
"{}\t{:d}\t{}\t{}\t{}\t{}", iLayer, good, signedDelta, signedDelta / (
mTrkParams[iteration].CellDeltaTanLambdaSigma), tanLambda, resolution) << std::endl;
324 if (deltaTanLambda /
mTrkParams[iteration].CellDeltaTanLambdaSigma <
mTrkParams[iteration].NSigmaCut) {
334 auto track{buildTrackSeed(cluster1_glo, cluster2_glo, cluster3_tf)};
338 for (
int iC{2}; iC--;) {
341 if (!track.rotate(trackingHit.alphaTrackingFrame)) {
345 if (!track.propagateTo(trackingHit.xTrackingFrame,
getBz())) {
349 constexpr float radl = 9.36f;
350 constexpr float rho = 2.33f;
351 if (!track.correctForMaterial(
mTrkParams[0].LayerxX0[iLayer + iC],
mTrkParams[0].LayerxX0[iLayer] * radl * rho,
true)) {
355 auto predChi2{track.getPredictedChi2Quiet(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)};
356 if (!track.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) {
359 if (!iC && predChi2 >
mTrkParams[iteration].MaxChi2ClusterAttachment) {
368 if (iLayer > 0 && (
int)
tf->getCellsLookupTable()[iLayer - 1].size() <= iTracklet) {
369 tf->getCellsLookupTable()[iLayer - 1].resize(iTracklet + 1,
tf->getCells()[iLayer].size());
371 tf->getCells()[iLayer].emplace_back(iLayer, clusId[0], clusId[1], clusId[2],
372 iTracklet, iNextTracklet, track, chi2);
377 tf->getCellsLookupTable()[iLayer - 1].resize(currentLayerTrackletsNum + 1,
tf->getCells()[iLayer].size());
380 if (!
tf->checkMemory(
mTrkParams[iteration].MaxMemory)) {
385 if (
tf->hasMCinformation()) {
386 for (
int iLayer{0}; iLayer <
mTrkParams[iteration].CellsPerRoad(); ++iLayer) {
387 for (
auto& cell :
tf->getCells()[iLayer]) {
388 MCCompLabel currentLab{
tf->getTrackletsLabel(iLayer)[cell.getFirstTrackletIndex()]};
389 MCCompLabel nextLab{
tf->getTrackletsLabel(iLayer + 1)[cell.getSecondTrackletIndex()]};
390 tf->getCellsLabel(iLayer).emplace_back(currentLab == nextLab ? currentLab :
MCCompLabel());
396 for (
int iLayer{0}; iLayer <
mTrkParams[iteration].CellsPerRoad(); ++iLayer) {
397 std::cout <<
"Cells on layer " << iLayer <<
" " <<
tf->getCells()[iLayer].size() << std::endl;
404#ifdef OPTIMISATION_OUTPUT
405 std::ofstream off(fmt::format(
"cellneighs{}.txt", iteration));
407 for (
int iLayer{0}; iLayer <
mTrkParams[iteration].CellsPerRoad() - 1; ++iLayer) {
408 const int nextLayerCellsNum{
static_cast<int>(
mTimeFrame->
getCells()[iLayer + 1].size())};
418 std::vector<std::pair<int, int>> cellsNeighbours;
419 cellsNeighbours.reserve(nextLayerCellsNum);
421 for (
int iCell{0}; iCell < layerCellsNum; ++iCell) {
424 const int nextLayerTrackletIndex{currentCellSeed.getSecondTrackletIndex()};
427 for (
int iNextCell{nextLayerFirstCellIndex}; iNextCell < nextLayerLastCellIndex; ++iNextCell) {
430 if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex) {
434 if (!nextCellSeed.rotate(currentCellSeed.getAlpha()) ||
435 !nextCellSeed.propagateTo(currentCellSeed.getX(),
getBz())) {
438 float chi2 = currentCellSeed.getPredictedChi2(nextCellSeed);
440#ifdef OPTIMISATION_OUTPUT
442 off << fmt::format(
"{}\t{:d}\t{}", iLayer, good, chi2) << std::endl;
445 if (chi2 >
mTrkParams[0].MaxChi2ClusterAttachment) {
450 cellsNeighbours.push_back(std::make_pair(iCell, iNextCell));
451 const int currentCellLevel{currentCellSeed.getLevel()};
453 if (currentCellLevel >= nextCellSeed.getLevel()) {
458 std::sort(cellsNeighbours.begin(), cellsNeighbours.end(), [](
const std::pair<int, int>&
a,
const std::pair<int, int>&
b) {
459 return a.second < b.second;
463 for (
auto& cellNeighboursIndex : cellsNeighbours) {
470void TrackerTraits::processNeighbours(
int iLayer,
int iLevel,
const std::vector<CellSeed>& currentCellSeed,
const std::vector<int>& currentCellId, std::vector<CellSeed>& updatedCellSeeds, std::vector<int>& updatedCellsIds)
472 if (iLevel < 2 || iLayer < 1) {
473 std::cout <<
"Error: layer " << iLayer <<
" or level " << iLevel <<
" cannot be processed by processNeighbours" << std::endl;
476 CA_DEBUGGER(std::cout <<
"Processing neighbours layer " << iLayer <<
" level " << iLevel <<
", size of the cell seeds: " << currentCellSeed.size() << std::endl);
478 updatedCellsIds.reserve(updatedCellSeeds.size());
481 int failed[5]{0, 0, 0, 0, 0}, attempts{0}, failedByMismatch{0};
484#pragma omp parallel for num_threads(mNThreads)
485 for (
unsigned int iCell = 0; iCell < currentCellSeed.size(); ++iCell) {
486 const CellSeed& currentCell{currentCellSeed[iCell]};
487 if (currentCell.getLevel() != iLevel) {
495 const int cellId = currentCellId.empty() ? iCell : currentCellId[iCell];
499 for (
int iNeighbourCell{startNeighbourId}; iNeighbourCell < endNeighbourId; ++iNeighbourCell) {
503 if (neighbourCell.getSecondTrackletIndex() != currentCell.getFirstTrackletIndex()) {
510 if (currentCell.getLevel() - 1 != neighbourCell.getLevel()) {
518 if (!seed.rotate(trHit.alphaTrackingFrame)) {
528 if (
mCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) {
531 if (!seed.correctForMaterial(
mTrkParams[0].LayerxX0[iLayer - 1],
mTrkParams[0].LayerxX0[iLayer - 1] * radl * rho,
true)) {
536 auto predChi2{seed.getPredictedChi2Quiet(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)};
537 if ((predChi2 >
mTrkParams[0].MaxChi2ClusterAttachment) || predChi2 < 0.f) {
541 seed.setChi2(seed.getChi2() + predChi2);
542 if (!seed.o2::track::TrackParCov::update(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)) {
546 seed.getClusters()[iLayer - 1] = neighbourCell.getFirstClusterIndex();
547 seed.setLevel(neighbourCell.getLevel());
548 seed.setFirstTrackletIndex(neighbourCell.getFirstTrackletIndex());
549 seed.setSecondTrackletIndex(neighbourCell.getSecondTrackletIndex());
552 updatedCellsIds.push_back(neighbourCellId);
553 updatedCellSeeds.push_back(seed);
558 std::cout <<
"\t\t- Found " << updatedCellSeeds.size() <<
" cell seeds out of " << attempts <<
" attempts" << std::endl;
559 std::cout <<
"\t\t\t> " <<
failed[0] <<
" failed because of level" << std::endl;
560 std::cout <<
"\t\t\t> " <<
failed[1] <<
" failed because of rotation" << std::endl;
561 std::cout <<
"\t\t\t> " <<
failed[2] <<
" failed because of propagation" << std::endl;
562 std::cout <<
"\t\t\t> " <<
failed[3] <<
" failed because of chi2 cut" << std::endl;
563 std::cout <<
"\t\t\t> " <<
failed[4] <<
" failed because of update" << std::endl;
564 std::cout <<
"\t\t\t> " << failedByMismatch <<
" failed because of mismatch" << std::endl;
570 CA_DEBUGGER(std::cout <<
"Finding roads, iteration " << iteration << std::endl);
571 for (
int startLevel{
mTrkParams[iteration].CellsPerRoad()}; startLevel >=
mTrkParams[iteration].CellMinimumLevel(); --startLevel) {
572 CA_DEBUGGER(std::cout <<
"\t > Processing level " << startLevel << std::endl);
573 const int minimumLayer{startLevel - 1};
574 std::vector<CellSeed> trackSeeds;
575 for (
int startLayer{
mTrkParams[iteration].CellsPerRoad() - 1}; startLayer >= minimumLayer; --startLayer) {
576 if ((
mTrkParams[iteration].StartLayerMask & (1 << (startLayer + 2))) == 0) {
579 CA_DEBUGGER(std::cout <<
"\t\t > Starting processing layer " << startLayer << std::endl);
580 std::vector<int> lastCellId, updatedCellId;
581 std::vector<CellSeed> lastCellSeed, updatedCellSeed;
585 int level = startLevel;
586 for (
int iLayer{startLayer - 1}; iLayer > 0 &&
level > 2; --iLayer) {
587 lastCellSeed.swap(updatedCellSeed);
588 lastCellId.swap(updatedCellId);
589 std::vector<CellSeed>().swap(updatedCellSeed);
590 updatedCellId.clear();
593 for (
auto& seed : updatedCellSeed) {
594 if (seed.getQ2Pt() > 1.e3 || seed.getChi2() >
mTrkParams[0].MaxChi2NDF * ((startLevel + 2) * 2 - 5)) {
597 trackSeeds.push_back(seed);
601 std::vector<TrackITSExt> tracks(trackSeeds.size());
602 std::atomic<size_t> trackIndex{0};
603#pragma omp parallel for num_threads(mNThreads)
604 for (
size_t seedId = 0; seedId < trackSeeds.size(); ++seedId) {
605 const CellSeed& seed{trackSeeds[seedId]};
607 temporaryTrack.resetCovariance();
608 temporaryTrack.setChi2(0);
609 for (
int iL{0}; iL < 7; ++iL) {
617 temporaryTrack.getParamOut() = temporaryTrack.getParamIn();
618 temporaryTrack.resetCovariance();
619 temporaryTrack.setChi2(0);
621 if (!fitSuccess || temporaryTrack.getPt() <
mTrkParams[iteration].MinPt[
mTrkParams[iteration].NLayers - temporaryTrack.getNClusters()]) {
624 tracks[trackIndex++] = temporaryTrack;
627 tracks.resize(trackIndex);
629 return a.getChi2() < b.getChi2();
632 for (
auto& track : tracks) {
634 bool isFirstShared{
false};
635 for (
int iLayer{0}; iLayer <
mTrkParams[0].NLayers; ++iLayer) {
647 std::array<int, 3> rofs{INT_MAX, INT_MAX, INT_MAX};
648 for (
int iLayer{0}; iLayer <
mTrkParams[0].NLayers; ++iLayer) {
654 for (
int iR{0}; iR < 3; ++iR) {
655 if (rofs[iR] == INT_MAX) {
656 rofs[iR] = currentROF;
658 if (rofs[iR] == currentROF) {
663 if (rofs[2] != INT_MAX) {
666 track.setUserField(0);
667 track.getParamOut().setUserField(0);
668 if (rofs[1] != INT_MAX) {
669 track.setNextROFbit();
742 std::array<int, 3> rofs{
746 if (rofs[0] != rofs[1] && rofs[1] != rofs[2] && rofs[0] != rofs[2]) {
751 if (rofs[1] == rofs[2]) {
759 TrackITSExt temporaryTrack{buildTrackSeed(cluster1_glo, cluster2_glo, cluster3_tf)};
760 temporaryTrack.setExternalClusterIndex(0, cluster1_glo.clusterId,
true);
761 temporaryTrack.setExternalClusterIndex(1, cluster2_glo.clusterId,
true);
762 temporaryTrack.setExternalClusterIndex(2, cluster3_glo.clusterId,
true);
765 bool fitSuccess = fitTrack(temporaryTrack, 1, -1, -1);
771 TrackITSExt bestTrack{temporaryTrack}, backup{temporaryTrack};
772 float bestChi2{std::numeric_limits<float>::max()};
773 for (
int iV{0}; iV < (
int)pvs.size(); ++iV) {
774 temporaryTrack = backup;
775 if (!temporaryTrack.rotate(pvsXAlpha[iV][1])) {
778 if (!propagator->propagateTo(temporaryTrack, pvsXAlpha[iV][0],
true)) {
782 float pvRes{
mTrkParams[0].PVres / o2::gpu::CAMath::Sqrt(
float(pvs[iV].getNContributors()))};
783 const float posVtx[2]{0.f, pvs[iV].getZ()};
784 const float covVtx[3]{pvRes, 0.f, pvRes};
785 float chi2 = temporaryTrack.getPredictedChi2Quiet(posVtx, covVtx);
786 if (chi2 < bestChi2) {
787 if (!temporaryTrack.track::TrackParCov::update(posVtx, covVtx)) {
790 bestTrack = temporaryTrack;
795 bestTrack.resetCovariance();
796 bestTrack.setChi2(0.f);
801 bestTrack.getParamOut() = bestTrack;
802 bestTrack.resetCovariance();
803 bestTrack.setChi2(0.f);
857 const int step = -1 + outward * 2;
858 const int end = outward ?
mTrkParams[iteration].NLayers - 1 : 0;
859 std::vector<TrackITSExt> hypotheses(1, *track);
860 for (
size_t iHypo{0}; iHypo < hypotheses.size(); ++iHypo) {
861 auto hypo{hypotheses[iHypo]};
862 int iLayer =
static_cast<int>(outward ? hypo.getLastClusterLayer() : hypo.getFirstClusterLayer());
864 while (iLayer !=
end) {
866 const float r =
mTrkParams[iteration].LayerRadii[iLayer];
873 auto& hypoParam{outward ? hypo.getParamOut() : hypo.getParamIn()};
874 if (!propInstance->propagateToX(hypoParam,
x,
mTimeFrame->
getBz(), PropagatorF::MAX_SIN_PHI,
875 PropagatorF::MAX_STEP,
mTrkParams[iteration].CorrType)) {
879 if (
mTrkParams[iteration].CorrType == PropagatorF::MatCorrType::USEMatCorrNONE) {
880 constexpr float radl = 9.36f;
881 constexpr float rho = 2.33f;
882 if (!hypoParam.correctForMaterial(
mTrkParams[iteration].LayerxX0[iLayer],
mTrkParams[iteration].LayerxX0[iLayer] * radl * rho,
true)) {
888 const float phi{hypoParam.getPhi()};
889 const float ePhi{o2::gpu::CAMath::Sqrt(hypoParam.getSigmaSnp2() / hypoParam.getCsp2())};
890 const float z{hypoParam.getZ()};
891 const float eZ{o2::gpu::CAMath::Sqrt(hypoParam.getSigmaZ2())};
893 if (selectedBinsRect.x == 0 && selectedBinsRect.y == 0 && selectedBinsRect.z == 0 && selectedBinsRect.w == 0) {
897 int phiBinsNum{selectedBinsRect.
w - selectedBinsRect.y + 1};
899 if (phiBinsNum < 0) {
904 if (layer1.empty()) {
909 for (
int iPhiCount = 0; iPhiCount < phiBinsNum; iPhiCount++) {
910 int iPhiBin = (selectedBinsRect.y + iPhiCount) %
mTrkParams[iteration].PhiBins;
912 const int maxBinIndex{firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1};
916 for (
int iNextCluster{firstRowClusterIndex}; iNextCluster < maxRowClusterIndex; ++iNextCluster) {
917 if (iNextCluster >= (
int)layer1.size()) {
920 const Cluster& nextCluster{layer1[iNextCluster]};
928 auto tbupdated{hypo};
929 auto& tbuParams = outward ? tbupdated.getParamOut() : tbupdated.getParamIn();
930 if (!tbuParams.rotate(trackingHit.alphaTrackingFrame)) {
934 if (!propInstance->propagateToX(tbuParams, trackingHit.xTrackingFrame,
mTimeFrame->
getBz(),
935 PropagatorF::MAX_SIN_PHI, PropagatorF::MAX_STEP, PropagatorF::MatCorrType::USEMatCorrNONE)) {
939 auto predChi2{tbuParams.getPredictedChi2Quiet(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)};
940 if (predChi2 >= track->getChi2() *
mTrkParams[iteration].NSigmaCut) {
944 if (!tbuParams.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) {
947 tbupdated.setChi2(tbupdated.getChi2() + predChi2);
948 tbupdated.setExternalClusterIndex(iLayer, nextCluster.clusterId,
true);
949 hypotheses.emplace_back(tbupdated);
957 for (
auto& hypo : hypotheses) {
958 if (hypo.isBetter(*bestHypo, track->getChi2() *
mTrkParams[iteration].NSigmaCut)) {