]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDseedV1.cxx
Updated tracking code by Alexandru und Markus
[u/mrichter/AliRoot.git] / TRD / AliTRDseedV1.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ////////////////////////////////////////////////////////////////////////////
19 //                                                                        //
20 //  The TRD track seed                                                    //
21 //                                                                        //
22 //  Authors:                                                              //
23 //    Alex Bercuci <A.Bercuci@gsi.de>                                     //
24 //    Markus Fasel <M.Fasel@gsi.de>                                       //
25 //                                                                        //
26 ////////////////////////////////////////////////////////////////////////////
27
28 #include "TMath.h"
29 #include "TLinearFitter.h"
30
31 #include "AliLog.h"
32 #include "AliMathBase.h"
33
34 #include "AliTRDseedV1.h"
35 #include "AliTRDcluster.h"
36 #include "AliTRDtrack.h"
37 #include "AliTRDcalibDB.h"
38 #include "AliTRDstackLayer.h"
39 #include "AliTRDrecoParam.h"
40
41 #define SEED_DEBUG
42
43 ClassImp(AliTRDseedV1)
44
45 //____________________________________________________________________
46 AliTRDseedV1::AliTRDseedV1(Int_t layer, AliTRDrecoParam *p) 
47   :AliTRDseed()
48   ,fPlane(layer)
49   ,fOwner(kFALSE)
50   ,fRecoParam(p)
51 {
52   //
53   // Constructor
54   //
55 }
56
57 //____________________________________________________________________
58 AliTRDseedV1::AliTRDseedV1(const AliTRDseedV1 &ref)
59   :AliTRDseed((AliTRDseed&)ref)
60   ,fPlane(ref.fPlane)
61   ,fOwner(kFALSE)
62   ,fRecoParam(ref.fRecoParam)
63 {
64   //
65   // Copy Constructor performing a deep copy
66   //
67
68         //AliInfo("");
69         if(ref.fOwner) SetOwner();
70 }
71
72
73 //____________________________________________________________________
74 AliTRDseedV1& AliTRDseedV1::operator=(const AliTRDseedV1 &ref)
75 {
76   //
77   // Assignment Operator using the copy function
78   //
79
80         //AliInfo("");
81         if(this != &ref){
82                 ref.Copy(*this);
83         }
84         return *this;
85
86 }
87
88 //____________________________________________________________________
89 AliTRDseedV1::~AliTRDseedV1()
90 {
91   //
92   // Destructor. The RecoParam object belongs to the underlying tracker.
93   //
94
95         //AliInfo(Form("fOwner[%s]", fOwner?"YES":"NO"));
96
97         if(fOwner) delete [] fClusters;
98 }
99
100 //____________________________________________________________________
101 void AliTRDseedV1::Copy(TObject &ref) const
102 {
103   //
104   // Copy function
105   //
106
107         //AliInfo("");
108         AliTRDseedV1 &target = (AliTRDseedV1 &)ref; 
109         
110         target.fPlane         = fPlane;
111         target.fRecoParam     = fRecoParam;
112         AliTRDseed::Copy(target);
113 }
114
115
116 //____________________________________________________________
117 void AliTRDseedV1::Init(AliTRDtrack *track)
118 {
119 // Initialize this tracklet using the track information
120 //
121 // Parameters:
122 //   track - the TRD track used to initialize the tracklet
123 // 
124 // Detailed description
125 // The function sets the starting point and direction of the
126 // tracklet according to the information from the TRD track.
127 // 
128 // Caution
129 // The TRD track has to be propagated to the beginning of the
130 // chamber where the tracklet will be constructed
131 //
132
133         Double_t y, z; 
134         track->GetProlongation(fX0, y, z);
135         fYref[0] = y;
136         fYref[1] = track->GetSnp() < 0. ? track->GetTgl() : -track->GetTgl();
137         fZref[0] = z;
138         // TO DO 
139         // tilting pad correction !!
140         fZref[1] = 0.; // TMath::Tan(track->Theta());
141
142         //printf("Tracklet ref x[%7.3f] y[%7.3f] z[%7.3f], snp[%f] tgl[%f]\n", fX0, fYref[0], fZref[0], track->GetSnp(), track->GetTgl());
143 }
144
145 //____________________________________________________________________
146 Float_t AliTRDseedV1::GetQuality(Bool_t kZcorr) const
147 {
148   //
149   // Returns a quality measurement of the current seed
150   //
151
152         Float_t zcorr = kZcorr ? fTilt * (fZProb - fZref[0]) : 0.;
153         return .5 * (18.0 - fN2)
154                 + 10.* TMath::Abs(fYfit[1] - fYref[1])
155                 + 5.* TMath::Abs(fYfit[0] - fYref[0] + zcorr)
156                 + 2. * TMath::Abs(fMeanz - fZref[0]) / fPadLength;
157 }
158
159 //____________________________________________________________________
160 void AliTRDseedV1::GetCovAt(Double_t /*x*/, Double_t *cov) const
161 {
162 // Computes covariance in the y-z plane at radial point x
163
164         const Float_t k0= .2; // to be checked in FindClusters
165         Double_t sy20   = k0*TMath::Tan(fYfit[1]); sy20 *= sy20;
166         
167         Double_t sy2    = fSigmaY2*fSigmaY2 + sy20;
168         Double_t sz2    = fPadLength/12.;
169
170         //printf("Yfit[1] %f sy20 %f SigmaY2 %f\n", fYfit[1], sy20, fSigmaY2);
171
172         cov[0] = sy2;
173         cov[1] = fTilt*(sy2-sz2);
174         cov[2] = sz2;
175 }
176
177 //____________________________________________________________________
178 void AliTRDseedV1::SetOwner(Bool_t own)
179 {
180   //
181   // Handles the ownership of the clusters
182   //
183         if(own){
184                 for(int ic=0; ic<fgTimeBins; ic++){
185                         if(!fClusters[ic]) continue;
186                         fClusters[ic] = new AliTRDcluster(*fClusters[ic]);
187                 }
188                 fOwner = kTRUE;
189         } else {
190                 if(fOwner){
191                         for(int ic=0; ic<fgTimeBins; ic++){
192                                 if(!fClusters[ic]) continue;
193                                 delete fClusters[ic];
194                         }
195                 }
196                 fOwner = kFALSE;
197         }
198 }
199
200 //____________________________________________________________________
201 Bool_t  AliTRDseedV1::AttachClustersIter(AliTRDstackLayer *layer
202                                        , Float_t quality
203                                        , Bool_t kZcorr
204                                        , AliTRDcluster *c)
205 {
206   //
207   // Iterative process to register clusters to the seed.
208   // In iteration 0 we try only one pad-row and if quality not
209   // sufficient we try 2 pad-rows (about 5% of tracks cross 2 pad-rows)
210   //
211         
212         if(!fRecoParam){
213                 AliError("Seed can not be used without a valid RecoParam.");
214                 return kFALSE;
215         }
216
217         //AliInfo(Form("TimeBins = %d TimeBinsRange = %d", fgTimeBins, fTimeBinsRange));
218
219         Float_t  tquality;
220         Double_t kroady = fRecoParam->GetRoad1y();
221         Double_t kroadz = fPadLength * .5 + 1.;
222         
223         // initialize configuration parameters
224         Float_t zcorr = kZcorr ? fTilt * (fZProb - fZref[0]) : 0.;
225         Int_t   niter = kZcorr ? 1 : 2;
226         
227         Double_t yexp, zexp;
228         Int_t ncl = 0;
229         // start seed update
230         for (Int_t iter = 0; iter < niter; iter++) {
231         //AliInfo(Form("iter = %i", iter));
232                 ncl = 0;
233                 for (Int_t iTime = 0; iTime < fgTimeBins; iTime++) {
234                         // define searching configuration
235                         Double_t dxlayer = layer[iTime].GetX() - fX0;
236                         if(c){
237                                 zexp = c->GetZ();
238                                 //Try 2 pad-rows in second iteration
239                                 if (iter > 0) {
240                                         zexp = fZref[0] + fZref[1] * dxlayer - zcorr;
241                                         if (zexp > c->GetZ()) zexp = c->GetZ() + fPadLength*0.5;
242                                         if (zexp < c->GetZ()) zexp = c->GetZ() - fPadLength*0.5;
243                                 }
244                         } else zexp = fZref[0];
245                         yexp  = fYref[0] + fYref[1] * dxlayer - zcorr;
246                         // get  cluster
247 //                      printf("xexp = %3.3f ,yexp = %3.3f, zexp = %3.3f\n",layer[iTime].GetX(),yexp,zexp);
248 //                      printf("layer[%i].GetNClusters() = %i\n", iTime, layer[iTime].GetNClusters());
249                         Int_t    index = layer[iTime].SearchNearestCluster(yexp, zexp, kroady, kroadz);
250
251 //                      printf("%d[%d] x[%7.3f | %7.3f] y[%7.3f] z[%7.3f]\n", iTime, layer[iTime].GetNClusters(), dxlayer, layer[iTime].GetX(), yexp, zexp);
252 //                      for(Int_t iclk = 0; iclk < layer[iTime].GetNClusters(); iclk++){
253 //                              AliTRDcluster *testcl = layer[iTime].GetCluster(iclk);
254 //                              printf("Cluster %i: %d x = %7.3f, y = %7.3f, z = %7.3f\n", iclk, testcl->GetLocalTimeBin(), testcl->GetX(), testcl->GetY(), testcl->GetZ());
255 //                      }
256 //                      printf("Index = %i\n",index);
257
258                         if (index < 0) continue;
259                         
260                         // Register cluster
261                         AliTRDcluster *cl = (AliTRDcluster*) layer[iTime].GetCluster(index);
262                         
263                         //printf("Cluster %i(0x%x): x = %3.3f, y = %3.3f, z = %3.3f\n", index, cl, cl->GetX(), cl->GetY(), cl->GetZ());
264
265                         Int_t globalIndex = layer[iTime].GetGlobalIndex(index);
266                         fIndexes[iTime]  = globalIndex;
267                         fClusters[iTime] = cl;
268                         fX[iTime]        = dxlayer;
269                         fY[iTime]        = cl->GetY();
270                         fZ[iTime]        = cl->GetZ();
271         
272                         // Debugging
273                         ncl++;
274                 }
275
276 #ifdef SEED_DEBUG
277 //              Int_t nclusters = 0;
278 //              Float_t fD[iter] = 0.;
279 //              for(int ic=0; ic<fgTimeBins+1; ic++){
280 //                      AliTRDcluster *ci = fClusters[ic];
281 //                      if(!ci) continue;
282 //                      for(int jc=ic+1; jc<fgTimeBins+1; jc++){
283 //                              AliTRDcluster *cj = fClusters[jc];
284 //                              if(!cj) continue;
285 //                              fD[iter] += TMath::Sqrt((ci->GetY()-cj->GetY())*(ci->GetY()-cj->GetY())+
286 //                              (ci->GetZ()-cj->GetZ())*(ci->GetZ()-cj->GetZ()));
287 //                              nclusters++;
288 //                      }
289 //              }
290 //              if(nclusters) fD[iter] /= float(nclusters);
291 #endif
292
293                 AliTRDseed::Update();
294
295                 if(IsOK()){
296                         tquality = GetQuality(kZcorr);
297                         if(tquality < quality) break;
298                         else quality = tquality;
299                 }
300                 kroadz *= 2.;
301         } // Loop: iter
302         if (!IsOK()) return kFALSE;
303
304         CookLabels();
305         UpdateUsed();
306         return kTRUE;   
307 }
308
309 //____________________________________________________________________
310 Bool_t  AliTRDseedV1::AttachClusters(AliTRDstackLayer *layer
311                                        ,Bool_t kZcorr)
312 {
313   //
314   // Projective algorithm to attach clusters to seeding tracklets
315   //
316   // Parameters
317   //
318   // Output
319   //
320   // Detailed description
321   // 1. Collapse x coordinate for the full detector plane
322   // 2. truncated mean on y (r-phi) direction
323   // 3. purge clusters
324   // 4. truncated mean on z direction
325   // 5. purge clusters
326   // 6. fit tracklet
327   //    
328
329         if(!fRecoParam){
330                 AliError("Seed can not be used without a valid RecoParam.");
331                 return kFALSE;
332         }
333
334         const Int_t kClusterCandidates = 2 * knTimebins;
335         
336         //define roads
337         Double_t kroady = fRecoParam->GetRoad1y();
338         Double_t kroadz = fPadLength * 1.5 + 1.;
339         // correction to y for the tilting angle
340         Float_t zcorr = kZcorr ? fTilt * (fZProb - fZref[0]) : 0.;
341
342         // working variables
343         AliTRDcluster *clusters[kClusterCandidates];
344         Double_t cond[4], yexp[knTimebins], zexp[knTimebins],
345                 yres[kClusterCandidates], zres[kClusterCandidates];
346         Int_t ncl, *index = 0x0, tboundary[knTimebins];
347         
348         // Do cluster projection
349         Int_t nYclusters = 0; Bool_t kEXIT = kFALSE;
350         for (Int_t iTime = 0; iTime < fgTimeBins; iTime++) {
351                 fX[iTime] = layer[iTime].GetX() - fX0;
352                 zexp[iTime] = fZref[0] + fZref[1] * fX[iTime];
353                 yexp[iTime] = fYref[0] + fYref[1] * fX[iTime] - zcorr;
354                 
355                 // build condition and process clusters
356                 cond[0] = yexp[iTime] - kroady; cond[1] = yexp[iTime] + kroady;
357                 cond[2] = zexp[iTime] - kroadz; cond[3] = zexp[iTime] + kroadz;
358                 layer[iTime].GetClusters(cond, index, ncl);
359                 for(Int_t ic = 0; ic<ncl; ic++){
360                         AliTRDcluster *c = layer[iTime].GetCluster(index[ic]);
361                         clusters[nYclusters] = c;
362                         yres[nYclusters++] = c->GetY() - yexp[iTime];
363                         if(nYclusters >= kClusterCandidates) {
364                                 AliWarning(Form("Cluster candidates reached limit %d. Some may be lost.", kClusterCandidates));
365                                 kEXIT = kTRUE;
366                                 break;
367                         }
368                 }
369                 tboundary[iTime] = nYclusters;
370                 if(kEXIT) break;
371         }
372         
373         // Evaluate truncated mean on the y direction
374         Double_t mean, sigma;
375         AliMathBase::EvaluateUni(nYclusters, yres, mean, sigma, Int_t(nYclusters*.8)-2);
376         //purge cluster candidates
377         Int_t nZclusters = 0;
378         for(Int_t ic = 0; ic<nYclusters; ic++){
379                 if(yres[ic] - mean > 4. * sigma){
380                         clusters[ic] = 0x0;
381                         continue;
382                 }
383                 zres[nZclusters++] = clusters[ic]->GetZ() - zexp[clusters[ic]->GetLocalTimeBin()];
384         }
385         
386         // Evaluate truncated mean on the z direction
387         AliMathBase::EvaluateUni(nZclusters, zres, mean, sigma, Int_t(nZclusters*.8)-2);
388         //purge cluster candidates
389         for(Int_t ic = 0; ic<nZclusters; ic++){
390                 if(zres[ic] - mean > 4. * sigma){
391                         clusters[ic] = 0x0;
392                         continue;
393                 }
394         }
395
396         
397         // Select only one cluster/TimeBin
398         Int_t lastCluster = 0;
399         fN2 = 0;
400         for (Int_t iTime = 0; iTime < fgTimeBins; iTime++) {
401                 ncl = tboundary[iTime] - lastCluster;
402                 if(!ncl) continue;
403                 AliTRDcluster *c = 0x0;
404                 if(ncl == 1){
405                         c = clusters[lastCluster];
406                 } else if(ncl > 1){
407                         Float_t dold = 9999.; Int_t iptr = lastCluster;
408                         for(int ic=lastCluster; ic<tboundary[iTime]; ic++){
409                                 if(!clusters[ic]) continue;
410                                 Float_t y = yexp[iTime] - clusters[ic]->GetY();
411                                 Float_t z = zexp[iTime] - clusters[ic]->GetZ();
412                                 Float_t d = y * y + z * z;
413                                 if(d > dold) continue;
414                                 dold = d;
415                                 iptr = ic;
416                         }
417                         c = clusters[iptr];
418                 }
419                 //Int_t GlobalIndex = layer[iTime].GetGlobalIndex(index);
420                 //fIndexes[iTime]  = GlobalIndex;
421                 fClusters[iTime] = c;
422                 fY[iTime]        = c->GetY();
423                 fZ[iTime]        = c->GetZ();
424                 lastCluster = tboundary[iTime];
425                 fN2++;
426         }
427         
428         // number of minimum numbers of clusters expected for the tracklet
429         Int_t kClmin = Int_t(fRecoParam->GetFindableClusters()*fgTimeBins);
430   if (fN2 < kClmin){
431                 AliWarning(Form("Not enough clusters to fit the tracklet %d [%d].", fN2, kClmin));
432     fN2 = 0;
433     return kFALSE;
434   }
435
436         // update used clusters
437         fNUsed = 0;
438         for (Int_t iTime = 0; iTime < fgTimeBins; iTime++) {
439                 if(!fClusters[iTime]) continue;
440                 if((fClusters[iTime]->IsUsed())) fNUsed++;
441         }
442
443   if (fN2-fNUsed < kClmin){
444                 AliWarning(Form("Too many clusters already in use %d (from %d).", fNUsed, fN2));
445     fN2 = 0;
446     return kFALSE;
447   }
448         
449         return kTRUE;
450 }
451
452 //____________________________________________________________________
453 Bool_t AliTRDseedV1::Fit()
454 {
455   //
456   // Linear fit of the tracklet
457   //
458   // Parameters :
459   //
460   // Output :
461   //  True if successful
462   //
463   // Detailed description
464   // 2. Check if tracklet crosses pad row boundary
465   // 1. Calculate residuals in the y (r-phi) direction
466   // 3. Do a Least Square Fit to the data
467   //
468
469         //Float_t  sigmaexp  = 0.05 + TMath::Abs(fYref[1] * 0.25); // Expected r.m.s in y direction
470   Float_t  ycrosscor = fPadLength * fTilt * 0.5; // Y correction for crossing
471   Float_t  anglecor = fTilt * fZref[1];  // Correction to the angle
472
473         // calculate residuals
474         Float_t yres[knTimebins]; // y (r-phi) residuals
475         Int_t zint[knTimebins],   // Histograming of the z coordinate
476               zout[2*knTimebins];//
477         
478         fN = 0;
479         for (Int_t iTime = 0; iTime < fTimeBinsRange; iTime++) {
480     if (!fClusters[iTime]) continue;
481     yres[iTime] = fY[iTime] - fYref[0] - (fYref[1] + anglecor) * fX[iTime];
482                 zint[fN] = Int_t(fZ[iTime]);
483                 fN++;
484         }
485
486         // calculate pad row boundary crosses
487         Int_t kClmin = Int_t(fRecoParam->GetFindableClusters()*fTimeBinsRange);
488         Int_t nz = AliMathBase::Freq(fN, zint, zout, kFALSE);
489   fZProb   = zout[0];
490   if(nz <= 1) zout[3] = 0;
491   if(zout[1] + zout[3] < kClmin) {
492                 AliWarning(Form("Not enough clusters to fit the cross boundary tracklet %d [%d].", zout[1]+zout[3], kClmin));
493                 return kFALSE;
494         }
495   // Z distance bigger than pad - length
496   if (TMath::Abs(zout[0]-zout[2]) > fPadLength) zout[3]=0;
497  
498
499   Double_t sumw   = 0., 
500                 sumwx  = 0.,
501                 sumwx2 = 0.,
502                 sumwy  = 0.,
503                 sumwxy = 0.,
504                 sumwz  = 0.,
505                 sumwxz = 0.;
506         Int_t npads;
507   fMPads = 0;
508         fMeanz = 0.;
509         // we will use only the clusters which are in the detector range
510         for(int iTime=0; iTime<fTimeBinsRange; iTime++){
511     fUsable[iTime] = kFALSE;
512     if (!fClusters[iTime]) continue;
513                 npads = fClusters[iTime]->GetNPads();
514
515                 fUsable[iTime] = kTRUE;
516     fN2++;
517     fMPads += npads;
518     Float_t weight = 1.0;
519     if(npads > 5) weight = 0.2;
520     else if(npads > 4) weight = 0.5;
521     sumw   += weight; 
522     sumwx  += fX[iTime] * weight;
523     sumwx2 += fX[iTime] * fX[iTime] * weight;
524     sumwy  += weight * yres[iTime];
525     sumwxy += weight * yres[iTime] * fX[iTime];
526     sumwz  += weight * fZ[iTime];    
527     sumwxz += weight * fZ[iTime] * fX[iTime];
528         }
529   if (fN2 < kClmin){
530                 AliWarning(Form("Not enough clusters to fit the tracklet %d [%d].", fN2, kClmin));
531     fN2 = 0;
532     return kFALSE;
533   }
534   fMeanz = sumwz / sumw;
535         fNChange = 0;
536
537         // Tracklet on boundary
538   Float_t correction = 0;
539   if (fNChange > 0) {
540     if (fMeanz < fZProb) correction =  ycrosscor;
541     if (fMeanz > fZProb) correction = -ycrosscor;
542   }
543
544   Double_t det = sumw * sumwx2 - sumwx * sumwx;
545   fYfitR[0]    = (sumwx2 * sumwy  - sumwx * sumwxy) / det;
546   fYfitR[1]    = (sumw   * sumwxy - sumwx * sumwy)  / det;
547   
548   fSigmaY2 = 0;
549   for (Int_t i = 0; i < fTimeBinsRange+1; i++) {
550     if (!fUsable[i]) continue;
551     Float_t delta = yres[i] - fYfitR[0] - fYfitR[1] * fX[i];
552     fSigmaY2 += delta*delta;
553   }
554   fSigmaY2 = TMath::Sqrt(fSigmaY2 / Float_t(fN2-2));
555   
556   fZfitR[0]  = (sumwx2 * sumwz  - sumwx * sumwxz) / det;
557   fZfitR[1]  = (sumw   * sumwxz - sumwx * sumwz)  / det;
558   fZfit[0]   = (sumwx2 * sumwz  - sumwx * sumwxz) / det;
559   fZfit[1]   = (sumw   * sumwxz - sumwx * sumwz)  / det;
560   fYfitR[0] += fYref[0] + correction;
561   fYfitR[1] += fYref[1];
562   fYfit[0]   = fYfitR[0];
563   fYfit[1]   = fYfitR[1];
564
565         return kTRUE;
566 }
567
568 //_____________________________________________________________________________
569 Float_t AliTRDseedV1::FitRiemanTilt(AliTRDseedV1 *cseed, Bool_t terror)
570 {
571   //
572   // Fit the Rieman tilt
573   //
574
575   // Fitting with tilting pads - kz not fixed
576         AliTRDcalibDB *cal = AliTRDcalibDB::Instance();
577         Int_t nTimeBins = cal->GetNumberOfTimeBins();
578   TLinearFitter fitterT2(4,"hyp4");  
579   fitterT2.StoreData(kTRUE);
580   Float_t xref2 = (cseed[2].fX0 + cseed[3].fX0) * 0.5; // Reference x0 for z
581   
582   Int_t npointsT = 0;
583   fitterT2.ClearPoints();
584
585   for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
586 //              printf("\nLayer %d\n", iLayer);
587 //     cseed[iLayer].Print();
588                 if (!cseed[iLayer].IsOK()) continue;
589     Double_t tilt = cseed[iLayer].fTilt;
590
591     for (Int_t itime = 0; itime < nTimeBins+1; itime++) {
592 //                      printf("\ttime %d\n", itime);
593       if (!cseed[iLayer].fUsable[itime]) continue;
594       // x relative to the midle chamber
595       Double_t x = cseed[iLayer].fX[itime] + cseed[iLayer].fX0 - xref2;  
596       Double_t y = cseed[iLayer].fY[itime];
597       Double_t z = cseed[iLayer].fZ[itime];
598
599       //
600       // Tilted rieman
601       //
602       Double_t uvt[6];
603       Double_t x2 = cseed[iLayer].fX[itime] + cseed[iLayer].fX0;      // Global x
604       Double_t t  = 1.0 / (x2*x2 + y*y);
605       uvt[1]  = t;
606       uvt[0]  = 2.0 * x2   * uvt[1];
607       uvt[2]  = 2.0 * tilt * uvt[1];
608       uvt[3]  = 2.0 * tilt *uvt[1] * x;       
609       uvt[4]  = 2.0 * (y + tilt * z) * uvt[1];
610       
611       Double_t error = 2.0 * uvt[1];
612       if (terror) {
613         error *= cseed[iLayer].fSigmaY;
614       }
615       else {
616         error *= 0.2; //Default error
617       }
618 //                      printf("\tadd point :\n");
619 //                      for(int i=0; i<5; i++) printf("%f ", uvt[i]);
620 //                      printf("\n");
621       fitterT2.AddPoint(uvt,uvt[4],error);
622       npointsT++;
623
624     }
625
626   }
627   fitterT2.Eval();
628   Double_t rpolz0 = fitterT2.GetParameter(3);
629   Double_t rpolz1 = fitterT2.GetParameter(4);       
630
631   //
632   // Linear fitter  - not possible to make boundaries
633   // non accept non possible z and dzdx combination
634   //        
635   Bool_t acceptablez = kTRUE;
636   for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
637     if (cseed[iLayer].IsOK()) {
638       Double_t zT2 = rpolz0 + rpolz1 * (cseed[iLayer].fX0 - xref2);
639       if (TMath::Abs(cseed[iLayer].fZProb - zT2) > cseed[iLayer].fPadLength * 0.5 + 1.0) {
640         acceptablez = kFALSE;
641       }
642     }
643   }
644   if (!acceptablez) {
645     Double_t zmf  = cseed[2].fZref[0] + cseed[2].fZref[1] * (xref2 - cseed[2].fX0);
646     Double_t dzmf = (cseed[2].fZref[1] + cseed[3].fZref[1]) * 0.5;
647     fitterT2.FixParameter(3,zmf);
648     fitterT2.FixParameter(4,dzmf);
649     fitterT2.Eval();
650     fitterT2.ReleaseParameter(3);
651     fitterT2.ReleaseParameter(4);
652     rpolz0 = fitterT2.GetParameter(3);
653     rpolz1 = fitterT2.GetParameter(4);
654   }
655   
656   Double_t chi2TR = fitterT2.GetChisquare() / Float_t(npointsT);  
657   Double_t params[3];
658   params[0] =  fitterT2.GetParameter(0);
659   params[1] =  fitterT2.GetParameter(1);
660   params[2] =  fitterT2.GetParameter(2);            
661   Double_t curvature =  1.0 + params[1] * params[1] - params[2] * params[0];
662
663   for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
664
665     Double_t  x  = cseed[iLayer].fX0;
666     Double_t  y  = 0;
667     Double_t  dy = 0;
668     Double_t  z  = 0;
669     Double_t  dz = 0;
670
671     // y
672     Double_t res2 = (x * params[0] + params[1]);
673     res2 *= res2;
674     res2  = 1.0 - params[2]*params[0] + params[1]*params[1] - res2;
675     if (res2 >= 0) {
676       res2 = TMath::Sqrt(res2);
677       y    = (1.0 - res2) / params[0];
678     }
679
680     //dy
681     Double_t x0 = -params[1] / params[0];
682     if (-params[2]*params[0] + params[1]*params[1] + 1 > 0) {
683       Double_t rm1 = params[0] / TMath::Sqrt(-params[2]*params[0] + params[1]*params[1] + 1); 
684       if (1.0/(rm1*rm1) - (x-x0) * (x-x0) > 0.0) {
685         Double_t res = (x - x0) / TMath::Sqrt(1.0 / (rm1*rm1) - (x-x0)*(x-x0));
686         if (params[0] < 0) res *= -1.0;
687         dy = res;
688       }
689     }
690     z  = rpolz0 + rpolz1 * (x - xref2);
691     dz = rpolz1;
692     cseed[iLayer].fYref[0] = y;
693     cseed[iLayer].fYref[1] = dy;
694     cseed[iLayer].fZref[0] = z;
695     cseed[iLayer].fZref[1] = dz;
696     cseed[iLayer].fC       = curvature;
697     
698   }
699
700   return chi2TR;
701
702 }
703
704 //___________________________________________________________________
705 void AliTRDseedV1::Print()
706 {
707   //
708   // Printing the seedstatus
709   //
710
711         AliTRDcalibDB *cal = AliTRDcalibDB::Instance();
712         Int_t nTimeBins = cal->GetNumberOfTimeBins();
713         
714         printf("Seed status :\n");
715         printf("  fTilt      = %f\n", fTilt);
716         printf("  fPadLength = %f\n", fPadLength);
717         printf("  fX0        = %f\n", fX0);
718         for(int ic=0; ic<nTimeBins; ic++) {
719           const Char_t *isUsable = fUsable[ic]?"Yes":"No";
720           printf("  %d X[%f] Y[%f] Z[%f] Indexes[%d] clusters[%p] usable[%s]\n"
721                 , ic
722                 , fX[ic]
723                 , fY[ic]
724                 , fZ[ic]
725                 , fIndexes[ic]
726                 , ((void*) fClusters[ic])
727                 , isUsable);
728         }
729
730         printf("  fYref[0] =%f fYref[1] =%f\n", fYref[0], fYref[1]);
731         printf("  fZref[0] =%f fZref[1] =%f\n", fZref[0], fZref[1]);
732         printf("  fYfit[0] =%f fYfit[1] =%f\n", fYfit[0], fYfit[1]);
733         printf("  fYfitR[0]=%f fYfitR[1]=%f\n", fYfitR[0], fYfitR[1]);
734         printf("  fZfit[0] =%f fZfit[1] =%f\n", fZfit[0], fZfit[1]);
735         printf("  fZfitR[0]=%f fZfitR[1]=%f\n", fZfitR[0], fZfitR[1]);
736         printf("  fSigmaY =%f\n", fSigmaY);
737         printf("  fSigmaY2=%f\n", fSigmaY2);            
738         printf("  fMeanz  =%f\n", fMeanz);
739         printf("  fZProb  =%f\n", fZProb);
740         printf("  fLabels[0]=%d fLabels[1]=%d\n", fLabels[0], fLabels[1]);
741         printf("  fN      =%d\n", fN);
742         printf("  fN2     =%d (>8 isOK)\n",fN2);
743         printf("  fNUsed  =%d\n", fNUsed);
744         printf("  fFreq   =%d\n", fFreq);
745         printf("  fNChange=%d\n",  fNChange);
746         printf("  fMPads  =%f\n", fMPads);
747         
748         printf("  fC      =%f\n", fC);        
749         printf("  fCC     =%f\n",fCC);      
750         printf("  fChi2   =%f\n", fChi2);  
751         printf("  fChi2Z  =%f\n", fChi2Z);
752
753 }