@@ -51,6 +51,7 @@ using namespace o2::tpc;
5151GPUd () bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger& GPUrestrict () merger, int32_t iTrk, int32_t& GPUrestrict() N, int32_t& GPUrestrict() NTolerated, float& GPUrestrict() Alpha, GPUTPCGMMergedTrack& GPUrestrict() track, bool rebuilt, bool retryAttempt)
5252{
5353 static constexpr float maxSinPhi = GPUCA_MAX_SIN_PHI;
54+ const float maxSinForUpdate = CAMath::Sin (70 .f * CAMath::Deg2Rad ());
5455
5556 const GPUParam& GPUrestrict () param = merger.Param ();
5657 GPUTPCGMMergedTrackHit* GPUrestrict () clusters = merger.Clusters () + track.FirstClusterRef ();
@@ -218,7 +219,6 @@ GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger& GPUrestrict() merger, int32_
218219 continue ;
219220 }
220221
221- const float maxSinForUpdate = CAMath::Sin (70 .f * CAMath::Deg2Rad ());
222222 if (mNDF > 0 && CAMath::Abs (prop.GetSinPhi0 ()) >= maxSinForUpdate) { // TODO: If NDF is large enough, and mP[2] is not yet out of range, reinit linearization
223223 const bool inward = clusters[0 ].row > clusters[maxN - 1 ].row ;
224224 const bool markHighIncl = (mP [2 ] > 0 ) ^ (mP [4 ] < 0 ) ^ inward ^ (iWay & 1 );
@@ -269,16 +269,102 @@ GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger& GPUrestrict() merger, int32_
269269 lastUpdateRow = cluster.row ;
270270 assert (!param.rec .tpc .mergerInterpolateErrors || rebuilt || iWay != nWays - 2 || ihit || interpolationIndex == 0 );
271271 }
272- if (finalOutInFit && !(param.rec .tpc .disableRefitAttachment & 4 ) && lastUpdateRow != 255 && !retryAttempt) {
273- StoreLoopPropagation (merger, lastSector, lastUpdateRow, iTrk, lastUpdateRow > clusters[(iWay & 1 ) ? (maxN - 1 ) : 0 ].row , prop.GetAlpha ());
274- CADEBUG (printf (" \t\t STORING %d lastUpdateRow %d row %d out %d\n " , iTrk, (int )lastUpdateRow, (int )clusters[(iWay & 1 ) ? (maxN - 1 ) : 0 ].row , lastUpdateRow > clusters[(iWay & 1 ) ? (maxN - 1 ) : 0 ].row ));
275- }
272+
276273 if (!(iWay & 1 ) && !finalFit && !track.CCE () && !track.Looper ()) {
277274 deltaZ = ShiftZ (clusters, merger, maxN);
278275 } else {
279276 deltaZ = 0 .f ;
280277 }
281278
279+ if (param.rec .tpc .rebuildTrackInFit && !rebuilt && param.rec .tpc .rebuildTrackInFitExtrapolate && iWay >= nWays - 3 && CAMath::Abs (mP [2 ]) < maxSinForUpdate && lastUpdateRow != 255 ) {
280+ const int32_t up = ((clusters[0 ].row < clusters[maxN - 1 ].row ) ^ (iWay & 1 )) ? 1 : -1 ;
281+ int32_t sector = lastSector;
282+ int32_t rowGap = 0 , missingRowsTotal = 0 ;
283+ prop.SetTrack (this , prop.GetAlpha ());
284+ for (int32_t iRow = lastPropagateRow + up; iRow >= 0 && iRow < GPUCA_ROW_COUNT; iRow += up) {
285+ bool fail = false ;
286+ for (int32_t iAttempt = 0 ; iAttempt < 2 ; iAttempt++) {
287+ float tmpX, tmpY, tmpZ;
288+ if (prop.GetPropagatedYZ (GPUTPCGeometry::Row2X (iRow), tmpY, tmpZ)) {
289+ fail = true ;
290+ break ;
291+ }
292+ merger.GetConstantMem ()->calibObjects .fastTransformHelper ->InverseTransformYZtoX (sector, iRow, tmpY, tmpZ, tmpX);
293+ if (prop.PropagateToXAlpha (tmpX, param.Alpha (sector), inFlyDirection)) {
294+ fail = true ;
295+ break ;
296+ }
297+ if (CAMath::Abs (mP [2 ]) > maxSinForUpdate) {
298+ fail = true ;
299+ break ;
300+ }
301+ if (CAMath::Abs (mP [0 ]) > CAMath::Abs (mX ) * CAMath::Tan (GPUTPCGeometry::kSectAngle () / 2 .f ) + 0 .1f ) {
302+ if (iAttempt) {
303+ fail = true ;
304+ break ;
305+ }
306+ const int32_t sectorSide = sector >= (GPUCA_NSECTORS / 2 ) ? (GPUCA_NSECTORS / 2 ) : 0 ;
307+ if (mP [0 ] > 0 ) {
308+ if (++sector >= sectorSide + 18 ) {
309+ sector -= 18 ;
310+ }
311+ } else {
312+ if (--sector < sectorSide) {
313+ sector += 18 ;
314+ }
315+ }
316+ }
317+ }
318+ if (fail) {
319+ break ;
320+ }
321+ CADEBUG (printf (" \t Extrapol. Row %2d/%3d Propaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n " , sector, iRow, prop.GetAlpha (), mX , mP [0 ], mP [1 ], mP [4 ], prop.GetQPt0 (), mP [2 ], prop.GetSinPhi0 (), sqrtf (mC [0 ]), sqrtf (mC [2 ]), sqrtf (mC [5 ]), sqrtf (mC [14 ]), mC [10 ]));
322+ gputpcgmmergertypes::InterpolationErrorHit inter;
323+ inter.markInvalid ();
324+ float uncorrectedY = FindBestInterpolatedHit (merger, inter, sector, iRow, deltaZ, sumInvSqrtCharge, nAvgCharge, prop, iTrk, false );
325+ auto & candidate = merger.ClusterCandidates ()[(iTrk * GPUCA_ROW_COUNT + iRow) * param.rec .tpc .rebuildTrackInFitClusterCandidates + 0 ];
326+ if (candidate.id >= 2 ) {
327+ float err2Y, err2Z, xx, yy, zz;
328+ const ClusterNative& GPUrestrict () cl = merger.GetConstantMem ()->ioPtrs .clustersNative ->clustersLinear [candidate.id - 2 ];
329+ merger.GetConstantMem ()->calibObjects .fastTransformHelper ->Transform (sector, iRow, cl.getPad (), cl.getTime (), xx, yy, zz, mTOffset );
330+ if (prop.PropagateToXAlpha (xx, prop.GetAlpha (), inFlyDirection)) {
331+ candidate.best = -1 ;
332+ break ;
333+ }
334+ const float time = merger.GetConstantMem ()->ioPtrs .clustersNative ? cl.getTime () : -1 .f ; // TODO: When is it possible that we do not have clusterNative?
335+ const float invSqrtCharge = merger.GetConstantMem ()->ioPtrs .clustersNative ? CAMath::InvSqrt (cl.qMax ) : 0 .f ;
336+ const float invCharge = merger.GetConstantMem ()->ioPtrs .clustersNative ? (1 .f / cl.qMax ) : 0 .f ;
337+ float invAvgCharge = (sumInvSqrtCharge += invSqrtCharge) / ++nAvgCharge;
338+ invAvgCharge *= invAvgCharge;
339+ const uint8_t clusterState = cl.getFlags ();
340+ prop.GetErr2 (err2Y, err2Z, param, zz, iRow, clusterState, sector, time, invAvgCharge, invCharge);
341+ CADEBUG (printf (" \t %21sResiduals %8.3f %8.3f --- Errors %8.3f %8.3f\n " , " " , yy - mP [0 ], zz - mP [1 ], CAMath::Sqrt (err2Y), CAMath::Sqrt (err2Z)));
342+ uint32_t retValUpd = prop.Update (yy, zz, iRow, param, clusterState, true , refit, err2Y, err2Z);
343+ CADEBUG (printf (" \t Extrapol. Row %2d/%3d Fit Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f), DzDs %5.2f %16s --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f - FErr %d\n " , sector, iRow, prop.GetAlpha (), mX , mP [0 ], mP [1 ], mP [4 ], prop.GetQPt0 (), mP [2 ], prop.GetSinPhi0 (), mP [3 ], " " , sqrtf (mC [0 ]), sqrtf (mC [2 ]), sqrtf (mC [5 ]), sqrtf (mC [14 ]), mC [10 ], retValUpd));
344+ if (retValUpd == 1 ) {
345+ candidate.best = -1 ;
346+ break ;
347+ }
348+ rowGap = 0 ;
349+ } else {
350+ if (++missingRowsTotal > 10 ) {
351+ break ;
352+ }
353+ uint32_t pad = CAMath::Float2UIntRn (GPUTPCGeometry::LinearY2Pad (sector, iRow, uncorrectedY));
354+ if (pad < GPUTPCGeometry::NPads (iRow) && (!merger.GetConstantMem ()->calibObjects .dEdxCalibContainer || !merger.GetConstantMem ()->calibObjects .dEdxCalibContainer ->isDead (sector, iRow, pad))) {
355+ if (++rowGap > param.rec .tpc .trackFollowingMaxRowGap ) {
356+ break ;
357+ }
358+ }
359+ }
360+ }
361+ }
362+
363+ if (finalOutInFit && !(param.rec .tpc .disableRefitAttachment & 4 ) && lastUpdateRow != 255 && !retryAttempt) {
364+ StoreLoopPropagation (merger, lastSector, lastUpdateRow, iTrk, lastUpdateRow > clusters[(iWay & 1 ) ? (maxN - 1 ) : 0 ].row , prop.GetAlpha ());
365+ CADEBUG (printf (" \t\t STORING %d lastUpdateRow %d row %d out %d\n " , iTrk, (int )lastUpdateRow, (int )clusters[(iWay & 1 ) ? (maxN - 1 ) : 0 ].row , lastUpdateRow > clusters[(iWay & 1 ) ? (maxN - 1 ) : 0 ].row ));
366+ }
367+
282368 if (param.rec .tpc .rebuildTrackInFit && iWay == nWays - 2 ) {
283369 Alpha = prop.GetAlpha ();
284370 if (ihitStart != 0 ) {
0 commit comments