/* *===================================================== * * CBM Level 1 Reconstruction * * Authors: I.Kisel, S.Gorbunov * * e-mail : ikisel@kip.uni-heidelberg.de * *===================================================== * * Finds tracks using the Cellular Automaton algorithm * */ #include "L1Algo/L1Algo.h" #include "L1Algo/L1TrackPar.h" #include "L1Algo/L1Branch.h" #include "L1Algo/L1Extrapolation.h" #include "L1Algo/L1Filtration.h" #include "L1Algo/L1AddMaterial.h" //#include "L1CADraw.h" //#include "L1CADebug.h" #include #include "TStopwatch.h" void L1Algo::CATrackFinder() { #ifdef DRAW InitL1Draw(); #endif #ifdef DEBUG_CA InitL1Histo(); #endif //cout.setf(ios::fixed); //cout.setf(ios::showpoint); cout.precision(6); //static double //stat_time = 0.0, stat_time_find = 0.0, stat_time_fit = 0.0, //stat_time_fit_bra = 0.0, stat_time_fit_fin = 0.0, //stat_time_find_10 = 0.0, stat_time_find_20 = 0.0, stat_time_find_30 = 0.0, stat_time_find_40 = 0.0, //stat_time_find_50 = 0.0, //stat_time_find_11 = 0.0, stat_time_find_21 = 0.0, stat_time_find_31 = 0.0; //static unsigned int stat_N = 0; //double //time_find = 0.0, time_fit = 0.0, time_fit_bra = 0.0, time_fit_fin = 0.0, //time_find_10 = 0.0, time_find_20 = 0.0, time_find_30 = 0.0, time_find_40 = 0.0, time_find_50 = 0.0, //time_find_11 = 0.0, time_find_21 = 0.0, time_find_31 = 0.0; const int FIRSTCASTATION = 0; TStopwatch c_time; //cout << endl << "===> CA Track Finder ..." << endl; vTracks.clear(); vRecoHits.clear(); // Arrays of duplets const int MaxArrSize = 40000; static unsigned short int vecA0[MaxArrSize], vecB0[MaxArrSize], vecA[MaxArrSize], vecB[MaxArrSize], *mrDuplets_hits = vecA, // right hits of middle-right duplets *mrDuplets_start = vecA0,// first right hit in mrDuplets_hits, array paralel to middle hits *lmDuplets_hits = vecB, // same for left-middle duplets *lmDuplets_start = vecB0; // static bool vecFakeA[MaxArrSize], vecFakeB[MaxArrSize], *vFake_m = vecFakeA, *vFake_l = vecFakeB; static pair vecTripA0[MaxArrSize], vecTripB0[MaxArrSize], *vTriplets0_m = vecTripA0, *vTriplets0_l = vecTripB0; pair dup_init(0,0); //(*vA).clear(); (*vB).clear(); for( vector::iterator is= vSFlag.begin(); is!=vSFlag.end(); ++is) *is &= 0xFC;//used=0 for( vector::iterator is= vSFlagB.begin(); is!=vSFlagB.end(); ++is) *is &= 0xFC;//used=0 fvec vINF = 10.0; unsigned int stat_max_n_trip = 0, stat_max_trip_size = 0, stat_max_n_dup = 0, stat_max_BranchSize = 0, stat_max_n_branches = 0; #ifdef DRAW Draw1(); #endif //for (int isec = 0; isec <= 2; isec++){ // all finder for (int isec = 0; isec <= fTrackingLevel; isec++){ // //for (int isec = 0; isec <= 0; isec++){ // D0 !!! unsigned int stat_n_trip = 0; //cout << "isec " << isec << " : "; for( vector::iterator is= vSFlag.begin(); is!=vSFlag.end(); ++is) *is &=0xFE; for( vector::iterator is= vSFlagB.begin(); is!=vSFlagB.end(); ++is) *is &=0xFE; //TStopwatch c_time_find; TRACK_CHI2_CUT = 10.0; // SG double Pick_m = 3.0; double Pick_r = 5.0; if (isec == 0){ Pick_m = 2.0; } double MaxInvMom = 1.0/1.; if (isec == 1) MaxInvMom = 1.0/0.2; if (isec == 2) MaxInvMom = 1.0/0.2; if (isec == fTrackingLevel ) MaxInvMom = 1./fMomentumCutOff; int nlevel[NStations]; for (int il = 0; il < NStations; ++il) nlevel[il] = 0; double SigmaTargetX, SigmaTargetY; // target constraint static L1FieldValue targB _fvecalignment; fvec targX= 0, targY= 0, targZ= 0; if (isec <= 1){// target targB = vtxFieldValue; if (isec ==-1) SigmaTargetX = SigmaTargetY = 0.01; // target else SigmaTargetX = SigmaTargetY = 0.1; } else{//use outer radius of the 1st station as a constraint L1Station &st = vStations[0]; SigmaTargetX = SigmaTargetY = st.Rmax[0]; targZ = 0.-1.; st.fieldSlice.GetFieldValue( 0, 0, targB ); } static L1XYMeasurementInfo TargetXYInfo _fvecalignment; TargetXYInfo.C00 = SigmaTargetX * SigmaTargetX; TargetXYInfo.C10 = 0; TargetXYInfo.C11 = SigmaTargetY * SigmaTargetY; //cout<<"Triplets found " << endl; //create triplets and find neighbors vTriplets.clear(); int nh = StsHitsStopIndex[NStations-1] - StsHitsStartIndex[NStations-1] + 1; L1StsHit *vStsHits_l = &(vStsHits[0]) + StsHitsStartIndex[NStations-1]; for (int ih =0 ; ih= 0; istal--){// //start downstream chambers for (int istal = NStations-2; istal >= FIRSTCASTATION; istal--){// //start downstream chambers //cout << "istal " << istal << ": " << endl; TripStartIndex[istal] = TripStopIndex[istal] = vTriplets.size(); int nstaltriplets = 0; int istam = istal+1; int istar = istal+2; unsigned int nDuplets_lm = 0; L1Station &stal = vStations[istal]; L1Station &stam = vStations[istam]; L1Station &star = vStations[istar]; fvec qp1 = MaxInvMom; fvec zl = stal.z[0]; fvec dzli = 1./(zl-targZ[0]); fvec Infqp = MaxInvMom/3.*MaxInvMom/3.; const int Portion = 16; // const int MaxPortionHit = Portion; const int MaxPortionDup = 10000; const int MaxPortionTrip = 10000; static L1FieldRegion fld_1[2000]; static L1FieldRegion fld_2[20000]; static L1TrackPar T_1[20000]; static L1TrackPar T_2[20000]; static L1TrackPar *T_3 = T_1; static unsigned short int hitsl_2[MaxPortionDup]; static unsigned short int hitsl_3[MaxPortionTrip]; static unsigned short int *hitsl_1 = hitsl_3; static unsigned short int hitsm_2[10000]; static unsigned short int hitsm_3[10000]; static unsigned short int hitsr_3[10000]; static fvec u_front[20000], u_back[20000]; static fvec x_minusV[20000], x_plusV[20000], y_minusV[20000], y_plusV[20000]; static float *x_minus = (float*) x_minusV; static float *x_plus = (float*) x_plusV; static float *y_minus = (float*) y_minusV; static float *y_plus = (float*) y_plusV; int stat_nhits=0, stat_nduplets=0, stat_n_triplet_c=0, stat_n_triplets=0; L1StsHit *vStsHits_l = &(vStsHits[0]) + StsHitsStartIndex[istal]; L1StsHit *vStsHits_m = &(vStsHits[0]) + StsHitsStartIndex[istam]; L1StsHit *vStsHits_r = 0; int NHits_l = StsHitsStopIndex[istal] - StsHitsStartIndex[istal] + 1; int NHits_m = StsHitsStopIndex[istam] - StsHitsStartIndex[istam] + 1; int NHits_r = 0; if( istar < NStations ){ vStsHits_r = &(vStsHits[0]) + StsHitsStartIndex[istar]; NHits_r = StsHitsStopIndex[istar] - StsHitsStartIndex[istar] + 1; } //hit on the middle plane to start int start_mhit = 0; //cout<<1<NHits_l ) end_lh = NHits_l; int n1 = 0, n1_V=0, n1_4=0; // prepare the portion of left hits //TStopwatch c_time_find_10; //cout<<10<=10000 ) cout<<"ilh="<0 ){ for( int i1_4=n1_4-1; n1_40 ) n1_V+=1; //c_time_find_10.Stop(); //time_find_10 += double(c_time_find_10.CpuTime()); //ms //cout<<"n1 = "<left hit-> Z of middle station //TStopwatch c_time_find_11; for( int i1_V=0; i1_V0 ){ L1FieldValue centB; L1Station &st = vStations[istal/2]; st.fieldSlice.GetFieldValue( tx*st.z, ty*st.z, centB ); fld.Set( l_B, stal.z, centB, st.z, targB, targZ ); fld_1[i1_V].Set( m_B, stam.z, l_B, stal.z, centB, st.z ); } else{ fld.Set( l_B, stal.z, targB, targZ ); fld_1[i1_V].Set( m_B, stam.z, l_B, stal.z, targB, targZ ); } L1TrackPar &T = T_1[i1_V]; T.chi2 = 0.; T.NDF = 2.; if( isec==2) T.NDF = 0; T.x = x; T.y = y; T.tx = tx; T.ty = ty; T.qp = 0.; T.z = zl; T.C00 = stal.XYInfo.C00; T.C10 = stal.XYInfo.C10; T.C11 = stal.XYInfo.C11; T.C22 = T.C33 = vINF; T.C44 = Infqp; //add the target { fvec eX, eY, J04, J14; fvec dz; dz = targZ - zl; L1ExtrapolateJXY0(T.tx, T.ty, dz, fld, eX, eY, J04, J14 ); fvec J[6]; J[0]= dz; J[1] = 0; J[2]= J04; J[3] = 0; J[4]= dz; J[5]= J14; L1FilterVtx( T, targX, targY, TargetXYInfo, eX, eY, J ); } L1AddMaterial( T, stal.materialInfo, qp1 ); L1Extrapolate0( T, stam.z, fld ); fvec dxm_est = Pick_m*sqrt(fabs(T.C00+stam.XYInfo.C00)); fvec dym_est = Pick_m*sqrt(fabs(T.C11+stam.XYInfo.C11)); x_minusV[i1_V] = T.x - dxm_est; x_plusV [i1_V] = T.x + dxm_est; y_minusV[i1_V] = T.y - dym_est; y_plusV [i1_V] = T.y + dym_est; }// i1_V //cout<<20<= y_minus[i1]) break; } lmDuplets_start[hitsl_1[i1]] = nDuplets_lm; for (int imh = start_mhit; imh < NHits_m; imh++){ if( n2>= MaxPortionDup ) break; //if( imh>=10000 ) cout<<"imh="< y_plus[i1] ) break; if ( (x < x_minus[i1] ) || (x > x_plus[i1]) ) continue; lmDuplets_hits[nDuplets_lm++]=imh; if (istar >= NStations) continue; if( mrDuplets_start[imh] >= mrDuplets_start[imh+1] ) continue; L1TrackPar &T1 = T_1[i1_V]; L1TrackPar &T2 = T_2[n2_V]; L1FieldRegion &f1 = fld_1[i1_V]; L1FieldRegion &f2 = fld_2[n2_V]; u_front[n2_V][n2_4] = x; u_back [n2_V][n2_4] = v; for( fvec *i=&T2.x, *j=&T1.x; i<=&T2.NDF; i++,j++ ) (*i)[n2_4]=(*j)[i1_4]; for( fvec *i=&f2.cx0, *j=&f1.cx0; i<=&f2.z0; i++,j++ ) (*i)[n2_4]=(*j)[i1_4]; hitsl_2[n2] = hitsl_1[i1]; hitsm_2[n2] = imh; n2++; n2_V = n2/fvecLen; n2_4 = n2 % fvecLen; } lmDuplets_start[hitsl_1[i1]+1] = nDuplets_lm; if( lmDuplets_start[hitsl_1[i1]] < nDuplets_lm){ L1StsHit &hitl = vStsHits_l[hitsl_1[i1]]; vFake_l[hitsl_1[i1]] = 0; vSFlag[hitl.f] |= 0x01; vSFlagB[hitl.b] |= 0x01; } }//i1 if( n2_4>0 ){ L1TrackPar &T2 = T_2[n2_V]; L1FieldRegion &f2 = fld_2[n2_V]; for( int i2_4=n2_4-1; n2_40 ) n2_V+=1; //cout<<30<= MaxPortionTrip ) break; int irh = mrDuplets_hits[irh_index]; //if( irh>=10000 ) cout<<"irh="< y_plus [i2] ) break; if ((xr < x_minus[i2]) || (xr > x_plus[i2])) continue; L1TrackPar &T3 = T_3[n3_V]; L1TrackPar &T2 = T_2[i2_V]; hitsl_3[n3] = hitsl_2[i2]; hitsm_3[n3] = hitsm_2[i2]; hitsr_3[n3] = irh; if( n3_4==0 ){ u_front[n3_V] = vStsStrips[hitr.f]; u_back [n3_V] = vStsStripsB[hitr.b]; for( fvec *i=&T3.x, *j=&T2.x; i<=&T3.NDF; i++,j++ ) *i=(*j)[i2_4]; }else{ u_front[n3_V][n3_4] = vStsStrips[hitr.f]; u_back [n3_V][n3_4] = vStsStripsB[hitr.b]; for( fvec *i=&T3.x, *j=&T2.x; i<=&T3.NDF; i++,j++ ) (*i)[n3_4]=(*j)[i2_4]; } n3++; n3_V = n3/fvecLen; n3_4 = n3 % fvecLen; } }// i2 if( n3>0 ) n3_V+=1; //cout<<"n3 = "< TRACK_CHI2_CUT * (T_3[i3_V].NDF[i3_4]-5)) continue; //cout<<510<<" "< MaxInvMom*2 ) qp = MaxInvMom*2; //cout<<"qp "<255 ) Cqp= 255; qp = (unsigned char) qp; //cout<<530<60000) //cout<<"ihitl="< stamap; stamap.clear(); //TStopwatch c_time_fit; int min_level = 0;//1; //remove pile-up in MAPS if (isec == -1) min_level = NStations-3 - 3; //only the longest tracks for (int ilev = NStations-3; ilev >= min_level; ilev--){ //TStopwatch c_time_fit_bra; static vector vtrackcandidate; vtrackcandidate.clear(); //how many levels to check int nlevel = (NStations-2)-ilev+1; int ntracks = 0; for( int ista = 0; ista<= NStations-3-ilev; ista++ ){ //cout<<"ista="<"<GetLevel(); //if(sta_first==34218 && ilev==1) cout<<2<GetLHit()<GetLHit()].f<GetLHit()].f]/4; ///if(sta_first==34218 && ilev==1) cout<<210<GetLHit()].f] | vSFlagB[vStsHits[first_trip->GetLHit()].b] ) & 0x02; //if(sta_first==34218 && ilev==1) cout<<220< collect only MAPS triplets if ( jst != 0) continue; } if( fl ) continue; // if used /* //check the level if (first_trip->GetLevel() != ilev) continue; if (ilev == 0){ //remove pile-up -> collect only MAPS triplets if (vSFlag[vStsHits[first_trip->GetLHit()].f]/4 != 0) continue; } //check if all hits are not used => clear start if( ( vSFlag[vStsHits[first_trip->GetLHit()].f] | vSFlagB[vStsHits[first_trip->GetLHit()].b] ) & 0x02 ) continue; // if used */ //cout<GetLHit()); unsigned char curr_L = 1; float curr_chi2 = first_trip->GetChi2(); L1Branch best_tr = curr_tr; float best_chi2 = curr_chi2; unsigned char best_L = curr_L; //cout<<3< TRACK_CHI2_CUT) continue; if( fGhostSuppression ){//suppress ghost if( best_L <3 ) continue; if( best_L == 3 ){ //if( isec == 2 ) continue; // too short secondary track if( ista != 0 ) continue; // too short non-MAPS track if( (isec<2)&&(best_chi2>5.0) ) continue; } } // track candidate is OK, store best_tr.Set( ista, best_L, best_chi2 ); vtrackcandidate.push_back(best_tr); ntracks++; } //cout<<" level "< vptrackcandidate; vptrackcandidate.clear(); for (vector::iterator trIt = vtrackcandidate.begin(); trIt != vtrackcandidate.end(); ++trIt){ vptrackcandidate.push_back(&(*trIt)); } sort(vptrackcandidate.begin(), vptrackcandidate.end(), L1Branch::comparePChi2); ntracks = 0; for (vector::iterator trIt = vptrackcandidate.begin(); trIt != vptrackcandidate.end(); ++trIt){ //count number of used hits L1Branch *tr = *trIt; int nused = 0; for (vector::iterator phIt = tr->StsHits.begin(); phIt != tr->StsHits.end(); ++phIt){ L1StsHit &h = vStsHits[*phIt]; if ( (vSFlag[h.f] | vSFlagB[h.b]) & 0x02 ) nused++; } if (nused != 0) continue; //======================================================= // gather MAPS hits using the Kalman filter // was here, skipped for a moment //======================================================= //store track for (vector::iterator phitIt = tr->StsHits.begin(); phitIt != tr->StsHits.end(); ++phitIt){ L1StsHit &h = vStsHits[*phitIt]; vSFlag[h.f] |= 0x02; vSFlagB[h.b] |= 0x02; vRecoHits.push_back(*phitIt); } //store track L1Track t; t.NHits = tr->StsHits.size(); vTracks.push_back(t); ntracks++; } //c_time_fit_fin.Stop(); //time_fit_fin += double(c_time_fit_fin.CpuTime()); unsigned int Bsize=0, nb=0; for (vector::iterator trIt = vptrackcandidate.begin(); trIt != vptrackcandidate.end(); ++trIt){ L1Branch *tr = *trIt; Bsize+= sizeof(L1Branch) + sizeof(unsigned short int) * tr->StsHits.size(); nb++; } if( Bsize>stat_max_BranchSize ) stat_max_BranchSize = Bsize; if( nb>stat_max_n_branches ) stat_max_n_branches = nb; //for (vector::iterator ih = vStsHits.begin(); ih != vStsHits.end(); ++ih){ //if( ih->strip_f->used || ih->strip_b->used) ih->used = 1; //} //cout<< " track candidates stored: "<< ntracks < ... CA Track Finder " << endl << endl; #endif #ifdef DRAW DrawAsk(); #endif } //1234567890123456789012345678901234567890123456789012345678901234567890 void L1Algo::CAFindTrack( int ista, const L1Triplet* curr_trip, L1Branch& best_tr, unsigned char &best_L, float &best_chi2, L1Branch &curr_tr, unsigned char &curr_L, float &curr_chi2 ){ /**************************************************************** * * * The routine performs recusrsive search for tracks * * * * I. Kisel 06.03.05 * * * ***************************************************************/ // cout << "CA track finder " << curr_trip->level << endl; if (curr_trip->GetLevel() == 0){ // the last triplet -> check and store if ((curr_L > best_L )|| ((curr_L == best_L )&&(curr_chi2level != 0 //store hits & triplets of the current track L1Branch temp_tr = curr_tr; unsigned char temp_L = curr_L; float temp_chi2 = curr_chi2; int offset = TripStartIndex[ista+1]; int first_neighbour = offset + curr_trip->GetFirstNeighbour(); int end_neighbour = first_neighbour + curr_trip->GetNNeighbours(); for(int index = first_neighbour; index < end_neighbour; ++index){ L1Triplet *new_trip = &vTriplets[index]; if (curr_trip->GetLevel() != new_trip->GetLevel()+1) continue; float qp1 = curr_trip->GetQp(); float qp2 = new_trip->GetQp(); float dqp = fabs(qp1 - qp2); float Cqp = curr_trip->Cqp; Cqp += new_trip->Cqp; if ( dqp > Cqp ) continue; //bad neighbour //no used hits allowed if ( ( vSFlag[vStsHits[new_trip->GetLHit()].f] | vSFlagB[vStsHits[new_trip->GetLHit()].b] ) &0x02 ) { if((curr_L > best_L)|| (curr_L == best_L)&&(curr_chi2GetLHit()); curr_L+= 1; dqp = dqp/Cqp*5.; curr_chi2 += dqp*dqp; if( new_trip->GetLevel()==0 ){ unsigned short int ihitm = new_trip->GetMHit(); unsigned short int ihitr = new_trip->GetRHit(); if( !( ( vSFlag[vStsHits[ihitm].f] | vSFlagB[vStsHits[ihitm].b] ) &0x02 ) ){ curr_tr.StsHits.push_back(ihitm); curr_L+= 1; } if( !( ( vSFlag[vStsHits[ihitr].f] | vSFlagB[vStsHits[ihitr].b] ) &0x02 ) ){ curr_tr.StsHits.push_back(ihitr); curr_L+= 1; } } if( curr_chi2 <= TRACK_CHI2_CUT * (curr_L) ){ // go further CAFindTrack(ista+1,new_trip, best_tr, best_L, best_chi2, curr_tr, curr_L,curr_chi2); } }//good triplet added }//first_triplet --- last_triplet }//level != 0 //cout << "Track finder finished " << endl; return; } //========================================================