// $Id: AliHLTTPCCAGBTracker.cxx,v 1.12 2010/09/01 10:38:27 ikulakov Exp $ // ************************************************************************** // This file is property of and copyright by the ALICE HLT Project * // ALICE Experiment at CERN, All rights reserved. * // * // Primary Authors: Sergey Gorbunov * // Ivan Kisel * // for The ALICE HLT Project. * // * // Developed by: Igor Kulakov * // Maksym Zyzak * // * // Permission to use, copy, modify and distribute this software and its * // documentation strictly for non-commercial purposes is hereby granted * // without fee, provided that the above copyright notice appears in all * // copies and that both the copyright notice and this permission notice * // appear in the supporting documentation. The authors make no claims * // about the suitability of this software for any purpose. It is * // provided "as is" without express or implied warranty. * // * //*************************************************************************** #include "AliHLTTPCCAGBTracker.h" #include "AliHLTTPCCAGBHit.h" #include "AliHLTTPCCAGBTrack.h" #include "AliHLTTPCCATrackParam.h" #include "AliHLTArray.h" #include "AliHLTTPCCAMath.h" #include "AliHLTTPCCAPerformance.h" #include "TStopwatch.h" #include "ITSCATarget.h" #include "ITSCAHits.h" #include "ITSCAHitsV.h" #include "ITSCASingletsV.h" #include "ITSCADoubletsV.h" #include "ITSCATriplets.h" #include "ITSCATripletsV.h" #include "ITSCATracks.h" #include #include #include using namespace std; //TODO DELL ME!!! #include "AliHLTTPCCAPerformance.h" #include "AliHLTTPCCAMCPoint.h" #include "AliHLTTPCPerformanceBase.h" #ifdef DRAW #include "AliHLTTPCCADisplay.h" #define MAIN_DRAW #define DRAW_FIT #define DRAW_CA #endif //DRAW // debug option //#define USE_IDEAL_TF #define USE_CA_FIT bool SINGLE_THREADED = false; AliHLTTPCCAGBTracker::AliHLTTPCCAGBTracker() : fHits( 0 ), fNHits( 0 ), fTrackHits( 0 ), fTracks( 0 ), fNTracks( 0 ), fTime( 0 ), fStatNEvents( 0 ), fSliceTrackerTime( 0 ), fSliceTrackerCpuTime( 0 ) { //* constructor for ( int i = 0; i < 20; i++ ) fStatTime[i] = 0; } void AliHLTTPCCAGBTracker::Init() { fNHits = 0; fTrackHits = 0; fTracks = 0; fNTracks = 0; fTime = 0.; fStatNEvents = 0; fSliceTrackerTime = 0.; fSliceTrackerCpuTime = 0.; for ( int i = 0; i < 20; ++i ) { fStatTime[i] = 0.; } } AliHLTTPCCAGBTracker::~AliHLTTPCCAGBTracker() { //* destructor StartEvent(); } void AliHLTTPCCAGBTracker::StartEvent() { //* clean up track and hit arrays delete[] fTrackHits; fTrackHits = 0; delete[] fTracks; fTracks = 0; fNHits = 0; fNTracks = 0; } void AliHLTTPCCAGBTracker::SetNHits( int nHits ) { //* set the number of hits fHits.Resize( nHits ); fNHits = nHits; } void AliHLTTPCCAGBTracker::IdealTrackFinder() { AliHLTTPCCAPerformance* perf = &AliHLTTPCCAPerformance::Instance(); const int NMCTracks = perf->GetMCTracks()->Size(); vector > hits(NMCTracks+1); for(int iH=0; iHHitLabel(id).fLab[0]; if(trackId < 0) continue; // don't find ghosts // trackId = NMCTracks; // find ghost hits[trackId].push_back(iH); } int nTracks = 0; for(int iT=0; iT0) nTracks++; if(fTracks) delete [] fTracks; fTracks = new AliHLTTPCCAGBTrack[nTracks]; fNTracks = nTracks; if(fTrackHits) delete [] fTrackHits; fTrackHits = new int[fHits.Size()]; int curHit = 0; int curTr = 0; for(int iT=0; iT nTrackHits[iV] - 1) continue; const int jhit = ihit; AliHLTTPCCAGBHit &h = fHits[fTrackHits[memFirstHits[iV] + jhit]]; AliHLTTPCCADisplay::Instance().DrawGBPoint(h.X(), h.Y(), h.Z(), h.Angle(), iV); } } AliHLTTPCCAGBHit &hh = fHits[fTrackHits[memFirstHits[0] ]]; const AliHLTTPCPerformanceBase::AliHLTTPCCAHitLabel &l = perf->HitLabel( hh.ID() ); const int MCIndex = l.fLab[0]; if(MCIndex>-1) { AliHLTTPCCAMCTrack &mc = (*perf->GetMCTracks())[MCIndex]; AliHLTTPCCALocalMCPoint mcPoint = (*perf->GetMCPoints())[mc.FirstMCPointID()]; double mcX0 = mcPoint.X(); double mcY0 = mcPoint.Y(); double mcZ = mcPoint.Z(); AliHLTTPCCADisplay::Instance().DrawGBPoint((float)mcX0, (float)mcY0, (float)mcZ, (int)2, (Size_t)1); } AliHLTTPCCADisplay::Instance().Ask(); #endif AliHLTTPCCATrackParamVector vStartPoint; AliHLTTPCCATrackParamVector vEndPoint; ConvertTrackParamToVector(startPoint,vStartPoint,nTracksVector); sfloat_m active0 = static_cast( ushort_v( Vc::IndexesFromZero ) < nTracksVector ); ushort_v firstHits(memFirstHits); sfloat_m fitted = sfloat_m(true); fitted &= static_cast(static_cast(nTrackHits) > 0); #ifdef USE_CA_FIT // fit only forward #ifdef DRAW_FIT AliHLTTPCCADisplay::Instance().ClearView(); AliHLTTPCCADisplay::Instance().SetTPCView(); AliHLTTPCCADisplay::Instance().DrawTPC(); AliHLTTPCCADisplay::Instance().DrawGBPoint(0,0,0, 2, 0.5); // target AliHLTTPCCADisplay::Instance().Ask(); #endif fitted &= FitTrackCA( vEndPoint, firstHits, nTrackHits, nTracksVector, active0, 0 ); #else InitialTrackApproximation( vStartPoint, firstHits, nTrackHits, nTracksVector, active0); for(int iTimes = 0; iTimes<1; iTimes++) { vEndPoint = vStartPoint; //refit in the forward direction: going from the first hit to the last, mask "fitted" marks with 0 tracks, which are not fitted correctly fitted &= FitTrack( vEndPoint, firstHits, nTrackHits, nTracksVector,active0, 0 ); #ifdef DRAW_FIT AliHLTTPCCADisplay::Instance().ClearView(); AliHLTTPCCADisplay::Instance().SetTPCView(); AliHLTTPCCADisplay::Instance().DrawTPC(); for(int ihit = 0; ihit nTrackHits[iV] - 1) continue; const int jhit = ihit; AliHLTTPCCAGBHit &h = fHits[fTrackHits[memFirstHits[iV] + jhit]]; AliHLTTPCCADisplay::Instance().DrawGBPoint(h.X(), h.Y(), h.Z(), h.GetAngle(),iV); } } AliHLTTPCCADisplay::Instance().Ask(); #endif vStartPoint = vEndPoint; //refit in the backward direction: going from the last hit to the first fitted &= FitTrack( vStartPoint, firstHits, nTrackHits, nTracksVector,active0, 1 ); #ifdef DRAW_FIT AliHLTTPCCADisplay::Instance().ClearView(); AliHLTTPCCADisplay::Instance().SetTPCView(); AliHLTTPCCADisplay::Instance().DrawTPC(); for(int ihit = 0; ihit nTrackHits[iV] - 1) continue; const int jhit = ihit; AliHLTTPCCAGBHit &h = fHits[fTrackHits[memFirstHits[iV] + jhit]]; AliHLTTPCCADisplay::Instance().DrawGBPoint(h.X(), h.Y(), h.Z(), h.GetAngle(),iV); } } AliHLTTPCCADisplay::Instance().Ask(); #endif } #endif // USE_CA_FIT for(int iV=0; iV < nTracksVector; iV++) { startPoint[iV] = AliHLTTPCCATrackParam( vStartPoint, iV ); endPoint[iV] = AliHLTTPCCATrackParam( vEndPoint, iV ); if ( !fitted[iV] ) { startPoint[iV].SetAsInvalid(); endPoint[iV].SetAsInvalid(); } } for(int iV = 0; iV(!active0)); // sfloat_m good = nHits > 2; // int nHitsMax = nHits.max(); // sfloat_v X(Vc::Zero), Y(Vc::Zero), R(Vc::Zero); // sfloat_v lx(Vc::Zero), ly(Vc::Zero), lx2(Vc::Zero), ly2(Vc::Zero), lr2(Vc::Zero); // sfloat_v x(Vc::Zero), y(Vc::Zero), // x2(Vc::Zero), y2(Vc::Zero), xy(Vc::Zero), // r2(Vc::Zero), xr2(Vc::Zero), yr2(Vc::Zero), r4(Vc::Zero); // sfloat_v::Memory xH0, yH0, zH0, angle0; // for(int iV=0; iV < nTracksV; iV++) // { // if( !(active0[iV]) ) continue; // AliHLTTPCCAGBHit &h = fHits[fTrackHits[firstHits[iV]]]; // xH0[iV] = h.X(); // yH0[iV] = h.Y(); // zH0[iV] = h.Z(); // angle0[iV] = h.GetAngle(); // } // sfloat_v xTmp(xH0); // sfloat_v yTmp(yH0); // const sfloat_v angleV0(angle0); // const sfloat_v sA = CAMath::Sin(angleV0); // const sfloat_v cA = CAMath::Cos(angleV0); // const sfloat_v xV0 = xTmp*cA + yTmp*sA; // const sfloat_v yV0 =-xTmp*sA + yTmp*cA; // const sfloat_v zV0(zH0); // vector xV(nHitsMax), yV(nHitsMax); // for ( unsigned short ihit = 0; ihit < nHitsMax; ihit++ ) { // sfloat_m active = static_cast( ihit < nHits ); // if(active.isEmpty()) continue; // sfloat_v::Memory xH, yH; // for(int iV=0; iV < nTracksV; iV++) // { // if( !(active[iV]) ) continue; // if( ihit > NTrackHits[iV] - 1) continue; // AliHLTTPCCAGBHit &h = fHits[fTrackHits[firstHits[iV] + ihit]]; // xH[iV] = h.X(); // yH[iV] = h.Y(); // } // xTmp.load(xH); // yTmp.load(yH); // xV[ihit] = xTmp*cA + yTmp*sA; // yV[ihit] =-xTmp*sA + yTmp*cA; // } // for(unsigned short ihit = 0; ihit < nHitsMax; ihit++) // { // sfloat_m active = static_cast( ihit < nHits ); // if(active.isEmpty()) continue; // lx = xV[ihit] - xV0; // ly = yV[ihit] - yV0; // lx2 = lx*lx; // ly2 = ly*ly; // lr2 = lx2+ly2; // x(active) += lx; // y(active) += ly; // x2(active) += lx2; // y2(active) += ly2; // xy(active) += lx*ly; // r2(active) += lr2; // xr2(active)+= lx*lr2; // yr2(active)+= ly*lr2; // r4(active) += lr2*lr2; // } // x /= static_cast(nHits); // y /= static_cast(nHits); // xy /= static_cast(nHits); // x2 /= static_cast(nHits); // y2 /= static_cast(nHits); // xr2 /= static_cast(nHits); // yr2 /= static_cast(nHits); // r2 /= static_cast(nHits); // r4 /= static_cast(nHits); // const sfloat_v Cxx = x2 - x*x; // const sfloat_v Cxy = xy - x*y; // const sfloat_v Cyy = y2 - y*y; // const sfloat_v Cxr2 = xr2 - x*r2; // const sfloat_v Cyr2 = yr2 - y*r2; // const sfloat_v Cr2r2 = r4 - r2*r2; // const sfloat_v Q1 = Cr2r2*Cxy - Cxr2*Cyr2; // const sfloat_v Q2 = Cr2r2*(Cxx-Cyy) - Cxr2*Cxr2 + Cyr2*Cyr2; // const sfloat_v Phi = 0.5f * CAMath::ATan2(2.f*Q1, Q2); // const sfloat_v SinPhi = CAMath::Sin(Phi); // const sfloat_v CosPhi = CAMath::Cos(Phi); // const sfloat_v Kappa = (SinPhi*Cxr2 - CosPhi*Cyr2)/Cr2r2; // const sfloat_v Delta = SinPhi*x - CosPhi*y - Kappa*r2; // const sfloat_v Rho = 2.f*Kappa / CAMath::Sqrt(sfloat_v(Vc::One) - 4.f*Delta*Kappa); // const sfloat_v D = 2.f*Delta / ( sfloat_v(Vc::One) + CAMath::Sqrt(sfloat_v(Vc::One) - 4.f*Delta*Kappa)); // R = sfloat_v(Vc::One)/Rho; // X = (D+R)*SinPhi; // Y = -(D+R)*CosPhi; // sfloat_v kappa(Vc::Zero); // kappa(good) = Rho; // const sfloat_v sinPhi0 = -X*kappa; // const sfloat_v cosPhi0 = Y*kappa; // sfloat_v dS(Vc::Zero), dS2(Vc::Zero), Z(Vc::Zero), dSZ(Vc::Zero); // for ( unsigned short ihit = 0; ihit < nHitsMax; ihit++ ) { // sfloat_m active = static_cast( ihit < nHits ); // if(active.isEmpty()) continue; // sfloat_v::Memory zH; // for(int iV=0; iV < nTracksV; iV++) // { // if( !(active[iV]) ) continue; // if( ihit > NTrackHits[iV] - 1) continue; // AliHLTTPCCAGBHit &h = fHits[fTrackHits[firstHits[iV] + ihit]]; // zH[iV] = h.Z(); // } // const sfloat_v zV(zH); // lx(active) = xV[ihit]-xV0; // ly(active) = yV[ihit]-yV0; // const sfloat_v ex = cosPhi0; // const sfloat_v ey = sinPhi0; // const sfloat_v dx = lx; // sfloat_v ey1 = kappa * dx + ey; // // check for intersection with X=x // sfloat_v ex1 = CAMath::Sqrt( 1.f - ey1 * ey1 ); // ex1( ex < Vc::Zero ) = -ex1; // const sfloat_v dx2 = dx * dx; // const sfloat_v ss = ey + ey1; // const sfloat_v cc = ex + ex1; // const sfloat_v cci = 1.f / cc; // const sfloat_v exi = 1.f / ex; // const sfloat_v ex1i = 1.f / ex1; // const sfloat_v tg = ss * cci; // tan((phi1+phi)/2) // const sfloat_v dy = dx * tg; // sfloat_v dl = dx * CAMath::Sqrt( 1.f + tg * tg ); // dl( cc < Vc::Zero ) = -dl; // const sfloat_v dSin = CAMath::Max( sfloat_v( -1.f ), CAMath::Min( sfloat_v( Vc::One ), dl * kappa * 0.5f ) ); // const sfloat_v ds = ( CAMath::Abs( kappa ) > 1.e-4 ) ? ( 2 * CAMath::ASin( dSin ) / kappa ) : dl; // dS(active) += ds; // dS2(active) += ds*ds; // Z(active) += zV; // dSZ(active) += ds*zV; // } // sfloat_v det = Vc::One/( static_cast(nHits)*dS2 - dS*dS ); // sfloat_v Z0(Vc::Zero), X0(Vc::Zero), Y0(Vc::Zero), dzds(Vc::Zero); // Z0(good) = det*( dS2*Z - dS*dSZ); // dzds(good) = det*( static_cast(nHits)*dSZ - Z*dS ); // sfloat_v signCosPhi0(Vc::One); // signCosPhi0(cosPhi0( ihit < nHits ); // if( !(active[iV]) ) continue; // if( ihit > NTrackHits[iV] - 1) continue; // AliHLTTPCCAGBHit &h = fHits[fTrackHits[firstHits[iV] + ihit]]; // AliHLTTPCCADisplay::Instance().DrawGBPoint(h.X(), h.Y(), h.Z(), h.GetAngle(),iV); // } // } // float xCL = (X+xV0)[0]; // float yCL = (Y+yV0)[0]; // float xC = xCL*cA[0] - yCL*sA[0]; // float yC = xCL*sA[0] + yCL*cA[0]; // float rad = fabs(R[0]); // AliHLTTPCCADisplay::Instance().DrawArc(xC, yC, rad, -1, 1); // AliHLTTPCCADisplay::Instance().DrawGBPoint(xC, yC, 0.f, 0.f,-1); // AliHLTTPCCADisplay::Instance().Ask(); // #endif // track.SetAngle(angleV0); // track.SetSinPhi(sinPhi0); // track.SetSignCosPhi(signCosPhi0); // track.SetX(xV0); // track.SetY(yV0); // track.SetZ(Z0); // track.SetDzDs(dzds); // track.SetQPt(kappa/GetParameters().cBz()); } sfloat_m AliHLTTPCCAGBTracker::FitTrack( AliHLTTPCCATrackParamVector &t, ushort_v &firstHits, ushort_v::Memory &NTrackHits, int &nTracksV, sfloat_m active0, bool dir ) { // TODO UNUSED_PARAM6( t, firstHits, NTrackHits, nTracksV, active0, dir ); // AliHLTTPCCATrackParamVector::AliHLTTPCCATrackFitParam fitPar; // AliHLTTPCCATrackLinearisationVector l( t ); // bool first = 1; // t.CalculateFitParameters( fitPar ); // ushort_v nHits(NTrackHits); // nHits.makeZero(static_cast(!active0)); // int nHitsMax = nHits.max(); // for ( unsigned short ihit = 0; ihit < nHitsMax; ihit++ ) { // sfloat_m active = active0 && static_cast( ihit < nHits ); // if(active.isEmpty()) continue; // sfloat_v::Memory xH, yH, yErrH, zH, zErrH, hitAlpha; // sfloat_v::Memory memXOverX0, memXTimesRho; // for(int iV=0; iV < nTracksV; iV++) // { // if( !(active[iV]) ) continue; // if( ihit > NTrackHits[iV] - 1) continue; // const int jhit = dir ? ( NTrackHits[iV] - 1 - ihit ) : ihit; // AliHLTTPCCAGBHit &h = fHits[fTrackHits[firstHits[iV] + jhit]]; // hitAlpha[iV] = h.GetAngle(); // xH[iV] = h.X(); // yH[iV] = h.Y(); // zH[iV] = h.Z(); // yErrH[iV] = h.Err2Y(); // zErrH[iV] = h.Err2Z(); // memXOverX0[iV] = GetParameters().GetXOverX0(h.IRow()); // memXTimesRho[iV] = GetParameters().GetXTimesRho(h.IRow()); // } // const sfloat_v err2Y(yErrH), err2Z(zErrH); // sfloat_v xV(xH); // sfloat_v yV(yH); // const sfloat_v zV(zH); // const sfloat_v hitAlphaV(hitAlpha); // const sfloat_v xOverX0(memXOverX0); // const sfloat_v xTimesRho(memXTimesRho); // #ifdef DRAW_FIT // for(int iV=0; iV(active) ); // t.CalculateFitParameters( fitPar ); // t.SetAngle(sfloat_v( hitAlpha )); // first = 0; // } // const sfloat_m &filtered = t.FilterWithMaterial(yV, zV, err2Y, err2Z, 0.999f,active); // active &= filtered; // if(active.isEmpty()) continue; // #ifdef DRAW_FIT // xGl = t.X()*cos(t.Angle()) - t.Y()*sin(t.Angle()); // yGl = t.X()*sin(t.Angle()) + t.Y()*cos(t.Angle()); // for(int iV=0; iV 50 ); //this check is wrong! X could be < 50, when a sector is rotated! // ok &= (c[0] > Vc::Zero) && (c[2] > Vc::Zero) && (c[5] > Vc::Zero) && (c[9] > Vc::Zero) && (c[14] > Vc::Zero); // // ok &= (c[0] < 5.) && (c[2] < 5.) && (c[5] < 2.) && (c[9] < 2.) && (c[14] < 2.); // ok &= CAMath::Abs( t.SinPhi() ) < .999f; // t.SetSignCosPhi( 1, ok && static_cast(l.CosPhi() >= Vc::Zero) ); // t.SetSignCosPhi(-1, ok && static_cast(l.CosPhi() < Vc::Zero) ); // return ok; return sfloat_m(true); } // used to check fit in CA sfloat_m AliHLTTPCCAGBTracker::FitTrackCA( AliHLTTPCCATrackParamVector &t, ushort_v &firstHits, ushort_v::Memory &NTrackHits, int &nTracksV, sfloat_m active0, bool dir ) { UNUSED_PARAM2(nTracksV, dir); // TODO clean me sfloat_m active = active0; ushort_v NTHits(NTrackHits); active &= NTHits >= 3; if (active.isEmpty()) return active; NTHits.setZero(static_cast(!active)); #if 0 // check tracks const unsigned short NHitsMax = NTHits.max(); const unsigned short FirstHit = 0; // check part of the track begining from x-th hit const bool AddLastHit = true; #else // check tracklets const unsigned short NHitsMax = 2; // check x-lets fit const unsigned short FirstHit = 0; // check part of the track begining from x-th hit const bool AddLastHit = false; #endif active &= NTHits >= NHitsMax+FirstHit; vector hits( NHitsMax ); for ( unsigned short ihit = 0+FirstHit; ihit < NHitsMax+FirstHit; ihit ++ ) { const ushort_m valid = ihit < NTHits; ushort_v::Memory id; const AliHLTTPCCAGBHit **hs = new const AliHLTTPCCAGBHit*[sfloat_v::Size]; foreach_bit(unsigned short iV, valid) { id[iV] = firstHits[iV] + ihit; hs[iV] = &(fHits[fTrackHits[id[iV]]]); } hits[ihit-FirstHit] = ITSCAHitV( hs, ushort_v(id), static_cast(valid) ); } const ITSCAHitV& hit0 = hits[0]; #if 0// start from target + hit initialization // ITSCATarget target( 0, 0, 0, 3, 10, 0 ); // target at 0 with 3 cm error // fMaxInvMom = 20.f; // 0.05 GeV tracks fMaxInvMom = 1.f; // 0.1 GeV tracks ITSCATarget target( 0, 0, 0, 0.1, 0.1, fMaxInvMom/3.f, GetParameters().VtxFieldValue(), 0 ); // target at 0 with 3 cm error // 0.1 GeV tracks t.InitByTarget( target ); t.SetAngle( hit0.Angle() ); t.InitDirection( hit0.X0(), hit0.X1(), hit0.X2() ); for ( unsigned short ihit = 0; ihit < NHitsMax; ihit++ ) { #elif 0 // start from 2 hits initialization const ITSCAHitV& hit1 = hits[1]; fMaxInvMom = 10.f; // 0.1 GeV tracks ITSCATarget target( 0, 0, 0, 10e10, 10e10, fMaxInvMom/3.f, GetParameters().VtxFieldValue(), 0 ); // target at 0 with 3 cm error t.InitByTarget( target ); t.SetAngle( hit0.Angle() ); sfloat_v dx = hit1.GX()-hit0.GX(); sfloat_v dy = hit1.GY()-hit0.GY(); sfloat_v dz = hit1.GZ()-hit0.GZ(); const sfloat_v cA = CAMath::Cos( hit0.Angle() ); const sfloat_v sA = CAMath::Sin( hit0.Angle() ); t.SetX( hit0.X() ); t.SetY( hit0.Y() ); t.SetZ( hit0.Z() ); t.InitDirection( dz, dx*cA + dy*sA, -dx*sA + dy*cA ); const L1Station sta0 = GetParameters().Station(hit0.IStation()); L1FieldValue fB0; sta0.fieldSlice.GetFieldValue( hit0.X(), hit0.Y(), fB0 ); t.SetField( 1, fB0, sta0.z ); const L1XYMeasurementInfo &info = GetParameters().Station(hit0.IStation()).XYInfo; t.SetCovX12( info.C00, info.C10, info.C11 ); t.SetNDF( -3 ); for ( unsigned short ihit = 1; ihit < NHitsMax; ihit++ ) { #else // start from hit + target fMaxInvMom = 1.f; // 0.1 GeV tracks ITSCATarget target( 0, 0, 0, 0.1, 0.1, fMaxInvMom/3.f, GetParameters().VtxFieldValue(), 2 ); // target at 0 with 3 cm error // 0.1 GeV tracks t.InitByHit( hit0, GetParameters(), fMaxInvMom/3.f ); t.SetAngle( hit0.Angle() ); t.InitDirection( hit0.X0(), hit0.X1(), hit0.X2() ); t.AddTarget( target ); for ( unsigned short ihit = 1; ihit < NHitsMax; ihit++ ) { #endif const ITSCAHitV& hit = hits[ihit]; active &= t.Transport( hit, GetParameters(), active ); if( AddLastHit || ihit != NHitsMax-1 ) { // don't add last hit, thereby checking extrapolation active &= t.Filter( hit, GetParameters(), active ); } #ifdef DRAW_FIT sfloat_v xGl, yGl, zGl; foreach_bit( unsigned short iV, active & hit.IsValid() ) { float gx0, gy0, gz0, gx1, gy1, gz1; AliHLTTPCCADisplay::Instance().HitToGlobal( hit, iV, gx0, gy0, gz0 ); AliHLTTPCCAParameters::CALocalToGlobal( t.X0()[iV], t.X1()[iV], t.X2()[iV], hit.Angle()[iV], gx1, gy1, gz1 ); AliHLTTPCCADisplay::Instance().DrawGBPoint( gx0, gy0, gz0, (int)4,(Size_t)1); AliHLTTPCCADisplay::Instance().DrawGBPoint( gx1, gy1, gz1 ,-1,0.5); // cout << xGl[iV] << " " << yGl[iV] << " " << t.Z()[iV] << endl; } AliHLTTPCCADisplay::Instance().Ask(); #endif } t.SetQP( sfloat_v(1.e-8f), CAMath::Abs( t.QP() ) < 1.e-8f ); sfloat_m ok = active; // if track has infinite partameters or covariances, or negative diagonal elements of Cov. matrix, mark it as fitted uncorrectly for ( unsigned char i = 0; i < 15; i++ ) ok &= CAMath::Finite( t.Cov(i) ); for ( unsigned char i = 0; i < 5; i++ ) ok &= CAMath::Finite( t.Par(i) ); /// ok = ok && ( t.GetX() > 50 ); //this check is wrong! X could be < 50, when a sector is rotated! ok &= (t.Cov(0) > Vc::Zero) && (t.Cov(2) > Vc::Zero) && (t.Cov(5) > Vc::Zero) && (t.Cov(9) > Vc::Zero) && (t.Cov(14) > Vc::Zero); return ok; } void AliHLTTPCCAGBTracker::FindTracks() { //* main tracking routine fTime = 0; fStatNEvents++; #ifdef MAIN_DRAW AliHLTTPCCAPerformance::Instance().SetTracker( this ); AliHLTTPCCADisplay::Instance().Init(); AliHLTTPCCADisplay::Instance().SetGB( this ); AliHLTTPCCADisplay::Instance().SetTPC( GetParameters() ); #endif //MAIN_DRAW #ifdef MAIN_DRAW // AliHLTTPCCADisplay::Instance().SetTPCView(); // AliHLTTPCCADisplay::Instance().DrawTPC(); // AliHLTTPCCADisplay::Instance().DrawGBHits( *this, -1, 0.2, 1 ); // AliHLTTPCCADisplay::Instance().SaveCanvasToFile( "Hits.pdf"); // AliHLTTPCCADisplay::Instance().Ask(); // // AliHLTTPCCADisplay::Instance().DrawGBHits( *this, kRed, 0.2, 2 ); // // AliHLTTPCCADisplay::Instance().SaveCanvasToFile( "Hits_b.pdf"); // // AliHLTTPCCADisplay::Instance().Ask(); #endif //MAIN_DRAW cout << " NHits = " << fNHits << endl; TStopwatch timer1; TStopwatch timer2; /// \brief The necessary data is transfered to the track-finder /// The necessary data is transfered to the track-finder ///Data is structured and saved by track-finders for each sector. ///To speed up the process in each row 2D-grid with the bin size ///inversely proportional to the number of hits in the row is introduced. ///Hits are sorted by grid bins and for each grid bin 1st hit is found and saved. ///Such data structure allows to quickly find closest hits to the point with given ///coordinates, which is required while neighbours hits are searched and additional ///hits are attached to segments. fSliceTrackerTime = 0; fSliceTrackerCpuTime = 0; fTime = 0; for ( int i = 0; i < 20; ++i ) { fStatTime[i] = 0.; } #ifdef USE_TIMERS timer1.Start(); #endif /// USE_TIMERS // AliHLTTPCCAPerformance::Instance().ShiftHitsToMC(); // dbg #ifdef USE_IDEAL_TF IdealTrackFinder(); FitTracks(); #else CATrackFinder(); // FitTracks(); #endif #ifdef USE_TIMERS timer1.Stop(); fStatTime[12] = timer1.RealTime(); #endif /// USE_TIMERS /// Read hits, row by row fSliceTrackerTime += timer1.RealTime(); fSliceTrackerCpuTime += timer1.CpuTime(); //fTime+=timerMerge.RealTime(); //std::cout<<"Merge time = "<> fParameters; // fSlices[iSlice].Initialize( param ); } void AliHLTTPCCAGBTracker::WriteTracks( std::ostream &out ) const { //* Write tracks to file out << fSliceTrackerTime << std::endl; int nTrackHits = 0; for ( int itr = 0; itr < fNTracks; itr++ ) { nTrackHits += fTracks[itr].NHits(); } out << nTrackHits << std::endl; for ( int ih = 0; ih < nTrackHits; ih++ ) { out << fTrackHits[ih] << " "; } out << std::endl; out << fNTracks << std::endl; for ( int itr = 0; itr < fNTracks; itr++ ) { AliHLTTPCCAGBTrack &t = fTracks[itr]; const AliHLTTPCCATrackParam &p = t.Param(); out << t.NHits() << " "; out << t.FirstHitRef() << " "; out << t.DeDx() << std::endl; out << p; } } void AliHLTTPCCAGBTracker::ReadTracks( std::istream &in ) { //* Read tracks from file in >> fTime; fSliceTrackerTime = fTime; fStatTime[0] += fTime; fStatNEvents++; delete[] fTrackHits; fTrackHits = 0; int nTrackHits = 0; in >> nTrackHits; fTrackHits = new int [nTrackHits]; for ( int ih = 0; ih < nTrackHits; ih++ ) { in >> TrackHits()[ih]; } delete[] fTracks; fTracks = 0; in >> fNTracks; fTracks = new AliHLTTPCCAGBTrack[fNTracks]; for ( int itr = 0; itr < fNTracks; itr++ ) { AliHLTTPCCAGBTrack &t = Tracks()[itr]; in >> t; } } void AliHLTTPCCAGBTracker::SetHits( std::vector &hits) { const int NHits2 = hits.size(); SetNHits(NHits2); fHits.Resize(NHits2); for (int iH = 0; iH < NHits2; iH++){ fHits[iH] = hits[iH]; } } // need for StRoot void AliHLTTPCCAGBTracker::SaveHitsInFile(string prefix) const { ofstream ofile((prefix+"hits.data").data(),std::ios::out|std::ios::app); const int Size = fHits.Size(); ofile << Size << std::endl; for (int i = 0; i < fHits.Size(); i++){ const AliHLTTPCCAGBHit &l = fHits[i]; ofile << l; } ofile.close(); } void AliHLTTPCCAGBTracker::SaveSettingsInFile(string prefix) const { ofstream ofile((prefix+"settings.data").data(),std::ios::out|std::ios::app); WriteSettings(ofile); } class L1StsHit { public: unsigned int f, b; // front and back strip indices unsigned int iz; // index of z coor. in L1Algo::vStsZPos }; bool AliHLTTPCCAGBTracker::ReadHitsFromFile(std::ifstream &ifile) { static int nEvent = 1; const int iVerbose = 0; if ( !ifile.is_open() ) return 0; vector vStsHits; vector vStsStrips, vStsStripsB, vStsZPos; int StsHitsStopIndex[20]; vStsHits.clear(); vStsStrips.clear(); vStsStripsB.clear(); vStsZPos.clear(); { // check correct position in file char s[] = "Event: "; int nEv; ifile >> s; ifile >> nEv; if (nEv != nEvent) cout << "-E- CbmL1: Can't read event number " << nEvent << endl; int n; // number of elements // read algo->vStsStrips ifile >> n; for (int i = 0; i < n; i++){ float element; ifile >> element; vStsStrips.push_back(element); } if (iVerbose >= 4) cout << "vStsStrips[" << n << "]" << " have been read." << endl; // read algo->vStsStripsB ifile >> n; for (int i = 0; i < n; i++){ float element; ifile >> element; vStsStripsB.push_back(element); } if (iVerbose >= 4) cout << "vStsStripsB[" << n << "]" << " have been read." << endl; // read algo->vStsZPos ifile >> n; for (int i = 0; i < n; i++){ float element; ifile >> element; vStsZPos.push_back(element); } if (iVerbose >= 4) cout << "vStsZPos[" << n << "]" << " have been read." << endl; // read algo->vSFlag ifile >> n; for (int i = 0; i < n; i++){ int element; ifile >> element; // vSFlag.push_back(static_cast(element)); } if (iVerbose >= 4) cout << "vSFlag[" << n << "]" << " have been read." << endl; // read algo->vSFlagB ifile >> n; for (int i = 0; i < n; i++){ int element; ifile >> element; // vSFlagB.push_back(static_cast(element)); } if (iVerbose >= 4) cout << "vSFlagB[" << n << "]" << " have been read." << endl; // read algo->vStsHits ifile >> n; SetNHits(n); int element_f; // for convert int element_b; int element_iz; for (int i = 0; i < n; i++){ L1StsHit element; ifile >> element_f >> element_b >> element_iz; element.f = static_cast(element_f); element.b = static_cast(element_b); element.iz = static_cast(element_iz); vStsHits.push_back(element); } if (iVerbose >= 4) cout << "vStsHits[" << n << "]" << " have been read." << endl; // read StsHitsStartIndex and StsHitsStopIndex n = 20; for (int i = 0; i < n; i++){ int tmp; ifile >> tmp; // if (fParameters.NStations()+1 > i) StsHitsStartIndex[i] = tmp; } for (int i = 0; i < n; i++){ int tmp; ifile >> tmp; if (fParameters.NStations()+1 > i) StsHitsStopIndex[i] = tmp; } if ( iVerbose >= 2 ) cout << "-I- CbmL1: CATrackFinder data for event " << nEvent << " has been read successfully." << endl; // if (nEvent == maxNEvent) fadata.close(); } nEvent++; // create Strips fFStrips.Resize(vStsStrips.size()); for( unsigned int i = 0; i < vStsStrips.size(); ++i ) { fFStrips[i] = vStsStrips[i]; } fBStrips.Resize(vStsStripsB.size()); for( unsigned int i = 0; i < vStsStripsB.size(); ++i ) { fBStrips[i] = vStsStripsB[i]; } // create AliHLTTPCCAGBHit hits fHits.Resize(NHits()); int ista = 0; for( int i = 0; i < NHits(); ++i ) { if ( i >= StsHitsStopIndex[ista] ) ista++; AliHLTTPCCAGBHit &h = fHits[i]; const L1StsHit &hi = vStsHits[i]; const L1Station &sta = fParameters.Station(ista); h.SetID(i); h.SetFStripP( &fFStrips[hi.f] ); h.SetBStripP( &fBStrips[hi.b] ); const float u = vStsStrips[hi.f]; const float v = vStsStripsB[hi.b]; h.SetX( (sta.xInfo.sin_phi*u + sta.xInfo.cos_phi*v)[0] ); h.SetY( (sta.yInfo.cos_phi*u + sta.yInfo.sin_phi*v)[0] ); h.SetZ(vStsZPos[hi.iz]); h.SetErr2X( sta.XYInfo.C00[0] ); h.SetErr2Y( sta.XYInfo.C11[0] ); h.SetIRow(ista); h.SetIRow(ista); h.SetID(i); } return 1; } bool AliHLTTPCCAGBTracker::ReadSettingsFromFile(string prefix) { ifstream ifile((prefix+"geo_algo.txt").data()); if ( !ifile.is_open() ) return 0; ReadSettings(ifile); return 1; } void AliHLTTPCCAGBTracker::CATrackFinder() { int curHit = 0; // counters, used to save tracks in output format int curTr = 0; // prepare memory for tracks if(fTracks) delete [] fTracks; fTracks = new AliHLTTPCCAGBTrack[2000]; // TODO fNTracks = 0; if(fTrackHits) delete [] fTrackHits; fTrackHits = new int[30000*AliHLTTPCCAParameters::MaxNStations]; // TODO // std::sort( fHits.Data(), fHits.Data() + fNHits, AliHLTTPCCAGBHit::Compare ); to make convertion faster ITSCAHits hits(NStations()); // convert hits for( int iH = 0; iH < fNHits; ++iH ) { hits.Add( ITSCAHit( fHits[iH], iH ) ); } hits.Sort(); /// Find Tracks ITSCATarget target; for( fFindIter = 0; fFindIter < fNFindIterations; ++fFindIter ) { // fFindIter = 2; // dbg ITSCAHitsV hitsV(hits); // get SIMDized hits #ifdef DRAW_CA AliHLTTPCCADisplay::Instance().SetTPCView(); AliHLTTPCCADisplay::Instance().DrawTPC(); AliHLTTPCCADisplay::Instance().ClearView(); AliHLTTPCCADisplay::Instance().DrawGBHits(hitsV); AliHLTTPCCADisplay::Instance().Ask(); #endif // set parameters; TODO depend on iteration const float kCorr = 1.5; // correction on pulls width const float kCorr2 = kCorr*kCorr; fPick_m = 3.*kCorr; fPick_r = 5.*kCorr; fPickNeighbour = 1.*kCorr; TRACK_CHI2_CUT = 10.*kCorr2; TRIPLET_CHI2_CUT = 5.*kCorr2; // Set correction in order to take into account overlaping // The reason is that low momentum tracks are too curved and goes not from target direction. That's why hit sort is not work idealy fMaxDX0 = 0; switch ( fFindIter ) { // fast primary case 0: fMaxInvMom = 2.f; // > 500 MeV tracks target = ITSCATarget( 0, 0, 0, 0.01, 0.01, fMaxInvMom/3.f, GetParameters().VtxFieldValue(), 2 ); // target at 0 with 0.1 cm error and 2 NDF (for debug) fFindGappedTracks = false; fMaxDX0 = 0; break; case 1: // all primary fMaxInvMom = 10.f; // > 100 MeV tracks target = ITSCATarget( 0, 0, 0, 0.1, 0.1, fMaxInvMom/3.f, GetParameters().VtxFieldValue(), 1 ); fMaxDX0 = 0.1; fFindGappedTracks = true; break; case 2: // all fMaxInvMom = 10.f; target = ITSCATarget( 0, 0, 0, 3, 3, fMaxInvMom/3.f, GetParameters().VtxFieldValue(), 0 ); fMaxDX0 = 0.1; fFindGappedTracks = false; break; } // reconstruct ITSCASingletsV singletsV( NStations(), &hits ); CreateSinglets( target, hitsV, singletsV ); fPick = fPick_m; ITSCADoubletsV doubletsV( NStations()-1, &hits ); CreateDoublets( singletsV, doubletsV ); fPick = fPick_r; ITSCATripletsV tripletsV( NStations()-2, &hits ); CreateTriplets( doubletsV, tripletsV ); ITSCATriplets triplets(tripletsV); fPick = fPickNeighbour; FindNeighbours( triplets ); ITSCATracks tracks(&hits); CreateTracks( triplets, tracks ); // save tracks in compact format const int NRTracks = tracks.size(); for(int iT=0; iT= 0; --iS ) { ITSCAElementsOnStation& ts1 = triplets.OnStation( iS ); for( unsigned int iT1 = 0; iT1 < ts1.size(); ++iT1 ) { ITSCATriplet& t1 = ts1[iT1]; if ( t1.ISta(1) >= triplets.NStations() ) continue; ITSCAElementsOnStation& ts2 = triplets.OnStation( t1.ISta(1) ); char maxLevel = -1; // maxLevel of neighbour triplets vector neighCands; // save neighbour candidates for( unsigned int iT2 = 0; iT2 < ts2.size(); ++iT2 ) { const ITSCATriplet& t2 = ts2[iT2]; if( !t1.IsRightNeighbour( fPick, t2 ) ) continue; if ( maxLevel < t2.Level() ) maxLevel = t2.Level(); if ( maxLevel == t2.Level() ) neighCands.push_back(iT2); } t1.Level() = maxLevel + 1; // save for( unsigned int iN = 0; iN < neighCands.size(); ++iN ) { const ITSCATriplet& t2 = ts2[ neighCands[iN] ]; if ( maxLevel == t2.Level() ) t1.INeighbours().push_back( neighCands[iN] ); } } // iTrip1 } // iStation } void AliHLTTPCCAGBTracker::CreateTracks( const ITSCATriplets& triplets, ITSCATracks& tracks ) { int min_level = AliHLTTPCCAParameters::MinimumHitsForRecoTrack - 3; // min level to start triplet. So min track length = min_level+3. // collect consequtive: the longest tracks, shorter, more shorter and so on for (int ilev = NStations()-3; ilev >= min_level; ilev--){ // choose length ITSCATracks vtrackcandidate( tracks.HitsRef() ); // how many levels to check int nlevel = (NStations()-2)-ilev+1; const unsigned char min_best_l = (ilev > min_level) ? ilev + 2 : min_level + 3; // lose maximum one hit and find all hits for min_level // const unsigned char min_best_l = ilev + 3; // find all hits (slower) // find candidates for( int istaF = 0; istaF <= NStations()-3-ilev; istaF++ ){ const ITSCAElementsOnStation& tsF = triplets.OnStation( istaF ); for( unsigned int iTrip=0; iTrip < tsF.size(); iTrip++ ){ const ITSCATriplet* tripF = &(tsF[iTrip]); { // ghost supression !!! if ( tripF->Level() == 0 ) continue; // ghost suppression // find track with 3 hits only if it was created from a chain of triplets, but not from only one triplet if ( tripF->Level() < ilev ) continue; // try only triplets, which can start track with ilev+3 length. w\o it have more ghosts, but efficiency either if ( (ilev == 0) && (tripF->ISta(0) != 0) ) continue; // ghost supression // collect only MAPS tracks-triplets } if( tsF.GetHit( 0, iTrip ).IsUsed() ) continue; ITSCATrack curr_tr; curr_tr.AddHit( tripF->IHit(0) ); curr_tr.Chi2() = tripF->Param().Chi2(); ITSCATrack best_tr = curr_tr; FindBestCandidate(istaF, best_tr, iTrip, curr_tr, min_best_l, triplets); if ( best_tr.NHits() < min_best_l ) continue; if ( best_tr.NHits() < AliHLTTPCCAParameters::MinimumHitsForRecoTrack ) continue; int ndf = best_tr.NHits()*2 - 5; best_tr.Chi2() /= ndf; vtrackcandidate.push_back(best_tr); } } // istaF // select and save best candidates if (--nlevel == 0) break; vtrackcandidate.SelectAndSaveTracks( tracks ); } // ilev #ifdef DRAW_CA AliHLTTPCCADisplay::Instance().DrawGBTracks(tracks); AliHLTTPCCADisplay::Instance().Ask(); #endif } void AliHLTTPCCAGBTracker::Merge( ITSCATracks& tracks ) { UNUSED_PARAM1( tracks ); // TODO // currently is not needed } ITSCAElementsOnStation AliHLTTPCCAGBTracker::Combine( const ITSCATarget& t, const ITSCAElementsOnStation& h) { ITSCAElementsOnStation r; for( unsigned short iH = 0; iH < h.size(); ++iH ) { const ITSCAHitV& hit = h[iH]; AliHLTTPCCATrackParamVector param; param.InitByHit( hit, GetParameters(), t.DQMom() ); param.InitDirection( hit.X0() - t.X0(), hit.X1() - t.X1(), hit.X2() - t.X2() ); // works only of t.X() = Y() = 0 param.SetAngle( hit.Angle() ); sfloat_m active = hit.IsValid(); active &= param.AddTarget( t, active ); r.push_back( ITSCASingletV( ushort_v::IndexesFromZero() + iH*ushort_v::Size, h.IStation(), param, active ) ); } return r; } ITSCAElementsOnStation AliHLTTPCCAGBTracker::Combine( const ITSCAElementsOnStation& a, const ITSCAElementsOnStation& b) { ITSCAElementsOnStation r; unsigned int iStartS2 = 0; // save first good singet2 for last singlet1 for( unsigned int iS1 = 0; iS1 < a.size(); ++iS1 ) { const ITSCASingletV& s1 = a[iS1]; const sfloat_m valid1 = s1.IsValid(); // find iStartS2 bool firstFound = false; unsigned int iStartS2V = iStartS2/sfloat_v::Size; unsigned int iStartS2E = iStartS2%sfloat_v::Size; for( unsigned int iS2 = iStartS2V; iS2 < b.size() && !firstFound; ++iS2 ) { const ITSCASingletV& s2 = b[iS2]; const sfloat_m valid2 = s2.IsValid() && static_cast(ushort_v(Vc::IndexesFromZero) >= iStartS2E); foreach_bit( unsigned int iV, valid2 ) { // try each hit from 2nd singlet with all 1st singlets if(firstFound) continue; const ITSCAHit& hit = b.GetHit(iV, 0, iS2); sfloat_m active = valid1; AliHLTTPCCATrackParamVector param = s1.Param(); active &= param.Transport( hit, GetParameters(), active ); const sfloat_v Pick2 = fPick*fPick; const sfloat_v dx2 = hit.X2() - param.X2() + 2*fMaxDX0*abs(param.Tx2()); const sfloat_v dx2_est2 = Pick2*(abs(param.Err2X2() + hit.Err2X2())); const sfloat_m inRange = (dx2*dx2 <= dx2_est2) || (dx2 > 0); if ( (!active || (active && !inRange)).isFull() ) continue; iStartS2 = iS2*sfloat_v::Size + iV; firstFound = true; // break; // doesn't work } // iV iStartS2E = 0; } // iS2 iStartS2V = iStartS2/sfloat_v::Size; iStartS2E = iStartS2%sfloat_v::Size; for( unsigned int iS2 = iStartS2V; iS2 < b.size(); ++iS2 ) { const ITSCASingletV& s2 = b[iS2]; const sfloat_m valid2 = s2.IsValid() && static_cast(ushort_v(Vc::IndexesFromZero) >= iStartS2E); foreach_bit( unsigned int iV, valid2 ) { // try each hit from 2nd singlet with all 1st singlets const ITSCAHit& hit = b.GetHit(iV, 0, iS2); sfloat_m active = valid1; AliHLTTPCCATrackParamVector param = s1.Param(); active &= param.Transport( hit, GetParameters(), active ); const sfloat_v Pick2 = fPick*fPick; const sfloat_v dx2 = hit.X2() - param.X2() - 2*fMaxDX0*abs(param.Tx2()); const sfloat_v dx2_est2 = Pick2*(abs(param.Err2X2() + hit.Err2X2())); const sfloat_m inRange = ( (dx2*dx2 <= dx2_est2) || (dx2 < 0) ); if ( (!valid1 || (active && !inRange)).isFull() ) break; active &= IsEqual( param, hit ); if ( active.isEmpty() ) continue; active &= param.Filter( hit, GetParameters(), active ); active &= param.Chi2() < TRIPLET_CHI2_CUT * static_cast(param.NDF() + 2); if ( active.isEmpty() ) continue; // param.Extrapolate( nextSta ); r.push_back( ITSCADoubletV( s1, s2, iV, param, active ) ); } // iV iStartS2E = 0; } // iS2 } // iS1 return r; } ITSCAElementsOnStation AliHLTTPCCAGBTracker::Combine( const ITSCAElementsOnStation& a, const ITSCAElementsOnStation& b) { ITSCAElementsOnStation r; for( unsigned int iD1 = 0; iD1 < a.size(); ++iD1 ) { const ITSCADoubletV& D1 = a[iD1]; const sfloat_m valid1 = D1.IsValid(); for( unsigned int iD2 = 0; iD2 < b.size(); ++iD2 ) { // try each 2nd hit from 2nd doubletVector with all 1st doublets const ITSCADoubletV& D2 = b[iD2]; const sfloat_m valid2 = D2.IsValid(); foreach_bit( unsigned int iV, valid2 ) { sfloat_m active = valid1; active &= D1.IHit(1) == D2.IHit(0)[iV]; if ( active.isEmpty() ) continue; const ITSCAHit& hit = b.GetHit(iV, 1, iD2 ); AliHLTTPCCATrackParamVector param = D1.Param(); active &= param.Transport( hit, GetParameters(), active ); active &= IsEqual( param, hit ); if ( active.isEmpty() ) continue; active &= param.Filter( hit, GetParameters(), active ); active &= param.Chi2() < TRIPLET_CHI2_CUT * static_cast(param.NDF()); if ( active.isEmpty() ) continue; r.push_back( ITSCATripletV( D1, D2, iV, param, active ) ); } } } return r; } void AliHLTTPCCAGBTracker::FindBestCandidate(int ista, ITSCATrack &bT, // best track int currITrip, // index of current triplet ITSCATrack &cT, // current track unsigned char min_best_l, const ITSCATriplets& triplets) { const ITSCAElementsOnStation& trs = triplets.OnStation( ista ); const ITSCATriplet* curr_trip = &(trs[currITrip]); if (curr_trip->Level() == 0){ // the end of the track -> check and store // -- finish with current track // add rest of hits if( !trs.GetHit( 1, currITrip ).IsUsed() ) { cT.AddHit( curr_trip->IHit(1) ); if( !trs.GetHit( 2, currITrip ).IsUsed() ) cT.AddHit( curr_trip->IHit(2) ); } if( cT.NHits() < min_best_l - 1 ) return; // suppose that only one hit can be added by extender if( cT.Chi2() > TRACK_CHI2_CUT * (cT.NHits()*2-5) ) return; // -- select the best if ( (cT.NHits() > bT.NHits()) || ( (cT.NHits() == bT.NHits()) && (cT.Chi2() < bT.Chi2()) ) ) bT = cT; } else { // level != 0 // try to extend. try all possible triplets int NNeighs = curr_trip->INeighbours().size(); for (int in = 0; in < NNeighs; in++) { int newITrip = curr_trip->INeighbours()[in]; const ITSCATriplet *new_trip = &(triplets.OnStation( curr_trip->ISta(1) )[newITrip]); // check new triplet const float qp1 = curr_trip->QMomentum(); const float qp2 = new_trip->QMomentum(); float dqp = fabs(qp1 - qp2); float Cqp = curr_trip->QMomentumErr(); Cqp += new_trip->QMomentumErr(); if ( triplets.OnStation( curr_trip->ISta(1) ).GetHit( 1, newITrip ).IsUsed() ){ // no used hits allowed -> compare and store track if ( (cT.NHits() > bT.NHits()) || ( (cT.NHits() == bT.NHits()) && (cT.Chi2() < bT.Chi2()) ) ) bT = cT; } else{ // add new triplet to the current track // restore current track // save current tracklet ITSCATrack nT = cT; // new track // add new hit nT.AddHit( new_trip->IHit(0) ); dqp = dqp/Cqp*5.; nT.Chi2() += dqp*dqp; if( nT.Chi2() > TRACK_CHI2_CUT * nT.NHits() ) continue; FindBestCandidate(new_trip->ISta(0), bT, newITrip, nT, min_best_l, triplets); } // add triplet to track } // for neighbours } // level = 0 } sfloat_m AliHLTTPCCAGBTracker::IsEqual( const AliHLTTPCCATrackParamVector& param, const ITSCAHit& hit ) { sfloat_m r = sfloat_m(true); const sfloat_v Pick2 = fPick*fPick; const sfloat_v dx1 = hit.X1() - param.X1(); const sfloat_v dx1_est2 = Pick2*(abs(param.Err2X1() + hit.Err2X1())); r &= dx1*dx1 < dx1_est2; const sfloat_v dx2 = hit.X2() - param.X2(); const sfloat_v dx2_est2 = Pick2*(abs(param.Err2X2() + hit.Err2X2())); r &= dx2*dx2 < dx2_est2; return r; }