]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/tracking-ca/AliHLTTPCCAMerger.cxx
update of GPU tracker from David Rohr
[u/mrichter/AliRoot.git] / HLT / TPCLib / tracking-ca / AliHLTTPCCAMerger.cxx
1 // $Id: AliHLTTPCCAMerger.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 "AliHLTTPCCASliceTrack.h"
22 #include "AliHLTTPCCATracker.h"
23 #include "AliHLTTPCCATrackParam.h"
24
25 #include "AliHLTTPCCAMerger.h"
26
27 #include "AliHLTTPCCAMath.h"
28 #include "TStopwatch.h"
29
30 #include "AliHLTTPCCATrackParam.h"
31 #include "AliHLTTPCCASliceTrack.h"
32 #include "AliHLTTPCCASliceOutput.h"
33 #include "AliHLTTPCCAMergedTrack.h"
34 #include "AliHLTTPCCAMergerOutput.h"
35 #include "AliHLTTPCCADataCompressor.h"
36 #include "AliHLTTPCCAParam.h"
37 #include "AliHLTTPCCATrackLinearisation.h"
38
39
40 class AliHLTTPCCAMerger::AliHLTTPCCASliceTrackInfo
41 {
42
43   public:
44
45     const AliHLTTPCCATrackParam &InnerParam() const { return fInnerParam;      }
46     const AliHLTTPCCATrackParam &OuterParam() const { return fOuterParam;      }
47     float InnerAlpha()                      const { return fInnerAlpha;      }
48     float OuterAlpha()                      const { return fOuterAlpha;      }
49     int   NClusters()                       const { return fNClusters;       }
50     int   FirstClusterRef()                 const { return fFirstClusterRef; }
51     int   PrevNeighbour()                   const { return fPrevNeighbour;   }
52     int   NextNeighbour()                   const { return fNextNeighbour;   }
53     bool  Used()                            const { return fUsed;            }
54
55     void SetInnerParam( const AliHLTTPCCATrackParam &v ) { fInnerParam = v;      }
56     void SetOuterParam( const AliHLTTPCCATrackParam &v ) { fOuterParam = v;      }
57     void SetInnerAlpha( float v )                      { fInnerAlpha = v;      }
58     void SetOuterAlpha( float v )                      { fOuterAlpha = v;      }
59     void SetNClusters ( int v )                        { fNClusters = v;       }
60     void SetFirstClusterRef( int v )                   { fFirstClusterRef = v; }
61     void SetPrevNeighbour( int v )                     { fPrevNeighbour = v;   }
62     void SetNextNeighbour( int v )                     { fNextNeighbour = v;   }
63     void SetUsed( bool v )                             { fUsed = v;            }
64
65   private:
66
67     AliHLTTPCCATrackParam fInnerParam; // inner parameters
68     AliHLTTPCCATrackParam fOuterParam; // outer parameters
69     float fInnerAlpha;               // alpha angle for inner parameters
70     float fOuterAlpha;               // alpha angle for outer parameters
71     int fNClusters;                  // N clusters
72     int fFirstClusterRef;  // index of the first track cluster in the global cluster array
73     int fPrevNeighbour;    // neighbour in the previous slise
74     int fNextNeighbour;    // neighbour in the next slise
75     bool fUsed;            // is the slice track already merged
76
77 };
78
79
80 class AliHLTTPCCAMerger::AliHLTTPCCABorderTrack
81 {
82
83   public:
84
85     const AliHLTTPCCATrackParam &Param() const { return fParam;     }
86     int   TrackID()                    const { return fTrackID;   }
87     int   NClusters()                  const { return fNClusters; }
88     int   IRow()                       const { return fIRow;      }
89     float X()                          const { return fX;         }
90     bool  OK()                         const { return fOK;        }
91
92     void SetParam     ( const AliHLTTPCCATrackParam &v ) { fParam     = v; }
93     void SetTrackID   ( int v )                        { fTrackID   = v; }
94     void SetNClusters ( int v )                        { fNClusters = v; }
95     void SetIRow      ( int v )                        { fIRow      = v; }
96     void SetX         ( float v )                      { fX         = v; }
97     void SetOK        ( bool v )                       { fOK        = v; }
98
99   private:
100
101     AliHLTTPCCATrackParam fParam;  // track parameters at the border
102     int   fTrackID;              // track index
103     int   fNClusters;            // n clusters
104     int   fIRow;                 // row number of the closest cluster
105     float fX;                    // X coordinate of the closest cluster
106     bool  fOK;                   // is the track rotated and extrapolated correctly
107
108 };
109
110
111
112 AliHLTTPCCAMerger::AliHLTTPCCAMerger()
113     :
114     fSliceParam(),
115     fOutput( 0 ),
116     fTrackInfos( 0 ),
117     fMaxTrackInfos( 0 ),
118     fClusterInfos( 0 ),
119     fMaxClusterInfos( 0 )
120 {
121   //* constructor
122   Clear();
123 }
124
125 /*
126 AliHLTTPCCAMerger::AliHLTTPCCAMerger(const AliHLTTPCCAMerger&)
127   :
128   fSliceParam(),
129   fkSlices(0),
130   fOutput(0),
131   fTrackInfos(0),
132   fMaxTrackInfos(0),
133   fClusterInfos(0),
134   fMaxClusterInfos(0)
135 {
136 }
137
138 const AliHLTTPCCAMerger &AliHLTTPCCAMerger::operator=(const AliHLTTPCCAMerger&) const
139 {
140   return *this;
141 }
142 */
143
144 AliHLTTPCCAMerger::~AliHLTTPCCAMerger()
145 {
146   //* destructor
147   if ( fTrackInfos ) delete[] fTrackInfos;
148   if ( fClusterInfos ) delete[] fClusterInfos;
149   if ( fOutput ) delete[] ( ( char* )( fOutput ) );
150 }
151
152 void AliHLTTPCCAMerger::Clear()
153 {
154   for ( int i = 0; i < fgkNSlices; ++i ) {
155     fkSlices[i] = 0;
156   }
157 }
158
159
160 void AliHLTTPCCAMerger::SetSliceData( int index, const AliHLTTPCCASliceOutput *SliceData )
161 {
162   fkSlices[index] = SliceData;
163 }
164
165 void AliHLTTPCCAMerger::Reconstruct()
166 {
167   //* main merging routine
168
169   UnpackSlices();
170   Merging();
171 }
172
173 void AliHLTTPCCAMerger::UnpackSlices()
174 {
175   //* unpack the cluster information from the slice tracks and initialize track info array
176
177   // get N tracks and N clusters in event
178
179   int nTracksTotal = 0;
180   int nTrackClustersTotal = 0;
181   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
182     if ( !fkSlices[iSlice] ) continue;
183     nTracksTotal += fkSlices[iSlice]->NTracks();
184     nTrackClustersTotal += fkSlices[iSlice]->NTrackClusters();
185   }
186
187   // book/clean memory if necessary
188   {
189     if ( nTracksTotal > fMaxTrackInfos || ( fMaxTrackInfos > 100 && nTracksTotal < 0.5*fMaxTrackInfos ) ) {
190       if ( fTrackInfos ) delete[] fTrackInfos;
191       fMaxTrackInfos = ( int ) ( nTracksTotal * 1.2 );
192       fTrackInfos = new AliHLTTPCCASliceTrackInfo[fMaxTrackInfos];
193     }
194
195     if ( nTrackClustersTotal > fMaxClusterInfos || ( fMaxClusterInfos > 1000 && nTrackClustersTotal < 0.5*fMaxClusterInfos ) ) {
196       if ( fClusterInfos ) delete[] fClusterInfos;
197       fMaxClusterInfos = ( int ) ( nTrackClustersTotal * 1.2 );
198       fClusterInfos = new AliHLTTPCCAClusterInfo [fMaxClusterInfos];
199     }
200
201     if ( fOutput ) delete[] ( ( char* )( fOutput ) );
202     int size = fOutput->EstimateSize( nTracksTotal, nTrackClustersTotal );
203     fOutput = ( AliHLTTPCCAMergerOutput* )( new float2[size/sizeof( float2 )+1] );
204   }
205
206   // unpack track and cluster information
207
208   int nTracksCurrent = 0;
209   int nClustersCurrent = 0;
210
211   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
212
213     fSliceTrackInfoStart[ iSlice ] = nTracksCurrent;
214     fSliceNTrackInfos[ iSlice ] = 0;
215
216     if ( !fkSlices[iSlice] ) continue;
217
218     const AliHLTTPCCASliceOutput &slice = *( fkSlices[iSlice] );
219
220     for ( int itr = 0; itr < slice.NTracks(); itr++ ) {
221
222       const AliHLTTPCCASliceTrack &sTrack = slice.Track( itr );
223       AliHLTTPCCATrackParam t0 = sTrack.Param();
224       int nCluNew = 0;
225
226       for ( int iTrClu = 0; iTrClu < sTrack.NClusters(); iTrClu++ ) {
227
228         // unpack cluster information
229
230         AliHLTTPCCAClusterInfo &clu = fClusterInfos[nClustersCurrent + nCluNew];
231         int ic = sTrack.FirstClusterRef() + iTrClu;
232
233         clu.SetISlice( iSlice );
234         clu.SetIRow( slice.ClusterRow( ic ) );
235         clu.SetId( slice.ClusterId( ic ) );
236         clu.SetPackedAmp( slice.ClusterPackedAmp( ic ) );
237         float2 yz = slice.ClusterUnpackedYZ( ic );
238         clu.SetX( slice.ClusterUnpackedX( ic ) );
239         clu.SetY( yz.x );
240         clu.SetZ( yz.y );
241
242         if ( !t0.TransportToX( clu.X(), fSliceParam.GetBz( t0 ), .999 ) ) continue;
243
244         float err2Y, err2Z;
245         fSliceParam.GetClusterErrors2( clu.IRow(), clu.Z(), t0.SinPhi(), t0.GetCosPhi(), t0.DzDs(), err2Y, err2Z );
246
247         clu.SetErr2Y( err2Y );
248         clu.SetErr2Z( err2Z );
249         nCluNew++ ;
250       }
251
252       if ( nCluNew < .8*sTrack.NClusters() ) continue;
253
254       // refit the track
255
256       int hits[1000];
257       int nHits = nCluNew;
258       for ( int i = 0; i < nHits; i++ ) hits[i] = nClustersCurrent + i;
259
260       AliHLTTPCCATrackParam startPoint = sTrack.Param();
261       AliHLTTPCCATrackParam endPoint = startPoint;
262       float startAlpha = fSliceParam.Alpha( iSlice );
263       float endAlpha = startAlpha;
264
265       if ( !FitTrack( endPoint, endAlpha, startPoint, startAlpha, hits, nHits, 0 ) ) continue;
266
267       startPoint = endPoint;
268       startAlpha = endAlpha;
269       if ( !FitTrack( startPoint, startAlpha, endPoint, endAlpha, hits, nHits, 1 ) ) continue;
270
271       if ( nHits < .8*sTrack.NClusters() ) continue;
272
273       // store the track
274
275       AliHLTTPCCASliceTrackInfo &track = fTrackInfos[nTracksCurrent];
276
277       track.SetInnerParam( startPoint );
278       track.SetInnerAlpha( startAlpha );
279       track.SetOuterParam( endPoint );
280       track.SetOuterAlpha( endAlpha );
281       track.SetFirstClusterRef( nClustersCurrent );
282       track.SetNClusters( nHits );
283       track.SetPrevNeighbour( -1 );
284       track.SetNextNeighbour( -1 );
285       track.SetUsed( 0 );
286
287       for ( int i = 0; i < nHits; i++ )
288         fClusterInfos[nClustersCurrent + i] = fClusterInfos[hits[i]];
289       nTracksCurrent++;
290       fSliceNTrackInfos[ iSlice ]++;
291       nClustersCurrent += nHits;
292     }
293     //std::cout<<"Unpack slice "<<iSlice<<": ntracks "<<slice.NTracks()<<"/"<<fSliceNTrackInfos[iSlice]<<std::endl;
294   }
295 }
296
297
298
299 bool AliHLTTPCCAMerger::FitTrack( AliHLTTPCCATrackParam &T, float &Alpha,
300                                   AliHLTTPCCATrackParam t0, float Alpha0,
301                                   int hits[], int &NTrackHits, bool dir,
302                                   AliHLTTPCCAClusterInfo *infoArray )
303 {
304   // Fit the track
305
306   AliHLTTPCCATrackParam::AliHLTTPCCATrackFitParam fitPar;
307   AliHLTTPCCATrackParam t = t0;
308   AliHLTTPCCATrackLinearisation l( t0 );
309
310   bool first = 1;
311   bool doErrors = 1;
312   if ( !infoArray ) {
313     infoArray = fClusterInfos;
314     doErrors = 0;
315   }
316
317   t.CalculateFitParameters( fitPar );
318
319   int hitsNew[1000];
320   int nHitsNew = 0;
321
322   for ( int ihit = 0; ihit < NTrackHits; ihit++ ) {
323
324     int jhit = dir ? ( NTrackHits - 1 - ihit ) : ihit;
325     AliHLTTPCCAClusterInfo &h = infoArray[hits[jhit]];
326
327     int iSlice = h.ISlice();
328
329     float sliceAlpha =  fSliceParam.Alpha( iSlice );
330
331     if ( CAMath::Abs( sliceAlpha - Alpha0 ) > 1.e-4 ) {
332       if ( ! t.Rotate(  sliceAlpha - Alpha0, l, .999 ) ) continue;
333       Alpha0 = sliceAlpha;
334     }
335
336     //float x = fSliceParam.RowX( h.IRow() );
337     float x = h.X();
338
339     if ( !t.TransportToXWithMaterial( x, l, fitPar, fSliceParam.GetBz( t ) ) ) continue;
340
341     if ( first ) {
342       t.SetCov( 0, 10 );
343       t.SetCov( 1,  0 );
344       t.SetCov( 2, 10 );
345       t.SetCov( 3,  0 );
346       t.SetCov( 4,  0 );
347       t.SetCov( 5,  1 );
348       t.SetCov( 6,  0 );
349       t.SetCov( 7,  0 );
350       t.SetCov( 8,  0 );
351       t.SetCov( 9,  1 );
352       t.SetCov( 10,  0 );
353       t.SetCov( 11,  0 );
354       t.SetCov( 12,  0 );
355       t.SetCov( 13,  0 );
356       t.SetCov( 14,  10 );
357       t.SetChi2( 0 );
358       t.SetNDF( -5 );
359       t.CalculateFitParameters( fitPar );
360     }
361
362     float err2Y = h.Err2Y();
363     float err2Z = h.Err2Z();
364     if ( doErrors ) fSliceParam.GetClusterErrors2( h.IRow(), h.Z(), l.SinPhi(), l.CosPhi(), l.DzDs(), err2Y, err2Z );
365     if ( !t.Filter( h.Y(), h.Z(), err2Y, err2Z ) ) continue;
366
367     first = 0;
368
369     hitsNew[nHitsNew++] = hits[jhit];
370   }
371
372   if ( CAMath::Abs( t.QPt() ) < 1.e-4 ) t.SetQPt( 1.e-4 );
373
374   bool ok = t.CheckNumericalQuality();
375
376   if ( CAMath::Abs( t.SinPhi() ) > .99 ) ok = 0;
377   else if ( l.CosPhi() >= 0 ) t.SetSignCosPhi( 1 );
378   else t.SetSignCosPhi( -1 );
379
380   if ( ok ) {
381     T = t;
382     Alpha = Alpha0;
383     NTrackHits = nHitsNew;
384     for ( int i = 0; i < NTrackHits; i++ ) {
385       hits[dir ?( NTrackHits-1-i ) :i] = hitsNew[i];
386     }
387   }
388   return ok;
389 }
390
391
392 float AliHLTTPCCAMerger::GetChi2( float x1, float y1, float a00, float a10, float a11,
393                                   float x2, float y2, float b00, float b10, float b11  )
394 {
395   //* Calculate Chi2/ndf deviation
396
397   float d[2] = { x1 - x2, y1 - y2 };
398
399   float mSi[3] = { a00 + b00, a10 + b10, a11 + b11 };
400
401   float s = ( mSi[0] * mSi[2] - mSi[1] * mSi[1] );
402
403   if ( s < 1.E-10 ) return 10000.;
404
405   float mS[3] = { mSi[2], -mSi[1], mSi[0] };
406
407   return AliHLTTPCCAMath::Abs( ( ( mS[0]*d[0] + mS[1]*d[1] )*d[0]
408                        + ( mS[1]*d[0] + mS[2]*d[1] )*d[1] ) / s / 2 );
409
410 }
411
412
413
414 void AliHLTTPCCAMerger::MakeBorderTracks( int iSlice, int iBorder, AliHLTTPCCABorderTrack B[], int &nB )
415 {
416   //* prepare slice tracks for merging with next/previous/same sector
417   //* each track transported to the border line,
418   //* in some cases both inner and outer parameters of the track are transported
419
420   static int statAll = 0, statOK = 0;
421   nB = 0;
422   float dAlpha = fSliceParam.DAlpha() / 2;
423   float x0 = 0;
424
425   if ( iBorder == 0 ) { // transport to the left age of the sector and rotate horisontally
426     dAlpha = dAlpha - CAMath::Pi() / 2 ;
427   } else if ( iBorder == 1 ) { //  transport to the right age of the sector and rotate horisontally
428     dAlpha = -dAlpha - CAMath::Pi() / 2 ;
429   } else if ( iBorder == 2 ) { // transport to the left age of the sector and rotate vertically
430     dAlpha = dAlpha;
431     x0 = fSliceParam.RowX( 63 );
432   } else if ( iBorder == 3 ) { // transport to the right age of the sector and rotate vertically
433     dAlpha = -dAlpha;
434     x0 =  fSliceParam.RowX( 63 );
435   } else if ( iBorder == 4 ) { // transport to the middle of the sector, w/o rotation
436     dAlpha = 0;
437     x0 = fSliceParam.RowX( 63 );
438   }
439
440   for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
441
442     const AliHLTTPCCASliceTrackInfo &track = fTrackInfos[ fSliceTrackInfoStart[iSlice] + itr ];
443
444     AliHLTTPCCATrackParam t0 = track.InnerParam();
445     AliHLTTPCCATrackParam t1 = track.OuterParam();
446
447     const float maxSin = CAMath::Sin( 60. / 180.*CAMath::Pi() );
448
449     bool ok0 = t0.Rotate( dAlpha, maxSin );
450     bool ok1 = t1.Rotate( dAlpha, maxSin );
451
452     bool do0 = ok0;
453     bool do1 = ok1 && ( !ok0 || t1.SignCosPhi() * t0.SignCosPhi() < 0 );
454
455     if ( ok0 && !do1 && ok1 && ( t1.X() < t0.X() ) ) {
456       do0 = 0;
457       do1 = 1;
458     }
459
460     if ( do0 ) {
461       AliHLTTPCCABorderTrack &b = B[nB];
462       b.SetX( t0.GetX() );
463       if ( t0.TransportToX( x0, fSliceParam.GetBz( t0 ), maxSin ) ) {
464         b.SetOK( 1 );
465         b.SetTrackID( itr );
466         b.SetNClusters( track.NClusters() );
467         b.SetIRow( fClusterInfos[ track.FirstClusterRef() + 0 ].IRow() );
468         b.SetParam( t0 );
469         nB++;
470       }
471     }
472     if ( do1 ) {
473       AliHLTTPCCABorderTrack &b = B[nB];
474       b.SetX( t1.GetX() );
475       if ( t1.TransportToX( x0, fSliceParam.GetBz( t1 ), maxSin ) ) {
476         b.SetOK( 1 );
477         b.SetTrackID( itr );
478         b.SetNClusters( track.NClusters() );
479         b.SetIRow( fClusterInfos[ track.FirstClusterRef() + track.NClusters()-1 ].IRow() );
480         b.SetParam( t1 );
481         nB++;
482       }
483     }
484     if ( do0 || do1 ) statOK++;
485     statAll++;
486   }
487 }
488
489
490
491 void AliHLTTPCCAMerger::SplitBorderTracks( int iSlice1, AliHLTTPCCABorderTrack B1[], int N1,
492     int iSlice2, AliHLTTPCCABorderTrack B2[], int N2
493                                          )
494 {
495   //* split two sets of tracks
496
497   float factor2ys = 1.;//1.5;//SG!!!
498   float factor2zt = 1.;//1.5;//SG!!!
499   float factor2k = 2.0;//2.2;
500
501   factor2k  = 3.5 * 3.5 * factor2k * factor2k;
502   factor2ys = 3.5 * 3.5 * factor2ys * factor2ys;
503   factor2zt = 3.5 * 3.5 * factor2zt * factor2zt;
504
505   int minNPartHits = 10;//SG!!!
506   int minNTotalHits = 20;
507
508   //float maxDX = fSliceParam.RowX(40) -  fSliceParam.RowX(0);
509
510   for ( int i1 = 0; i1 < N1; i1++ ) {
511     AliHLTTPCCABorderTrack &b1 = B1[i1];
512     if ( !b1.OK() ) continue;
513     if ( b1.NClusters() < minNPartHits ) continue;
514     const AliHLTTPCCATrackParam &t1 = b1.Param();
515     int iBest2 = -1;
516     int lBest2 = 0;
517     int start2 = ( iSlice1 != iSlice2 ) ? 0 : i1 + 1;
518     for ( int i2 = start2; i2 < N2; i2++ ) {
519       AliHLTTPCCABorderTrack &b2 = B2[i2];
520       if ( !b2.OK() ) continue;
521       if ( b2.NClusters() < minNPartHits ) continue;
522       if ( b2.NClusters() < lBest2 ) continue;
523       if ( b1.NClusters() + b2.NClusters() < minNTotalHits ) continue;
524
525       //if( TMath::Abs(b1.fX - b2.fX)>maxDX ) continue;
526
527       const AliHLTTPCCATrackParam &t2 = b2.Param();
528
529       float c = t2.SignCosPhi() * t1.SignCosPhi() >= 0 ? 1 : -1;
530       float dk = t2.QPt() - c * t1.QPt();
531       float s2k = t2.Err2QPt() + t1.Err2QPt();
532
533       if ( dk*dk > factor2k*s2k ) continue;
534
535
536       float chi2ys = GetChi2( t1.Y(), c * t1.SinPhi(), t1.Cov()[0], c * t1.Cov()[3], t1.Cov()[5],
537                               t2.Y(),  t2.SinPhi(), t2.Cov()[0],  t2.Cov()[3], t2.Cov()[5] );
538
539       if ( chi2ys > factor2ys ) continue;
540
541       float chi2zt = GetChi2( t1.Z(), c * t1.DzDs(), t1.Cov()[2], c * t1.Cov()[7], t1.Cov()[9],
542                               t2.Z(),  t2.DzDs(), t2.Cov()[2],  t2.Cov()[7], t2.Cov()[9] );
543
544       if ( chi2zt > factor2zt ) continue;
545
546       lBest2 = b2.NClusters();
547       iBest2 = b2.TrackID();
548     }
549
550     if ( iBest2 < 0 ) continue;
551
552     AliHLTTPCCASliceTrackInfo &newTrack1 = fTrackInfos[fSliceTrackInfoStart[iSlice1] + b1.TrackID() ];
553     AliHLTTPCCASliceTrackInfo &newTrack2 = fTrackInfos[fSliceTrackInfoStart[iSlice2] + iBest2 ];
554
555     int old1 = newTrack2.PrevNeighbour();
556
557     if ( old1 >= 0 ) {
558       AliHLTTPCCASliceTrackInfo &oldTrack1 = fTrackInfos[fSliceTrackInfoStart[iSlice1] + old1];
559       if ( oldTrack1.NClusters()  < newTrack1.NClusters() ) {
560         newTrack2.SetPrevNeighbour( -1 );
561         oldTrack1.SetNextNeighbour( -1 );
562       } else continue;
563     }
564     int old2 = newTrack1.NextNeighbour();
565     if ( old2 >= 0 ) {
566       AliHLTTPCCASliceTrackInfo &oldTrack2 = fTrackInfos[fSliceTrackInfoStart[iSlice2] + old2];
567       if ( oldTrack2.NClusters() < newTrack2.NClusters() ) {
568         oldTrack2.SetPrevNeighbour( -1 );
569       } else continue;
570     }
571     newTrack1.SetNextNeighbour( iBest2 );
572     newTrack2.SetPrevNeighbour( b1.TrackID() );
573   }
574
575 }
576
577
578 void AliHLTTPCCAMerger::Merging()
579 {
580   //* track merging between slices
581
582   fOutput->SetNTracks( 0 );
583   fOutput->SetNTrackClusters( 0 );
584   fOutput->SetPointers();
585
586
587   // for each slice set number of the next neighbouring slice
588
589   int nextSlice[100], prevSlice[100];
590
591   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
592     nextSlice[iSlice] = iSlice + 1;
593     prevSlice[iSlice] = iSlice - 1;
594   }
595   int mid = fgkNSlices / 2 - 1 ;
596   int last = fgkNSlices - 1 ;
597   if ( mid < 0 ) mid = 0; // to avoid compiler warning
598   if ( last < 0 ) last = 0; //
599   nextSlice[ mid ] = 0;
600   prevSlice[ 0 ] = mid;
601   nextSlice[ last ] = fgkNSlices / 2;
602   prevSlice[ fgkNSlices/2 ] = last;
603
604   int maxNSliceTracks = 0;
605   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
606     if ( maxNSliceTracks < fSliceNTrackInfos[iSlice] ) maxNSliceTracks = fSliceNTrackInfos[iSlice];
607   }
608
609   if ( 1 ) {// merging track segments withing one slice
610
611     AliHLTResizableArray<AliHLTTPCCABorderTrack> bord( maxNSliceTracks*10 );
612
613     AliHLTTPCCASliceTrackInfo *tmpT = new AliHLTTPCCASliceTrackInfo[maxNSliceTracks];
614     AliHLTTPCCAClusterInfo *tmpH = new AliHLTTPCCAClusterInfo[fMaxClusterInfos];
615
616     for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
617
618       int nBord = 0;
619       MakeBorderTracks( iSlice, 4, bord.Data(), nBord );
620       SplitBorderTracks( iSlice, bord.Data(), nBord, iSlice, bord.Data(), nBord );
621
622       int nTr = 0, nH = 0;
623       int sliceFirstClusterRef = 0;
624       for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
625         AliHLTTPCCASliceTrackInfo &track = fTrackInfos[ fSliceTrackInfoStart[iSlice] + itr];
626         if ( itr == 0 ) sliceFirstClusterRef = track.FirstClusterRef();
627         track.SetPrevNeighbour( -1 );
628         if ( track.NextNeighbour() == -2 ) {
629           track.SetNextNeighbour( -1 );
630           continue;
631         }
632         AliHLTTPCCASliceTrackInfo &trackNew = tmpT[nTr];
633         trackNew = track;
634         trackNew.SetFirstClusterRef( sliceFirstClusterRef + nH );
635
636         for ( int ih = 0; ih < track.NClusters(); ih++ ) tmpH[nH+ih] = fClusterInfos[track.FirstClusterRef()+ih];
637         nTr++;
638         nH += track.NClusters();
639
640         int jtr =  track.NextNeighbour();
641
642         if ( jtr < 0 ) continue;
643         AliHLTTPCCASliceTrackInfo &neighTrack = fTrackInfos[ fSliceTrackInfoStart[iSlice] + jtr];
644
645         track.SetNextNeighbour( -1 );
646         neighTrack.SetNextNeighbour( -2 );
647
648         for ( int ih = 0; ih < neighTrack.NClusters(); ih++ )
649           tmpH[nH+ih] = fClusterInfos[neighTrack.FirstClusterRef()+ih];
650
651         trackNew.SetNClusters( trackNew.NClusters() + neighTrack.NClusters() );
652         trackNew.SetNextNeighbour( -1 );
653         nH += neighTrack.NClusters();
654         if ( neighTrack.InnerParam().X() < track.InnerParam().X() ) trackNew.SetInnerParam( neighTrack.InnerParam() );
655         if ( neighTrack.OuterParam().X() > track.OuterParam().X() ) trackNew.SetOuterParam( neighTrack.OuterParam() );
656       }
657
658       fSliceNTrackInfos[iSlice] = nTr;
659       for ( int itr = 0; itr < nTr; itr++ ) fTrackInfos[ fSliceTrackInfoStart[iSlice] + itr] = tmpT[itr];
660       for ( int ih = 0; ih < nH; ih++ ) fClusterInfos[sliceFirstClusterRef + ih] = tmpH[ih];
661
662     }
663     delete[] tmpT;
664     delete[] tmpH;
665   }
666
667
668   //* merging tracks between slices
669
670
671   // arrays for the rotated track parameters
672
673   AliHLTTPCCABorderTrack
674   *bCurr0 = new AliHLTTPCCABorderTrack[maxNSliceTracks*10],
675   *bNext0 = new AliHLTTPCCABorderTrack[maxNSliceTracks*10],
676   *bCurr = new AliHLTTPCCABorderTrack[maxNSliceTracks*10],
677   *bNext = new AliHLTTPCCABorderTrack[maxNSliceTracks*10];
678
679   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
680
681     int jSlice = nextSlice[iSlice];
682
683     int nCurr0 = 0, nNext0 = 0;
684     int nCurr = 0, nNext = 0;
685
686     MakeBorderTracks( iSlice, 0, bCurr, nCurr );
687     MakeBorderTracks( jSlice, 1, bNext, nNext );
688     MakeBorderTracks( iSlice, 2, bCurr0, nCurr0 );
689     MakeBorderTracks( jSlice, 3, bNext0, nNext0 );
690
691     SplitBorderTracks( iSlice, bCurr0, nCurr0, jSlice, bNext0, nNext0 );
692     SplitBorderTracks( iSlice, bCurr, nCurr, jSlice, bNext, nNext );
693   }
694
695   if ( bCurr0 ) delete[] bCurr0;
696   if ( bNext0 ) delete[] bNext0;
697   if ( bCurr  ) delete[] bCurr;
698   if ( bNext  ) delete[] bNext;
699
700
701   //static int nRejected = 0;
702
703   int nOutTracks = 0;
704   int nOutTrackClusters = 0;
705
706   AliHLTTPCCAMergedTrack *outTracks = new AliHLTTPCCAMergedTrack[fMaxTrackInfos];
707   unsigned int   *outClusterId = new unsigned int [fMaxClusterInfos];
708   UChar_t  *outClusterPackedAmp = new UChar_t [fMaxClusterInfos];
709
710   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
711
712     for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
713
714       AliHLTTPCCASliceTrackInfo &track = fTrackInfos[fSliceTrackInfoStart[iSlice] + itr];
715
716       if ( track.Used() ) continue;
717       if ( track.PrevNeighbour() >= 0 ) continue;
718
719       AliHLTTPCCATrackParam startPoint = track.InnerParam(), endPoint = track.OuterParam();
720       float startAlpha = track.InnerAlpha(), endAlpha = track.OuterAlpha();
721
722       int hits[2000];
723       int firstHit = 1000;
724       int nHits = 0;
725       int jSlice = iSlice;
726       int jtr = itr;
727
728       {
729         track.SetUsed( 1 );
730         for ( int jhit = 0; jhit < track.NClusters(); jhit++ ) {
731           int id = track.FirstClusterRef() + jhit;
732           hits[firstHit+jhit] = id;
733         }
734         nHits = track.NClusters();
735         jtr = track.NextNeighbour();
736         jSlice = nextSlice[iSlice];
737       }
738
739       while ( jtr >= 0 ) {
740         AliHLTTPCCASliceTrackInfo &segment = fTrackInfos[fSliceTrackInfoStart[jSlice] + jtr];
741         if ( segment.Used() ) break;
742         segment.SetUsed( 1 );
743         bool dir = 0;
744         int startHit = firstHit + nHits;
745         float d00 = startPoint.GetDistXZ2( segment.InnerParam() );
746         float d01 = startPoint.GetDistXZ2( segment.OuterParam() );
747         float d10 = endPoint.GetDistXZ2( segment.InnerParam() );
748         float d11 = endPoint.GetDistXZ2( segment.OuterParam() );
749         if ( d00 <= d01 && d00 <= d10 && d00 <= d11 ) {
750           startPoint = segment.OuterParam();
751           startAlpha = segment.OuterAlpha();
752           dir = 1;
753           firstHit -= segment.NClusters();
754           startHit = firstHit;
755         } else if ( d01 <= d10 && d01 <= d11 ) {
756           startPoint = segment.InnerParam();
757           startAlpha = segment.InnerAlpha();
758           dir = 0;
759           firstHit -= segment.NClusters();
760           startHit = firstHit;
761         } else if ( d10 <= d11 ) {
762           endPoint = segment.OuterParam();
763           endAlpha = segment.OuterAlpha();
764           dir = 0;
765         } else {
766           endPoint = segment.InnerParam();
767           endAlpha = segment.InnerAlpha();
768           dir = 1;
769         }
770
771         for ( int jhit = 0; jhit < segment.NClusters(); jhit++ ) {
772           int id = segment.FirstClusterRef() + jhit;
773           hits[startHit+( dir ?( segment.NClusters()-1-jhit ) :jhit )] = id;
774         }
775         nHits += segment.NClusters();
776         jtr = segment.NextNeighbour();
777         jSlice = nextSlice[jSlice];
778       }
779
780       if ( endPoint.X() < startPoint.X() ) { // swap
781         for ( int i = 0; i < nHits; i++ ) hits[i] = hits[firstHit+nHits-1-i];
782         firstHit = 0;
783       }
784
785       if ( nHits < 30 ) continue;    //SG!!!
786
787       // refit
788
789       // need best t0!!!SG
790
791       endPoint = startPoint;
792       if ( !FitTrack( endPoint, endAlpha, startPoint, startAlpha, hits + firstHit, nHits, 0 ) ) continue;
793       if ( !FitTrack( startPoint, startAlpha, endPoint, endAlpha, hits + firstHit, nHits, 1 ) ) continue;
794
795       if ( nHits < 30 ) continue;    //SG!!!
796
797       AliHLTTPCCATrackParam &p = startPoint;
798
799       {
800         double xTPC = 83.65; //SG!!!
801         double dAlpha = 0.00609235;
802         AliHLTTPCCATrackParam::AliHLTTPCCATrackFitParam fitPar;
803         p.CalculateFitParameters( fitPar );
804
805         if ( p.TransportToXWithMaterial( xTPC, fitPar, fSliceParam.GetBz( p ) ) ) {
806           double y = p.GetY();
807           double ymax = xTPC * CAMath::Tan( dAlpha / 2. );
808           if ( y > ymax ) {
809             if ( p.Rotate( dAlpha ) ) { startAlpha += dAlpha;  p.TransportToXWithMaterial( xTPC, fitPar, fSliceParam.GetBz( p ) ); }
810           } else if ( y < -ymax ) {
811             if ( p.Rotate( -dAlpha ) ) {  startAlpha -= dAlpha; p.TransportToXWithMaterial( xTPC, fitPar, fSliceParam.GetBz( p ) );}
812           }
813         }
814       }
815
816       if ( !p.CheckNumericalQuality() ) continue;
817
818       AliHLTTPCCAMergedTrack &mergedTrack = outTracks[nOutTracks];
819       mergedTrack.SetNClusters( nHits );
820       mergedTrack.SetFirstClusterRef( nOutTrackClusters );
821       mergedTrack.SetInnerParam( startPoint );
822       mergedTrack.SetInnerAlpha( startAlpha );
823       mergedTrack.SetOuterParam( endPoint );
824       mergedTrack.SetOuterAlpha( endAlpha );
825
826       for ( int i = 0; i < nHits; i++ ) {
827         AliHLTTPCCAClusterInfo &clu = fClusterInfos[hits[firstHit+i]];
828         outClusterId[nOutTrackClusters+i] = clu.Id();
829         outClusterPackedAmp[nOutTrackClusters+i] = clu.PackedAmp();
830       }
831
832       nOutTracks++;
833       nOutTrackClusters += nHits;
834     }
835   }
836
837   fOutput->SetNTracks( nOutTracks );
838 #ifdef HLTCA_STANDALONE
839   printf("Tracks Output: %d\n", nOutTracks);
840 #endif
841   fOutput->SetNTrackClusters( nOutTrackClusters );
842   fOutput->SetPointers();
843
844   for ( int itr = 0; itr < nOutTracks; itr++ ) fOutput->SetTrack( itr, outTracks[itr] );
845
846   for ( int ic = 0; ic < nOutTrackClusters; ic++ ) {
847     fOutput->SetClusterId( ic, outClusterId[ic] );
848     fOutput->SetClusterPackedAmp( ic, outClusterPackedAmp[ic] );
849   }
850
851   delete[] outTracks;
852   delete[] outClusterId;
853   delete[] outClusterPackedAmp;
854 }