94GPUTRDTracker_t<TRDTRK, PROP>::GPUTRDTracker_t() : mR(nullptr), mIsInitialized(false), mGenerateSpacePoints(false), mProcessPerTimeFrame(false), mNAngleHistogramBins(25), mAngleHistogramRange(50), mMemoryPermanent(-1), mMemoryTracklets(-1), mMemoryTracks(-1), mNMaxCollisions(0), mNMaxTracks(0), mNMaxSpacePoints(0), mTracks(nullptr), mTrackAttribs(nullptr), mNCandidates(1), mNTracks(0), mNEvents(0), mMaxBackendThreads(100), mTrackletIndexArray(nullptr), mHypothesis(nullptr), mCandidates(nullptr), mSpacePoints(nullptr), mGeo(nullptr), mRPhiA2(0), mRPhiB(0), mRPhiC2(0), mDyA2(0), mDyB(0), mDyC2(0), mAngleToDyA(0), mAngleToDyB(0), mAngleToDyC(0), mDebugOutput(false), mMaxEta(0.84f), mRoadZ(18.f), mZCorrCoefNRC(1.4f), mTPCVdrift(2.58f), mTPCTDriftOffset(0.f), mDebug(new
GPUTRDTrackerDebug<TRDTRK>())
101template <
class TRDTRK,
class PROP>
110template <
class TRDTRK,
class PROP>
119 mDebug->ExpandVectors();
120 mIsInitialized =
true;
123template <
class TRDTRK,
class PROP>
129 mGeo = (
const GPUTRDGeometry*)GetConstantMem()->calibObjects.trdGeometry;
131 GPUFatal(
"TRD geometry must be provided externally");
133 float Bz =
Param().bzkG;
134 float resRPhiIdeal2 =
Param().rec.trd.trkltResRPhiIdeal *
Param().rec.trd.trkltResRPhiIdeal;
135 GPUInfo(
"Initializing with B-field: %f kG", Bz);
136 if (CAMath::Abs(CAMath::Abs(Bz) - 2) < 0.1f) {
139 GPUInfo(
"Loading error parameterization for Bz = +2 kG");
140 mRPhiA2 = resRPhiIdeal2, mRPhiB = -1.43e-2f, mRPhiC2 = 4.55e-2f;
141 mDyA2 = 1.225e-3f, mDyB = -9.8e-3f, mDyC2 = 3.88e-2f;
142 mAngleToDyA = -0.1f, mAngleToDyB = 1.89f, mAngleToDyC = -0.4f;
144 GPUInfo(
"Loading error parameterization for Bz = -2 kG");
145 mRPhiA2 = resRPhiIdeal2, mRPhiB = 1.43e-2f, mRPhiC2 = 4.55e-2f;
146 mDyA2 = 1.225e-3f, mDyB = 9.8e-3f, mDyC2 = 3.88e-2f;
147 mAngleToDyA = 0.1f, mAngleToDyB = 1.89f, mAngleToDyC = 0.4f;
149 }
else if (CAMath::Abs(CAMath::Abs(Bz) - 5) < 0.1f) {
152 GPUInfo(
"Loading error parameterization for Bz = +5 kG");
153 mRPhiA2 = resRPhiIdeal2, mRPhiB = 0.125f, mRPhiC2 = 0.0961f;
154 mDyA2 = 1.681e-3f, mDyB = 0.15f, mDyC2 = 0.1849f;
155 mAngleToDyA = 0.13f, mAngleToDyB = 2.43f, mAngleToDyC = -0.58f;
157 GPUInfo(
"Loading error parameterization for Bz = -5 kG");
158 mRPhiA2 = resRPhiIdeal2, mRPhiB = -0.14f, mRPhiC2 = 0.1156f;
159 mDyA2 = 2.209e-3f, mDyB = -0.15f, mDyC2 = 0.2025f;
160 mAngleToDyA = -0.15f, mAngleToDyB = 2.34f, mAngleToDyC = 0.56f;
165 GPUWarning(
"No error parameterization available for Bz = %.2f kG. Keeping default value (sigma_y = const. = 1cm)", Bz);
170 float x0[kNLayers] = {300.2f, 312.8f, 325.4f, 338.0f, 350.6f, 363.2f};
171 auto* matrix = mGeo->GetClusterMatrix(0);
172 float loc[3] = {mGeo->AnodePos(), 0.f, 0.f};
173 float glb[3] = {0.f, 0.f, 0.f};
174 for (int32_t iDet = 0; iDet < kNChambers; ++iDet) {
175 matrix = mGeo->GetClusterMatrix(iDet);
177 mR[iDet] =
x0[mGeo->GetLayer(iDet)];
180 matrix->LocalToMaster(loc, glb);
185template <
class TRDTRK,
class PROP>
194template <
class TRDTRK,
class PROP>
202 for (uint32_t iColl = 0; iColl < GetConstantMem()->ioPtrs.nTRDTriggerRecords; ++iColl) {
203 if (GetConstantMem()->ioPtrs.trdTrigRecMask && GetConstantMem()->ioPtrs.trdTrigRecMask[iColl] == 0) {
208 int32_t idxOffset = 0;
209 if (mProcessPerTimeFrame) {
210 idxOffset = GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iColl];
211 nTrklts = (iColl < GetConstantMem()->ioPtrs.nTRDTriggerRecords - 1) ? GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iColl + 1] - GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iColl] : GetConstantMem()->ioPtrs.nTRDTracklets - GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iColl];
213 nTrklts = GetConstantMem()->ioPtrs.nTRDTracklets;
216 int32_t* trkltIndexArray = &mTrackletIndexArray[iColl * (kNChambers + 1) + 1];
217 trkltIndexArray[-1] = 0;
220 int32_t trkltCounter = 0;
221 for (int32_t iTrklt = 0; iTrklt < nTrklts; ++iTrklt) {
222 if (
tracklets[iTrklt].GetDetector() > currDet) {
223 nextDet =
tracklets[iTrklt].GetDetector();
224 for (int32_t iDet = currDet; iDet < nextDet; ++iDet) {
225 trkltIndexArray[iDet] = trkltCounter;
231 for (int32_t iDet = currDet; iDet <= kNChambers; ++iDet) {
232 trkltIndexArray[iDet] = trkltCounter;
234 if (mGenerateSpacePoints) {
235 if (!CalculateSpacePoints(iColl)) {
236 GPUError(
"Space points for at least one chamber could not be calculated (for interaction %i)", iColl);
241 if (mGenerateSpacePoints) {
247template <
class TRDTRK,
class PROP>
253 if (!mIsInitialized) {
256 GPUError(
"Cannot change mNCandidates after initialization");
260template <
class TRDTRK,
class PROP>
266 GPUInfo(
"##############################################################");
267 GPUInfo(
"Current settings for GPU TRD tracker:");
268 GPUInfo(
" maxChi2(%.2f), chi2Penalty(%.2f), nCandidates(%i), maxMissingLayers(%i)",
Param().
rec.trd.maxChi2,
Param().
rec.trd.penaltyChi2, mNCandidates,
Param().
rec.trd.stopTrkAfterNMissLy);
269 GPUInfo(
" ptCut = %.2f GeV, abs(eta) < %.2f",
Param().
rec.trd.minTrackPt, mMaxEta);
270 GPUInfo(
"##############################################################");
273template <
class TRDTRK,
class PROP>
276 mDebug->CreateStreamer();
284 return &
Param().polynomialField;
287template <
class TRDTRK,
class PROP>
290 return GetConstantMem()->calibObjects.o2Propagator;
293template <
class TRDTRK,
class PROP>
296 if (!trk.CheckNumericalQuality()) {
299 if (CAMath::Abs(trk.getEta()) > mMaxEta) {
302 if (trk.getPt() <
Param().
rec.trd.minTrackPt) {
308template <
class TRDTRK,
class PROP>
309GPUd() int32_t
GPUTRDTracker_t<TRDTRK, PROP>::LoadTrack(const TRDTRK& trk, uint32_t tpcTrackId,
bool checkTrack, HelperTrackAttributes* attribs)
311 if (mNTracks >= mNMaxTracks) {
313 GPUError(
"Error: Track dropped (no memory available) -> must not happen");
317 if (checkTrack && !CheckTrackTRDCandidate(trk)) {
320 mTracks[mNTracks] = trk;
321 mTracks[mNTracks].setRefGlobalTrackIdRaw(tpcTrackId);
323 mTrackAttribs[mNTracks] = *attribs;
330template <
class TRDTRK,
class PROP>
336 GPUInfo(
"There are in total %i tracklets loaded", GetConstantMem()->ioPtrs.nTRDTracklets);
337 GPUInfo(
"There are %i tracks loaded. mNMaxTracks(%i)", mNTracks, mNMaxTracks);
338 for (int32_t
i = 0;
i < mNTracks; ++
i) {
339 auto* trk = &(mTracks[
i]);
340 GPUInfo(
"track %i: x=%f, alpha=%f, nTracklets=%i, pt=%f, time=%f",
i, trk->getX(), trk->getAlpha(), trk->getNtracklets(), trk->getPt(), mTrackAttribs[
i].mTime);
344template <
class TRDTRK,
class PROP>
345GPUd() int32_t
GPUTRDTracker_t<TRDTRK, PROP>::GetCollisionIDs(int32_t iTrk, int32_t* collisionIds)
const
355 for (uint32_t iColl = 0; iColl < GetConstantMem()->ioPtrs.nTRDTriggerRecords; ++iColl) {
356 if (GetConstantMem()->ioPtrs.trdTrigRecMask && GetConstantMem()->ioPtrs.trdTrigRecMask[iColl] == 0) {
359 if (GetConstantMem()->ioPtrs.trdTriggerTimes[iColl] > mTrackAttribs[iTrk].GetTimeMin() && GetConstantMem()->ioPtrs.trdTriggerTimes[iColl] < mTrackAttribs[iTrk].GetTimeMax()) {
361 GPUError(
"Found too many collision candidates for track with tMin(%f) and tMax(%f)", mTrackAttribs[iTrk].GetTimeMin(), mTrackAttribs[iTrk].GetTimeMax());
364 collisionIds[nColls++] = iColl;
370template <
class TRDTRK,
class PROP>
376 int32_t collisionIds[20] = {0};
377 int32_t nCollisionIds = 1;
378 if (mProcessPerTimeFrame) {
379 nCollisionIds = GetCollisionIDs(iTrk, collisionIds);
380 if (nCollisionIds == 0) {
382 GPUInfo(
"Did not find TRD data for track %i with t=%f. tMin(%f), tMax(%f)", iTrk, mTrackAttribs[iTrk].mTime, mTrackAttribs[iTrk].GetTimeMin(), mTrackAttribs[iTrk].GetTimeMax());
388 PROP prop(getPropagatorParam());
389 mTracks[iTrk].setChi2(
Param().
rec.trd.penaltyChi2);
390 auto trkStart = mTracks[iTrk];
391 for (int32_t iColl = 0; iColl < nCollisionIds; ++iColl) {
393 auto trkCopy = trkStart;
394 prop.setTrack(&trkCopy);
395 prop.setFitInProjections(
true);
396 if (!FollowProlongation(&prop, &trkCopy, iTrk, threadId, collisionIds[iColl])) {
400 if (trkCopy.getReducedChi2() < mTracks[iTrk].getReducedChi2()) {
401 mTracks[iTrk] = trkCopy;
406template <
class TRDTRK,
class PROP>
415 int32_t idxOffset = iCollision * (kNChambers + 1);
419 for (int32_t iDet = 0; iDet < kNChambers; ++iDet) {
420 int32_t iFirstTrackletInDet = mTrackletIndexArray[idxOffset + iDet];
421 int32_t iFirstTrackletInNextDet = mTrackletIndexArray[idxOffset + iDet + 1];
422 int32_t nTrackletsInDet = iFirstTrackletInNextDet - iFirstTrackletInDet;
423 if (nTrackletsInDet == 0) {
426 if (!mGeo->ChamberInGeometry(iDet)) {
427 GPUError(
"Found TRD tracklets in chamber %i which is not included in the geometry", iDet);
430 auto* matrix = mGeo->GetClusterMatrix(iDet);
432 GPUError(
"No cluster matrix available for chamber %i. Skipping it...", iDet);
438 int32_t trkltIdxOffset = (mProcessPerTimeFrame) ? GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iCollision] : 0;
439 int32_t trkltIdxStart = trkltIdxOffset + iFirstTrackletInDet;
440 for (int32_t trkltIdx = trkltIdxStart; trkltIdx < trkltIdxStart + nTrackletsInDet; ++trkltIdx) {
441 int32_t trkltZbin =
tracklets[trkltIdx].GetZbin();
442 float xTrkltDet[3] = {0.f};
443 float xTrkltSec[3] = {0.f};
444 xTrkltDet[0] = mGeo->AnodePos() + sRadialOffset;
445 xTrkltDet[1] =
tracklets[trkltIdx].GetY();
446 xTrkltDet[2] = pp->GetRowPos(trkltZbin) - pp->GetRowSize(trkltZbin) / 2.f - pp->GetRowPos(pp->GetNrows() / 2);
448 matrix->LocalToMaster(xTrkltDet, xTrkltSec);
449 mSpacePoints[trkltIdx].setX(xTrkltSec[0]);
450 mSpacePoints[trkltIdx].setY(xTrkltSec[1]);
451 mSpacePoints[trkltIdx].setZ(xTrkltSec[2]);
452 mSpacePoints[trkltIdx].setDy(
tracklets[trkltIdx].GetdY());
460template <
class TRDTRK,
class PROP>
461GPUd() bool
GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK* t, int32_t iTrk, int32_t threadId, int32_t collisionId)
471 GPUInfo(
"Start track following for track %i at x=%f with pt=%f", t->getRefGlobalTrackIdRaw(), t->getX(), t->getPt());
475 float zShiftTrk = 0.f;
476 if (mProcessPerTimeFrame) {
477 zShiftTrk = (mTrackAttribs[iTrk].mTime - GetConstantMem()->ioPtrs.trdTriggerTimes[collisionId]) * mTPCVdrift * mTrackAttribs[iTrk].mSide;
485 const GPUTRDSpacePoint* spacePoints = GetConstantMem()->ioPtrs.trdSpacePoints;
487#ifdef ENABLE_GPUTRDDEBUG
488 TRDTRK trackNoUp(*t);
491 int32_t candidateIdxOffset = threadId * 2 * mNCandidates;
492 int32_t hypothesisIdxOffset = threadId * mNCandidates;
493 int32_t trkltIdxOffset = collisionId * (kNChambers + 1);
494 int32_t glbTrkltIdxOffset = (mProcessPerTimeFrame) ? GetConstantMem()->ioPtrs.trdTrackletIdxFirst[collisionId] : 0;
497 if (mNCandidates > 1) {
499 mCandidates[candidateIdxOffset] = *t;
502 int32_t nCandidates = 1;
503 int32_t nCurrHypothesis = 0;
508 const int32_t nMaxChambersToSearch = 4;
510 mDebug->SetGeneralInfo(mNEvents, mNTracks, iTrk, t->getPt());
512 for (int32_t iLayer = 0; iLayer < kNLayers; ++iLayer) {
515 int32_t currIdx = candidateIdxOffset + iLayer % 2;
516 int32_t nextIdx = candidateIdxOffset + (iLayer + 1) % 2;
517 pad = mGeo->GetPadPlane(iLayer, 0);
518 float tilt = CAMath::Tan(CAMath::Pi() / 180.f * pad->GetTiltingAngle());
519 const float zMaxTRD = pad->GetRow0();
526 for (int32_t iCandidate = 0; iCandidate < nCandidates; iCandidate++) {
528 int32_t det[nMaxChambersToSearch] = {-1, -1, -1, -1};
530 if (mNCandidates > 1) {
531 trkWork = &mCandidates[2 * iCandidate + currIdx];
532 prop->setTrack(trkWork);
535 if (trkWork->getIsStopped()) {
536 Hypothesis hypo(trkWork->getNlayersFindable(), iCandidate, -1, trkWork->getChi2());
537 InsertHypothesis(hypo, nCurrHypothesis, hypothesisIdxOffset);
543 if (!prop->propagateToX(mR[2 * kNLayers + iLayer], .8f, 2.f)) {
545 GPUInfo(
"Track propagation failed for track %i candidate %i in layer %i (pt=%f, x=%f, mR[layer]=%f)", iTrk, iCandidate, iLayer, trkWork->getPt(), trkWork->getX(), mR[2 * kNLayers + iLayer]);
551 if (!AdjustSector(prop, trkWork)) {
553 GPUInfo(
"Adjusting sector failed for track %i candidate %i in layer %i", iTrk, iCandidate, iLayer);
559 if (IsGeoFindable(trkWork, iLayer, prop->getAlpha(), zShiftTrk)) {
560 trkWork->setIsFindable(iLayer);
564 roadY = 7.f * CAMath::Sqrt(trkWork->getSigmaY2() + 0.1f * 0.1f) +
Param().rec.trd.extraRoadY;
566 roadZ = mRoadZ +
Param().rec.trd.extraRoadZ;
568 if (CAMath::Abs(trkWork->getZ() + zShiftTrk) - roadZ >= zMaxTRD) {
570 GPUInfo(
"Track out of TRD acceptance with z=%f in layer %i (eta=%f)", trkWork->getZ() + zShiftTrk, iLayer, trkWork->getEta());
576 FindChambersInRoad(trkWork, roadY, roadZ, iLayer, det, zMaxTRD, prop->getAlpha(), zShiftTrk);
579 mDebug->SetTrackParameter(*trkWork, iLayer);
582 for (int32_t iDet = 0; iDet < nMaxChambersToSearch; iDet++) {
583 int32_t currDet = det[iDet];
587 pad = mGeo->GetPadPlane(currDet);
588 int32_t currSec = mGeo->GetSector(currDet);
589 if (currSec != GetSector(prop->getAlpha())) {
590 if (!prop->rotate(GetAlphaOfSector(currSec))) {
592 GPUWarning(
"Track could not be rotated in tracklet coordinate system");
597 if (currSec != GetSector(prop->getAlpha())) {
598 GPUError(
"Track is in sector %i and sector %i is searched for tracklets", GetSector(prop->getAlpha()), currSec);
602 if (!prop->propagateToX(mR[currDet], .8f, .2f)) {
604 GPUWarning(
"Track parameter for track %i, x=%f at chamber %i x=%f in layer %i cannot be retrieved", iTrk, trkWork->getX(), currDet, mR[currDet], iLayer);
608 for (int32_t trkltIdx = glbTrkltIdxOffset + mTrackletIndexArray[trkltIdxOffset + currDet]; trkltIdx < glbTrkltIdxOffset + mTrackletIndexArray[trkltIdxOffset + currDet + 1]; ++trkltIdx) {
609 if (CAMath::Abs(trkWork->getY() - spacePoints[trkltIdx].getY()) > roadY || CAMath::Abs(trkWork->getZ() + zShiftTrk - spacePoints[trkltIdx].getZ()) > roadZ) {
615 prop->getPropagatedYZ(spacePoints[trkltIdx].
getX(), projY, projZ);
617 float tiltCorr = tilt * (spacePoints[trkltIdx].getZ() - projZ);
618 float lPad = pad->GetRowSize(
tracklets[trkltIdx].GetZbin());
619 if (!((CAMath::Abs(spacePoints[trkltIdx].getZ() - projZ) < lPad) && (trkWork->getSigmaZ2() < (lPad * lPad / 12.f)))) {
623 float zPosCorr = spacePoints[trkltIdx].getZ() + mZCorrCoefNRC * trkWork->getTgl();
624 float yPosCorr = spacePoints[trkltIdx].getY() - tiltCorr;
625 zPosCorr -= zShiftTrk;
626 float deltaY = yPosCorr - projY;
627 float deltaZ = zPosCorr - projZ;
628 float trkltPosTmpYZ[2] = {yPosCorr, zPosCorr};
629 float trkltCovTmp[3] = {0.f};
630 if ((CAMath::Abs(deltaY) < roadY) && (CAMath::Abs(deltaZ) < roadZ)) {
632 RecalcTrkltCov(tilt, trkWork->getSnp(), pad->GetRowSize(
tracklets[trkltIdx].GetZbin()), trkltCovTmp);
633 float chi2 = prop->getPredictedChi2(trkltPosTmpYZ, trkltCovTmp);
635 if ((chi2 >
Param().
rec.trd.maxChi2) || (
Param().
rec.trd.applyDeflectionCut && CAMath::Abs(GetAngularPull(spacePoints[trkltIdx].getDy(), trkWork->getSnp())) > 4)) {
638 Hypothesis hypo(trkWork->getNlayersFindable(), iCandidate, trkltIdx, trkWork->getChi2() + chi2);
639 InsertHypothesis(hypo, nCurrHypothesis, hypothesisIdxOffset);
645 Hypothesis hypoNoUpdate(trkWork->getNlayersFindable(), iCandidate, -1, trkWork->getChi2() +
Param().
rec.trd.penaltyChi2);
646 InsertHypothesis(hypoNoUpdate, nCurrHypothesis, hypothesisIdxOffset);
650 mDebug->SetChi2Update(mHypothesis[0 + hypothesisIdxOffset].mChi2 - t->getChi2(), iLayer);
651 mDebug->SetRoad(roadY, roadZ, iLayer);
652 bool wasTrackStored =
false;
660 for (int32_t iUpdate = 0; iUpdate < nCurrHypothesis && iUpdate < mNCandidates; iUpdate++) {
661 if (mHypothesis[iUpdate + hypothesisIdxOffset].mCandidateId == -1) {
668 nCandidates = iUpdate + 1;
669 if (mNCandidates > 1) {
670 mCandidates[2 * iUpdate + nextIdx] = mCandidates[2 * mHypothesis[iUpdate + hypothesisIdxOffset].mCandidateId + currIdx];
671 trkWork = &mCandidates[2 * iUpdate + nextIdx];
673 if (mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId == -1) {
675 if (trkWork->getIsFindable(iLayer)) {
676 if (trkWork->getNmissingConsecLayers(iLayer) >
Param().
rec.trd.stopTrkAfterNMissLy) {
677 trkWork->setIsStopped();
679 trkWork->setChi2(trkWork->getChi2() +
Param().
rec.trd.penaltyChi2);
681 if (iUpdate == 0 && mNCandidates > 1) {
682 *t = mCandidates[2 * iUpdate + nextIdx];
687 if (mNCandidates > 1) {
688 prop->setTrack(trkWork);
690 int32_t trkltSec = mGeo->GetSector(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector());
691 if (trkltSec != GetSector(prop->getAlpha())) {
693 prop->rotate(GetAlphaOfSector(trkltSec));
695 if (!prop->propagateToX(spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getX(), .8f, 2.f)) {
697 GPUWarning(
"Final track propagation for track %i update %i in layer %i failed", iTrk, iUpdate, iLayer);
699 trkWork->setChi2(trkWork->getChi2() +
Param().
rec.trd.penaltyChi2);
700 if (trkWork->getIsFindable(iLayer)) {
701 if (trkWork->getNmissingConsecLayers(iLayer) >=
Param().
rec.trd.stopTrkAfterNMissLy) {
702 trkWork->setIsStopped();
705 if (iUpdate == 0 && mNCandidates > 1) {
706 *t = mCandidates[2 * iUpdate + nextIdx];
711 pad = mGeo->GetPadPlane(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector());
712 float tiltCorrUp = tilt * (spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getZ() - trkWork->getZ());
713 float zPosCorrUp = spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getZ() + mZCorrCoefNRC * trkWork->getTgl();
714 zPosCorrUp -= zShiftTrk;
715 float padLength = pad->GetRowSize(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetZbin());
716 if (!((trkWork->getSigmaZ2() < (padLength * padLength / 12.f)) && (CAMath::Abs(spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getZ() - trkWork->getZ()) < padLength))) {
719 float trkltPosUp[2] = {spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getY() - tiltCorrUp, zPosCorrUp};
720 float trkltCovUp[3] = {0.f};
721 RecalcTrkltCov(tilt, trkWork->getSnp(), pad->GetRowSize(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetZbin()), trkltCovUp);
723#ifdef ENABLE_GPUTRDDEBUG
724 prop->setTrack(&trackNoUp);
725 prop->rotate(GetAlphaOfSector(trkltSec));
727 prop->propagateToX(mR[
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector()], .8f, 2.f);
728 prop->setTrack(trkWork);
731 if (!wasTrackStored) {
732#ifdef ENABLE_GPUTRDDEBUG
733 mDebug->SetTrackParameterNoUp(trackNoUp, iLayer);
735 mDebug->SetTrackParameter(*trkWork, iLayer);
736 mDebug->SetRawTrackletPosition(spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].
getX(), spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].
getY(), spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getZ(), iLayer);
737 mDebug->SetCorrectedTrackletPosition(trkltPosUp, iLayer);
738 mDebug->SetTrackletCovariance(trkltCovUp, iLayer);
739 mDebug->SetTrackletProperties(spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getDy(),
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector(), iLayer);
740 wasTrackStored =
true;
743 if (!prop->update(trkltPosUp, trkltCovUp)) {
745 GPUWarning(
"Failed to update track %i with space point in layer %i", iTrk, iLayer);
747 trkWork->setChi2(trkWork->getChi2() +
Param().
rec.trd.penaltyChi2);
748 if (trkWork->getIsFindable(iLayer)) {
749 if (trkWork->getNmissingConsecLayers(iLayer) >=
Param().
rec.trd.stopTrkAfterNMissLy) {
750 trkWork->setIsStopped();
753 if (iUpdate == 0 && mNCandidates > 1) {
754 *t = mCandidates[2 * iUpdate + nextIdx];
758 if (!trkWork->CheckNumericalQuality()) {
760 GPUInfo(
"Track %i has invalid covariance matrix. Aborting track following\n", iTrk);
764 trkWork->addTracklet(iLayer, mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId);
765 trkWork->setChi2(mHypothesis[iUpdate + hypothesisIdxOffset].mChi2);
766 trkWork->setIsFindable(iLayer);
767 trkWork->setCollisionId(collisionId);
769 float projZEntry, projYEntry;
771 prop->getPropagatedYZ(trkWork->getX() - mGeo->GetCdrHght(), projYEntry, projZEntry);
777 const auto padrowEntry = pad->GetPadRowNumber(projZEntry);
778 const auto padrowExit = pad->GetPadRowNumber(trkWork->getZ());
779 if (padrowEntry != padrowExit) {
780 trkWork->setIsCrossingNeighbor(iLayer);
781 trkWork->setHasPadrowCrossing();
783 const auto currDet =
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector();
785 for (int32_t trkltIdx = glbTrkltIdxOffset + mTrackletIndexArray[trkltIdxOffset + currDet]; trkltIdx < glbTrkltIdxOffset + mTrackletIndexArray[trkltIdxOffset + currDet + 1]; ++trkltIdx) {
787 if (mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId == trkltIdx) {
790 if (GPUCommonMath::Abs(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetZbin() -
tracklets[trkltIdx].GetZbin()) == 1 &&
791 GPUCommonMath::Abs(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetY() -
tracklets[trkltIdx].GetY()) < 1) {
792 trkWork->setIsCrossingNeighbor(iLayer);
793 trkWork->setHasNeighbor();
797 if (iUpdate == 0 && mNCandidates > 1) {
798 *t = mCandidates[2 * iUpdate + nextIdx];
804 GPUInfo(
"Track %i cannot be followed. Stopped in layer %i", iTrk, iLayer);
815 mDebug->SetTrack(*t);
819 GPUInfo(
"Ended track following for track %i at x=%f with pt=%f. Attached %i tracklets", t->getRefGlobalTrackIdRaw(), t->getX(), t->getPt(), t->getNtracklets());
821 if (nCurrHypothesis > 1) {
822 if (CAMath::Abs(mHypothesis[hypothesisIdxOffset + 1].GetReducedChi2() - mHypothesis[hypothesisIdxOffset].GetReducedChi2()) <
Param().
rec.trd.chi2SeparationCut) {
829template <
class TRDTRK,
class PROP>
830GPUd()
void GPUTRDTracker_t<TRDTRK, PROP>::InsertHypothesis(Hypothesis hypo, int32_t& nCurrHypothesis, int32_t idxOffset)
836 if (nCurrHypothesis == 0) {
838 mHypothesis[idxOffset] = hypo;
840 }
else if (nCurrHypothesis > 0 && nCurrHypothesis < mNCandidates) {
842 for (int32_t
i = idxOffset;
i < nCurrHypothesis + idxOffset; ++
i) {
843 if (hypo.GetReducedChi2() < mHypothesis[
i].GetReducedChi2()) {
844 for (int32_t k = nCurrHypothesis + idxOffset; k >
i; --k) {
845 mHypothesis[k] = mHypothesis[k - 1];
847 mHypothesis[
i] = hypo;
852 mHypothesis[nCurrHypothesis + idxOffset] = hypo;
857 int32_t
i = nCurrHypothesis + idxOffset - 1;
858 for (;
i >= idxOffset; --
i) {
859 if (mHypothesis[
i].GetReducedChi2() < hypo.GetReducedChi2()) {
863 if (
i < (nCurrHypothesis + idxOffset - 1)) {
865 for (int32_t k = nCurrHypothesis + idxOffset - 1; k >
i + 1; --k) {
866 mHypothesis[k] = mHypothesis[k - 1];
868 mHypothesis[
i + 1] = hypo;
873template <
class TRDTRK,
class PROP>
884 int32_t sector = GetSector(
alpha);
886 return mGeo->GetDetector(
layer,
stack, sector);
889template <
class TRDTRK,
class PROP>
897 float alpha = mGeo->GetAlpha();
898 float xTmp = t->getX();
900 float yMax = t->getX() * CAMath::Tan(0.5f *
alpha);
901 float alphaCurr = t->getAlpha();
903 if (CAMath::Abs(
y) > 2.f *
yMax) {
905 GPUInfo(
"AdjustSector: Track %i with pT = %f crossing two sector boundaries at x = %f", t->getRefGlobalTrackIdRaw(), t->getPt(), t->getX());
911 while (CAMath::Abs(
y) >
yMax) {
915 int32_t sign = (
y > 0) ? 1 : -1;
916 float alphaNew = alphaCurr +
alpha * sign;
917 if (alphaNew > CAMath::Pi()) {
918 alphaNew -= 2 * CAMath::Pi();
919 }
else if (alphaNew < -CAMath::Pi()) {
920 alphaNew += 2 * CAMath::Pi();
922 if (!prop->rotate(alphaNew)) {
925 if (!prop->propagateToX(xTmp, .8f, 2.f)) {
934template <
class TRDTRK,
class PROP>
941 alpha += 2.f * CAMath::Pi();
942 }
else if (
alpha >= 2.f * CAMath::Pi()) {
943 alpha -= 2.f * CAMath::Pi();
945 return (int32_t)(
alpha * (
float)kNSectors / (2.f * CAMath::Pi()));
948template <
class TRDTRK,
class PROP>
954 float alpha = 2.0f * CAMath::Pi() / (
float)kNSectors * ((
float)sec + 0.5f);
955 if (
alpha > CAMath::Pi()) {
956 alpha -= 2 * CAMath::Pi();
961template <
class TRDTRK,
class PROP>
962GPUd()
void GPUTRDTracker_t<TRDTRK, PROP>::RecalcTrkltCov(const
float tilt, const
float snp, const
float rowSize,
float (&cov)[3])
968 float t2 = tilt * tilt;
969 float c2 = 1.f / (1.f + t2);
970 float sy2 = GetRPhiRes(snp);
971 float sz2 = rowSize * rowSize / 12.f;
972 cov[0] =
c2 * (sy2 + t2 * sz2);
973 cov[1] =
c2 * tilt * (sz2 - sy2);
974 cov[2] =
c2 * (t2 * sy2 + sz2);
977template <
class TRDTRK,
class PROP>
978GPUd() float
GPUTRDTracker_t<TRDTRK, PROP>::GetAngularPull(
float dYtracklet,
float snp)
const
980 float dYtrack = ConvertAngleToDy(snp);
981 float dYresolution = GetAngularResolution(snp);
982 if (dYresolution < 1e-6f) {
985 return (dYtracklet - dYtrack) / CAMath::Sqrt(dYresolution);
988template <
class TRDTRK,
class PROP>
989GPUd()
void GPUTRDTracker_t<TRDTRK, PROP>::FindChambersInRoad(const TRDTRK* t, const
float roadY, const
float roadZ, const int32_t iLayer, int32_t* det, const
float zMax, const
float alpha, const
float zShiftTrk)
const
997 const float yMax = CAMath::Abs(mGeo->GetCol0(iLayer));
998 float zTrk = t->getZ() + zShiftTrk;
1000 int32_t currStack = mGeo->GetStack(zTrk, iLayer);
1001 int32_t currSec = GetSector(
alpha);
1006 if (currStack > -1) {
1008 currDet = mGeo->GetDetector(iLayer, currStack, currSec);
1009 det[nDets++] = currDet;
1011 int32_t lastPadRow = mGeo->GetRowMax(iLayer, currStack, 0);
1012 float zCenter = pp->GetRowPos(lastPadRow / 2);
1013 if ((zTrk + roadZ) > pp->GetRow0() || (zTrk - roadZ) < pp->GetRowEnd()) {
1014 int32_t addStack = zTrk > zCenter ? currStack - 1 : currStack + 1;
1015 if (addStack < kNStacks && addStack > -1) {
1016 det[nDets++] = mGeo->GetDetector(iLayer, addStack, currSec);
1020 if (CAMath::Abs(zTrk) >
zMax) {
1023 currDet = mGeo->GetDetector(iLayer, 0, currSec);
1025 currDet = mGeo->GetDetector(iLayer, kNStacks - 1, currSec);
1027 det[nDets++] = currDet;
1028 currStack = mGeo->GetStack(currDet);
1032 currDet = GetDetectorNumber(zTrk + 4.0f,
alpha, iLayer);
1033 if (currDet != -1) {
1034 det[nDets++] = currDet;
1036 currDet = GetDetectorNumber(zTrk - 4.0f,
alpha, iLayer);
1037 if (currDet != -1) {
1038 det[nDets++] = currDet;
1043 if ((CAMath::Abs(t->getY()) + roadY) >
yMax) {
1044 const int32_t nStacksToSearch = nDets;
1046 if (t->getY() > 0) {
1047 newSec = (currSec + 1) % kNSectors;
1049 newSec = (currSec > 0) ? currSec - 1 : kNSectors - 1;
1051 for (int32_t idx = 0;
idx < nStacksToSearch; ++
idx) {
1052 currStack = mGeo->GetStack(det[idx]);
1053 det[nDets++] = mGeo->GetDetector(iLayer, currStack, newSec);
1057 for (int32_t iDet = 0; iDet < nDets; iDet++) {
1058 if (!mGeo->ChamberInGeometry(det[iDet])) {
1064template <
class TRDTRK,
class PROP>
1065GPUd() bool
GPUTRDTracker_t<TRDTRK, PROP>::IsGeoFindable(const TRDTRK* t, const int32_t
layer, const
float alpha, const
float zShiftTrk)
const
1072 float zTrk = t->getZ() + zShiftTrk;
1074 int32_t det = GetDetectorNumber(zTrk,
alpha,
layer);
1082 if (!mGeo->ChamberInGeometry(det)) {
1087 float yMax = pp->GetColEnd();
1088 float zMax = pp->GetRow0();
1089 float zMin = pp->GetRowEnd();
1095 if (
yMax - CAMath::Abs(t->getY()) < epsY) {
1099 if (!((zTrk >
zMin + epsZ) && (zTrk <
zMax - epsZ))) {
1107#ifndef GPUCA_GPUCODE