64 computePointerWithAlignment(base, mR, kNChambers);
65 computePointerWithAlignment(base, mHypothesis, mNCandidates * mMaxBackendThreads);
66 computePointerWithAlignment(base, mCandidates, mNCandidates * 2 * mMaxBackendThreads);
70template <
class TRDTRK,
class PROP>
77 if (mGenerateSpacePoints) {
78 computePointerWithAlignment(base, mSpacePoints, mNMaxSpacePoints);
80 computePointerWithAlignment(base, mTrackletIndexArray, (kNChambers + 1) * mNMaxCollisions);
84template <
class TRDTRK,
class PROP>
90 computePointerWithAlignment(base, mTracks, mNMaxTracks);
91 computePointerWithAlignment(base, mTrackAttribs, mNMaxTracks);
95template <
class TRDTRK,
class PROP>
96GPUTRDTracker_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), mFT0TriggeredBC(nullptr), mNFT0BC(0), mHypothesis(nullptr), mCandidates(nullptr), mSpacePoints(nullptr), mGeo(nullptr), mRecoParam(nullptr), mDebugOutput(false), mMaxEta(0.84f), mRoadZ(18.f), mTPCVdrift(2.58f), mTPCTDriftOffset(0.f), mDebug(new
GPUTRDTrackerDebug<TRDTRK>())
103template <
class TRDTRK,
class PROP>
112template <
class TRDTRK,
class PROP>
118 mRecoParam = GetConstantMem()->calibObjects.trdRecoParam;
120 mDebug->ExpandVectors();
121 mIsInitialized =
true;
124template <
class TRDTRK,
class PROP>
130 mGeo = (
const GPUTRDGeometry*)GetConstantMem()->calibObjects.trdGeometry;
132 GPUFatal(
"TRD geometry must be provided externally");
135 float x0[kNLayers] = {300.2f, 312.8f, 325.4f, 338.0f, 350.6f, 363.2f};
136 auto* matrix = mGeo->GetClusterMatrix(0);
137 float loc[3] = {mGeo->AnodePos(), 0.f, 0.f};
138 float glb[3] = {0.f, 0.f, 0.f};
139 for (int32_t iDet = 0; iDet < kNChambers; ++iDet) {
140 matrix = mGeo->GetClusterMatrix(iDet);
142 mR[iDet] =
x0[mGeo->GetLayer(iDet)];
145 matrix->LocalToMaster(loc, glb);
150template <
class TRDTRK,
class PROP>
159template <
class TRDTRK,
class PROP>
167 for (uint32_t iColl = 0; iColl < GetConstantMem()->ioPtrs.nTRDTriggerRecords; ++iColl) {
168 if (GetConstantMem()->ioPtrs.trdTrigRecMask && GetConstantMem()->ioPtrs.trdTrigRecMask[iColl] == 0) {
173 int32_t idxOffset = 0;
174 if (mProcessPerTimeFrame) {
175 idxOffset = GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iColl];
176 nTrklts = (iColl < GetConstantMem()->ioPtrs.nTRDTriggerRecords - 1) ? GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iColl + 1] - GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iColl] : GetConstantMem()->ioPtrs.nTRDTracklets - GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iColl];
178 nTrklts = GetConstantMem()->ioPtrs.nTRDTracklets;
181 int32_t* trkltIndexArray = &mTrackletIndexArray[iColl * (kNChambers + 1) + 1];
182 trkltIndexArray[-1] = 0;
185 int32_t trkltCounter = 0;
186 for (int32_t iTrklt = 0; iTrklt < nTrklts; ++iTrklt) {
187 if (
tracklets[iTrklt].GetDetector() > currDet) {
188 nextDet =
tracklets[iTrklt].GetDetector();
189 for (int32_t iDet = currDet; iDet < nextDet; ++iDet) {
190 trkltIndexArray[iDet] = trkltCounter;
196 for (int32_t iDet = currDet; iDet <= kNChambers; ++iDet) {
197 trkltIndexArray[iDet] = trkltCounter;
199 if (mGenerateSpacePoints) {
200 if (!CalculateSpacePoints(iColl)) {
201 GPUError(
"Space points for at least one chamber could not be calculated (for interaction %i)", iColl);
206 if (mGenerateSpacePoints) {
212template <
class TRDTRK,
class PROP>
218 if (!mIsInitialized) {
221 GPUError(
"Cannot change mNCandidates after initialization");
225template <
class TRDTRK,
class PROP>
231 GPUInfo(
"##############################################################");
232 GPUInfo(
"Current settings for GPU TRD tracker:");
233 GPUInfo(
" maxChi2(%.2f), chi2Penalty(%.2f), nCandidates(%i), maxMissingLayers(%i)", Param().
rec.trd.maxChi2, Param().
rec.trd.penaltyChi2, mNCandidates, Param().
rec.trd.stopTrkAfterNMissLy);
234 GPUInfo(
" ptCut = %.2f GeV, abs(eta) < %.2f", Param().
rec.trd.minTrackPt, mMaxEta);
235 GPUInfo(
"##############################################################");
238template <
class TRDTRK,
class PROP>
241 mDebug->CreateStreamer();
249 return &Param().polynomialField;
252template <
class TRDTRK,
class PROP>
255 return GetConstantMem()->calibObjects.o2Propagator;
258template <
class TRDTRK,
class PROP>
261 if (!trk.CheckNumericalQuality()) {
264 if (CAMath::Abs(trk.getEta()) > mMaxEta) {
267 if (trk.getPt() < Param().
rec.trd.minTrackPt) {
273template <
class TRDTRK,
class PROP>
274GPUd() int32_t
GPUTRDTracker_t<TRDTRK, PROP>::LoadTrack(const TRDTRK& trk, uint32_t tpcTrackId,
bool checkTrack, HelperTrackAttributes* attribs)
276 if (mNTracks >= mNMaxTracks) {
278 GPUError(
"Error: Track dropped (no memory available) -> must not happen");
282 if (checkTrack && !CheckTrackTRDCandidate(trk)) {
285 mTracks[mNTracks] = trk;
286 mTracks[mNTracks].setRefGlobalTrackIdRaw(tpcTrackId);
288 mTrackAttribs[mNTracks] = *attribs;
294template <
class TRDTRK,
class PROP>
300 GPUInfo(
"There are in total %i tracklets loaded", GetConstantMem()->ioPtrs.nTRDTracklets);
301 GPUInfo(
"There are %i tracks loaded. mNMaxTracks(%i)", mNTracks, mNMaxTracks);
302 for (int32_t
i = 0;
i < mNTracks; ++
i) {
303 auto* trk = &(mTracks[
i]);
304 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);
308template <
class TRDTRK,
class PROP>
309GPUd() int32_t
GPUTRDTracker_t<TRDTRK, PROP>::GetCollisionIDs(int32_t iTrk, int32_t* collisionIds)
const
319 for (uint32_t iColl = 0; iColl < GetConstantMem()->ioPtrs.nTRDTriggerRecords; ++iColl) {
320 if (GetConstantMem()->ioPtrs.trdTrigRecMask && GetConstantMem()->ioPtrs.trdTrigRecMask[iColl] == 0) {
323 if (GetConstantMem()->ioPtrs.trdTriggerTimes[iColl] > mTrackAttribs[iTrk].GetTimeMin() && GetConstantMem()->ioPtrs.trdTriggerTimes[iColl] < mTrackAttribs[iTrk].GetTimeMax()) {
325 GPUError(
"Found too many collision candidates for track with tMin(%f) and tMax(%f)", mTrackAttribs[iTrk].GetTimeMin(), mTrackAttribs[iTrk].GetTimeMax());
328 collisionIds[nColls++] = iColl;
334template <
class TRDTRK,
class PROP>
340 int32_t collisionIds[20] = {0};
341 int32_t nCollisionIds = 1;
342 if (mProcessPerTimeFrame) {
343 nCollisionIds = GetCollisionIDs(iTrk, collisionIds);
344 if (nCollisionIds == 0) {
346 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());
352 PROP prop(getPropagatorParam());
353 mTracks[iTrk].setChi2(Param().
rec.trd.penaltyChi2);
355 auto trkStart = mTracks[iTrk];
356 for (int32_t iColl = 0; iColl < nCollisionIds; ++iColl) {
358 auto trkCopy = trkStart;
359 prop.setTrack(&trkCopy);
360 prop.setFitInProjections(
true);
361 if (!FollowProlongation(&prop, &trkCopy, iTrk, threadId, collisionIds[iColl])) {
365 if (trkCopy.getReducedChi2() < mTracks[iTrk].getReducedChi2()) {
366 mTracks[iTrk] = trkCopy;
371template <
class TRDTRK,
class PROP>
380 int32_t idxOffset = iCollision * (kNChambers + 1);
384 for (int32_t iDet = 0; iDet < kNChambers; ++iDet) {
385 int32_t iFirstTrackletInDet = mTrackletIndexArray[idxOffset + iDet];
386 int32_t iFirstTrackletInNextDet = mTrackletIndexArray[idxOffset + iDet + 1];
387 int32_t nTrackletsInDet = iFirstTrackletInNextDet - iFirstTrackletInDet;
388 if (nTrackletsInDet == 0) {
391 if (!mGeo->ChamberInGeometry(iDet)) {
392 GPUError(
"Found TRD tracklets in chamber %i which is not included in the geometry", iDet);
395 auto* matrix = mGeo->GetClusterMatrix(iDet);
397 GPUError(
"No cluster matrix available for chamber %i. Skipping it...", iDet);
403 int32_t trkltIdxOffset = (mProcessPerTimeFrame) ? GetConstantMem()->ioPtrs.trdTrackletIdxFirst[iCollision] : 0;
404 int32_t trkltIdxStart = trkltIdxOffset + iFirstTrackletInDet;
405 for (int32_t trkltIdx = trkltIdxStart; trkltIdx < trkltIdxStart + nTrackletsInDet; ++trkltIdx) {
406 int32_t trkltZbin =
tracklets[trkltIdx].GetZbin();
407 float xTrkltDet[3] = {0.f};
408 float xTrkltSec[3] = {0.f};
409 xTrkltDet[0] = mGeo->AnodePos() + sRadialOffset;
410 xTrkltDet[1] =
tracklets[trkltIdx].GetY();
411 xTrkltDet[2] = pp->GetRowPos(trkltZbin) - pp->GetRowSize(trkltZbin) / 2.f - pp->GetRowPos(pp->GetNrows() / 2);
413 matrix->LocalToMaster(xTrkltDet, xTrkltSec);
414 mSpacePoints[trkltIdx].setX(xTrkltSec[0]);
415 mSpacePoints[trkltIdx].setY(xTrkltSec[1]);
416 mSpacePoints[trkltIdx].setZ(xTrkltSec[2]);
417 mSpacePoints[trkltIdx].setDy(
tracklets[trkltIdx].GetdY());
425template <
class TRDTRK,
class PROP>
426GPUd() bool
GPUTRDTracker_t<TRDTRK, PROP>::FollowProlongation(PROP* prop, TRDTRK* t, int32_t iTrk, int32_t threadId, int32_t collisionId)
436 GPUInfo(
"Start track following for track %i at x=%f with pt=%f", t->getRefGlobalTrackIdRaw(), t->getX(), t->getPt());
442 int32_t nIdxBCMin = -1;
443 int32_t nIdxBCMax = -1;
445 for (int32_t iBC = 0; iBC < mNFT0BC; iBC++) {
446 int32_t deltaBC = CAMath::Round(mFT0TriggeredBC[iBC] - GetConstantMem()->ioPtrs.trdTriggerTimes[collisionId] / o2::constants::lhc::LHCBunchSpacingMUS);
447 if (nIdxBCMin == -1 && deltaBC > mRecoParam->getPileUpRangeBefore()) {
450 if (deltaBC >= mRecoParam->getPileUpRangeAfter()) {
454 if (iBC == mNFT0BC - 1) {
456 if (nIdxBCMin == -1) {
458 nIdxBCMin = nIdxBCMax;
463 float zShiftTrk = 0.f;
464 if (mProcessPerTimeFrame) {
465 zShiftTrk = (mTrackAttribs[iTrk].mTime - GetConstantMem()->ioPtrs.trdTriggerTimes[collisionId]) * mTPCVdrift * mTrackAttribs[iTrk].mSide;
473 const GPUTRDSpacePoint* spacePoints = GetConstantMem()->ioPtrs.trdSpacePoints;
475#ifdef ENABLE_GPUTRDDEBUG
476 TRDTRK trackNoUp(*t);
479 int32_t candidateIdxOffset = threadId * 2 * mNCandidates;
480 int32_t hypothesisIdxOffset = threadId * mNCandidates;
481 int32_t trkltIdxOffset = collisionId * (kNChambers + 1);
482 int32_t glbTrkltIdxOffset = (mProcessPerTimeFrame) ? GetConstantMem()->ioPtrs.trdTrackletIdxFirst[collisionId] : 0;
485 if (mNCandidates > 1) {
487 mCandidates[candidateIdxOffset] = *t;
490 int32_t nCandidates = 1;
491 int32_t nCurrHypothesis = 0;
496 const int32_t nMaxChambersToSearch = 4;
498 mDebug->SetGeneralInfo(mNEvents, mNTracks, iTrk, t->getPt());
500 for (int32_t iLayer = 0; iLayer < kNLayers; ++iLayer) {
503 int32_t currIdx = candidateIdxOffset + iLayer % 2;
504 int32_t nextIdx = candidateIdxOffset + (iLayer + 1) % 2;
505 pad = mGeo->GetPadPlane(iLayer, 0);
506 float tilt = CAMath::Tan(CAMath::Pi() / 180.f * pad->GetTiltingAngle());
507 const float zMaxTRD = pad->GetRow0();
514 for (int32_t iCandidate = 0; iCandidate < nCandidates; iCandidate++) {
516 int32_t det[nMaxChambersToSearch] = {-1, -1, -1, -1};
518 if (mNCandidates > 1) {
519 trkWork = &mCandidates[2 * iCandidate + currIdx];
520 prop->setTrack(trkWork);
523 if (trkWork->getIsStopped()) {
524 Hypothesis hypo(trkWork->getNlayersFindable(), iCandidate, -1, trkWork->getChi2());
525 InsertHypothesis(hypo, nCurrHypothesis, hypothesisIdxOffset);
531 if (!prop->propagateToX(mR[2 * kNLayers + iLayer], .8f, 2.f)) {
533 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]);
539 if (!AdjustSector(prop, trkWork)) {
541 GPUInfo(
"Adjusting sector failed for track %i candidate %i in layer %i", iTrk, iCandidate, iLayer);
547 if (IsGeoFindable(trkWork, iLayer, prop->getAlpha(), zShiftTrk)) {
548 trkWork->setIsFindable(iLayer);
552 roadY = 7.f * CAMath::Sqrt(trkWork->getSigmaY2() + 0.1f * 0.1f) + Param().rec.trd.extraRoadY;
554 roadZ = mRoadZ + Param().rec.trd.extraRoadZ;
556 if (CAMath::Abs(trkWork->getZ() + zShiftTrk) - roadZ >= zMaxTRD) {
558 GPUInfo(
"Track out of TRD acceptance with z=%f in layer %i (eta=%f)", trkWork->getZ() + zShiftTrk, iLayer, trkWork->getEta());
564 FindChambersInRoad(trkWork, roadY, roadZ, iLayer, det, zMaxTRD, prop->getAlpha(), zShiftTrk);
567 mDebug->SetTrackParameter(*trkWork, iLayer);
570 for (int32_t iDet = 0; iDet < nMaxChambersToSearch; iDet++) {
571 int32_t currDet = det[iDet];
575 pad = mGeo->GetPadPlane(currDet);
576 int32_t currSec = mGeo->GetSector(currDet);
577 if (currSec != GetSector(prop->getAlpha())) {
578 if (!prop->rotate(GetAlphaOfSector(currSec))) {
580 GPUWarning(
"Track could not be rotated in tracklet coordinate system");
585 if (currSec != GetSector(prop->getAlpha())) {
586 GPUError(
"Track is in sector %i and sector %i is searched for tracklets", GetSector(prop->getAlpha()), currSec);
590 if (!prop->propagateToX(mR[currDet], .8f, .2f)) {
592 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);
597 for (int32_t trkltIdx = glbTrkltIdxOffset + mTrackletIndexArray[trkltIdxOffset + currDet]; trkltIdx < glbTrkltIdxOffset + mTrackletIndexArray[trkltIdxOffset + currDet + 1]; ++trkltIdx) {
598 if (CAMath::Abs(trkWork->getY() - spacePoints[trkltIdx].getY()) > roadY || CAMath::Abs(trkWork->getZ() + zShiftTrk - spacePoints[trkltIdx].getZ()) > roadZ) {
604 prop->getPropagatedYZ(spacePoints[trkltIdx].
getX(), projY, projZ);
606 float tiltCorr = tilt * (spacePoints[trkltIdx].getZ() - projZ);
607 float dyTiltCorr = tilt * trkWork->getTgl() * mGeo->GetCdrHght();
608 float lPad = pad->GetRowSize(
tracklets[trkltIdx].GetZbin());
609 if (!((CAMath::Abs(spacePoints[trkltIdx].getZ() - projZ) < lPad) && (trkWork->getSigmaZ2() < (lPad * lPad / 12.f)))) {
617 float yCorrPileUp = 0.f;
618 float yAddErrPileUp2 = 0.f;
620 float zShiftTrkPileUp = 0.f;
621 if (nIdxBCMax - nIdxBCMin >= 2) {
625 float sumCorr2 = 0.f;
628 float slopeFactor =
tracklets[trkltIdx].GetSlopeFloat() * mGeo->GetPadPlaneWidthIPad(
tracklets[trkltIdx].GetDetector()) / 4.f;
629 for (int32_t iBC = nIdxBCMin; iBC < nIdxBCMax; iBC++) {
630 int32_t deltaBC = CAMath::Round(mFT0TriggeredBC[iBC] - GetConstantMem()->ioPtrs.trdTriggerTimes[collisionId] / o2::constants::lhc::LHCBunchSpacingMUS);
631 float probBC = mRecoParam->getPileUpProbTracklet(deltaBC,
true, (
tracklets[trkltIdx].GetQ0() != 0), (
tracklets[trkltIdx].GetQ1() != 0));
632 sumCorr += probBC * slopeFactor * deltaBC;
633 sumCorr2 += probBC * slopeFactor * deltaBC * slopeFactor * deltaBC;
635 if (probBC > maxProb) {
637 yCorrPileUp = -slopeFactor * deltaBC;
638 zShiftTrkPileUp = -deltaBC * o2::constants::lhc::LHCBunchSpacingMUS * mTPCVdrift * mTrackAttribs[iTrk].mSide;
641 if (sumProb > 1e-6f) {
642 yAddErrPileUp2 = sumCorr2 / sumProb - 2 * yCorrPileUp * sumCorr / sumProb + yCorrPileUp * yCorrPileUp;
647 int nTrackletsChamber = mTrackletIndexArray[trkltIdxOffset + currDet + 1] - mTrackletIndexArray[trkltIdxOffset + currDet];
648 float angularPull = GetAngularPull(spacePoints[trkltIdx].getDy() + dyTiltCorr, trkWork->getSnp(), nTrackletsChamber);
651 float zPosCorr = spacePoints[trkltIdx].getZ() + mRecoParam->getZCorrCoeffNRC() * trkWork->getTgl();
652 float yPosCorr = spacePoints[trkltIdx].getY() - tiltCorr + yCorrPileUp;
653 zPosCorr -= zShiftTrk + zShiftTrkPileUp;
656 if (Param().
rec.trd.useAngularPull == 3 || Param().
rec.trd.useAngularPull == 4) {
657 float corrPull = -angularPull * mRecoParam->getCorrYDy(trkWork->getSnp());
658 yPosCorr += corrPull;
661 float deltaY = yPosCorr - projY;
662 float deltaZ = zPosCorr - projZ;
664 float trkltPosTmpYZ[2] = {yPosCorr, zPosCorr};
665 float trkltCovTmp[3] = {0.f};
666 if ((CAMath::Abs(deltaY) < roadY) && (CAMath::Abs(deltaZ) < roadZ)) {
668 RecalcTrkltCov(tilt, trkWork->getSnp(), pad->GetRowSize(
tracklets[trkltIdx].GetZbin()), (Param().
rec.trd.useAngularPull == 2 || Param().
rec.trd.useAngularPull == 4 ? angularPull : 0.f), nTrackletsChamber, trkltCovTmp);
669 trkltCovTmp[0] += yAddErrPileUp2;
670 float chi2 = prop->getPredictedChi2(trkltPosTmpYZ, trkltCovTmp);
672 if (Param().
rec.trd.addDeflectionInChi2 >= 1 && (trkWork->getSnp() < 1.f - 1e-6f) && (trkWork->getSnp() > -1.f + 1e-6f)) {
674 float trkltCovTmpWithDy[6] = {trkltCovTmp[0], trkltCovTmp[1], trkltCovTmp[2], 0.f, 0.f, 0.f};
675 RecalcTrkltCovDy(tilt, trkWork->getSnp(), (Param().
rec.trd.useAngularPull == 2 || Param().
rec.trd.useAngularPull == 4 ? angularPull : 0.f), nTrackletsChamber, trkltCovTmpWithDy);
676 trkltCovTmpWithDy[0] += trkWork->getSigmaY2();
677 trkltCovTmpWithDy[1] += trkWork->getSigmaZY();
678 trkltCovTmpWithDy[2] += trkWork->getSigmaZ2();
680 if (Param().
rec.trd.useAngularPull == 3 || Param().
rec.trd.useAngularPull == 4) {
682 trkltCovTmpWithDy[3] = 0.;
683 trkltCovTmpWithDy[4] = 0.;
687 trkltCovTmpWithDy[3] += trkWork->getSigmaSnpY() * mGeo->GetCdrHght();
688 trkltCovTmpWithDy[4] += trkWork->getSigmaSnpZ() * mGeo->GetCdrHght();
691 float sigmaZ2 = trkltCovTmpWithDy[2];
692 float sigmaDy2 = trkltCovTmpWithDy[5];
695 if (InvertCov(trkltCovTmpWithDy)) {
696 float deltaDy = spacePoints[trkltIdx].getDy() + dyTiltCorr - mRecoParam->convertAngleToDy(trkWork->getSnp());
697 if (Param().
rec.trd.addDeflectionInChi2 == 2 || Param().
rec.trd.addDeflectionInChi2 == 3) {
699 double likelihood = mRecoParam->getDyLikelihood(trkWork->getSnp(), spacePoints[trkltIdx].getDy() + dyTiltCorr, nTrackletsChamber);
700 if (likelihood < 1e-6f) {
703 deltaDy = CAMath::Sqrt(-2.f * CAMath::Log(likelihood) * sigmaDy2) * (deltaDy > 0.f ? 1.f : -1.f);
705 if (Param().rec.trd.addDeflectionInChi2 == 3) {
707 double likelihood = mRecoParam->getZLikelihood(deltaZ, pad->GetRowSize(
tracklets[trkltIdx].GetZbin()), CAMath::Sqrt(trkWork->getSigmaZ2()));
708 if (likelihood < 1e-6f) {
711 deltaZ = CAMath::Sqrt(-2.f * CAMath::Log(likelihood) * sigmaZ2) * (deltaZ > 0.f ? 1.f : -1.f);
713 chi2 = deltaY * trkltCovTmpWithDy[0] * deltaY + 2 * deltaY * trkltCovTmpWithDy[1] * deltaZ + 2 * deltaY * trkltCovTmpWithDy[3] * deltaDy + deltaZ * trkltCovTmpWithDy[2] * deltaZ + 2 * deltaZ * trkltCovTmpWithDy[4] * deltaDy + deltaDy * trkltCovTmpWithDy[5] * deltaDy;
717 if ((
chi2 > Param().
rec.trd.maxChi2) || (Param().rec.trd.applyDeflectionCut && CAMath::Abs(angularPull) > 4)) {
720 Hypothesis hypo(trkWork->getNlayersFindable(), iCandidate, trkltIdx, trkWork->getChi2() +
chi2);
721 InsertHypothesis(hypo, nCurrHypothesis, hypothesisIdxOffset);
727 Hypothesis hypoNoUpdate(trkWork->getNlayersFindable(), iCandidate, -1, trkWork->getChi2() + Param().
rec.trd.penaltyChi2);
728 InsertHypothesis(hypoNoUpdate, nCurrHypothesis, hypothesisIdxOffset);
732 mDebug->SetChi2Update(mHypothesis[0 + hypothesisIdxOffset].mChi2 - t->getChi2(), iLayer);
733 mDebug->SetRoad(roadY, roadZ, iLayer);
734 bool wasTrackStored =
false;
742 for (int32_t iUpdate = 0; iUpdate < nCurrHypothesis && iUpdate < mNCandidates; iUpdate++) {
743 if (mHypothesis[iUpdate + hypothesisIdxOffset].mCandidateId == -1) {
750 nCandidates = iUpdate + 1;
751 if (mNCandidates > 1) {
752 mCandidates[2 * iUpdate + nextIdx] = mCandidates[2 * mHypothesis[iUpdate + hypothesisIdxOffset].mCandidateId + currIdx];
753 trkWork = &mCandidates[2 * iUpdate + nextIdx];
755 if (mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId == -1) {
757 if (trkWork->getIsFindable(iLayer)) {
758 if (trkWork->getNmissingConsecLayers(iLayer) > Param().
rec.trd.stopTrkAfterNMissLy) {
759 trkWork->setIsStopped();
761 trkWork->setChi2(trkWork->getChi2() + Param().
rec.trd.penaltyChi2);
763 if (iUpdate == 0 && mNCandidates > 1) {
764 *t = mCandidates[2 * iUpdate + nextIdx];
769 if (mNCandidates > 1) {
770 prop->setTrack(trkWork);
772 int32_t trkltSec = mGeo->GetSector(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector());
773 if (trkltSec != GetSector(prop->getAlpha())) {
775 prop->rotate(GetAlphaOfSector(trkltSec));
777 if (!prop->propagateToX(spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getX(), .8f, 2.f)) {
779 GPUWarning(
"Final track propagation for track %i update %i in layer %i failed", iTrk, iUpdate, iLayer);
781 trkWork->setChi2(trkWork->getChi2() + Param().
rec.trd.penaltyChi2);
782 if (trkWork->getIsFindable(iLayer)) {
783 if (trkWork->getNmissingConsecLayers(iLayer) >= Param().
rec.trd.stopTrkAfterNMissLy) {
784 trkWork->setIsStopped();
787 if (iUpdate == 0 && mNCandidates > 1) {
788 *t = mCandidates[2 * iUpdate + nextIdx];
793 pad = mGeo->GetPadPlane(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector());
794 float tiltCorrUp = tilt * (spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getZ() - trkWork->getZ());
795 float dyTiltCorr = tilt * trkWork->getTgl() * mGeo->GetCdrHght();
797 float yPosCorrUp = spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getY() - tiltCorrUp;
799 float zPosCorrUp = spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getZ() + mRecoParam->getZCorrCoeffNRC() * trkWork->getTgl();
800 zPosCorrUp -= zShiftTrk;
801 float padLength = pad->GetRowSize(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetZbin());
802 if (!((trkWork->getSigmaZ2() < (padLength * padLength / 12.f)) && (CAMath::Abs(spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getZ() - trkWork->getZ()) < padLength))) {
810 float yCorrPileUp = 0.f;
811 float yAddErrPileUp2 = 0.f;
812 float zShiftTrkPileUp = 0.f;
813 if (nIdxBCMax - nIdxBCMin >= 2) {
817 float sumCorr2 = 0.f;
820 float slopeFactor =
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetSlopeFloat() * mGeo->GetPadPlaneWidthIPad(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector()) / 4.f;
821 for (int32_t iBC = nIdxBCMin; iBC < nIdxBCMax; iBC++) {
822 int32_t deltaBC = CAMath::Round(mFT0TriggeredBC[iBC] - GetConstantMem()->ioPtrs.trdTriggerTimes[collisionId] / o2::constants::lhc::LHCBunchSpacingMUS);
823 float probBC = mRecoParam->getPileUpProbTracklet(deltaBC,
true, (
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetQ0() != 0), (
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetQ1() != 0));
824 sumCorr += probBC * slopeFactor * deltaBC;
825 sumCorr2 += probBC * slopeFactor * deltaBC * slopeFactor * deltaBC;
827 if (probBC > maxProb) {
829 yCorrPileUp = -slopeFactor * deltaBC;
830 zShiftTrkPileUp = -deltaBC * o2::constants::lhc::LHCBunchSpacingMUS * mTPCVdrift * mTrackAttribs[iTrk].mSide;
833 if (sumProb > 1e-6f) {
834 yAddErrPileUp2 = sumCorr2 / sumProb - 2 * yCorrPileUp * sumCorr / sumProb + yCorrPileUp * yCorrPileUp;
838 zPosCorrUp -= zShiftTrkPileUp;
839 yPosCorrUp += yCorrPileUp;
841 const auto currDet =
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector();
842 int nTrackletsChamber = mTrackletIndexArray[trkltIdxOffset + currDet + 1] - mTrackletIndexArray[trkltIdxOffset + currDet];
843 float angularPull = GetAngularPull(spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getDy() + dyTiltCorr, trkWork->getSnp(), nTrackletsChamber);
846 if (Param().
rec.trd.useAngularPull == 3 || Param().
rec.trd.useAngularPull == 4) {
847 float corrPull = -angularPull * mRecoParam->getCorrYDy(trkWork->getSnp());
848 yPosCorrUp += corrPull;
851 float trkltPosUp[2] = {yPosCorrUp, zPosCorrUp};
852 float trkltCovUp[3] = {0.f};
853 RecalcTrkltCov(tilt, trkWork->getSnp(), pad->GetRowSize(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetZbin()), ((Param().
rec.trd.useAngularPull != 0) ? angularPull : 0.f), nTrackletsChamber, trkltCovUp);
854 trkltCovUp[0] += yAddErrPileUp2;
856#ifdef ENABLE_GPUTRDDEBUG
857 prop->setTrack(&trackNoUp);
858 prop->rotate(GetAlphaOfSector(trkltSec));
860 prop->propagateToX(mR[
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector()], .8f, 2.f);
861 prop->setTrack(trkWork);
864 if (!wasTrackStored) {
865#ifdef ENABLE_GPUTRDDEBUG
866 mDebug->SetTrackParameterNoUp(trackNoUp, iLayer);
868 mDebug->SetTrackParameter(*trkWork, iLayer);
869 mDebug->SetRawTrackletPosition(spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].
getX(), spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].
getY(), spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getZ(), iLayer);
870 mDebug->SetCorrectedTrackletPosition(trkltPosUp, iLayer);
871 mDebug->SetTrackletCovariance(trkltCovUp, iLayer);
872 mDebug->SetTrackletProperties(spacePoints[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].getDy(),
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetDetector(), iLayer);
873 wasTrackStored =
true;
876 if (!prop->update(trkltPosUp, trkltCovUp)) {
878 GPUWarning(
"Failed to update track %i with space point in layer %i", iTrk, iLayer);
880 trkWork->setChi2(trkWork->getChi2() + Param().
rec.trd.penaltyChi2);
881 if (trkWork->getIsFindable(iLayer)) {
882 if (trkWork->getNmissingConsecLayers(iLayer) >= Param().
rec.trd.stopTrkAfterNMissLy) {
883 trkWork->setIsStopped();
886 if (iUpdate == 0 && mNCandidates > 1) {
887 *t = mCandidates[2 * iUpdate + nextIdx];
891 if (!trkWork->CheckNumericalQuality()) {
893 GPUInfo(
"Track %i has invalid covariance matrix. Aborting track following\n", iTrk);
897 trkWork->addTracklet(iLayer, mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId);
898 trkWork->setChi2(mHypothesis[iUpdate + hypothesisIdxOffset].mChi2);
899 trkWork->setIsFindable(iLayer);
900 trkWork->setCollisionId(collisionId);
902 float projZEntry, projYEntry;
904 prop->getPropagatedYZ(trkWork->getX() - mGeo->GetCdrHght(), projYEntry, projZEntry);
910 const auto padrowEntry = pad->GetPadRowNumber(projZEntry);
911 const auto padrowExit = pad->GetPadRowNumber(trkWork->getZ());
912 if (padrowEntry != padrowExit) {
913 trkWork->setIsCrossingNeighbor(iLayer);
914 trkWork->setHasPadrowCrossing();
918 for (int32_t trkltIdx = glbTrkltIdxOffset + mTrackletIndexArray[trkltIdxOffset + currDet]; trkltIdx < glbTrkltIdxOffset + mTrackletIndexArray[trkltIdxOffset + currDet + 1]; ++trkltIdx) {
920 if (mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId == trkltIdx) {
923 if (CAMath::Abs(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetZbin() -
tracklets[trkltIdx].GetZbin()) == 1 &&
924 CAMath::Abs(
tracklets[mHypothesis[iUpdate + hypothesisIdxOffset].mTrackletId].GetY() -
tracklets[trkltIdx].GetY()) < 1) {
925 trkWork->setIsCrossingNeighbor(iLayer);
926 trkWork->setHasNeighbor();
930 if (iUpdate == 0 && mNCandidates > 1) {
931 *t = mCandidates[2 * iUpdate + nextIdx];
938 GPUInfo(
"Track %i cannot be followed. Stopped in layer %i", iTrk, iLayer);
949 mDebug->SetTrack(*t);
953 GPUInfo(
"Ended track following for track %i at x=%f with pt=%f. Attached %i tracklets", t->getRefGlobalTrackIdRaw(), t->getX(), t->getPt(), t->getNtracklets());
955 if (nCurrHypothesis > 1) {
956 if (CAMath::Abs(mHypothesis[hypothesisIdxOffset + 1].GetReducedChi2() - mHypothesis[hypothesisIdxOffset].GetReducedChi2()) < Param().
rec.trd.chi2SeparationCut) {
963template <
class TRDTRK,
class PROP>
964GPUd()
void GPUTRDTracker_t<TRDTRK, PROP>::InsertHypothesis(Hypothesis hypo, int32_t& nCurrHypothesis, int32_t idxOffset)
970 if (nCurrHypothesis == 0) {
972 mHypothesis[idxOffset] = hypo;
974 }
else if (nCurrHypothesis > 0 && nCurrHypothesis < mNCandidates) {
976 for (int32_t
i = idxOffset;
i < nCurrHypothesis + idxOffset; ++
i) {
977 if (hypo.GetReducedChi2() < mHypothesis[
i].GetReducedChi2()) {
978 for (int32_t k = nCurrHypothesis + idxOffset; k >
i; --k) {
979 mHypothesis[k] = mHypothesis[k - 1];
981 mHypothesis[
i] = hypo;
986 mHypothesis[nCurrHypothesis + idxOffset] = hypo;
991 int32_t
i = nCurrHypothesis + idxOffset - 1;
992 for (;
i >= idxOffset; --
i) {
993 if (mHypothesis[
i].GetReducedChi2() < hypo.GetReducedChi2()) {
997 if (
i < (nCurrHypothesis + idxOffset - 1)) {
999 for (int32_t k = nCurrHypothesis + idxOffset - 1; k >
i + 1; --k) {
1000 mHypothesis[k] = mHypothesis[k - 1];
1002 mHypothesis[
i + 1] = hypo;
1007template <
class TRDTRK,
class PROP>
1018 int32_t sector = GetSector(
alpha);
1020 return mGeo->GetDetector(
layer,
stack, sector);
1023template <
class TRDTRK,
class PROP>
1031 float alpha = mGeo->GetAlpha();
1032 float xTmp = t->getX();
1033 float y = t->getY();
1034 float yMax = t->getX() * CAMath::Tan(0.5f *
alpha);
1035 float alphaCurr = t->getAlpha();
1037 if (CAMath::Abs(
y) > 2.f *
yMax) {
1039 GPUInfo(
"AdjustSector: Track %i with pT = %f crossing two sector boundaries at x = %f", t->getRefGlobalTrackIdRaw(), t->getPt(), t->getX());
1045 while (CAMath::Abs(
y) >
yMax) {
1049 int32_t sign = (
y > 0) ? 1 : -1;
1050 float alphaNew = alphaCurr +
alpha * sign;
1051 if (alphaNew > CAMath::Pi()) {
1052 alphaNew -= 2 * CAMath::Pi();
1053 }
else if (alphaNew < -CAMath::Pi()) {
1054 alphaNew += 2 * CAMath::Pi();
1056 if (!prop->rotate(alphaNew)) {
1059 if (!prop->propagateToX(xTmp, .8f, 2.f)) {
1068template <
class TRDTRK,
class PROP>
1075 alpha += 2.f * CAMath::Pi();
1076 }
else if (
alpha >= 2.f * CAMath::Pi()) {
1077 alpha -= 2.f * CAMath::Pi();
1079 return (int32_t)(
alpha * (float)kNSectors / (2.f * CAMath::Pi()));
1082template <
class TRDTRK,
class PROP>
1088 float alpha = 2.0f * CAMath::Pi() / (float)kNSectors * ((
float)sec + 0.5f);
1089 if (
alpha > CAMath::Pi()) {
1090 alpha -= 2 * CAMath::Pi();
1095template <
class TRDTRK,
class PROP>
1096GPUd()
void GPUTRDTracker_t<TRDTRK, PROP>::RecalcTrkltCov(const
float tilt, const
float snp, const
float rowSize, const
float pull, const
int occupancy,
float (&cov)[3])
1102 float t2 = tilt * tilt;
1103 float c2 = 1.f / (1.f + t2);
1104 float sy2 = mRecoParam->getRPhiRes(snp, CAMath::Abs(pull), occupancy);
1105 float sz2 = rowSize * rowSize / 12.f;
1106 cov[0] = c2 * (sy2 + t2 * sz2);
1107 cov[1] = c2 * tilt * (sz2 - sy2);
1108 cov[2] = c2 * (t2 * sy2 + sz2);
1111template <
class TRDTRK,
class PROP>
1112GPUd()
void GPUTRDTracker_t<TRDTRK, PROP>::RecalcTrkltCovDy(const
float tilt, const
float snp, const
float pull, const
int occupancy,
float (&cov)[6])
1114 float t2 = tilt * tilt;
1115 float c2 = 1.f / (1.f + t2);
1117 float sdy2 = mRecoParam->getDyRes(snp, occupancy);
1118 cov[3] = mRecoParam->getCorrYDy(snp) * CAMath::Sqrt(sdy2 * c2);
1119 cov[4] = -tilt * mRecoParam->getCorrYDy(snp) * CAMath::Sqrt(sdy2 * c2);
1123template <
class TRDTRK,
class PROP>
1128 float c00 = cov[2] * cov[5] - cov[4] * cov[4];
1129 float c01 = cov[4] * cov[3] - cov[1] * cov[5];
1130 float c02 = cov[1] * cov[4] - cov[2] * cov[3];
1131 float c11 = cov[5] * cov[0] - cov[3] * cov[3];
1132 float c12 = cov[3] * cov[1] - cov[4] * cov[0];
1133 float c22 = cov[0] * cov[2] - cov[1] * cov[1];
1135 float t0 = CAMath::Abs(cov[0]);
1136 float t1 = CAMath::Abs(cov[1]);
1137 float t2 = CAMath::Abs(cov[3]);
1145 det = c12 * c01 - c11 * c02;
1148 det = c11 * c22 - c12 * c12;
1150 }
else if (t2 >=
t1) {
1152 det = c12 * c01 - c11 * c02;
1155 det = c02 * c12 - c01 * c22;
1158 if (det == 0 || tmp == 0) {
1162 float s = tmp / det;
1174template <
class TRDTRK,
class PROP>
1175GPUd() float
GPUTRDTracker_t<TRDTRK, PROP>::GetAngularPull(
float dYtracklet,
float snp,
int occupancy)
const
1177 float dYtrack = mRecoParam->convertAngleToDy(snp);
1178 float dYresolution = mRecoParam->getDyRes(snp, occupancy);
1179 if (dYresolution < 1e-6f) {
1182 return (dYtracklet - dYtrack) / CAMath::Sqrt(dYresolution);
1185template <
class TRDTRK,
class PROP>
1186GPUd() int
GPUTRDTracker_t<TRDTRK, PROP>::GetNtrackletsChamber(
int collisionId,
int detector)
const
1189 int32_t trkltIdxOffset = collisionId * (kNChambers + 1);
1190 int nTrackletsChamber = mTrackletIndexArray[trkltIdxOffset + detector + 1] - mTrackletIndexArray[trkltIdxOffset + detector];
1191 return nTrackletsChamber;
1194template <
class TRDTRK,
class PROP>
1195GPUd()
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
1203 const float yMax = CAMath::Abs(mGeo->GetCol0(iLayer));
1204 float zTrk = t->getZ() + zShiftTrk;
1206 int32_t currStack = mGeo->GetStack(zTrk, iLayer);
1207 int32_t currSec = GetSector(
alpha);
1212 if (currStack > -1) {
1214 currDet = mGeo->GetDetector(iLayer, currStack, currSec);
1215 det[nDets++] = currDet;
1217 int32_t lastPadRow = mGeo->GetRowMax(iLayer, currStack, 0);
1218 float zCenter = pp->GetRowPos(lastPadRow / 2);
1219 if ((zTrk + roadZ) > pp->GetRow0() || (zTrk - roadZ) < pp->GetRowEnd()) {
1220 int32_t addStack = zTrk > zCenter ? currStack - 1 : currStack + 1;
1221 if (addStack < kNStacks && addStack > -1) {
1222 det[nDets++] = mGeo->GetDetector(iLayer, addStack, currSec);
1226 if (CAMath::Abs(zTrk) >
zMax) {
1229 currDet = mGeo->GetDetector(iLayer, 0, currSec);
1231 currDet = mGeo->GetDetector(iLayer, kNStacks - 1, currSec);
1233 det[nDets++] = currDet;
1234 currStack = mGeo->GetStack(currDet);
1238 currDet = GetDetectorNumber(zTrk + 4.0f,
alpha, iLayer);
1239 if (currDet != -1) {
1240 det[nDets++] = currDet;
1242 currDet = GetDetectorNumber(zTrk - 4.0f,
alpha, iLayer);
1243 if (currDet != -1) {
1244 det[nDets++] = currDet;
1249 if ((CAMath::Abs(t->getY()) + roadY) >
yMax) {
1250 const int32_t nStacksToSearch = nDets;
1252 if (t->getY() > 0) {
1253 newSec = (currSec + 1) % kNSectors;
1255 newSec = (currSec > 0) ? currSec - 1 : kNSectors - 1;
1257 for (int32_t idx = 0;
idx < nStacksToSearch; ++
idx) {
1258 currStack = mGeo->GetStack(det[idx]);
1259 det[nDets++] = mGeo->GetDetector(iLayer, currStack, newSec);
1263 for (int32_t iDet = 0; iDet < nDets; iDet++) {
1264 if (!mGeo->ChamberInGeometry(det[iDet])) {
1270template <
class TRDTRK,
class PROP>
1271GPUd() bool
GPUTRDTracker_t<TRDTRK, PROP>::IsGeoFindable(const TRDTRK* t, const int32_t
layer, const
float alpha, const
float zShiftTrk)
const
1278 float zTrk = t->getZ() + zShiftTrk;
1280 int32_t det = GetDetectorNumber(zTrk,
alpha,
layer);
1288 if (!mGeo->ChamberInGeometry(det)) {
1293 if (mChamberStatus[det]) {
1298 float yMax = pp->GetColEnd();
1299 float zMax = pp->GetRow0();
1300 float zMin = pp->GetRowEnd();
1306 if (
yMax - CAMath::Abs(t->getY()) < epsY) {
1310 if (!((zTrk >
zMin + epsZ) && (zTrk <
zMax - epsZ))) {
1325#ifndef GPUCA_GPUCODE