]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/src/AliL3Fitter.cxx
Added Gautes changes from Bergen.
[u/mrichter/AliRoot.git] / HLT / src / AliL3Fitter.cxx
1 // @(#) $Id$
2
3 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
4 //*-- Copyright &copy ALICE HLT Group 
5
6 #include "AliL3StandardIncludes.h"
7 #include <math.h>
8
9 #include "AliL3Logging.h"
10 #include "AliL3Fitter.h"
11 #include "AliL3Vertex.h"
12 #include "AliL3Track.h"
13 #include "AliL3SpacePointData.h"
14 #include "AliL3MemHandler.h"
15 #include "AliL3Transform.h"
16 #include "AliLevel3.h"
17
18 /** \class AliL3Fitter
19 <pre>
20 //_____________________________________________________________
21 // AliL3Fitter
22 //
23 // Fit class HLT
24 </pre>
25 */
26
27 ClassImp(AliL3Fitter)
28
29
30 AliL3Fitter::AliL3Fitter()
31 {
32   fTrack=0;
33   fVertex=0;
34   memset(fClusters,0,36*6*sizeof(AliL3SpacePointData*));
35 }
36
37 AliL3Fitter::AliL3Fitter(AliL3Vertex *vertex,Bool_t vertexconstraint)
38 {
39   //constructor
40   fTrack=0;
41   fVertex = vertex;
42   fVertexConstraint=vertexconstraint;
43   memset(fClusters,0,36*6*sizeof(AliL3SpacePointData*));
44 }
45
46 AliL3Fitter::~AliL3Fitter()
47 {
48   for(Int_t i=0; i<36; i++)
49     {
50       for(Int_t j=0; j<6; j++)
51         {
52           if(fClusters[i][j])
53             delete fClusters[i][j];
54         }
55     }
56 }
57
58 void AliL3Fitter::LoadClusters(Char_t *path,Int_t event,Bool_t sp)
59 {
60   Char_t fname[256];
61   AliL3MemHandler *clusterfile[36][6];
62   for(Int_t s=0; s<=35; s++)
63     {
64       for(Int_t p=0; p<6; p++)
65         {
66           Int_t patch;
67           if(sp==kTRUE)
68             patch=-1;
69           else
70             patch=p;
71           if(fClusters[s][p])
72             delete fClusters[s][p];
73           fClusters[s][p] = 0;
74           clusterfile[s][p] = new AliL3MemHandler();
75           sprintf(fname,"%s/points_%d_%d_%d.raw",path,event,s,patch);
76           if(!clusterfile[s][p]->SetBinaryInput(fname))
77             {
78               delete clusterfile[s][p];
79               clusterfile[s][p] = 0; 
80               continue;
81             }
82           fClusters[s][p] = (AliL3SpacePointData*)clusterfile[s][p]->Allocate();
83           clusterfile[s][p]->Binary2Memory(fNcl[s][p],fClusters[s][p]);
84           clusterfile[s][p]->CloseBinaryInput();
85           if(sp==kTRUE)
86             break;
87         }
88     }
89 }
90
91 void AliL3Fitter::SortTrackClusters(AliL3Track *track)
92 {
93   //Sort the internal cluster list in each track with respect to row numbering.
94   //This may be necessary when no conventional track follower has been
95   //applied, in which the cluster list has been maintained in a more
96   //arbitrary fashion.
97
98   Int_t nhits = track->GetNHits();
99   Int_t *ids = (Int_t*)track->GetHitNumbers();
100   Int_t *origids = new Int_t[nhits];
101   Int_t *mk = new Int_t[nhits];
102   Int_t k;
103
104   for(k=0; k<nhits; k++) {origids[k] = ids[k]; mk[k] = -1;}
105   
106   Int_t slice,patch,id,padrow,maxrow,maxk;
107   UInt_t pos;
108   for(Int_t j=0; j<nhits; j++)
109     {
110       maxrow=-1;
111       maxk=200;
112       for(k=0; k<nhits; k++)
113         {
114           id=ids[k];
115           if(id < 0) continue;
116           slice = (id>>25) & 0x7f;
117           patch = (id>>22) & 0x7;
118           pos = id&0x3fffff;          
119           AliL3SpacePointData *points = fClusters[slice][patch];
120           padrow = points[pos].fPadRow;
121           if(padrow > maxrow)
122             {
123               maxrow = padrow;
124               maxk=k;
125             }
126         }
127       mk[j]=maxk;
128       ids[maxk]=-1;
129     }
130     
131   for(k=0; k<nhits; k++)
132     ids[k] = origids[mk[k]];
133   delete [] origids;
134   delete [] mk;
135 }
136
137 Int_t AliL3Fitter::FitHelix(AliL3Track *track)
138 {
139   fTrack = track;
140   if(FitCircle())
141     {
142       LOG(AliL3Log::kError,"AliL3Fitter::FitHelix","TrackFit")<<AliL3Log::kDec<<
143         "Problems during circle fit"<<ENDLOG;
144       return 1;
145     }
146   if(FitLine())
147     {
148       LOG(AliL3Log::kError,"AliL3Fitter::FitHelix","TrackFit")<<AliL3Log::kDec<<
149         "Problems during line fit"<<ENDLOG;
150       return 1;
151     }
152   return 0;
153 }
154
155 Int_t AliL3Fitter::FitCircle()
156 {
157   //-----------------------------------------------------------------
158   //Fits circle parameters using algorithm
159   //described by ChErnov and Oskov in Computer Physics
160   //Communications.
161   // 
162   //Written in FORTRAN by Jawluen Tang, Physics department , UT-Austin 
163   //Moved to C by Pablo Yepes
164   //Moved to AliROOT by ASV.
165   //------------------------------------------------------------------
166   
167   Double_t wsum  = 0.0 ;
168   Double_t xav   = 0.0 ;
169   Double_t yav   = 0.0 ;
170   
171   //
172   //     Loop over hits calculating average
173   //  Double_t fXYWeight[(fTrack->GetNHits())];
174   Double_t * fXYWeight = new Double_t[(fTrack->GetNHits())];
175   UInt_t *hitnum = fTrack->GetHitNumbers();
176   for(Int_t i=0; i<fTrack->GetNHits(); i++)
177     {
178       UInt_t id = hitnum[i];
179       Int_t slice = (id>>25) & 0x7f;
180       Int_t patch = (id>>22) & 0x7;
181       UInt_t pos = id&0x3fffff;
182       AliL3SpacePointData *points = fClusters[slice][patch];
183       fXYWeight[i] = 1./ (Double_t)(points[pos].fSigmaY2 + points[pos].fSigmaY2);
184       wsum += fXYWeight[i];
185       xav += fXYWeight[i]*points[pos].fX;
186       yav += fXYWeight[i]*points[pos].fY;
187     }
188   if (fVertexConstraint == kTRUE)
189     {    
190       wsum += fVertex->GetXYWeight() ;
191       xav  += fVertex->GetX() ;
192       yav  += fVertex->GetY() ;
193     }
194   
195   xav = xav / wsum ;
196   yav = yav / wsum ;
197 //
198 //  CALCULATE <X**2>, <XY>, AND <Y**2> WITH <X> = 0, & <Y> = 0
199 //
200   Double_t xxav  = 0.0 ;
201   Double_t xyav  = 0.0 ; 
202   Double_t yyav  = 0.0 ;
203   Double_t xi, yi ;
204   
205   for(Int_t i=0; i<fTrack->GetNHits(); i++)
206     { 
207       UInt_t id = hitnum[i];
208       Int_t slice = (id>>25) & 0x7f;
209       Int_t patch = (id>>22) & 0x7;
210       UInt_t pos = id&0x3fffff;
211       AliL3SpacePointData *points = fClusters[slice][patch];
212
213       xi = points[pos].fX -xav;
214       yi        = points[pos].fY - yav ;
215       xxav     += xi * xi * fXYWeight[i];
216       xyav     += xi * yi * fXYWeight[i];
217       yyav     += yi * yi * fXYWeight[i];
218     }
219   
220   if (fVertexConstraint == kTRUE)
221     {
222       xi        = fVertex->GetX() - xav ;
223       yi        = fVertex->GetY() - yav ;
224       xxav     += xi * xi * fVertex->GetXYWeight() ;
225       xyav     += xi * yi * fVertex->GetXYWeight() ;
226       yyav     += yi * yi * fVertex->GetXYWeight() ; 
227     }
228   xxav = xxav / wsum ;
229   xyav = xyav / wsum ;
230   yyav = yyav / wsum ;
231 //
232 //-->  ROTATE COORDINATES SO THAT <XY> = 0
233 //
234 //-->  SIGN(C**2 - S**2) = SIGN(XXAV - YYAV) >
235 //-->  &                                     > ==> NEW : (XXAV-YYAV) > 0
236 //-->  SIGN(S) = SIGN(XYAV)                  >
237
238   Double_t a = fabs( xxav - yyav ) ;
239   Double_t b = 4.0 * xyav * xyav ;
240
241   Double_t asqpb  = a * a + b  ;
242   Double_t rasqpb = sqrt ( asqpb) ;
243
244   Double_t splus  = 1.0 + a / rasqpb ;
245   Double_t sminus = b / (asqpb * splus) ;
246
247   splus  = sqrt (0.5 * splus ) ;
248   sminus = sqrt (0.5 * sminus) ;
249 //
250 //->  FIRST REQUIRE : SIGN(C**2 - S**2) = SIGN(XXAV - YYAV)
251 //
252   Double_t sinrot, cosrot ;
253   if ( xxav <= yyav ) {
254          cosrot = sminus ;
255          sinrot = splus  ;
256   }
257   else {
258           cosrot = splus ;
259           sinrot = sminus ;
260   }
261 //
262 //->  REQUIRE : SIGN(S) = SIGN(XYAV) * SIGN(C) (ASSUMING SIGN(C) > 0)
263 //
264   if ( xyav < 0.0 ) sinrot = - sinrot ;
265 //
266 //-->  WE NOW HAVE THE SMALLEST ANGLE THAT GUARANTEES <X**2> > <Y**2>
267 //-->  TO GET THE SIGN OF THE CHARGE RIGHT, THE NEW X-AXIS MUST POINT
268 //-->  OUTWARD FROM THE ORGIN.  WE ARE FREE TO CHANGE SIGNS OF BOTH
269 //-->  COSROT AND SINROT SIMULTANEOUSLY TO ACCOMPLISH THIS.
270 //
271 //-->  CHOOSE SIGN OF C WISELY TO BE ABLE TO GET THE SIGN OF THE CHARGE
272 //
273   if ( cosrot*xav+sinrot*yav < 0.0 ) {
274           cosrot = -cosrot ;
275           sinrot = -sinrot ;
276   }
277 //
278 //->  NOW GET <R**2> AND RSCALE= SQRT(<R**2>)
279 //
280   Double_t rrav   = xxav + yyav ;
281   Double_t rscale = sqrt(rrav) ;
282
283   xxav   = 0.0 ;
284   yyav   = 0.0 ;
285   xyav   = 0.0 ;
286   Double_t xrrav = 0.0 ;
287   Double_t yrrav = 0.0 ;
288   Double_t rrrrav  = 0.0 ;
289
290   Double_t xixi, yiyi, riri, wiriri, xold, yold ;
291   
292   for(Int_t i=0; i<fTrack->GetNHits(); i++)
293     { 
294       UInt_t id = hitnum[i];
295       Int_t slice = (id>>25) & 0x7f;
296       Int_t patch = (id>>22) & 0x7;
297       UInt_t pos = id&0x3fffff;
298       AliL3SpacePointData *points = fClusters[slice][patch];
299       
300       xold = points[pos].fX - xav ;
301       yold = points[pos].fY - yav ;
302       //
303       //-->  ROTATE SO THAT <XY> = 0 & DIVIDE BY RSCALE SO THAT <R**2> = 1
304       //
305       xi = (  cosrot * xold + sinrot * yold ) / rscale ;
306       yi = ( -sinrot * xold + cosrot * yold ) / rscale ;
307       
308       xixi   = xi * xi ;
309       yiyi   = yi * yi ;
310       riri   = xixi + yiyi ;
311       wiriri = fXYWeight[i] * riri ;
312       
313       xyav   += fXYWeight[i] * xi * yi ;
314       xxav   += fXYWeight[i] * xixi ;
315       yyav   += fXYWeight[i] * yiyi ;
316       
317       xrrav  += wiriri * xi ;
318       yrrav  += wiriri * yi ;
319       rrrrav += wiriri * riri ;
320     }
321   //
322 //   Include vertex if required
323 //
324   if (fVertexConstraint == kTRUE)
325     {
326       xold = fVertex->GetX() - xav ;
327         yold = fVertex->GetY() - yav ;
328         //
329         //-->  ROTATE SO THAT <XY> = 0 & DIVIDE BY RSCALE SO THAT <R**2> = 1
330         //
331         xi = (  cosrot * xold + sinrot * yold ) / rscale ;
332         yi = ( -sinrot * xold + cosrot * yold ) / rscale ;
333         
334         xixi   = xi * xi ;
335         yiyi   = yi * yi ;
336         riri   = xixi + yiyi ;
337         wiriri = fVertex->GetXYWeight() * riri ;
338
339         xyav   += fVertex->GetXYWeight() * xi * yi ;
340         xxav   += fVertex->GetXYWeight() * xixi ;
341         yyav   += fVertex->GetXYWeight() * yiyi ;
342
343         xrrav  += wiriri * xi ;
344         yrrav  += wiriri * yi ;
345         rrrrav += wiriri * riri ;
346   }
347   //
348   //    
349   //
350   //-->  DIVIDE BY WSUM TO MAKE AVERAGES
351   //
352   xxav    = xxav   / wsum ;
353   yyav    = yyav   / wsum ;
354   xrrav   = xrrav  / wsum ;
355   yrrav   = yrrav  / wsum ;
356   rrrrav  = rrrrav / wsum ;
357   xyav    = xyav   / wsum ;
358
359   Int_t const ntry = 5 ;
360 //
361 //-->  USE THESE TO GET THE COEFFICIENTS OF THE 4-TH ORDER POLYNIMIAL
362 //-->  DON'T PANIC - THE THIRD ORDER TERM IS ZERO !
363 //
364   Double_t xrrxrr = xrrav * xrrav ;
365   Double_t yrryrr = yrrav * yrrav ;
366   Double_t rrrrm1 = rrrrav - 1.0  ;
367   Double_t xxyy   = xxav  * yyav  ;        
368
369   Double_t c0  =          rrrrm1*xxyy - xrrxrr*yyav - yrryrr*xxav ;
370   Double_t c1  =        - rrrrm1      + xrrxrr      + yrryrr   - 4.0*xxyy ;        
371   Double_t c2  =   4.0  + rrrrm1                               - 4.0*xxyy ;           
372   Double_t c4  = - 4.0  ;                
373 //
374 //-->  COEFFICIENTS OF THE DERIVATIVE - USED IN NEWTON-RAPHSON ITERATIONS
375 //
376   Double_t c2d =   2.0 * c2 ;
377   Double_t c4d =   4.0 * c4 ;
378 //
379 //-->  0'TH VALUE OF LAMDA - LINEAR INTERPOLATION BETWEEN P(0) & P(YYAV)
380 //
381 //   LAMDA = YYAV * C0 / (C0 + YRRSQ * (XXAV-YYAV))
382   Double_t lamda  = 0.0 ;
383   Double_t dlamda = 0.0 ;
384 //
385   Double_t chiscl = wsum * rscale * rscale ;
386   Double_t dlamax = 0.001 / chiscl ;   
387    
388   Double_t p, pd ;
389   for ( int itry = 1 ; itry <= ntry ; itry++ ) {
390      p      = c0 + lamda * (c1 + lamda * (c2 + lamda * lamda * c4 )) ;
391      pd     = (c1 + lamda * (c2d + lamda * lamda * c4d)) ;
392      dlamda = -p / pd ;
393      lamda  = lamda + dlamda ;
394      if (fabs(dlamda)<   dlamax) break ;
395   }
396
397   //Double_t chi2 = (Double_t)(chiscl * lamda) ;
398  
399   //fTrack->SetChiSq1(chi2);
400   // Double_t dchisq = chiscl * dlamda ;             
401   //
402   //-->  NOW CALCULATE THE MATRIX ELEMENTS FOR ALPHA, BETA & KAPPA
403   //
404   Double_t h11   = xxav  -     lamda ;
405   Double_t h14   = xrrav ;
406   Double_t h22   = yyav  -     lamda ; 
407   Double_t h24   = yrrav ;
408   Double_t h34   = 1.0   + 2.0*lamda ;
409   if ( h11 == 0.0 || h22 == 0.0 ){
410     LOG(AliL3Log::kError,"AliL3Fitter::FitCircle","TrackFit")<<AliL3Log::kDec<<
411       "Problems fitting circle"<<ENDLOG;
412     return 1 ;
413   }
414   Double_t rootsq = (h14*h14)/(h11*h11) + 4.0*h34 ;
415
416   Double_t ratio, kappa, beta ;
417   if ( fabs(h22) > fabs(h24) ) {
418      ratio  = h24 / h22 ;
419      rootsq = ratio * ratio + rootsq ;
420      kappa = 1.0 / sqrt(rootsq) ;
421      beta  = - ratio * kappa ;
422   }
423   else {
424      ratio  = h22 / h24 ;
425      rootsq = 1.0 + ratio * ratio * rootsq ;
426      beta  = 1.0 / sqrt(rootsq) ;
427      if ( h24 > 0 ) beta = - beta ;
428      kappa = -ratio * beta ;
429   }            
430   Double_t alpha = - (h14/h11) * kappa ;
431 //
432 //-->  transform these into the lab coordinate system
433 //-->  first get kappa and back to real dimensions
434 //
435   Double_t kappa1 = kappa / rscale ;
436   Double_t dbro   = 0.5   / kappa1 ;
437 //
438 //-->  next rotate alpha and beta and scale
439 //
440   Double_t alphar = (cosrot * alpha - sinrot * beta)* dbro ;
441   Double_t betar  = (sinrot * alpha + cosrot * beta)* dbro ;
442 //
443 //-->  then translate by (xav,yav)
444 //
445   Double_t acent  = (double)(xav - alphar) ;
446   Double_t bcent  = (double)(yav - betar ) ;
447   Double_t radius = (double)dbro ;
448 //
449 //   Get charge
450 //
451   Int_t q = ( ( yrrav < 0 ) ? 1 : -1 ) ;
452
453   fTrack->SetCharge(q);
454   
455   //Set the first point on the track to the space point coordinates of the innermost track
456   //This will be updated to lie on the fit later on (AliL3Track::UpdateToFirstPoint).
457   Double_t x0,y0,psi,pt ;
458   Int_t lastid=fTrack->GetNHits()-1;
459   UInt_t id = hitnum[lastid];
460   Int_t slice = (id>>25) & 0x7f;
461   Int_t patch = (id>>22) & 0x7;
462   UInt_t pos = id&0x3fffff;
463   AliL3SpacePointData *points = fClusters[slice][patch];
464   x0   =  points[pos].fX;
465   y0   =  points[pos].fY;
466   fTrack->SetFirstPoint(x0,y0,0); //Z-value is set in FitLine
467   
468   //Set the remaining fit parameters
469   psi  = (Double_t)atan2(bcent-y0,acent-x0) ;
470   psi  = psi + q * 0.5F * AliL3Transform::Pi() ;
471   if ( psi < 0 ) psi = psi + 2*AliL3Transform::Pi();
472   
473   pt   = (Double_t)(AliL3Transform::GetBFact() * AliL3Transform::GetBField() * radius ) ;
474   fTrack->SetPsi(psi);
475   fTrack->SetPt(pt);
476   fTrack->SetRadius(radius);
477   fTrack->SetCenterX(acent);
478   fTrack->SetCenterY(bcent);
479   //
480 //    Get errors from fast fit
481 //
482   //if ( getPara()->getErrors ) getErrorsCircleFit ( acent, bcent, radius ) ;
483 //
484   delete [] fXYWeight;
485   return 0 ;
486   
487 }
488
489 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
490 //    Fit Line in s-z plane
491 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
492 Int_t AliL3Fitter::FitLine ( )
493 {
494   //
495   //Initialization 
496   //
497   Double_t sum = 0.F ;
498   Double_t ss  = 0.F ;
499   Double_t sz  = 0.F ;
500   Double_t sss = 0.F ;
501   Double_t ssz = 0.F ;
502   //
503   //find sum , sums ,sumz, sumss 
504   // 
505   Double_t dx, dy ;
506   Double_t radius = (Double_t)(fTrack->GetPt() / ( AliL3Transform::GetBFact() * AliL3Transform::GetBField() ) ) ;
507
508   //TObjArray *hits = fTrack->GetHits();
509   //Int_t num_of_hits = fTrack->GetNumberOfPoints();
510
511   //  Double_t fS[(fTrack->GetNHits())];
512   Double_t * fS = new Double_t[(fTrack->GetNHits())];
513   Double_t *fZWeight = new Double_t[fTrack->GetNHits()];
514   UInt_t *hitnum = fTrack->GetHitNumbers();
515   if (0)//fVertexConstraint==kTRUE)
516     {
517       UInt_t id = hitnum[0];
518       Int_t slice = (id>>25) & 0x7f;
519       Int_t patch = (id>>22) & 0x7;
520       UInt_t pos = id&0x3fffff;
521       AliL3SpacePointData *points = fClusters[slice][patch];
522       
523       dx = points[pos].fX - fVertex->GetX();
524       dy = points[pos].fY - fVertex->GetY();
525     }
526   else 
527     {
528       UInt_t id = hitnum[0];
529       Int_t slice = (id>>25) & 0x7f;
530       Int_t patch = (id>>22) & 0x7;
531       UInt_t posf = id&0x3fffff;
532       AliL3SpacePointData *pointsf = fClusters[slice][patch];
533       id = hitnum[(fTrack->GetNHits()-1)];
534       slice = (id>>25) & 0x7f;
535       patch = (id>>22) & 0x7;
536       UInt_t posl = id&0x3fffff;
537       AliL3SpacePointData *pointsl = fClusters[slice][patch];
538       dx = pointsf[posf].fX - pointsl[posl].fX;
539       dy = pointsf[posf].fY - pointsl[posl].fY;
540     }
541
542   Double_t localPsi = 0.5F * sqrt ( dx*dx + dy*dy ) / radius ;
543   Double_t total_s ;
544   
545   if ( fabs(localPsi) < 1. ) 
546     {
547       total_s = 2.0 * radius * asin ( localPsi ) ;
548     } 
549   else 
550     { 
551       total_s = 2.0 * radius * AliL3Transform::Pi() ;
552     } 
553   
554   Double_t dpsi,s;
555   
556   for(Int_t i=0; i<fTrack->GetNHits(); i++)
557     { 
558       UInt_t id = hitnum[i];
559       Int_t slice = (id>>25) & 0x7f;
560       Int_t patch = (id>>22) & 0x7;
561       UInt_t pos = id&0x3fffff;
562       AliL3SpacePointData *points = fClusters[slice][patch];
563       
564       fZWeight[i] = 1./(Double_t)(points[pos].fSigmaZ2);
565       if(i>0)
566         {
567           id = hitnum[i-1];
568           slice = (id>>25) & 0x7f;
569           patch = (id>>22) & 0x7;
570           UInt_t lastpos = id&0x3fffff;
571           AliL3SpacePointData *lastpoints = fClusters[slice][patch];
572           dx = points[pos].fX -lastpoints[lastpos].fX;
573           dy = points[pos].fY -lastpoints[lastpos].fY;
574           dpsi = 0.5 * (Double_t)sqrt ( dx*dx + dy*dy ) / radius ;
575           if(fabs(dpsi) > 1)
576             return 1;
577           fTrack->SetPsierr(dpsi);
578           s = fS[i-1] - 2.0 * radius * (Double_t)asin ( dpsi ) ;
579           fS[i]=s;
580         }
581       else
582         fS[i]=total_s;
583       
584       sum += fZWeight[i];
585       ss  += fZWeight[i] * fS[i];
586       sz  += fZWeight[i] * points[pos].fZ;
587       sss += fZWeight[i] * fS[i] * fS[i];
588       ssz += fZWeight[i] * fS[i] * points[pos].fZ;
589       
590     }
591   
592   
593   Double_t chi2,det = sum * sss - ss * ss;
594   if ( fabs(det) < 1e-20)
595     { 
596       chi2 = 99999.F ;
597       //fTrack->SetChiSq2(chi2);
598       return 0 ;
599     }
600   
601   //Compute the best fitted parameters A,B
602   Double_t tanl,z0,dtanl,dz0;
603
604   tanl = (Double_t)((sum * ssz - ss * sz ) / det );
605   z0   = (Double_t)((sz * sss - ssz * ss ) / det );
606
607   fTrack->SetTgl(tanl);
608   fTrack->SetZ0(z0);
609   
610   //     calculate chi-square 
611   
612   chi2 = 0.;
613   Double_t r1 ;
614   
615   for(Int_t i=0; i<fTrack->GetNHits(); i++)
616     { 
617       UInt_t id = hitnum[i];
618       Int_t slice = (id>>25) & 0x7f;
619       Int_t patch = (id>>22) & 0x7;
620       UInt_t pos = id&0x3fffff;
621       AliL3SpacePointData *points = fClusters[slice][patch];
622       r1   = points[pos].fZ - tanl * fS[i] - z0 ;
623       chi2 += (Double_t) ( (Double_t)(fZWeight[i]) * (r1 * r1) );
624     }
625   
626   //fTrack->SetChiSq2(chi2);
627   //
628   //     calculate estimated variance
629   //      varsq=chi/(double(n)-2.) 
630   //     calculate covariance matrix 
631   //      siga=sqrt(varsq*sxx/det) 
632   //      sigb=sqrt(varsq*sum/det) 
633   //
634   dtanl = (Double_t) ( sum / det );
635   dz0   = (Double_t) ( sss / det );
636   
637   fTrack->SetTglerr(dtanl);
638   fTrack->SetZ0err(dz0);
639   delete [] fZWeight;
640   delete [] fS;
641   return 0 ;
642