]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/merger-ca/AliHLTTPCGMMerger.cxx
0317908cd830edf7d1007bfec82bbacbaa882309
[u/mrichter/AliRoot.git] / HLT / TPCLib / merger-ca / AliHLTTPCGMMerger.cxx
1 // $Id: AliHLTTPCGMMerger.cxx 30732 2009-01-22 23:02:02Z sgorbuno $
2 // **************************************************************************
3 // This file is property of and copyright by the ALICE HLT Project          *
4 // ALICE Experiment at CERN, All rights reserved.                           *
5 //                                                                          *
6 // Primary Authors: Sergey Gorbunov <sergey.gorbunov@kip.uni-heidelberg.de> *
7 //                  Ivan Kisel <kisel@kip.uni-heidelberg.de>                *
8 //                  for The ALICE HLT Project.                              *
9 //                                                                          *
10 // Permission to use, copy, modify and distribute this software and its     *
11 // documentation strictly for non-commercial purposes is hereby granted     *
12 // without fee, provided that the above copyright notice appears in all     *
13 // copies and that both the copyright notice and this permission notice     *
14 // appear in the supporting documentation. The authors make no claims       *
15 // about the suitability of this software for any purpose. It is            *
16 // provided "as is" without express or implied warranty.                    *
17 //                                                                          *
18 //***************************************************************************
19
20 #include <stdio.h>
21 #include "AliHLTTPCCASliceOutTrack.h"
22 #include "AliHLTTPCCATracker.h"
23 #include "AliHLTTPCCATrackParam.h"
24 #include "AliHLTTPCGMCluster.h"
25
26 #include "AliHLTTPCGMMerger.h"
27
28 #include "AliHLTTPCCAMath.h"
29 #include "TStopwatch.h"
30
31 #include "AliHLTTPCCATrackParam.h"
32 #include "AliHLTTPCCASliceOutput.h"
33 #include "AliHLTTPCGMMergedTrack.h"
34 #include "AliHLTTPCCADataCompressor.h"
35 #include "AliHLTTPCCAParam.h"
36 #include "AliHLTTPCCATrackLinearisation.h"
37 #include "AliHLTTPCCADataCompressor.h"
38
39 #include "AliHLTTPCGMTrackParam.h"
40 #include "AliHLTTPCGMTrackLinearisation.h"
41 #include "AliHLTTPCGMSliceTrack.h"
42 #include "AliHLTTPCGMBorderTrack.h"
43 #include <cmath>
44
45 #include <algorithm>
46
47 #include "AliHLTTPCCAGPUConfig.h"
48 #include "MemoryAssignmentHelpers.h"
49
50 AliHLTTPCGMMerger::AliHLTTPCGMMerger()
51   :
52   fSliceParam(),
53   fNOutputTracks( 0 ),
54   fNOutputTrackClusters( 0 ),
55   fOutputTracks( 0 ),
56   fOutputClusterIds(0),
57   fSliceTrackInfos( 0 ),  
58   fMaxSliceTracks(0),
59   fClusterX(0),
60   fClusterY(0),
61   fClusterZ(0),
62   fClusterRowType(0),
63   fClusterAngle(0),
64   fBorderMemory(0),
65   fBorderRangeMemory(0),
66   fGPUTracker(NULL),
67   fDebugLevel(0),
68   fNClusters(0)
69 {
70   //* constructor
71   
72   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
73     fNextSliceInd[iSlice] = iSlice + 1;
74     fPrevSliceInd[iSlice] = iSlice - 1;
75   }
76   int mid = fgkNSlices / 2 - 1 ;
77   int last = fgkNSlices - 1 ;
78   fNextSliceInd[ mid ] = 0;
79   fPrevSliceInd[ 0 ] = mid;  fNextSliceInd[ last ] = fgkNSlices / 2;
80   fPrevSliceInd[ fgkNSlices/2 ] = last;
81   
82   Clear();
83 }
84
85
86 AliHLTTPCGMMerger::AliHLTTPCGMMerger(const AliHLTTPCGMMerger&)
87   :
88   fSliceParam(),
89   fNOutputTracks( 0 ),
90   fNOutputTrackClusters( 0 ),
91   fOutputTracks( 0 ),
92   fOutputClusterIds(0),
93   fSliceTrackInfos( 0 ),  
94   fMaxSliceTracks(0),
95   fClusterX(0),
96   fClusterY(0),
97   fClusterZ(0),
98   fClusterRowType(0),
99   fClusterAngle(0),
100   fBorderMemory(0),
101   fBorderRangeMemory(0),
102   fGPUTracker(NULL),
103   fDebugLevel(0),
104   fNClusters(0)
105 {
106   //* dummy
107   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
108     fNextSliceInd[iSlice] = 0;
109     fPrevSliceInd[iSlice] = 0;
110   }
111   Clear();
112 }
113
114 const AliHLTTPCGMMerger &AliHLTTPCGMMerger::operator=(const AliHLTTPCGMMerger&) const
115 {
116   //* dummy
117   return *this;
118 }
119
120
121 AliHLTTPCGMMerger::~AliHLTTPCGMMerger()
122 {
123   //* destructor
124   ClearMemory();
125 }
126
127 void AliHLTTPCGMMerger::Clear()
128 {
129   for ( int i = 0; i < fgkNSlices; ++i ) {
130     fkSlices[i] = 0;
131     fSliceNTrackInfos[ i ] = 0;
132     fSliceTrackInfoStart[ i ] = 0;
133   }
134   ClearMemory();
135 }
136  
137
138 void AliHLTTPCGMMerger::ClearMemory()
139 {
140   delete[] fOutputClusterIds;
141   delete[] fSliceTrackInfos;  
142   if (!fGPUTracker)
143   {
144           delete[] fOutputTracks;
145           delete[] fClusterX;
146           delete[] fClusterY;
147           delete[] fClusterZ;
148           delete[] fClusterRowType;
149           delete[] fClusterAngle;
150   }
151   delete[] fBorderMemory;
152   delete[] fBorderRangeMemory;
153
154   fNOutputTracks = 0;
155   fOutputTracks = 0;
156   fOutputClusterIds = 0;
157   fSliceTrackInfos = 0;
158   fMaxSliceTracks = 0;
159   fClusterX = 0;
160   fClusterY = 0;
161   fClusterZ = 0;
162   fClusterRowType = 0;
163   fClusterAngle = 0;
164   fBorderMemory = 0;  
165   fBorderRangeMemory = 0;
166 }
167
168
169 void AliHLTTPCGMMerger::SetSliceData( int index, const AliHLTTPCCASliceOutput *sliceData )
170 {
171   fkSlices[index] = sliceData;
172 }
173
174
175 bool AliHLTTPCGMMerger::Reconstruct()
176 {
177   //* main merging routine
178
179   {
180     const double kCLight = 0.000299792458;
181     double constBz = fSliceParam.BzkG() * kCLight;
182
183     fPolinomialFieldBz[0] = constBz * (  0.999286   );
184     fPolinomialFieldBz[1] = constBz * ( -4.54386e-7 );
185     fPolinomialFieldBz[2] = constBz * (  2.32950e-5 );
186     fPolinomialFieldBz[3] = constBz * ( -2.99912e-7 );
187     fPolinomialFieldBz[4] = constBz * ( -2.03442e-8 );
188     fPolinomialFieldBz[5] = constBz * (  9.71402e-8 );    
189   }
190   
191   int nIter = 1;
192   TStopwatch timer;
193 #ifdef HLTCA_STANDALONE
194   unsigned long long int a, b, c, d, e, f, g;
195   AliHLTTPCCATracker::StandaloneQueryFreq(&g);
196 #endif
197   //cout<<"Merger..."<<endl;
198   for( int iter=0; iter<nIter; iter++ ){
199     if( !AllocateMemory() ) return 0;
200 #ifdef HLTCA_STANDALONE
201         AliHLTTPCCATracker::StandaloneQueryTime(&a);
202 #endif
203     UnpackSlices();
204 #ifdef HLTCA_STANDALONE
205         AliHLTTPCCATracker::StandaloneQueryTime(&b);
206 #endif
207     MergeWithingSlices();
208 #ifdef HLTCA_STANDALONE
209         AliHLTTPCCATracker::StandaloneQueryTime(&c);
210 #endif
211     MergeSlices();
212 #ifdef HLTCA_STANDALONE
213         AliHLTTPCCATracker::StandaloneQueryTime(&d);
214 #endif
215     CollectMergedTracks();
216 #ifdef HLTCA_STANDALONE
217         AliHLTTPCCATracker::StandaloneQueryTime(&e);
218 #endif
219     Refit();
220 #ifdef HLTCA_STANDALONE
221         AliHLTTPCCATracker::StandaloneQueryTime(&f);
222         if (fDebugLevel > 0)
223         {
224                 printf("Merge Time:\tUnpack Slices:\t%lld us\n", (b - a) * 1000000 / g);
225                 printf("\t\tMerge Within:\t%lld us\n", (c - b) * 1000000 / g);
226                 printf("\t\tMerge Slices:\t%lld us\n", (d - c) * 1000000 / g);
227                 printf("\t\tCollect:\t%lld us\n", (e - d) * 1000000 / g);
228                 printf("\t\tRefit:\t\t%lld us\n", (f - e) * 1000000 / g);
229         }
230         int newTracks = 0;
231         for (int i = 0;i < fNOutputTracks;i++) if (fOutputTracks[i].OK()) newTracks++;
232         printf("Output Tracks: %d\n", newTracks);
233 #endif
234   }  
235   timer.Stop();  
236   //cout<<"\nMerger time = "<<timer.CpuTime()*1.e3/nIter<<" ms\n"<<endl;
237
238   return 1;
239 }
240
241
242
243 bool AliHLTTPCGMMerger::AllocateMemory()
244 {
245   //* memory allocation
246   
247   ClearMemory();
248
249   int nTracks = 0;
250   fNClusters = 0;
251   fMaxSliceTracks  = 0;
252   
253   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
254     if ( !fkSlices[iSlice] ) continue;
255     nTracks += fkSlices[iSlice]->NTracks();
256     fNClusters += fkSlices[iSlice]->NTrackClusters();
257     if( fMaxSliceTracks < fkSlices[iSlice]->NTracks() ) fMaxSliceTracks = fkSlices[iSlice]->NTracks();
258   }
259
260   //cout<<"\nMerger: input "<<nTracks<<" tracks, "<<nClusters<<" clusters"<<endl;
261
262   fOutputClusterIds = new UInt_t[fNClusters];
263   fSliceTrackInfos = new AliHLTTPCGMSliceTrack[nTracks];
264   if (fGPUTracker)
265   {
266         char* basemem = fGPUTracker->MergerBaseMemory();
267         AssignMemory(fClusterX, basemem, fNClusters);
268         AssignMemory(fClusterY, basemem, fNClusters);
269         AssignMemory(fClusterZ, basemem, fNClusters);
270         AssignMemory(fClusterAngle, basemem, fNClusters);
271         AssignMemory(fClusterRowType, basemem, fNClusters);
272         AssignMemory(fOutputTracks, basemem, nTracks);
273   }
274   else
275   {
276           fOutputTracks = new AliHLTTPCGMMergedTrack[nTracks];
277           fClusterX = new float[fNClusters];
278           fClusterY = new float[fNClusters];
279           fClusterZ = new float[fNClusters];
280           fClusterRowType = new UInt_t[fNClusters];
281           fClusterAngle = new float[fNClusters];        
282   }
283   fBorderMemory = new AliHLTTPCGMBorderTrack[fMaxSliceTracks*2];
284   fBorderRangeMemory = new AliHLTTPCGMBorderTrack::Range[fMaxSliceTracks*2];  
285
286   return ( ( fOutputTracks!=NULL )
287            && ( fOutputClusterIds!=NULL )
288            && ( fSliceTrackInfos!=NULL )
289            && ( fClusterX!=NULL )
290            && ( fClusterY!=NULL )
291            && ( fClusterZ!=NULL )
292            && ( fClusterRowType!=NULL )
293            && ( fClusterAngle!=NULL )
294            && ( fBorderMemory!=NULL )
295            && ( fBorderRangeMemory!=NULL )
296            );
297 }
298
299
300
301 void AliHLTTPCGMMerger::UnpackSlices()
302 {
303   //* unpack the cluster information from the slice tracks and initialize track info array
304   
305   int nTracksCurrent = 0;
306   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
307
308     fSliceTrackInfoStart[ iSlice ] = nTracksCurrent;
309
310     fSliceNTrackInfos[ iSlice ] = 0;
311
312     if ( !fkSlices[iSlice] ) continue;
313
314     float alpha = fSliceParam.Alpha( iSlice );
315
316     const AliHLTTPCCASliceOutput &slice = *( fkSlices[iSlice] );
317     const AliHLTTPCCASliceOutTrack *sliceTr = slice.GetFirstTrack();    
318
319     for ( int itr = 0; itr < slice.NTracks(); itr++, sliceTr = sliceTr->GetNextTrack() ) {
320       AliHLTTPCGMSliceTrack &track = fSliceTrackInfos[nTracksCurrent];
321       track.Set( sliceTr, alpha );
322       if( !track.FilterErrors( fSliceParam, .999 ) ) continue;
323       track.SetPrevNeighbour( -1 );
324       track.SetNextNeighbour( -1 );
325       track.SetSliceNeighbour( -1 );
326       track.SetUsed( 0 );           
327       nTracksCurrent++;
328       fSliceNTrackInfos[ iSlice ]++;
329     }
330     
331     //std::cout<<"Unpack slice "<<iSlice<<": ntracks "<<slice.NTracks()<<"/"<<fSliceNTrackInfos[iSlice]<<std::endl;
332   } 
333 }
334
335
336
337
338
339 void AliHLTTPCGMMerger::MakeBorderTracks( int iSlice, int iBorder, AliHLTTPCGMBorderTrack B[], int &nB )
340 {
341   //* prepare slice tracks for merging with next/previous/same sector
342   //* each track transported to the border line
343
344   float fieldBz = fSliceParam.ConstBz();
345   
346   nB = 0;
347   
348   float dAlpha = fSliceParam.DAlpha() / 2;
349   float x0 = 0;
350
351   if ( iBorder == 0 ) { // transport to the left age of the sector and rotate horisontally
352     dAlpha = dAlpha - CAMath::Pi() / 2 ;
353   } else if ( iBorder == 1 ) { //  transport to the right age of the sector and rotate horisontally
354     dAlpha = -dAlpha - CAMath::Pi() / 2 ;
355   } else if ( iBorder == 2 ) { // transport to the left age of the sector and rotate vertically
356     dAlpha = dAlpha;
357     x0 = fSliceParam.RowX( 63 );
358   } else if ( iBorder == 3 ) { // transport to the right age of the sector and rotate vertically
359     dAlpha = -dAlpha;
360     x0 =  fSliceParam.RowX( 63 );
361   } else if ( iBorder == 4 ) { // transport to the middle of the sector, w/o rotation
362     dAlpha = 0;
363     x0 = fSliceParam.RowX( 63 );
364   }
365
366   const float maxSin = CAMath::Sin( 60. / 180.*CAMath::Pi() );
367   float cosAlpha = AliHLTTPCCAMath::Cos( dAlpha );
368   float sinAlpha = AliHLTTPCCAMath::Sin( dAlpha );
369
370   for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
371
372     AliHLTTPCGMSliceTrack &track = fSliceTrackInfos[ fSliceTrackInfoStart[iSlice] + itr ];
373
374     if( track.Used() ) continue;
375     AliHLTTPCGMBorderTrack &b = B[nB];
376     
377     if(  track.TransportToXAlpha( x0, sinAlpha, cosAlpha, fieldBz, b, maxSin)){
378       b.SetTrackID( itr );
379       b.SetNClusters( track.NClusters() );
380       nB++; 
381     }
382   }
383 }
384
385
386 void AliHLTTPCGMMerger::MergeBorderTracks ( int iSlice1, AliHLTTPCGMBorderTrack B1[],  int N1,
387                                             int iSlice2, AliHLTTPCGMBorderTrack B2[],  int N2 )
388 {
389   //* merge two sets of tracks
390
391   //std::cout<<" Merge slices "<<iSlice1<<"+"<<iSlice2<<": tracks "<<N1<<"+"<<N2<<std::endl;
392   int statAll=0, statMerged=0;
393   float factor2ys = 1.5;//1.5;//SG!!!
394   float factor2zt = 1.5;//1.5;//SG!!!
395   float factor2k = 2.0;//2.2;
396
397   factor2k  = 3.5 * 3.5 * factor2k * factor2k;
398   factor2ys = 3.5 * 3.5 * factor2ys * factor2ys;
399   factor2zt = 3.5 * 3.5 * factor2zt * factor2zt;
400  
401   int minNPartHits = 10;//SG!!!
402   int minNTotalHits = 20;
403
404   AliHLTTPCGMBorderTrack::Range *range1 = fBorderRangeMemory;
405   AliHLTTPCGMBorderTrack::Range *range2 = fBorderRangeMemory + N1;
406
407   bool sameSlice = (iSlice1 == iSlice2);
408   {
409     for ( int itr = 0; itr < N1; itr++ ){
410       AliHLTTPCGMBorderTrack &b = B1[itr];
411       //   if( iSlice1==7 && iSlice2==8 ){
412       //cout<<b.TrackID()<<": "<<b.Cov()[0]<<" "<<b.Cov()[1]<<endl;
413       //}
414       float d = 3.5*sqrt(b.Cov()[1]);
415       range1[itr].fId = itr;
416       range1[itr].fMin = b.Par()[1] - d;
417       range1[itr].fMax = b.Par()[1] + d;
418     }
419     std::sort(range1,range1+N1,AliHLTTPCGMBorderTrack::Range::CompMin);
420     if( sameSlice ){
421       for(int i=0; i<N1; i++) range2[i]= range1[i];
422       std::sort(range2,range2+N1,AliHLTTPCGMBorderTrack::Range::CompMax);
423       N2 = N1;
424       B2 = B1;
425     }else{
426       for ( int itr = 0; itr < N2; itr++ ){
427         AliHLTTPCGMBorderTrack &b = B2[itr];
428         float d = 3.5*sqrt(b.Cov()[1]);
429         range2[itr].fId = itr;
430         range2[itr].fMin = b.Par()[1] - d;
431         range2[itr].fMax = b.Par()[1] + d;
432       }        
433       std::sort(range2,range2+N2,AliHLTTPCGMBorderTrack::Range::CompMax);
434     }
435   }
436
437   int i2 = 0;
438   for ( int i1 = 0; i1 < N1; i1++ ) {
439
440     AliHLTTPCGMBorderTrack::Range r1 = range1[i1];
441     while( i2<N2 && range2[i2].fMax< r1.fMin ) i2++;
442  
443     AliHLTTPCGMBorderTrack &b1 = B1[r1.fId];   
444     if ( b1.NClusters() < minNPartHits ) continue;
445     int iBest2 = -1;
446     int lBest2 = 0;
447     statAll++;
448     for( int k2 = i2; k2<N2; k2++){
449       
450       AliHLTTPCGMBorderTrack::Range r2 = range2[k2];
451       if( r2.fMin > r1.fMax ) break;
452       if( sameSlice && (r1.fId >= r2.fId) ) continue;
453       // do check
454       AliHLTTPCGMBorderTrack &b2 = B2[r2.fId];
455       if ( b2.NClusters() < lBest2 ) continue;
456       
457       if( !b1.CheckChi2Y(b2, factor2ys ) ) continue;
458       //if( !b1.CheckChi2Z(b2, factor2zt ) ) continue;
459       if( !b1.CheckChi2QPt(b2, factor2k ) ) continue;
460       if( !b1.CheckChi2YS(b2, factor2ys ) ) continue;
461       if( !b1.CheckChi2ZT(b2, factor2zt ) ) continue;
462       if ( b2.NClusters() < minNPartHits ) continue;
463       if ( b1.NClusters() + b2.NClusters() < minNTotalHits ) continue;      
464
465       lBest2 = b2.NClusters();
466       iBest2 = b2.TrackID();
467     }
468
469     if ( iBest2 < 0 ) continue;
470     statMerged++;
471     AliHLTTPCGMSliceTrack &newTrack1 = fSliceTrackInfos[fSliceTrackInfoStart[iSlice1] + b1.TrackID() ];
472     AliHLTTPCGMSliceTrack &newTrack2 = fSliceTrackInfos[fSliceTrackInfoStart[iSlice2] + iBest2 ];
473
474     int old1 = newTrack2.PrevNeighbour();
475
476     if ( old1 >= 0 ) {
477       AliHLTTPCGMSliceTrack &oldTrack1 = fSliceTrackInfos[fSliceTrackInfoStart[iSlice1] + old1];
478       if ( oldTrack1.NClusters()  < newTrack1.NClusters() ) {
479         newTrack2.SetPrevNeighbour( -1 );
480         oldTrack1.SetNextNeighbour( -1 );
481       } else continue;
482     }
483     int old2 = newTrack1.NextNeighbour();
484     if ( old2 >= 0 ) {
485       AliHLTTPCGMSliceTrack &oldTrack2 = fSliceTrackInfos[fSliceTrackInfoStart[iSlice2] + old2];
486       if ( oldTrack2.NClusters() < newTrack2.NClusters() ) {
487         oldTrack2.SetPrevNeighbour( -1 );
488       } else continue;
489     }
490     newTrack1.SetNextNeighbour( iBest2 );
491     newTrack2.SetPrevNeighbour( b1.TrackID() );
492   }
493   //cout<<"slices "<<iSlice1<<","<<iSlice2<<": all "<<statAll<<" merged "<<statMerged<<endl;
494 }
495
496
497 void AliHLTTPCGMMerger::MergeWithingSlices()
498 {
499   //* merge track segments withing one slice
500
501   float x0 = fSliceParam.RowX( 63 );  
502   const float maxSin = CAMath::Sin( 60. / 180.*CAMath::Pi() );
503
504   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
505
506     int nBord = 0;
507     for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
508       AliHLTTPCGMSliceTrack &track = fSliceTrackInfos[ fSliceTrackInfoStart[iSlice] + itr ];
509       //track.SetPrevNeighbour( -1 );      
510       //track.SetNextNeighbour( -1 );
511       //track.SetSliceNeighbour( -1 );
512       //track.SetUsed(0);
513       
514       AliHLTTPCGMBorderTrack &b = fBorderMemory[nBord];
515       if( track.TransportToX( x0, fSliceParam.ConstBz(), b, maxSin) ){
516         b.SetTrackID( itr );
517         b.SetNClusters( track.NClusters() );
518         nBord++;
519       }
520     }  
521
522     MergeBorderTracks( iSlice, fBorderMemory, nBord, iSlice, fBorderMemory, nBord );
523     
524     for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
525       AliHLTTPCGMSliceTrack &track = fSliceTrackInfos[ fSliceTrackInfoStart[iSlice] + itr];
526       if( track.PrevNeighbour()>=0 || track.Used() ) continue;
527       int jtr = track.NextNeighbour();
528       track.SetSliceNeighbour( jtr );
529       track.SetNextNeighbour(-1);
530       while( jtr>=0 ){
531         AliHLTTPCGMSliceTrack &trackN = fSliceTrackInfos[ fSliceTrackInfoStart[iSlice] + jtr];
532         if( trackN.NClusters()>track.NClusters() ) track.CopyParamFrom(trackN);
533         trackN.SetUsed(2);
534         jtr = trackN.NextNeighbour();
535         trackN.SetSliceNeighbour( jtr );
536         trackN.SetNextNeighbour(-1);
537         trackN.SetPrevNeighbour(-1);
538       }
539     }
540   }
541 }
542
543
544
545
546 void AliHLTTPCGMMerger::MergeSlices()
547 {
548   //* track merging between slices
549
550   //for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
551   //for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
552   //AliHLTTPCGMSliceTrack &track = fSliceTrackInfos[ fSliceTrackInfoStart[iSlice] + itr ];
553   //track.SetPrevNeighbour( -1 );
554   //track.SetNextNeighbour( -1 );
555   //}
556   //}
557
558   AliHLTTPCGMBorderTrack 
559     *bCurr = fBorderMemory,
560     *bNext = fBorderMemory + fMaxSliceTracks;
561   
562   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {    
563     int jSlice = fNextSliceInd[iSlice];    
564     int nCurr = 0, nNext = 0;
565     MakeBorderTracks( iSlice, 2, bCurr, nCurr );
566     MakeBorderTracks( jSlice, 3, bNext, nNext );
567     MergeBorderTracks( iSlice, bCurr, nCurr, jSlice, bNext, nNext );
568     MakeBorderTracks( iSlice, 0, bCurr, nCurr );
569     MakeBorderTracks( jSlice, 1, bNext, nNext );
570     MergeBorderTracks( iSlice, bCurr, nCurr, jSlice, bNext, nNext );
571   }
572 }
573
574
575
576
577
578 void AliHLTTPCGMMerger::CollectMergedTracks()
579 {
580   //* 
581
582   //for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
583   //for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
584   //AliHLTTPCGMSliceTrack &track = fSliceTrackInfos[ fSliceTrackInfoStart[iSlice] + itr ];
585   //if( track.Used()!=2 ) track.SetUsed(0);
586   //}
587   //}
588
589   fNOutputTracks = 0;
590   int nOutTrackClusters = 0;
591   const int kMaxParts = 400;
592   const int kMaxClusters = 1000;
593
594   const AliHLTTPCGMSliceTrack *trackParts[kMaxParts];
595
596   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
597
598     for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
599
600       AliHLTTPCGMSliceTrack &track = fSliceTrackInfos[fSliceTrackInfoStart[iSlice] + itr];
601
602       if ( track.Used() ) continue;
603       if ( track.PrevNeighbour() >= 0 ) continue;
604       int nParts = 0;
605       int jSlice = iSlice;
606       AliHLTTPCGMSliceTrack *trbase = &track, *tr = &track;
607       tr->SetUsed( 1 );
608       do{
609         if( nParts >= kMaxParts ) break;
610         trackParts[nParts++] = tr;
611         int jtr = tr->SliceNeighbour();
612         if( jtr >= 0 ) {
613           tr = &(fSliceTrackInfos[fSliceTrackInfoStart[jSlice] + jtr]);
614           tr->SetUsed( 2 );
615           continue;
616         }
617         jtr = trbase->NextNeighbour();
618         if( jtr>=0 ){
619           jSlice = fNextSliceInd[jSlice];
620           trbase = &(fSliceTrackInfos[fSliceTrackInfoStart[jSlice] + jtr]);
621           tr = trbase;
622           if( tr->Used() ) break;
623           tr->SetUsed( 1 );
624           continue;       
625         }
626         break;
627       }while(1);
628
629       // unpack and sort clusters
630       
631           std::sort(trackParts, trackParts+nParts, CompareTrackParts );
632
633       AliHLTTPCCASliceOutCluster tmp[kMaxClusters];
634       int currCluster = nOutTrackClusters;
635       int nHits = 0;
636       for( int ipart=0; ipart<nParts; ipart++ ){
637         const AliHLTTPCGMSliceTrack *t = trackParts[ipart];
638         int nTrackHits = t->NClusters();
639         if( nHits + nTrackHits >= kMaxClusters ) break;
640         const AliHLTTPCCASliceOutCluster *c= t->OrigTrack()->Clusters();
641         AliHLTTPCCASliceOutCluster *c2 = tmp+nHits + nTrackHits-1;
642         for( int i=0; i<nTrackHits; i++, c++, c2-- ) *c2 = *c;  
643         float alpha =  t->Alpha();
644         for( int i=0; i<nTrackHits; i++) fClusterAngle[currCluster++] = alpha;
645         nHits+=nTrackHits;
646       }
647
648       UInt_t *clId = fOutputClusterIds + nOutTrackClusters;      
649       for( int i=0; i<nHits; i++ ) clId[i] = tmp[i].GetId();      
650       
651       UInt_t *clT  = fClusterRowType + nOutTrackClusters;
652       for( int i=0; i<nHits; i++ ) clT[i] = tmp[i].GetRowType();  
653       
654       float *clX = fClusterX + nOutTrackClusters;
655       for( int i=0; i<nHits; i++ ) clX[i] = tmp[i].GetX();      
656
657       float *clY = fClusterY + nOutTrackClusters;
658       for( int i=0; i<nHits; i++ ) clY[i] = tmp[i].GetY();      
659
660       float *clZ = fClusterZ + nOutTrackClusters;
661       for( int i=0; i<nHits; i++ ) clZ[i] = tmp[i].GetZ();      
662
663       if ( nHits < 30 ) continue;   
664
665       AliHLTTPCGMMergedTrack &mergedTrack = fOutputTracks[fNOutputTracks];
666       mergedTrack.SetOK(1);
667       mergedTrack.SetNClusters( nHits );
668       mergedTrack.SetFirstClusterRef( nOutTrackClusters );
669       AliHLTTPCGMTrackParam &p1 = mergedTrack.Param();
670       const AliHLTTPCGMSliceTrack &p2 = *(trackParts[0]);
671
672       p1.X() = p2.X();
673       p1.Y() = p2.Y();
674       p1.Z() = p2.Z();
675       p1.SinPhi()  = p2.SinPhi();
676       p1.DzDs()  = p2.DzDs();
677       p1.QPt()  = p2.QPt();
678       mergedTrack.SetAlpha( p2.Alpha() );
679
680       fNOutputTracks++;
681       nOutTrackClusters += nHits;
682     }
683   }
684   fNOutputTrackClusters = nOutTrackClusters;
685 }
686
687 void AliHLTTPCGMMerger::Refit()
688 {
689   //* final refit
690 #ifdef HLTCA_GPU_MERGER
691         if (fGPUTracker)
692         {
693                 fGPUTracker->RefitMergedTracks(this);
694         }
695         else
696 #endif
697         {
698 #ifdef HLTCA_STANDALONE
699 #pragma omp parallel for
700 #endif
701           for ( int itr = 0; itr < fNOutputTracks; itr++ ) {
702                 AliHLTTPCGMMergedTrack &track = fOutputTracks[itr];
703                 if( !track.OK() ) continue;    
704
705                 int nTrackHits = track.NClusters();
706                
707                 AliHLTTPCGMTrackParam t = track.Param();
708                 float Alpha = track.Alpha();  
709             
710                 t.Fit( fPolinomialFieldBz,
711                    fClusterX+track.FirstClusterRef(),
712                    fClusterY+track.FirstClusterRef(),
713                    fClusterZ+track.FirstClusterRef(),
714                    fClusterRowType+track.FirstClusterRef(),
715                    fClusterAngle+track.FirstClusterRef(),
716                    fSliceParam, nTrackHits, Alpha, 0 );      
717             
718                 if ( fabs( t.QPt() ) < 1.e-4 ) t.QPt() = 1.e-4 ;
719                 
720                 bool ok = nTrackHits >= 30 && t.CheckNumericalQuality() && fabs( t.SinPhi() ) <= .999;
721                 track.SetOK(ok);
722                 if( !ok ) continue;
723
724                 if( 1 ){//SG!!!
725                   track.SetNClusters( nTrackHits );
726                   track.Param() = t;
727                   track.Alpha() = Alpha;
728                 }
729
730                 {
731                   int ind = track.FirstClusterRef();
732                   float alpha = fClusterAngle[ind];
733                   float x = fClusterX[ind];
734                   float y = fClusterY[ind];
735                   float z = fClusterZ[ind];
736                   float sinA = AliHLTTPCCAMath::Sin( alpha - track.Alpha());
737                   float cosA = AliHLTTPCCAMath::Cos( alpha - track.Alpha());
738                   track.SetLastX( x*cosA - y*sinA );
739                   track.SetLastY( x*sinA + y*cosA );
740                   track.SetLastZ( z );
741                 }
742           }
743         }
744 }
745