]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/tracking-ca/AliHLTTPCCAMerger.cxx
bug fix: reconstruction crash when the output buffer size exceed
[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;
224           t0.InitParam();
225           t0.SetParam(sTrack.Param());
226       int nCluNew = 0;
227
228       for ( int iTrClu = 0; iTrClu < sTrack.NClusters(); iTrClu++ ) {
229
230         // unpack cluster information
231
232         AliHLTTPCCAClusterInfo &clu = fClusterInfos[nClustersCurrent + nCluNew];
233         int ic = sTrack.FirstClusterRef() + iTrClu;
234
235         clu.SetISlice( iSlice );
236         clu.SetIRow( slice.ClusterRow( ic ) );
237         clu.SetId( slice.ClusterId( ic ) );
238         clu.SetPackedAmp( 0 );
239         float2 yz = slice.ClusterUnpackedYZ( ic );
240         clu.SetX( slice.ClusterUnpackedX( ic ) );
241         clu.SetY( yz.x );
242         clu.SetZ( yz.y );
243
244         if ( !t0.TransportToX( clu.X(), fSliceParam.GetBz( t0 ), .999 ) ) continue;
245
246         float err2Y, err2Z;
247         fSliceParam.GetClusterErrors2( clu.IRow(), clu.Z(), t0.SinPhi(), t0.GetCosPhi(), t0.DzDs(), err2Y, err2Z );
248
249         clu.SetErr2Y( err2Y );
250         clu.SetErr2Z( err2Z );
251         nCluNew++ ;
252       }
253
254       if ( nCluNew < .8*sTrack.NClusters() ) continue;
255
256       // refit the track
257
258       int hits[1000];
259       int nHits = nCluNew;
260       for ( int i = 0; i < nHits; i++ ) hits[i] = nClustersCurrent + i;
261
262       AliHLTTPCCATrackParam startPoint;
263           startPoint.InitParam();
264           startPoint.SetParam(sTrack.Param());
265       AliHLTTPCCATrackParam endPoint = startPoint;
266       float startAlpha = fSliceParam.Alpha( iSlice );
267       float endAlpha = startAlpha;
268
269       if ( !FitTrack( endPoint, endAlpha, startPoint, startAlpha, hits, nHits, 0 ) ) continue;
270
271       startPoint = endPoint;
272       startAlpha = endAlpha;
273       if ( !FitTrack( startPoint, startAlpha, endPoint, endAlpha, hits, nHits, 1 ) ) continue;
274
275       if ( nHits < .8*sTrack.NClusters() ) continue;
276
277       // store the track
278
279       AliHLTTPCCASliceTrackInfo &track = fTrackInfos[nTracksCurrent];
280
281       track.SetInnerParam( startPoint );
282       track.SetInnerAlpha( startAlpha );
283       track.SetOuterParam( endPoint );
284       track.SetOuterAlpha( endAlpha );
285       track.SetFirstClusterRef( nClustersCurrent );
286       track.SetNClusters( nHits );
287       track.SetPrevNeighbour( -1 );
288       track.SetNextNeighbour( -1 );
289       track.SetUsed( 0 );
290
291       for ( int i = 0; i < nHits; i++ )
292         fClusterInfos[nClustersCurrent + i] = fClusterInfos[hits[i]];
293       nTracksCurrent++;
294       fSliceNTrackInfos[ iSlice ]++;
295       nClustersCurrent += nHits;
296     }
297     //std::cout<<"Unpack slice "<<iSlice<<": ntracks "<<slice.NTracks()<<"/"<<fSliceNTrackInfos[iSlice]<<std::endl;
298   }
299 }
300
301
302
303 bool AliHLTTPCCAMerger::FitTrack( AliHLTTPCCATrackParam &T, float &Alpha,
304                                   AliHLTTPCCATrackParam t0, float Alpha0,
305                                   int hits[], int &NTrackHits, bool dir, bool final,
306                                   AliHLTTPCCAClusterInfo *infoArray )
307 {
308   // Fit the track
309
310   AliHLTTPCCATrackParam::AliHLTTPCCATrackFitParam fitPar;
311   AliHLTTPCCATrackParam t = t0;
312   AliHLTTPCCATrackLinearisation l( t0 );
313
314   bool first = 1;
315   bool doErrors = 1;
316   if ( !infoArray ) {
317     infoArray = fClusterInfos;
318     doErrors = 0;
319   }
320
321   t.CalculateFitParameters( fitPar );
322
323   int hitsNew[1000];
324   int nHitsNew = 0;
325
326   for ( int ihit = 0; ihit < NTrackHits; ihit++ ) {
327
328     int jhit = dir ? ( NTrackHits - 1 - ihit ) : ihit;
329     AliHLTTPCCAClusterInfo &h = infoArray[hits[jhit]];
330
331     int iSlice = h.ISlice();
332
333     float sliceAlpha =  fSliceParam.Alpha( iSlice );
334
335     if ( CAMath::Abs( sliceAlpha - Alpha0 ) > 1.e-4 ) {
336       if ( ! t.Rotate(  sliceAlpha - Alpha0, l, .999 ) ) continue;
337       Alpha0 = sliceAlpha;
338     }
339
340     //float x = fSliceParam.RowX( h.IRow() );
341     float x = h.X();
342
343     if ( !t.TransportToXWithMaterial( x, l, fitPar, fSliceParam.GetBz( t ) ) ) continue;
344
345     if ( first ) {
346       t.SetCov( 0, 10 );
347       t.SetCov( 1,  0 );
348       t.SetCov( 2, 10 );
349       t.SetCov( 3,  0 );
350       t.SetCov( 4,  0 );
351       t.SetCov( 5,  1 );
352       t.SetCov( 6,  0 );
353       t.SetCov( 7,  0 );
354       t.SetCov( 8,  0 );
355       t.SetCov( 9,  1 );
356       t.SetCov( 10,  0 );
357       t.SetCov( 11,  0 );
358       t.SetCov( 12,  0 );
359       t.SetCov( 13,  0 );
360       t.SetCov( 14,  10 );
361       t.SetChi2( 0 );
362       t.SetNDF( -5 );
363       t.CalculateFitParameters( fitPar );
364     }
365
366     float err2Y = h.Err2Y();
367     float err2Z = h.Err2Z();
368     if ( doErrors ) fSliceParam.GetClusterErrors2( h.IRow(), h.Z(), l.SinPhi(), l.CosPhi(), l.DzDs(), err2Y, err2Z );
369     if( !final ){
370       err2Y*= fSliceParam.ClusterError2CorrectionY();
371       err2Z*= fSliceParam.ClusterError2CorrectionZ();
372     }
373
374     if ( !t.Filter( h.Y(), h.Z(), err2Y, err2Z ) ) continue;
375
376     first = 0;
377
378     hitsNew[nHitsNew++] = hits[jhit];
379   }
380
381   if ( CAMath::Abs( t.QPt() ) < 1.e-4 ) t.SetQPt( 1.e-4 );
382
383   bool ok = t.CheckNumericalQuality();
384
385   if ( CAMath::Abs( t.SinPhi() ) > .99 ) ok = 0;
386   else if ( l.CosPhi() >= 0 ) t.SetSignCosPhi( 1 );
387   else t.SetSignCosPhi( -1 );
388
389   if ( ok ) {
390     T = t;
391     Alpha = Alpha0;
392     NTrackHits = nHitsNew;
393     for ( int i = 0; i < NTrackHits; i++ ) {
394       hits[dir ?( NTrackHits-1-i ) :i] = hitsNew[i];
395     }
396   }
397   return ok;
398 }
399
400
401 float AliHLTTPCCAMerger::GetChi2( float x1, float y1, float a00, float a10, float a11,
402                                   float x2, float y2, float b00, float b10, float b11  )
403 {
404   //* Calculate Chi2/ndf deviation
405
406   float d[2] = { x1 - x2, y1 - y2 };
407
408   float mSi[3] = { a00 + b00, a10 + b10, a11 + b11 };
409
410   float s = ( mSi[0] * mSi[2] - mSi[1] * mSi[1] );
411
412   if ( s < 1.E-10 ) return 10000.;
413
414   float mS[3] = { mSi[2], -mSi[1], mSi[0] };
415
416   return AliHLTTPCCAMath::Abs( ( ( mS[0]*d[0] + mS[1]*d[1] )*d[0]
417                        + ( mS[1]*d[0] + mS[2]*d[1] )*d[1] ) / s / 2 );
418
419 }
420
421
422
423 void AliHLTTPCCAMerger::MakeBorderTracks( int iSlice, int iBorder, AliHLTTPCCABorderTrack B[], int &nB )
424 {
425   //* prepare slice tracks for merging with next/previous/same sector
426   //* each track transported to the border line,
427   //* in some cases both inner and outer parameters of the track are transported
428
429   static int statAll = 0, statOK = 0;
430   nB = 0;
431   float dAlpha = fSliceParam.DAlpha() / 2;
432   float x0 = 0;
433
434   if ( iBorder == 0 ) { // transport to the left age of the sector and rotate horisontally
435     dAlpha = dAlpha - CAMath::Pi() / 2 ;
436   } else if ( iBorder == 1 ) { //  transport to the right age of the sector and rotate horisontally
437     dAlpha = -dAlpha - CAMath::Pi() / 2 ;
438   } else if ( iBorder == 2 ) { // transport to the left age of the sector and rotate vertically
439     dAlpha = dAlpha;
440     x0 = fSliceParam.RowX( 63 );
441   } else if ( iBorder == 3 ) { // transport to the right age of the sector and rotate vertically
442     dAlpha = -dAlpha;
443     x0 =  fSliceParam.RowX( 63 );
444   } else if ( iBorder == 4 ) { // transport to the middle of the sector, w/o rotation
445     dAlpha = 0;
446     x0 = fSliceParam.RowX( 63 );
447   }
448
449   for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
450
451     const AliHLTTPCCASliceTrackInfo &track = fTrackInfos[ fSliceTrackInfoStart[iSlice] + itr ];
452
453     AliHLTTPCCATrackParam t0 = track.InnerParam();
454     AliHLTTPCCATrackParam t1 = track.OuterParam();
455
456     const float maxSin = CAMath::Sin( 60. / 180.*CAMath::Pi() );
457
458     bool ok0 = t0.Rotate( dAlpha, maxSin );
459     bool ok1 = t1.Rotate( dAlpha, maxSin );
460
461     bool do0 = ok0;
462     bool do1 = ok1 && ( !ok0 || t1.SignCosPhi() * t0.SignCosPhi() < 0 );
463
464     if ( ok0 && !do1 && ok1 && ( t1.X() < t0.X() ) ) {
465       do0 = 0;
466       do1 = 1;
467     }
468
469     if ( do0 ) {
470       AliHLTTPCCABorderTrack &b = B[nB];
471       b.SetX( t0.GetX() );
472       
473       if ( t0.TransportToX( x0, fSliceParam.GetBz( t0 ), maxSin ) ) {
474         b.SetOK( 1 );
475         b.SetTrackID( itr );
476         b.SetNClusters( track.NClusters() );
477         b.SetIRow( fClusterInfos[ track.FirstClusterRef() + 0 ].IRow() );
478         b.SetParam( t0 );
479         nB++;
480       }
481     }
482     if ( do1 ) {
483       AliHLTTPCCABorderTrack &b = B[nB];
484       b.SetX( t1.GetX() );
485       
486       if ( t1.TransportToX( x0, fSliceParam.GetBz( t1 ), maxSin ) ) {
487         b.SetOK( 1 );
488         b.SetTrackID( itr );
489         b.SetNClusters( track.NClusters() );
490         b.SetIRow( fClusterInfos[ track.FirstClusterRef() + track.NClusters()-1 ].IRow() );
491         b.SetParam( t1 );
492         nB++;
493       }
494     }
495     if ( do0 || do1 ) statOK++;
496     statAll++;
497   }
498 }
499
500
501
502 void AliHLTTPCCAMerger::MergeBorderTracks( int iSlice1, AliHLTTPCCABorderTrack B1[], int N1,
503     int iSlice2, AliHLTTPCCABorderTrack B2[], int N2
504                                          )
505 {
506   //* merge two sets of tracks
507
508   //std::cout<<" Merge slices "<<iSlice1<<"+"<<iSlice2<<": tracks "<<N1<<"+"<<N2<<std::endl;
509   
510   float factor2ys = 1.;//1.5;//SG!!!
511   float factor2zt = 1.;//1.5;//SG!!!
512   float factor2k = 2.0;//2.2;
513
514   factor2k  = 3.5 * 3.5 * factor2k * factor2k;
515   factor2ys = 3.5 * 3.5 * factor2ys * factor2ys;
516   factor2zt = 3.5 * 3.5 * factor2zt * factor2zt;
517
518   int minNPartHits = 10;//SG!!!
519   int minNTotalHits = 20;
520
521   //float maxDX = fSliceParam.RowX(40) -  fSliceParam.RowX(0);
522
523   for ( int i1 = 0; i1 < N1; i1++ ) {
524     AliHLTTPCCABorderTrack &b1 = B1[i1];
525     if ( !b1.OK() ) continue;
526     if ( b1.NClusters() < minNPartHits ) continue;
527     const AliHLTTPCCATrackParam &t1 = b1.Param();
528     int iBest2 = -1;
529     int lBest2 = 0;
530     int start2 = ( iSlice1 != iSlice2 ) ? 0 : i1 + 1;
531     for ( int i2 = start2; i2 < N2; i2++ ) {
532       AliHLTTPCCABorderTrack &b2 = B2[i2];
533       if ( !b2.OK() ) continue;
534       if ( b2.NClusters() < minNPartHits ) continue;
535       if ( b2.NClusters() < lBest2 ) continue;
536       if ( b1.NClusters() + b2.NClusters() < minNTotalHits ) continue;
537
538       //if( TMath::Abs(b1.fX - b2.fX)>maxDX ) continue;
539
540       const AliHLTTPCCATrackParam &t2 = b2.Param();
541
542       float c = t2.SignCosPhi() * t1.SignCosPhi() >= 0 ? 1 : -1;
543       float dk = t2.QPt() - c * t1.QPt();
544       float s2k = t2.Err2QPt() + t1.Err2QPt();
545       //std::cout<<" check 1.. "<<dk/sqrt(factor2k)<<std::endl;
546       if ( dk*dk > factor2k*s2k ) continue;
547
548
549       float chi2ys = GetChi2( t1.Y(), c * t1.SinPhi(), t1.Cov()[0], c * t1.Cov()[3], t1.Cov()[5],
550                               t2.Y(),  t2.SinPhi(), t2.Cov()[0],  t2.Cov()[3], t2.Cov()[5] );
551
552       //std::cout<<" check 2.. "<<sqrt(chi2ys/factor2ys)<<std::endl;
553       if ( chi2ys > factor2ys ) continue;
554       
555
556       float chi2zt = GetChi2( t1.Z(), c * t1.DzDs(), t1.Cov()[2], c * t1.Cov()[7], t1.Cov()[9],
557                               t2.Z(),  t2.DzDs(), t2.Cov()[2],  t2.Cov()[7], t2.Cov()[9] );
558
559       //std::cout<<" check 3.. "<<sqrt(chi2zt/factor2zt)<<std::endl;
560       if ( chi2zt > factor2zt ) continue;
561
562       lBest2 = b2.NClusters();
563       iBest2 = b2.TrackID();
564     }
565
566     if ( iBest2 < 0 ) continue;
567
568     //std::cout<<"Neighbour found for "<<i1<<": "<<iBest2<<std::endl;
569     AliHLTTPCCASliceTrackInfo &newTrack1 = fTrackInfos[fSliceTrackInfoStart[iSlice1] + b1.TrackID() ];
570     AliHLTTPCCASliceTrackInfo &newTrack2 = fTrackInfos[fSliceTrackInfoStart[iSlice2] + iBest2 ];
571
572     int old1 = newTrack2.PrevNeighbour();
573
574     if ( old1 >= 0 ) {
575       AliHLTTPCCASliceTrackInfo &oldTrack1 = fTrackInfos[fSliceTrackInfoStart[iSlice1] + old1];
576       if ( oldTrack1.NClusters()  < newTrack1.NClusters() ) {
577         newTrack2.SetPrevNeighbour( -1 );
578         oldTrack1.SetNextNeighbour( -1 );
579       } else continue;
580     }
581     int old2 = newTrack1.NextNeighbour();
582     if ( old2 >= 0 ) {
583       AliHLTTPCCASliceTrackInfo &oldTrack2 = fTrackInfos[fSliceTrackInfoStart[iSlice2] + old2];
584       if ( oldTrack2.NClusters() < newTrack2.NClusters() ) {
585         oldTrack2.SetPrevNeighbour( -1 );
586       } else continue;
587     }
588     newTrack1.SetNextNeighbour( iBest2 );
589     newTrack2.SetPrevNeighbour( b1.TrackID() );
590     //std::cout<<"Neighbourhood is set"<<std::endl;
591   }
592
593 }
594
595
596 void AliHLTTPCCAMerger::Merging()
597 {
598   //* track merging between slices
599
600   fOutput->SetNTracks( 0 );
601   fOutput->SetNTrackClusters( 0 );
602   fOutput->SetPointers();
603
604
605   // for each slice set number of the next neighbouring slice
606
607   int nextSlice[100], prevSlice[100];
608
609   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
610     nextSlice[iSlice] = iSlice + 1;
611     prevSlice[iSlice] = iSlice - 1;
612   }
613   int mid = fgkNSlices / 2 - 1 ;
614   int last = fgkNSlices - 1 ;
615   if ( mid < 0 ) mid = 0; // to avoid compiler warning
616   if ( last < 0 ) last = 0; //
617   nextSlice[ mid ] = 0;
618   prevSlice[ 0 ] = mid;
619   nextSlice[ last ] = fgkNSlices / 2;
620   prevSlice[ fgkNSlices/2 ] = last;
621
622   int maxNSliceTracks = 0;
623   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
624     if ( maxNSliceTracks < fSliceNTrackInfos[iSlice] ) maxNSliceTracks = fSliceNTrackInfos[iSlice];
625   }
626
627   if ( 1 ) {// merging track segments withing one slice
628
629     AliHLTResizableArray<AliHLTTPCCABorderTrack> bord( maxNSliceTracks*2 );
630
631     AliHLTTPCCASliceTrackInfo *tmpT = new AliHLTTPCCASliceTrackInfo[maxNSliceTracks];
632     AliHLTTPCCAClusterInfo *tmpH = new AliHLTTPCCAClusterInfo[fMaxClusterInfos];
633
634     for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
635
636       int nBord = 0;
637       MakeBorderTracks( iSlice, 4, bord.Data(), nBord );
638       MergeBorderTracks( iSlice, bord.Data(), nBord, iSlice, bord.Data(), nBord );
639
640       int nTr = 0, nH = 0;
641       int sliceFirstClusterRef = 0;
642       for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
643         AliHLTTPCCASliceTrackInfo &track = fTrackInfos[ fSliceTrackInfoStart[iSlice] + itr];
644         if ( itr == 0 ) sliceFirstClusterRef = track.FirstClusterRef();
645         track.SetPrevNeighbour( -1 );
646         if ( track.NextNeighbour() == -2 ) {
647           track.SetNextNeighbour( -1 );
648           continue;
649         }
650         AliHLTTPCCASliceTrackInfo &trackNew = tmpT[nTr];
651         trackNew = track;
652         trackNew.SetFirstClusterRef( sliceFirstClusterRef + nH );
653
654         for ( int ih = 0; ih < track.NClusters(); ih++ ) tmpH[nH+ih] = fClusterInfos[track.FirstClusterRef()+ih];
655         nTr++;
656         nH += track.NClusters();
657
658         int jtr =  track.NextNeighbour();
659
660         if ( jtr < 0 ) continue;
661         AliHLTTPCCASliceTrackInfo &neighTrack = fTrackInfos[ fSliceTrackInfoStart[iSlice] + jtr];
662
663         track.SetNextNeighbour( -1 );
664         neighTrack.SetNextNeighbour( -2 );
665
666         for ( int ih = 0; ih < neighTrack.NClusters(); ih++ )
667           tmpH[nH+ih] = fClusterInfos[neighTrack.FirstClusterRef()+ih];
668
669         trackNew.SetNClusters( trackNew.NClusters() + neighTrack.NClusters() );
670         trackNew.SetNextNeighbour( -1 );
671         nH += neighTrack.NClusters();
672         if ( neighTrack.InnerParam().X() < track.InnerParam().X() ) trackNew.SetInnerParam( neighTrack.InnerParam() );
673         if ( neighTrack.OuterParam().X() > track.OuterParam().X() ) trackNew.SetOuterParam( neighTrack.OuterParam() );
674       }
675
676       fSliceNTrackInfos[iSlice] = nTr;
677       for ( int itr = 0; itr < nTr; itr++ ) fTrackInfos[ fSliceTrackInfoStart[iSlice] + itr] = tmpT[itr];
678       for ( int ih = 0; ih < nH; ih++ ) fClusterInfos[sliceFirstClusterRef + ih] = tmpH[ih];
679
680     }
681     delete[] tmpT;
682     delete[] tmpH;
683   }
684
685
686   //* merging tracks between slices
687
688
689   // arrays for the rotated track parameters
690
691   AliHLTTPCCABorderTrack
692   *bCurr0 = new AliHLTTPCCABorderTrack[maxNSliceTracks*2],
693   *bNext0 = new AliHLTTPCCABorderTrack[maxNSliceTracks*2],
694   *bCurr = new AliHLTTPCCABorderTrack[maxNSliceTracks*2],
695   *bNext = new AliHLTTPCCABorderTrack[maxNSliceTracks*2];
696
697   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
698
699     int jSlice = nextSlice[iSlice];
700
701     int nCurr0 = 0, nNext0 = 0;
702     int nCurr = 0, nNext = 0;
703
704     MakeBorderTracks( iSlice, 0, bCurr, nCurr );
705     MakeBorderTracks( jSlice, 1, bNext, nNext );
706     MakeBorderTracks( iSlice, 2, bCurr0, nCurr0 );
707     MakeBorderTracks( jSlice, 3, bNext0, nNext0 );
708
709     MergeBorderTracks( iSlice, bCurr0, nCurr0, jSlice, bNext0, nNext0 );
710     MergeBorderTracks( iSlice, bCurr, nCurr, jSlice, bNext, nNext );
711   }
712
713   if ( bCurr0 ) delete[] bCurr0;
714   if ( bNext0 ) delete[] bNext0;
715   if ( bCurr  ) delete[] bCurr;
716   if ( bNext  ) delete[] bNext;
717
718
719   //static int nRejected = 0;
720
721   int nOutTracks = 0;
722   int nOutTrackClusters = 0;
723
724   AliHLTTPCCAMergedTrack *outTracks = new AliHLTTPCCAMergedTrack[fMaxTrackInfos];
725   unsigned int   *outClusterId = new unsigned int [fMaxClusterInfos];
726   UChar_t  *outClusterPackedAmp = new UChar_t [fMaxClusterInfos];
727
728   for ( int iSlice = 0; iSlice < fgkNSlices; iSlice++ ) {
729
730     for ( int itr = 0; itr < fSliceNTrackInfos[iSlice]; itr++ ) {
731
732       AliHLTTPCCASliceTrackInfo &track = fTrackInfos[fSliceTrackInfoStart[iSlice] + itr];
733
734       if ( track.Used() ) continue;
735       if ( track.PrevNeighbour() >= 0 ) continue;
736       //std::cout<<"Merged track candidate, nhits "<<track.NClusters()<<std::endl;
737       AliHLTTPCCATrackParam startPoint = track.InnerParam(), endPoint = track.OuterParam();
738       float startAlpha = track.InnerAlpha(), endAlpha = track.OuterAlpha();
739
740       int hits[2000];
741       int firstHit = 1000;
742       int nHits = 0;
743       int jSlice = iSlice;
744       int jtr = itr;
745
746       {
747         track.SetUsed( 1 );
748         for ( int jhit = 0; jhit < track.NClusters(); jhit++ ) {
749           int id = track.FirstClusterRef() + jhit;
750           hits[firstHit+jhit] = id;
751         }
752         nHits = track.NClusters();
753         jtr = track.NextNeighbour();
754         jSlice = nextSlice[iSlice];
755       }
756
757       while ( jtr >= 0 ) {
758         AliHLTTPCCASliceTrackInfo &segment = fTrackInfos[fSliceTrackInfoStart[jSlice] + jtr];
759         if ( segment.Used() ) break;
760         segment.SetUsed( 1 );
761         bool dir = 0;
762         int startHit = firstHit + nHits;
763         float d00 = startPoint.GetDistXZ2( segment.InnerParam() );
764         float d01 = startPoint.GetDistXZ2( segment.OuterParam() );
765         float d10 = endPoint.GetDistXZ2( segment.InnerParam() );
766         float d11 = endPoint.GetDistXZ2( segment.OuterParam() );
767         if ( d00 <= d01 && d00 <= d10 && d00 <= d11 ) {
768           startPoint = segment.OuterParam();
769           startAlpha = segment.OuterAlpha();
770           dir = 1;
771           firstHit -= segment.NClusters();
772           startHit = firstHit;
773         } else if ( d01 <= d10 && d01 <= d11 ) {
774           startPoint = segment.InnerParam();
775           startAlpha = segment.InnerAlpha();
776           dir = 0;
777           firstHit -= segment.NClusters();
778           startHit = firstHit;
779         } else if ( d10 <= d11 ) {
780           endPoint = segment.OuterParam();
781           endAlpha = segment.OuterAlpha();
782           dir = 0;
783         } else {
784           endPoint = segment.InnerParam();
785           endAlpha = segment.InnerAlpha();
786           dir = 1;
787         }
788
789         for ( int jhit = 0; jhit < segment.NClusters(); jhit++ ) {
790           int id = segment.FirstClusterRef() + jhit;
791           hits[startHit+( dir ?( segment.NClusters()-1-jhit ) :jhit )] = id;
792         }
793         nHits += segment.NClusters();
794         jtr = segment.NextNeighbour();
795         jSlice = nextSlice[jSlice];
796       }
797
798       if ( endPoint.X() < startPoint.X() ) { // swap
799         for ( int i = 0; i < nHits; i++ ) hits[i] = hits[firstHit+nHits-1-i];
800         firstHit = 0;
801       }
802
803       if ( nHits < 30 ) continue;    //SG!!!
804
805       // refit
806
807       // need best t0!!!SG
808
809       endPoint = startPoint;
810
811       if ( !FitTrack( endPoint, endAlpha, startPoint, startAlpha, hits + firstHit, nHits, 0,1 ) ) continue;
812       if ( !FitTrack( startPoint, startAlpha, endPoint, endAlpha, hits + firstHit, nHits, 1,1 ) ) continue;
813       if ( nHits < 30 ) continue;    //SG!!!
814
815       AliHLTTPCCATrackParam p = startPoint;
816       
817       if(0){
818         double xTPC = 83.65; //SG!!!
819         double dAlpha = 0.349066;
820         double ymax = 2.* xTPC * CAMath::Tan( dAlpha / 2. );
821         
822         double dRot = 0;
823         if ( p.TransportToXWithMaterial( xTPC, fSliceParam.GetBz( p ) ) ) {
824           double y = p.GetY();
825           if ( y > ymax ) {         
826             if ( p.Rotate( dAlpha ) ){
827               dRot = dAlpha;
828               p.TransportToXWithMaterial( xTPC, fSliceParam.GetBz( p ) );
829             }
830           } else if( y< -ymax ){
831             if ( p.Rotate( -dAlpha ) ){
832               dRot = -dAlpha;
833               p.TransportToXWithMaterial( xTPC, fSliceParam.GetBz( p ) );
834             }
835           }
836         }
837         
838         if ( -ymax <= p.GetY() && p.GetY() <= ymax && p.CheckNumericalQuality() ){
839           startPoint = p;
840           startAlpha+=dRot;
841         }     
842       }
843
844       if ( !startPoint.CheckNumericalQuality() ) continue;
845
846       AliHLTTPCCAMergedTrack &mergedTrack = outTracks[nOutTracks];
847       mergedTrack.SetNClusters( nHits );
848       mergedTrack.SetFirstClusterRef( nOutTrackClusters );
849       mergedTrack.SetInnerParam( startPoint );
850       mergedTrack.SetInnerAlpha( startAlpha );
851       mergedTrack.SetOuterParam( endPoint );
852       mergedTrack.SetOuterAlpha( endAlpha );
853
854       for ( int i = 0; i < nHits; i++ ) {
855         AliHLTTPCCAClusterInfo &clu = fClusterInfos[hits[firstHit+i]];
856         outClusterId[nOutTrackClusters+i] = clu.Id();
857         outClusterPackedAmp[nOutTrackClusters+i] = clu.PackedAmp();
858       }
859
860       nOutTracks++;
861       nOutTrackClusters += nHits;
862     }
863   }
864
865   fOutput->SetNTracks( nOutTracks );
866   #ifdef HLTCA_STANDALONE
867   printf("Tracks Output: %d\n", nOutTracks);
868   #endif
869   fOutput->SetNTrackClusters( nOutTrackClusters );
870   fOutput->SetPointers();
871
872   for ( int itr = 0; itr < nOutTracks; itr++ ) fOutput->SetTrack( itr, outTracks[itr] );
873
874   for ( int ic = 0; ic < nOutTrackClusters; ic++ ) {
875     fOutput->SetClusterId( ic, outClusterId[ic] );
876     fOutput->SetClusterPackedAmp( ic, outClusterPackedAmp[ic] );
877   }
878
879   delete[] outTracks;
880   delete[] outClusterId;
881   delete[] outClusterPackedAmp;
882 }