]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDtrackerV1.cxx
update TRDin status flag for the ESD track (Markus)
[u/mrichter/AliRoot.git] / TRD / AliTRDtrackerV1.cxx
1
2 /**************************************************************************
3 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 *                                                                        *
5 * Author: The ALICE Off-line Project.                                    *
6 * Contributors are mentioned in the code where appropriate.              *
7 *                                                                        *
8 * Permission to use, copy, modify and distribute this software and its   *
9 * documentation strictly for non-commercial purposes is hereby granted   *
10 * without fee, provided that the above copyright notice appears in all   *
11 * copies and that both the copyright notice and this permission notice   *
12 * appear in the supporting documentation. The authors make no claims     *
13 * about the suitability of this software for any purpose. It is          *
14 * provided "as is" without express or implied warranty.                  *
15 **************************************************************************/
16
17 /* $Id$ */
18
19 ///////////////////////////////////////////////////////////////////////////////
20 //                                                                           //
21 //  Track finder                                                             //
22 //                                                                           //
23 //  Authors:                                                                 //
24 //    Alex Bercuci <A.Bercuci@gsi.de>                                        //
25 //    Markus Fasel <M.Fasel@gsi.de>                                          //
26 //                                                                           //
27 ///////////////////////////////////////////////////////////////////////////////
28
29 // #include <Riostream.h>
30 // #include <stdio.h>
31 // #include <string.h>
32
33 #include <TBranch.h>
34 #include <TDirectory.h>
35 #include <TLinearFitter.h>
36 #include <TTree.h>  
37 #include <TClonesArray.h>
38 #include <TTreeStream.h>
39
40 #include "AliLog.h"
41 #include "AliESDEvent.h"
42 #include "AliGeomManager.h"
43 #include "AliRieman.h"
44 #include "AliTrackPointArray.h"
45
46 #include "AliTRDgeometry.h"
47 #include "AliTRDpadPlane.h"
48 #include "AliTRDcalibDB.h"
49 #include "AliTRDReconstructor.h"
50 #include "AliTRDCalibraFillHisto.h"
51 #include "AliTRDrecoParam.h"
52
53 #include "AliTRDcluster.h" 
54 #include "AliTRDseedV1.h"
55 #include "AliTRDtrackV1.h"
56 #include "AliTRDtrackerV1.h"
57 #include "AliTRDtrackerDebug.h"
58 #include "AliTRDtrackingChamber.h"
59 #include "AliTRDchamberTimeBin.h"
60
61
62
63 ClassImp(AliTRDtrackerV1)
64
65
66 const  Float_t  AliTRDtrackerV1::fgkMinClustersInTrack =  0.5;  //
67 const  Float_t  AliTRDtrackerV1::fgkLabelFraction      =  0.8;  //
68 const  Double_t AliTRDtrackerV1::fgkMaxChi2            = 12.0;  //
69 const  Double_t AliTRDtrackerV1::fgkMaxSnp             =  0.95; // Maximum local sine of the azimuthal angle
70 const  Double_t AliTRDtrackerV1::fgkMaxStep            =  2.0;  // Maximal step size in propagation 
71 Double_t AliTRDtrackerV1::fgTopologicQA[kNConfigs] = {
72   0.1112, 0.1112, 0.1112, 0.0786, 0.0786,
73   0.0786, 0.0786, 0.0579, 0.0579, 0.0474,
74   0.0474, 0.0408, 0.0335, 0.0335, 0.0335
75 };
76 Int_t AliTRDtrackerV1::fgNTimeBins = 0;
77 TTreeSRedirector *AliTRDtrackerV1::fgDebugStreamer = 0x0;
78 AliRieman* AliTRDtrackerV1::fgRieman = 0x0;
79 TLinearFitter* AliTRDtrackerV1::fgTiltedRieman = 0x0;
80 TLinearFitter* AliTRDtrackerV1::fgTiltedRiemanConstrained = 0x0;
81
82 //____________________________________________________________________
83 AliTRDtrackerV1::AliTRDtrackerV1(AliTRDReconstructor *rec) 
84   :AliTracker()
85   ,fReconstructor(0x0)
86   ,fGeom(new AliTRDgeometry())
87   ,fClusters(0x0)
88   ,fTracklets(0x0)
89   ,fTracks(0x0)
90   ,fSieveSeeding(0)
91 {
92   //
93   // Default constructor.
94   // 
95   AliTRDcalibDB *trd = 0x0;
96   if (!(trd = AliTRDcalibDB::Instance())) {
97     AliFatal("Could not get calibration object");
98   }
99
100   if(!fgNTimeBins) fgNTimeBins = trd->GetNumberOfTimeBins();
101
102   for (Int_t isector = 0; isector < AliTRDgeometry::kNsector; isector++) new(&fTrSec[isector]) AliTRDtrackingSector(fGeom, isector);
103   
104   for(Int_t isl =0; isl<kNSeedPlanes; isl++) fSeedTB[isl] = 0x0;
105
106   // Initialize debug stream
107   if(rec) SetReconstructor(rec);
108 }
109
110 //____________________________________________________________________
111 AliTRDtrackerV1::~AliTRDtrackerV1()
112
113   //
114   // Destructor
115   //
116   
117   if(fgDebugStreamer) delete fgDebugStreamer;
118   if(fgRieman) delete fgRieman;
119   if(fgTiltedRieman) delete fgTiltedRieman;
120   if(fgTiltedRiemanConstrained) delete fgTiltedRiemanConstrained;
121   for(Int_t isl =0; isl<kNSeedPlanes; isl++) if(fSeedTB[isl]) delete fSeedTB[isl];
122   if(fTracks) {fTracks->Delete(); delete fTracks;}
123   if(fTracklets) {fTracklets->Delete(); delete fTracklets;}
124   if(fClusters) {fClusters->Delete(); delete fClusters;}
125   if(fGeom) delete fGeom;
126 }
127
128 //____________________________________________________________________
129 Int_t AliTRDtrackerV1::Clusters2Tracks(AliESDEvent *esd)
130 {
131   //
132   // Steering stand alone tracking for full TRD detector
133   //
134   // Parameters :
135   //   esd     : The ESD event. On output it contains 
136   //             the ESD tracks found in TRD.
137   //
138   // Output :
139   //   Number of tracks found in the TRD detector.
140   // 
141   // Detailed description
142   // 1. Launch individual SM trackers. 
143   //    See AliTRDtrackerV1::Clusters2TracksSM() for details.
144   //
145
146   if(!fReconstructor->GetRecoParam() ){
147     AliError("Reconstruction configuration not initialized. Call first AliTRDReconstructor::SetRecoParam().");
148     return 0;
149   }
150   
151   //AliInfo("Start Track Finder ...");
152   Int_t ntracks = 0;
153   for(int ism=0; ism<AliTRDgeometry::kNsector; ism++){
154     //  for(int ism=1; ism<2; ism++){
155     //AliInfo(Form("Processing supermodule %i ...", ism));
156     ntracks += Clusters2TracksSM(ism, esd);
157   }
158   AliInfo(Form("Number of found tracks : %d", ntracks));
159   return ntracks;
160 }
161
162
163 //_____________________________________________________________________________
164 Bool_t AliTRDtrackerV1::GetTrackPoint(Int_t index, AliTrackPoint &p) const
165 {
166   //AliInfo(Form("Asking for tracklet %d", index));
167   
168   AliTRDseedV1 *tracklet = GetTracklet(index); 
169   if (!tracklet) return kFALSE;
170   
171   // get detector for this tracklet
172   AliTRDcluster *cl = 0x0;
173   Int_t ic = 0; do; while(!(cl = tracklet->GetClusters(ic++)));  
174   Int_t  idet     = cl->GetDetector();
175     
176   Double_t local[3];
177   local[0] = tracklet->GetX0(); 
178   local[1] = tracklet->GetYfit(0);
179   local[2] = tracklet->GetZfit(0);
180   Double_t global[3];
181   fGeom->RotateBack(idet, local, global);
182   p.SetXYZ(global[0],global[1],global[2]);
183   
184   
185   // setting volume id
186   AliGeomManager::ELayerID iLayer = AliGeomManager::kTRD1;
187   switch (fGeom->GetLayer(idet)) {
188   case 0:
189     iLayer = AliGeomManager::kTRD1;
190     break;
191   case 1:
192     iLayer = AliGeomManager::kTRD2;
193     break;
194   case 2:
195     iLayer = AliGeomManager::kTRD3;
196     break;
197   case 3:
198     iLayer = AliGeomManager::kTRD4;
199     break;
200   case 4:
201     iLayer = AliGeomManager::kTRD5;
202     break;
203   case 5:
204     iLayer = AliGeomManager::kTRD6;
205     break;
206   };
207   Int_t    modId = fGeom->GetSector(idet) * fGeom->Nstack() + fGeom->GetStack(idet);
208   UShort_t volid = AliGeomManager::LayerToVolUID(iLayer, modId);
209   p.SetVolumeID(volid);
210     
211   return kTRUE;
212 }
213
214 //____________________________________________________________________
215 TLinearFitter* AliTRDtrackerV1::GetTiltedRiemanFitter()
216 {
217   if(!fgTiltedRieman) fgTiltedRieman = new TLinearFitter(4, "hyp4");
218   return fgTiltedRieman;
219 }
220
221 //____________________________________________________________________
222 TLinearFitter* AliTRDtrackerV1::GetTiltedRiemanFitterConstraint()
223 {
224   if(!fgTiltedRiemanConstrained) fgTiltedRiemanConstrained = new TLinearFitter(2, "hyp2");
225   return fgTiltedRiemanConstrained;
226 }
227   
228 //____________________________________________________________________  
229 AliRieman* AliTRDtrackerV1::GetRiemanFitter()
230 {
231   if(!fgRieman) fgRieman = new AliRieman(AliTRDtrackingChamber::kNTimeBins * AliTRDgeometry::kNlayer);
232   return fgRieman;
233 }
234   
235 //_____________________________________________________________________________
236 Int_t AliTRDtrackerV1::PropagateBack(AliESDEvent *event) 
237 {
238   //
239   // Gets seeds from ESD event. The seeds are AliTPCtrack's found and
240   // backpropagated by the TPC tracker. Each seed is first propagated 
241   // to the TRD, and then its prolongation is searched in the TRD.
242   // If sufficiently long continuation of the track is found in the TRD
243   // the track is updated, otherwise it's stored as originaly defined 
244   // by the TPC tracker.   
245   //  
246
247   // Calibration monitor
248   AliTRDCalibraFillHisto *calibra = AliTRDCalibraFillHisto::Instance();
249   if (!calibra) AliInfo("Could not get Calibra instance\n");
250   
251   Int_t   found    = 0;     // number of tracks found
252   Float_t foundMin = 20.0;
253   
254   Float_t *quality = 0x0;
255   Int_t   *index   = 0x0;
256   Int_t    nSeed   = event->GetNumberOfTracks();
257   if(nSeed){  
258     quality = new Float_t[nSeed];
259     index   = new Int_t[nSeed];
260     for (Int_t iSeed = 0; iSeed < nSeed; iSeed++) {
261       AliESDtrack *seed = event->GetTrack(iSeed);
262       Double_t covariance[15];
263       seed->GetExternalCovariance(covariance);
264       quality[iSeed] = covariance[0] + covariance[2];
265     }
266     // Sort tracks according to covariance of local Y and Z
267     TMath::Sort(nSeed,quality,index,kFALSE);
268   }
269   
270   // Backpropagate all seeds
271   Int_t   expectedClr;
272   AliTRDtrackV1 track;
273   for (Int_t iSeed = 0; iSeed < nSeed; iSeed++) {
274   
275     // Get the seeds in sorted sequence
276     AliESDtrack *seed = event->GetTrack(index[iSeed]);
277   
278     // Check the seed status
279     ULong_t status = seed->GetStatus();
280     if ((status & AliESDtrack::kTPCout) == 0) continue;
281     if ((status & AliESDtrack::kTRDout) != 0) continue;
282   
283     // Do the back prolongation
284     new(&track) AliTRDtrackV1(*seed);
285     //track->Print();
286     //Int_t   lbl         = seed->GetLabel();
287     //track.SetSeedLabel(lbl);
288
289     // Make backup and mark entrance in the TRD
290     seed->UpdateTrackParams(&track, AliESDtrack::kTRDbackup | AliESDtrack::kTRDin); 
291     Float_t p4          = track.GetC();
292     expectedClr = FollowBackProlongation(track);
293
294     if (expectedClr<0) continue; // Back prolongation failed
295
296     if(expectedClr){
297       found++;  
298       // computes PID for track
299       track.CookPID();
300       // update calibration references using this track
301       if(calibra->GetHisto2d()) calibra->UpdateHistogramsV1(&track);
302       // save calibration object
303       if ((track.GetNumberOfClusters() > 15) && (track.GetNumberOfClusters() > 0.5*expectedClr)) {
304         seed->UpdateTrackParams(&track, AliESDtrack::kTRDout);
305   
306         track.UpdateESDtrack(seed);
307         
308         // Add TRD track to ESDfriendTrack
309         if (fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 0 /*&& quality TODO*/){ 
310           AliTRDtrackV1 *calibTrack = new AliTRDtrackV1(track);
311           calibTrack->SetOwner();
312           seed->AddCalibObject(calibTrack);
313         }
314       }
315     }
316
317     if ((TMath::Abs(track.GetC() - p4) / TMath::Abs(p4) < 0.2) ||(track.Pt() > 0.8)) {
318       //
319       // Make backup for back propagation
320       //
321       Int_t foundClr = track.GetNumberOfClusters();
322       if (foundClr >= foundMin) {
323         //AliInfo(Form("Making backup track ncls [%d]...", foundClr));
324         //track.CookdEdx();
325         //track.CookdEdxTimBin(seed->GetID());
326         track.CookLabel(1. - fgkLabelFraction);
327         if(track.GetBackupTrack()) UseClusters(track.GetBackupTrack());
328         
329
330         // Sign only gold tracks
331         if (track.GetChi2() / track.GetNumberOfClusters() < 4) {
332           if ((seed->GetKinkIndex(0)      ==   0) && (track.Pt() <  1.5)) UseClusters(&track);
333         }
334         Bool_t isGold = kFALSE;
335   
336         // Full gold track
337         if (track.GetChi2() / track.GetNumberOfClusters() < 5) {
338           if (track.GetBackupTrack()) seed->UpdateTrackParams(track.GetBackupTrack(),AliESDtrack::kTRDbackup);
339
340           isGold = kTRUE;
341         }
342   
343         // Almost gold track
344         if ((!isGold)  && (track.GetNCross() == 0) &&   (track.GetChi2() / track.GetNumberOfClusters()  < 7)) {
345           //seed->UpdateTrackParams(track, AliESDtrack::kTRDbackup);
346           if (track.GetBackupTrack()) seed->UpdateTrackParams(track.GetBackupTrack(),AliESDtrack::kTRDbackup);
347   
348           isGold = kTRUE;
349         }
350         
351         if ((!isGold) && (track.GetBackupTrack())) {
352           if ((track.GetBackupTrack()->GetNumberOfClusters() > foundMin) && ((track.GetBackupTrack()->GetChi2()/(track.GetBackupTrack()->GetNumberOfClusters()+1)) < 7)) {
353             seed->UpdateTrackParams(track.GetBackupTrack(),AliESDtrack::kTRDbackup);
354             isGold = kTRUE;
355           }
356         }
357   
358         //if ((track->StatusForTOF() > 0) && (track->GetNCross() == 0) && (Float_t(track->GetNumberOfClusters()) / Float_t(track->GetNExpected())  > 0.4)) {
359         //seed->UpdateTrackParams(track->GetBackupTrack(), AliESDtrack::kTRDbackup);
360         //}
361       }
362     }
363     
364     // Propagation to the TOF (I.Belikov)
365     if (track.IsStopped() == kFALSE) {
366       Double_t xtof  = 371.0;
367       Double_t xTOF0 = 370.0;
368     
369       Double_t c2    = track.GetSnp() + track.GetC() * (xtof - track.GetX());
370       if (TMath::Abs(c2) >= 0.99) continue;
371       
372       if (!PropagateToX(track, xTOF0, fgkMaxStep)) continue;
373   
374       // Energy losses taken to the account - check one more time
375       c2 = track.GetSnp() + track.GetC() * (xtof - track.GetX());
376       if (TMath::Abs(c2) >= 0.99) continue;
377       
378       //if (!PropagateToX(*track,xTOF0,fgkMaxStep)) {
379       //        fHBackfit->Fill(7);
380       //delete track;
381       //        continue;
382       //}
383   
384       Double_t ymax = xtof * TMath::Tan(0.5 * AliTRDgeometry::GetAlpha());
385       Double_t y;
386       track.GetYAt(xtof,GetBz(),y);
387       if (y >  ymax) {
388         if (!track.Rotate( AliTRDgeometry::GetAlpha())) continue;       
389       }else if (y < -ymax) {
390         if (!track.Rotate(-AliTRDgeometry::GetAlpha())) continue;
391       }
392           
393       if (track.PropagateTo(xtof)) {
394         seed->UpdateTrackParams(&track, AliESDtrack::kTRDout);
395         track.UpdateESDtrack(seed);
396       }
397     } else {                    
398       if ((track.GetNumberOfClusters() > 15) && (track.GetNumberOfClusters() > 0.5*expectedClr)) {
399         seed->UpdateTrackParams(&track, AliESDtrack::kTRDout);
400   
401         track.UpdateESDtrack(seed);
402       }
403     }
404   
405     seed->SetTRDQuality(track.StatusForTOF());
406     seed->SetTRDBudget(track.GetBudget(0));
407   }
408   if(index) delete [] index;
409   if(quality) delete [] quality;
410   
411
412   AliInfo(Form("Number of seeds: %d", nSeed));
413   AliInfo(Form("Number of back propagated TRD tracks: %d", found));
414       
415   // run stand alone tracking
416   if (fReconstructor->IsSeeding()) Clusters2Tracks(event);
417   
418   return 0;
419 }
420
421
422 //____________________________________________________________________
423 Int_t AliTRDtrackerV1::RefitInward(AliESDEvent *event)
424 {
425   //
426   // Refits tracks within the TRD. The ESD event is expected to contain seeds 
427   // at the outer part of the TRD. 
428   // The tracks are propagated to the innermost time bin 
429   // of the TRD and the ESD event is updated
430   // Origin: Thomas KUHR (Thomas.Kuhr@cern.ch)
431   //
432
433   Int_t   nseed    = 0; // contor for loaded seeds
434   Int_t   found    = 0; // contor for updated TRD tracks
435   
436   
437   AliTRDtrackV1 track;
438   for (Int_t itrack = 0; itrack < event->GetNumberOfTracks(); itrack++) {
439     AliESDtrack *seed = event->GetTrack(itrack);
440     new(&track) AliTRDtrackV1(*seed);
441
442     if (track.GetX() < 270.0) {
443       seed->UpdateTrackParams(&track, AliESDtrack::kTRDbackup);
444       continue;
445     }
446
447     ULong_t status = seed->GetStatus();
448     // reject tracks which failed propagation in the TRD
449     if((status & AliESDtrack::kTRDout) == 0) continue;
450
451     // reject tracks which are produced by the TRD stand alone track finder.
452     if((status & AliESDtrack::kTRDin)  == 0) continue;
453     nseed++; 
454
455     track.ResetCovariance(50.0);
456
457     // do the propagation and processing
458     Bool_t kUPDATE = kFALSE;
459     Double_t xTPC = 250.0;
460     if(FollowProlongation(track)){      
461       // Prolongate to TPC
462       if (PropagateToX(track, xTPC, fgkMaxStep)) { //  -with update
463   seed->UpdateTrackParams(&track, AliESDtrack::kTRDrefit);
464   found++;
465   kUPDATE = kTRUE;
466       }
467     }    
468     
469     // Prolongate to TPC without update
470     if(!kUPDATE) {
471       AliTRDtrackV1 tt(*seed);
472       if (PropagateToX(tt, xTPC, fgkMaxStep)) seed->UpdateTrackParams(&tt, AliESDtrack::kTRDrefit);
473     }
474   }
475   AliInfo(Form("Number of loaded seeds: %d",nseed));
476   AliInfo(Form("Number of found tracks from loaded seeds: %d",found));
477   
478   return 0;
479 }
480
481 //____________________________________________________________________
482 Int_t AliTRDtrackerV1::FollowProlongation(AliTRDtrackV1 &t)
483 {
484   // Extrapolates the TRD track in the TPC direction.
485   //
486   // Parameters
487   //   t : the TRD track which has to be extrapolated
488   // 
489   // Output
490   //   number of clusters attached to the track
491   //
492   // Detailed description
493   //
494   // Starting from current radial position of track <t> this function
495   // extrapolates the track through the 6 TRD layers. The following steps
496   // are being performed for each plane:
497   // 1. prepare track:
498   //   a. get plane limits in the local x direction
499   //   b. check crossing sectors 
500   //   c. check track inclination
501   // 2. search tracklet in the tracker list (see GetTracklet() for details)
502   // 3. evaluate material budget using the geo manager
503   // 4. propagate and update track using the tracklet information.
504   //
505   // Debug level 2
506   //
507   
508   Int_t    nClustersExpected = 0;
509   Int_t lastplane = 5; //GetLastPlane(&t);
510   for (Int_t iplane = lastplane; iplane >= 0; iplane--) {
511     Int_t   index   = 0;
512     AliTRDseedV1 *tracklet = GetTracklet(&t, iplane, index);
513     if(!tracklet) continue;
514     if(!tracklet->IsOK()) AliWarning("tracklet not OK");
515     
516     Double_t x  = tracklet->GetX0();
517     // reject tracklets which are not considered for inward refit
518     if(x > t.GetX()+fgkMaxStep) continue;
519
520     // append tracklet to track
521     t.SetTracklet(tracklet, index);
522     
523     if (x < (t.GetX()-fgkMaxStep) && !PropagateToX(t, x+fgkMaxStep, fgkMaxStep)) break;
524     if (!AdjustSector(&t)) break;
525     
526     // Start global position
527     Double_t xyz0[3];
528     t.GetXYZ(xyz0);
529
530     // End global position
531     Double_t alpha = t.GetAlpha(), y, z;
532     if (!t.GetProlongation(x,y,z)) break;    
533     Double_t xyz1[3];
534     xyz1[0] =  x * TMath::Cos(alpha) - y * TMath::Sin(alpha);
535     xyz1[1] =  x * TMath::Sin(alpha) + y * TMath::Cos(alpha);
536     xyz1[2] =  z;
537         
538     // Get material budget
539     Double_t param[7];
540     AliTracker::MeanMaterialBudget(xyz0, xyz1, param);
541     Double_t xrho= param[0]*param[4];
542     Double_t xx0 = param[1]; // Get mean propagation parameters
543
544     // Propagate and update             
545     t.PropagateTo(x, xx0, xrho);
546     if (!AdjustSector(&t)) break;
547     
548     Double_t maxChi2 = t.GetPredictedChi2(tracklet);
549     if (maxChi2 < 1e+10 && t.Update(tracklet, maxChi2)){ 
550       nClustersExpected += tracklet->GetN();
551     }
552   }
553
554   if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 1){
555     Int_t index;
556     for(int iplane=0; iplane<6; iplane++){
557       AliTRDseedV1 *tracklet = GetTracklet(&t, iplane, index);
558       if(!tracklet) continue;
559       t.SetTracklet(tracklet, index);
560     }
561
562     Int_t eventNumber = AliTRDtrackerDebug::GetEventNumber();
563     TTreeSRedirector &cstreamer = *fgDebugStreamer;
564     cstreamer << "FollowProlongation"
565         << "EventNumber="       << eventNumber
566         << "ncl="                                       << nClustersExpected
567         //<< "track.="                  << &t
568         << "\n";
569   }
570
571   return nClustersExpected;
572
573 }
574
575 //_____________________________________________________________________________
576 Int_t AliTRDtrackerV1::FollowBackProlongation(AliTRDtrackV1 &t)
577 {
578   // Extrapolates the TRD track in the TOF direction.
579   //
580   // Parameters
581   //   t : the TRD track which has to be extrapolated
582   // 
583   // Output
584   //   number of clusters attached to the track
585   //
586   // Detailed description
587   //
588   // Starting from current radial position of track <t> this function
589   // extrapolates the track through the 6 TRD layers. The following steps
590   // are being performed for each plane:
591   // 1. prepare track:
592   //   a. get plane limits in the local x direction
593   //   b. check crossing sectors 
594   //   c. check track inclination
595   // 2. build tracklet (see AliTRDseed::AttachClusters() for details)
596   // 3. evaluate material budget using the geo manager
597   // 4. propagate and update track using the tracklet information.
598   //
599   // Debug level 2
600   //
601
602   Int_t nClustersExpected = 0;
603   Double_t clength = AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick();
604   AliTRDtrackingChamber *chamber = 0x0;
605   
606   AliTRDseedV1 tracklet, *ptrTracklet = 0x0;
607   // in case of stand alone tracking we store all the pointers to the tracklets in a temporary array
608   AliTRDseedV1 *tracklets[kNPlanes];
609   memset(tracklets, 0, sizeof(AliTRDseedV1 *) * kNPlanes);
610   for(Int_t ip = 0; ip < kNPlanes; ip++){
611     tracklets[ip] = t.GetTracklet(ip);
612     t.UnsetTracklet(ip);
613   } 
614
615   // Loop through the TRD layers
616   for (Int_t ilayer = 0; ilayer < AliTRDgeometry::Nlayer(); ilayer++) {
617     // BUILD TRACKLET IF NOT ALREADY BUILT
618     Double_t x = 0., y, z, alpha;
619     ptrTracklet  = tracklets[ilayer];
620     if(!ptrTracklet){
621       ptrTracklet = new(&tracklet) AliTRDseedV1(ilayer);
622       ptrTracklet->SetReconstructor(fReconstructor);
623       alpha = t.GetAlpha();
624       Int_t sector = Int_t(alpha/AliTRDgeometry::GetAlpha() + (alpha>0. ? 0 : AliTRDgeometry::kNsector));
625
626       if(!fTrSec[sector].GetNChambers()) continue;
627       
628       if((x = fTrSec[sector].GetX(ilayer)) < 1.) continue;
629     
630       if (!t.GetProlongation(x, y, z)) return -nClustersExpected;
631       Int_t stack = fGeom->GetStack(z, ilayer);
632       Int_t nCandidates = stack >= 0 ? 1 : 2;
633       z -= stack >= 0 ? 0. : 4.; 
634       
635       for(int icham=0; icham<nCandidates; icham++, z+=8){
636         if((stack = fGeom->GetStack(z, ilayer)) < 0) continue;
637       
638         if(!(chamber = fTrSec[sector].GetChamber(stack, ilayer))) continue;
639       
640         if(chamber->GetNClusters() < fgNTimeBins*fReconstructor->GetRecoParam() ->GetFindableClusters()) continue;
641       
642         x = chamber->GetX();
643       
644         AliTRDpadPlane *pp = fGeom->GetPadPlane(ilayer, stack);
645         tracklet.SetTilt(TMath::Tan(TMath::DegToRad()*pp->GetTiltingAngle()));
646         tracklet.SetPadLength(pp->GetLengthIPad());
647         tracklet.SetPlane(ilayer);
648         tracklet.SetX0(x);
649         if(!tracklet.Init(&t)){
650           t.SetStopped(kTRUE);
651           return nClustersExpected;
652         }
653         if(!tracklet.AttachClustersIter(chamber, 1000.)) continue;
654         tracklet.Init(&t);
655         
656         if(tracklet.GetN() < fgNTimeBins*fReconstructor->GetRecoParam() ->GetFindableClusters()) continue;
657       
658         break;
659       }
660     }
661     if(!ptrTracklet->IsOK()){
662       if(x < 1.) continue; //temporary
663       if(!PropagateToX(t, x-fgkMaxStep, fgkMaxStep)) return -nClustersExpected;
664       if(!AdjustSector(&t)) return -nClustersExpected;
665       if(TMath::Abs(t.GetSnp()) > fgkMaxSnp) return -nClustersExpected;
666       continue;
667     }
668     
669     // Propagate closer to the current chamber if neccessary 
670     x -= clength;
671     if (x > (fgkMaxStep + t.GetX()) && !PropagateToX(t, x-fgkMaxStep, fgkMaxStep)) return -nClustersExpected;
672     if (!AdjustSector(&t)) return -nClustersExpected;
673     if (TMath::Abs(t.GetSnp()) > fgkMaxSnp) return -nClustersExpected;
674     
675     // load tracklet to the tracker and the track
676     ptrTracklet = SetTracklet(ptrTracklet);
677     t.SetTracklet(ptrTracklet, fTracklets->GetEntriesFast()-1);
678   
679   
680     // Calculate the mean material budget along the path inside the chamber
681     //Calculate global entry and exit positions of the track in chamber (only track prolongation)
682     Double_t xyz0[3]; // entry point 
683     t.GetXYZ(xyz0);
684     alpha = t.GetAlpha();
685     x = ptrTracklet->GetX0();
686     if (!t.GetProlongation(x, y, z)) return -nClustersExpected;
687     Double_t xyz1[3]; // exit point
688     xyz1[0] =  x * TMath::Cos(alpha) - y * TMath::Sin(alpha); 
689     xyz1[1] = +x * TMath::Sin(alpha) + y * TMath::Cos(alpha);
690     xyz1[2] =  z;
691     Double_t param[7];
692     AliTracker::MeanMaterialBudget(xyz0, xyz1, param);  
693     // The mean propagation parameters
694     Double_t xrho = param[0]*param[4]; // density*length
695     Double_t xx0  = param[1]; // radiation length
696     
697     // Propagate and update track
698     if (!t.PropagateTo(x, xx0, xrho)) return -nClustersExpected;
699     if (!AdjustSector(&t)) return -nClustersExpected;
700     Double_t maxChi2 = t.GetPredictedChi2(ptrTracklet);
701     if (!t.Update(ptrTracklet, maxChi2)) return -nClustersExpected;
702     if (maxChi2<1e+10) { 
703       nClustersExpected += ptrTracklet->GetN();
704       //t.SetTracklet(&tracklet, index);
705     }
706     // Reset material budget if 2 consecutive gold
707     if(ilayer>0 && t.GetTracklet(ilayer-1) && ptrTracklet->GetN() + t.GetTracklet(ilayer-1)->GetN() > 20) t.SetBudget(2, 0.);
708
709     // Make backup of the track until is gold
710     // TO DO update quality check of the track.
711     // consider comparison with fTimeBinsRange
712     Float_t ratio0 = ptrTracklet->GetN() / Float_t(fgNTimeBins);
713     //Float_t ratio1 = Float_t(t.GetNumberOfClusters()+1) / Float_t(t.GetNExpected()+1);        
714     //printf("tracklet.GetChi2() %f     [< 18.0]\n", tracklet.GetChi2()); 
715     //printf("ratio0    %f              [>   0.8]\n", ratio0);
716     //printf("ratio1     %f             [>   0.6]\n", ratio1); 
717     //printf("ratio0+ratio1 %f          [>   1.5]\n", ratio0+ratio1); 
718     //printf("t.GetNCross()  %d         [==    0]\n", t.GetNCross()); 
719     //printf("TMath::Abs(t.GetSnp()) %f [<  0.85]\n", TMath::Abs(t.GetSnp()));
720     //printf("t.GetNumberOfClusters() %d [>    20]\n", t.GetNumberOfClusters());
721     
722     if (//(tracklet.GetChi2()      <  18.0) && TO DO check with FindClusters and move it to AliTRDseed::Update 
723         (ratio0                  >   0.8) && 
724         //(ratio1                  >   0.6) && 
725         //(ratio0+ratio1           >   1.5) && 
726         (t.GetNCross()           ==    0) && 
727         (TMath::Abs(t.GetSnp())  <  0.85) &&
728         (t.GetNumberOfClusters() >    20)) t.MakeBackupTrack();
729     
730   } // end layers loop
731
732   if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 1){
733     TTreeSRedirector &cstreamer = *fgDebugStreamer;
734     Int_t eventNumber = AliTRDtrackerDebug::GetEventNumber();
735     //AliTRDtrackV1 *debugTrack = new AliTRDtrackV1(t);
736     //debugTrack->SetOwner();
737     cstreamer << "FollowBackProlongation"
738         << "EventNumber="                       << eventNumber
739         << "ncl="                                                       << nClustersExpected
740         //<< "track.="                                  << debugTrack
741         << "\n";
742   }
743   
744   return nClustersExpected;
745 }
746
747 //_________________________________________________________________________
748 Float_t AliTRDtrackerV1::FitRieman(AliTRDseedV1 *tracklets, Double_t *chi2, Int_t *planes){
749   //
750   // Fits a Riemann-circle to the given points without tilting pad correction.
751   // The fit is performed using an instance of the class AliRieman (equations 
752   // and transformations see documentation of this class)
753   // Afterwards all the tracklets are Updated
754   //
755   // Parameters: - Array of tracklets (AliTRDseedV1)
756   //             - Storage for the chi2 values (beginning with direction z)  
757   //             - Seeding configuration
758   // Output:     - The curvature
759   //
760   AliRieman *fitter = AliTRDtrackerV1::GetRiemanFitter();
761   fitter->Reset();
762   Int_t allplanes[] = {0, 1, 2, 3, 4, 5};
763   Int_t *ppl = &allplanes[0];
764   Int_t maxLayers = 6;
765   if(planes){
766     maxLayers = 4;
767     ppl = planes;
768   }
769   for(Int_t il = 0; il < maxLayers; il++){
770     if(!tracklets[ppl[il]].IsOK()) continue;
771     fitter->AddPoint(tracklets[ppl[il]].GetX0(), tracklets[ppl[il]].GetYfitR(0), tracklets[ppl[il]].GetZProb(),1,10);
772   }
773   fitter->Update();
774   // Set the reference position of the fit and calculate the chi2 values
775   memset(chi2, 0, sizeof(Double_t) * 2);
776   for(Int_t il = 0; il < maxLayers; il++){
777     // Reference positions
778     tracklets[ppl[il]].Init(fitter);
779     
780     // chi2
781     if((!tracklets[ppl[il]].IsOK()) && (!planes)) continue;
782     chi2[0] += tracklets[ppl[il]].GetChi2Y();
783     chi2[1] += tracklets[ppl[il]].GetChi2Z();
784   }
785   return fitter->GetC();
786 }
787
788 //_________________________________________________________________________
789 void AliTRDtrackerV1::FitRieman(AliTRDcluster **seedcl, Double_t chi2[2])
790 {
791   //
792   // Performs a Riemann helix fit using the seedclusters as spacepoints
793   // Afterwards the chi2 values are calculated and the seeds are updated
794   //
795   // Parameters: - The four seedclusters
796   //             - The tracklet array (AliTRDseedV1)
797   //             - The seeding configuration
798   //             - Chi2 array
799   //
800   // debug level 2
801   //
802   AliRieman *fitter = AliTRDtrackerV1::GetRiemanFitter();
803   fitter->Reset();
804   for(Int_t i = 0; i < 4; i++)
805     fitter->AddPoint(seedcl[i]->GetX(), seedcl[i]->GetY(), seedcl[i]->GetZ(), 1, 10);
806   fitter->Update();
807   
808   
809   // Update the seed and calculated the chi2 value
810   chi2[0] = 0; chi2[1] = 0;
811   for(Int_t ipl = 0; ipl < kNSeedPlanes; ipl++){
812     // chi2
813     chi2[0] += (seedcl[ipl]->GetZ() - fitter->GetZat(seedcl[ipl]->GetX())) * (seedcl[ipl]->GetZ() - fitter->GetZat(seedcl[ipl]->GetX()));
814     chi2[1] += (seedcl[ipl]->GetY() - fitter->GetYat(seedcl[ipl]->GetX())) * (seedcl[ipl]->GetY() - fitter->GetYat(seedcl[ipl]->GetX()));
815   }     
816 }
817
818
819 //_________________________________________________________________________
820 Float_t AliTRDtrackerV1::FitTiltedRiemanConstraint(AliTRDseedV1 *tracklets, Double_t zVertex)
821 {
822   //
823   // Fits a helix to the clusters. Pad tilting is considered. As constraint it is 
824   // assumed that the vertex position is set to 0.
825   // This method is very usefull for high-pt particles
826   // Basis for the fit: (x - x0)^2 + (y - y0)^2 - R^2 = 0
827   //      x0, y0: Center of the circle
828   // Measured y-position: ymeas = y - tan(phiT)(zc - zt)
829   //      zc: center of the pad row
830   // Equation which has to be fitted (after transformation):
831   // a + b * u + e * v + 2*(ymeas + tan(phiT)(z - zVertex))*t = 0
832   // Transformation:
833   // t = 1/(x^2 + y^2)
834   // u = 2 * x * t
835   // v = 2 * x * tan(phiT) * t
836   // Parameters in the equation: 
837   //    a = -1/y0, b = x0/y0, e = dz/dx
838   //
839   // The Curvature is calculated by the following equation:
840   //               - curv = a/Sqrt(b^2 + 1) = 1/R
841   // Parameters:   - the 6 tracklets
842   //               - the Vertex constraint
843   // Output:       - the Chi2 value of the track
844   //
845   // debug level 5
846   //
847
848   TLinearFitter *fitter = GetTiltedRiemanFitterConstraint();
849   fitter->StoreData(kTRUE);
850   fitter->ClearPoints();
851   AliTRDcluster *cl = 0x0;
852   
853   Float_t x, y, z, w, t, error, tilt;
854   Double_t uvt[2];
855   Int_t nPoints = 0;
856   for(Int_t ilr = 0; ilr < AliTRDgeometry::kNlayer; ilr++){
857     if(!tracklets[ilr].IsOK()) continue;
858     for(Int_t itb = 0; itb < fgNTimeBins; itb++){
859       if(!tracklets[ilr].IsUsable(itb)) continue;
860       cl = tracklets[ilr].GetClusters(itb);
861       x = cl->GetX();
862       y = cl->GetY();
863       z = cl->GetZ();
864       tilt = tracklets[ilr].GetTilt();
865       // Transformation
866       t = 1./(x * x + y * y);
867       uvt[0] = 2. * x * t;
868       uvt[1] = 2. * x * t * tilt ;
869       w = 2. * (y + tilt * (z - zVertex)) * t;
870       error = 2. * 0.2 * t;
871       fitter->AddPoint(uvt, w, error);
872       nPoints++;
873     }
874   }
875   fitter->Eval();
876
877   // Calculate curvature
878   Double_t a = fitter->GetParameter(0);
879   Double_t b = fitter->GetParameter(1);
880   Double_t curvature = a/TMath::Sqrt(b*b + 1);
881
882   Float_t chi2track = fitter->GetChisquare()/Double_t(nPoints);
883   for(Int_t ip = 0; ip < AliTRDtrackerV1::kNPlanes; ip++)
884     tracklets[ip].SetCC(curvature);
885
886 /*  if(fReconstructor->GetStreamLevel() >= 5){
887     //Linear Model on z-direction
888     Double_t xref = CalculateReferenceX(tracklets);             // Relative to the middle of the stack
889     Double_t slope = fitter->GetParameter(2);
890     Double_t zref = slope * xref;
891     Float_t chi2Z = CalculateChi2Z(tracklets, zref, slope, xref);
892     Int_t eventNumber = AliTRDtrackerDebug::GetEventNumber();
893     Int_t candidateNumber = AliTRDtrackerDebug::GetCandidateNumber();
894     TTreeSRedirector &treeStreamer = *fgDebugStreamer;
895     treeStreamer << "FitTiltedRiemanConstraint"
896     << "EventNumber="           << eventNumber
897     << "CandidateNumber="       << candidateNumber
898     << "Curvature="                             << curvature
899     << "Chi2Track="                             << chi2track
900     << "Chi2Z="                                         << chi2Z
901     << "zref="                                          << zref
902     << "\n";
903   }*/
904   return chi2track;
905 }
906
907 //_________________________________________________________________________
908 Float_t AliTRDtrackerV1::FitTiltedRieman(AliTRDseedV1 *tracklets, Bool_t sigError)
909 {
910   //
911   // Performs a Riemann fit taking tilting pad correction into account
912   // The equation of a Riemann circle, where the y position is substituted by the 
913   // measured y-position taking pad tilting into account, has to be transformed
914   // into a 4-dimensional hyperplane equation
915   // Riemann circle: (x-x0)^2 + (y-y0)^2 -R^2 = 0
916   // Measured y-Position: ymeas = y - tan(phiT)(zc - zt)
917   //          zc: center of the pad row
918   //          zt: z-position of the track
919   // The z-position of the track is assumed to be linear dependent on the x-position
920   // Transformed equation: a + b * u + c * t + d * v  + e * w - 2 * (ymeas + tan(phiT) * zc) * t = 0
921   // Transformation:       u = 2 * x * t
922   //                       v = 2 * tan(phiT) * t
923   //                       w = 2 * tan(phiT) * (x - xref) * t
924   //                       t = 1 / (x^2 + ymeas^2)
925   // Parameters:           a = -1/y0
926   //                       b = x0/y0
927   //                       c = (R^2 -x0^2 - y0^2)/y0
928   //                       d = offset
929   //                       e = dz/dx
930   // If the offset respectively the slope in z-position is impossible, the parameters are fixed using 
931   // results from the simple riemann fit. Afterwards the fit is redone.
932   // The curvature is calculated according to the formula:
933   //                       curv = a/(1 + b^2 + c*a) = 1/R
934   //
935   // Paramters:   - Array of tracklets (connected to the track candidate)
936   //              - Flag selecting the error definition
937   // Output:      - Chi2 values of the track (in Parameter list)
938   //
939   TLinearFitter *fitter = GetTiltedRiemanFitter();
940   fitter->StoreData(kTRUE);
941   fitter->ClearPoints();
942   AliTRDLeastSquare zfitter;
943   AliTRDcluster *cl = 0x0;
944
945   Double_t xref = CalculateReferenceX(tracklets);
946   Double_t x, y, z, t, tilt, dx, w, we;
947   Double_t uvt[4];
948   Int_t nPoints = 0;
949   // Containers for Least-square fitter
950   for(Int_t ipl = 0; ipl < kNPlanes; ipl++){
951     if(!tracklets[ipl].IsOK()) continue;
952     for(Int_t itb = 0; itb < fgNTimeBins; itb++){
953       if(!(cl = tracklets[ipl].GetClusters(itb))) continue;
954       if (!tracklets[ipl].IsUsable(itb)) continue;
955       x = cl->GetX();
956       y = cl->GetY();
957       z = cl->GetZ();
958       tilt = tracklets[ipl].GetTilt();
959       dx = x - xref;
960       // Transformation
961       t = 1./(x*x + y*y);
962       uvt[0] = 2. * x * t;
963       uvt[1] = t;
964       uvt[2] = 2. * tilt * t;
965       uvt[3] = 2. * tilt * dx * t;
966       w = 2. * (y + tilt*z) * t;
967       // error definition changes for the different calls
968       we = 2. * t;
969       we *= sigError ? tracklets[ipl].GetSigmaY() : 0.2;
970       fitter->AddPoint(uvt, w, we);
971       zfitter.AddPoint(&x, z, static_cast<Double_t>(TMath::Sqrt(cl->GetSigmaZ2())));
972       nPoints++;
973     }
974   }
975   fitter->Eval();
976   zfitter.Eval();
977
978   Double_t offset = fitter->GetParameter(3);
979   Double_t slope  = fitter->GetParameter(4);
980
981   // Linear fitter  - not possible to make boundaries
982   // Do not accept non possible z and dzdx combinations
983   Bool_t acceptablez = kTRUE;
984   Double_t zref = 0.0;
985   for (Int_t iLayer = 0; iLayer < kNPlanes; iLayer++) {
986     if(!tracklets[iLayer].IsOK()) continue;
987     zref = offset + slope * (tracklets[iLayer].GetX0() - xref);
988     if (TMath::Abs(tracklets[iLayer].GetZProb() - zref) > tracklets[iLayer].GetPadLength() * 0.5 + 1.0) 
989       acceptablez = kFALSE;
990   }
991   if (!acceptablez) {
992     Double_t dzmf       = zfitter.GetFunctionParameter(1);
993     Double_t zmf        = zfitter.GetFunctionValue(&xref);
994     fgTiltedRieman->FixParameter(3, zmf);
995     fgTiltedRieman->FixParameter(4, dzmf);
996     fitter->Eval();
997     fitter->ReleaseParameter(3);
998     fitter->ReleaseParameter(4);
999     offset = fitter->GetParameter(3);
1000     slope = fitter->GetParameter(4);
1001   }
1002
1003   // Calculate Curvarture
1004   Double_t a     =  fitter->GetParameter(0);
1005   Double_t b     =  fitter->GetParameter(1);
1006   Double_t c     =  fitter->GetParameter(2);
1007   Double_t curvature =  1.0 + b*b - c*a;
1008   if (curvature > 0.0) 
1009     curvature  =  a / TMath::Sqrt(curvature);
1010
1011   Double_t chi2track = fitter->GetChisquare()/Double_t(nPoints);
1012
1013   // Update the tracklets
1014   Double_t dy, dz;
1015   for(Int_t iLayer = 0; iLayer < AliTRDtrackerV1::kNPlanes; iLayer++) {
1016
1017     x  = tracklets[iLayer].GetX0();
1018     y  = 0;
1019     z  = 0;
1020     dy = 0;
1021     dz = 0;
1022
1023     // y:     R^2 = (x - x0)^2 + (y - y0)^2
1024     //     =>   y = y0 +/- Sqrt(R^2 - (x - x0)^2)
1025     //          R = Sqrt() = 1/Curvature
1026     //     =>   y = y0 +/- Sqrt(1/Curvature^2 - (x - x0)^2)  
1027     Double_t res = (x * a + b);                                                         // = (x - x0)/y0
1028     res *= res;
1029     res  = 1.0 - c * a + b * b - res;                                   // = (R^2 - (x - x0)^2)/y0^2
1030     if (res >= 0) {
1031       res = TMath::Sqrt(res);
1032       y    = (1.0 - res) / a;
1033     }
1034
1035     // dy:      R^2 = (x - x0)^2 + (y - y0)^2
1036     //     =>     y = +/- Sqrt(R^2 - (x - x0)^2) + y0
1037     //     => dy/dx = (x - x0)/Sqrt(R^2 - (x - x0)^2) 
1038     // Curvature: cr = 1/R = a/Sqrt(1 + b^2 - c*a)
1039     //     => dy/dx =  (x - x0)/(1/(cr^2) - (x - x0)^2) 
1040     Double_t x0 = -b / a;
1041     if (-c * a + b * b + 1 > 0) {
1042       if (1.0/(curvature * curvature) - (x - x0) * (x - x0) > 0.0) {
1043   Double_t yderiv = (x - x0) / TMath::Sqrt(1.0/(curvature * curvature) - (x - x0) * (x - x0));
1044   if (a < 0) yderiv *= -1.0;
1045   dy = yderiv;
1046       }
1047     }
1048     z  = offset + slope * (x - xref);
1049     dz = slope;
1050     tracklets[iLayer].SetYref(0, y);
1051     tracklets[iLayer].SetYref(1, dy);
1052     tracklets[iLayer].SetZref(0, z);
1053     tracklets[iLayer].SetZref(1, dz);
1054     tracklets[iLayer].SetC(curvature);
1055     tracklets[iLayer].SetChi2(chi2track);
1056   }
1057   
1058 /*  if(fReconstructor->GetStreamLevel() >=5){
1059     TTreeSRedirector &cstreamer = *fgDebugStreamer;
1060     Int_t eventNumber                   = AliTRDtrackerDebug::GetEventNumber();
1061     Int_t candidateNumber       = AliTRDtrackerDebug::GetCandidateNumber();
1062     Double_t chi2z = CalculateChi2Z(tracklets, offset, slope, xref);
1063     cstreamer << "FitTiltedRieman0"
1064         << "EventNumber="                       << eventNumber
1065         << "CandidateNumber="   << candidateNumber
1066         << "xref="                                              << xref
1067         << "Chi2Z="                                             << chi2z
1068         << "\n";
1069   }*/
1070   return chi2track;
1071 }
1072
1073
1074 //____________________________________________________________________
1075 Double_t AliTRDtrackerV1::FitLine(AliTRDtrackV1 *track, AliTRDseedV1 *tracklets, Bool_t err, Int_t np, AliTrackPoint *points)
1076 {
1077   AliTRDLeastSquare yfitter, zfitter;
1078   AliTRDcluster *cl = 0x0;
1079
1080   AliTRDseedV1 work[kNPlanes], *tracklet = 0x0;
1081   if(!tracklets){
1082     for(Int_t ipl = 0; ipl < kNPlanes; ipl++){
1083       if(!(tracklet = track->GetTracklet(ipl))) continue;
1084       if(!tracklet->IsOK()) continue;
1085       new(&work[ipl]) AliTRDseedV1(*tracklet);
1086     }
1087     tracklets = &work[0];
1088   }
1089
1090   Double_t xref = CalculateReferenceX(tracklets);
1091   Double_t x, y, z, dx, ye, yr, tilt;
1092   for(Int_t ipl = 0; ipl < kNPlanes; ipl++){
1093     if(!tracklets[ipl].IsOK()) continue;
1094     for(Int_t itb = 0; itb < fgNTimeBins; itb++){
1095       if(!(cl = tracklets[ipl].GetClusters(itb))) continue;
1096       if (!tracklets[ipl].IsUsable(itb)) continue;
1097       x = cl->GetX();
1098       z = cl->GetZ();
1099       dx = x - xref;
1100       zfitter.AddPoint(&dx, z, static_cast<Double_t>(TMath::Sqrt(cl->GetSigmaZ2())));
1101     }
1102   }
1103   zfitter.Eval();
1104   Double_t z0    = zfitter.GetFunctionParameter(0);
1105   Double_t dzdx  = zfitter.GetFunctionParameter(1);
1106   for(Int_t ipl = 0; ipl < kNPlanes; ipl++){
1107     if(!tracklets[ipl].IsOK()) continue;
1108     for(Int_t itb = 0; itb < fgNTimeBins; itb++){
1109       if(!(cl = tracklets[ipl].GetClusters(itb))) continue;
1110       if (!tracklets[ipl].IsUsable(itb)) continue;
1111       x = cl->GetX();
1112       y = cl->GetY();
1113       z = cl->GetZ();
1114       tilt = tracklets[ipl].GetTilt();
1115       dx = x - xref;
1116       yr = y + tilt*(z - z0 - dzdx*dx); 
1117       // error definition changes for the different calls
1118       ye = tilt*TMath::Sqrt(cl->GetSigmaZ2());
1119       ye += err ? tracklets[ipl].GetSigmaY() : 0.2;
1120       yfitter.AddPoint(&dx, yr, ye);
1121     }
1122   }
1123   yfitter.Eval();
1124   Double_t y0   = yfitter.GetFunctionParameter(0);
1125   Double_t dydx = yfitter.GetFunctionParameter(1);
1126   Double_t chi2 = 0.;//yfitter.GetChisquare()/Double_t(nPoints);
1127
1128   //update track points array
1129   if(np && points){
1130     Float_t xyz[3];
1131     for(int ip=0; ip<np; ip++){
1132       points[ip].GetXYZ(xyz);
1133       xyz[1] = y0 + dydx * (xyz[0] - xref);
1134       xyz[2] = z0 + dzdx * (xyz[0] - xref);
1135       points[ip].SetXYZ(xyz);
1136     }
1137   }
1138   return chi2;
1139 }
1140
1141
1142 //_________________________________________________________________________
1143 Double_t AliTRDtrackerV1::FitRiemanTilt(AliTRDtrackV1 *track, AliTRDseedV1 *tracklets, Bool_t sigError, Int_t np, AliTrackPoint *points)
1144 {
1145   //
1146   // Performs a Riemann fit taking tilting pad correction into account
1147   // The equation of a Riemann circle, where the y position is substituted by the 
1148   // measured y-position taking pad tilting into account, has to be transformed
1149   // into a 4-dimensional hyperplane equation
1150   // Riemann circle: (x-x0)^2 + (y-y0)^2 -R^2 = 0
1151   // Measured y-Position: ymeas = y - tan(phiT)(zc - zt)
1152   //          zc: center of the pad row
1153   //          zt: z-position of the track
1154   // The z-position of the track is assumed to be linear dependent on the x-position
1155   // Transformed equation: a + b * u + c * t + d * v  + e * w - 2 * (ymeas + tan(phiT) * zc) * t = 0
1156   // Transformation:       u = 2 * x * t
1157   //                       v = 2 * tan(phiT) * t
1158   //                       w = 2 * tan(phiT) * (x - xref) * t
1159   //                       t = 1 / (x^2 + ymeas^2)
1160   // Parameters:           a = -1/y0
1161   //                       b = x0/y0
1162   //                       c = (R^2 -x0^2 - y0^2)/y0
1163   //                       d = offset
1164   //                       e = dz/dx
1165   // If the offset respectively the slope in z-position is impossible, the parameters are fixed using 
1166   // results from the simple riemann fit. Afterwards the fit is redone.
1167   // The curvature is calculated according to the formula:
1168   //                       curv = a/(1 + b^2 + c*a) = 1/R
1169   //
1170   // Paramters:   - Array of tracklets (connected to the track candidate)
1171   //              - Flag selecting the error definition
1172   // Output:      - Chi2 values of the track (in Parameter list)
1173   //
1174   TLinearFitter *fitter = GetTiltedRiemanFitter();
1175   fitter->StoreData(kTRUE);
1176   fitter->ClearPoints();
1177   AliTRDLeastSquare zfitter;
1178   AliTRDcluster *cl = 0x0;
1179
1180   AliTRDseedV1 work[kNPlanes], *tracklet = 0x0;
1181   if(!tracklets){
1182     for(Int_t ipl = 0; ipl < kNPlanes; ipl++){
1183       if(!(tracklet = track->GetTracklet(ipl))) continue;
1184       if(!tracklet->IsOK()) continue;
1185       new(&work[ipl]) AliTRDseedV1(*tracklet);
1186     }
1187     tracklets = &work[0];
1188   }
1189
1190   Double_t xref = CalculateReferenceX(tracklets);
1191   Double_t x, y, z, t, tilt, dx, w, we;
1192   Double_t uvt[4];
1193   Int_t nPoints = 0;
1194   // Containers for Least-square fitter
1195   for(Int_t ipl = 0; ipl < kNPlanes; ipl++){
1196     if(!tracklets[ipl].IsOK()) continue;
1197     for(Int_t itb = 0; itb < fgNTimeBins; itb++){
1198       if(!(cl = tracklets[ipl].GetClusters(itb))) continue;
1199       if (!tracklets[ipl].IsUsable(itb)) continue;
1200       x = cl->GetX();
1201       y = cl->GetY();
1202       z = cl->GetZ();
1203       tilt = tracklets[ipl].GetTilt();
1204       dx = x - xref;
1205       // Transformation
1206       t = 1./(x*x + y*y);
1207       uvt[0] = 2. * x * t;
1208       uvt[1] = t;
1209       uvt[2] = 2. * tilt * t;
1210       uvt[3] = 2. * tilt * dx * t;
1211       w = 2. * (y + tilt*z) * t;
1212       // error definition changes for the different calls
1213       we = 2. * t;
1214       we *= sigError ? tracklets[ipl].GetSigmaY() : 0.2;
1215       fitter->AddPoint(uvt, w, we);
1216       zfitter.AddPoint(&x, z, static_cast<Double_t>(TMath::Sqrt(cl->GetSigmaZ2())));
1217       nPoints++;
1218     }
1219   }
1220   if(fitter->Eval()) return 1.E10;
1221
1222   Double_t z0    = fitter->GetParameter(3);
1223   Double_t dzdx  = fitter->GetParameter(4);
1224
1225
1226   // Linear fitter  - not possible to make boundaries
1227   // Do not accept non possible z and dzdx combinations
1228   Bool_t accept = kTRUE;
1229   Double_t zref = 0.0;
1230   for (Int_t iLayer = 0; iLayer < kNPlanes; iLayer++) {
1231     if(!tracklets[iLayer].IsOK()) continue;
1232     zref = z0 + dzdx * (tracklets[iLayer].GetX0() - xref);
1233     if (TMath::Abs(tracklets[iLayer].GetZProb() - zref) > tracklets[iLayer].GetPadLength() * 0.5 + 1.0) 
1234       accept = kFALSE;
1235   }
1236   if (!accept) {
1237     zfitter.Eval();
1238     Double_t dzmf       = zfitter.GetFunctionParameter(1);
1239     Double_t zmf        = zfitter.GetFunctionValue(&xref);
1240     fitter->FixParameter(3, zmf);
1241     fitter->FixParameter(4, dzmf);
1242     fitter->Eval();
1243     fitter->ReleaseParameter(3);
1244     fitter->ReleaseParameter(4);
1245     z0   = fitter->GetParameter(3); // = zmf ?
1246     dzdx = fitter->GetParameter(4); // = dzmf ?
1247   }
1248
1249   // Calculate Curvature
1250   Double_t a    =  fitter->GetParameter(0);
1251   Double_t b    =  fitter->GetParameter(1);
1252   Double_t c    =  fitter->GetParameter(2);
1253   Double_t y0   = 1. / a;
1254   Double_t x0   = -b * y0;
1255   Double_t R    = TMath::Sqrt(y0*y0 + x0*x0 - c*y0);
1256   Double_t C    =  1.0 + b*b - c*a;
1257   if (C > 0.0) C  =  a / TMath::Sqrt(C);
1258
1259   // Calculate chi2 of the fit 
1260   Double_t chi2 = fitter->GetChisquare()/Double_t(nPoints);
1261
1262   // Update the tracklets
1263   if(!track){
1264     for(Int_t ip = 0; ip < kNPlanes; ip++) {
1265       x = tracklets[ip].GetX0();
1266       Double_t tmp = TMath::Sqrt(R*R-(x-x0)*(x-x0));  
1267
1268       // y:     R^2 = (x - x0)^2 + (y - y0)^2
1269       //     =>   y = y0 +/- Sqrt(R^2 - (x - x0)^2)
1270       tracklets[ip].SetYref(0, y0 - (y0>0.?1.:-1)*tmp);
1271       //     => dy/dx = (x - x0)/Sqrt(R^2 - (x - x0)^2) 
1272       tracklets[ip].SetYref(1, (x - x0) / tmp);
1273       tracklets[ip].SetZref(0, z0 + dzdx * (x - xref));
1274       tracklets[ip].SetZref(1, dzdx);
1275       tracklets[ip].SetC(C);
1276       tracklets[ip].SetChi2(chi2);
1277     }
1278   }
1279
1280   //update track points array
1281   if(np && points){
1282     Float_t xyz[3];
1283     for(int ip=0; ip<np; ip++){
1284       points[ip].GetXYZ(xyz);
1285       xyz[1] = y0 - (y0>0.?1.:-1)*TMath::Sqrt(R*R-(xyz[0]-x0)*(xyz[0]-x0));
1286       xyz[2] = z0 + dzdx * (xyz[0] - xref);
1287       points[ip].SetXYZ(xyz);
1288     }
1289   }
1290   
1291 /*  if(fReconstructor->GetStreamLevel() >=5){
1292     TTreeSRedirector &cstreamer = *fgDebugStreamer;
1293     Int_t eventNumber                   = AliTRDtrackerDebug::GetEventNumber();
1294     Int_t candidateNumber       = AliTRDtrackerDebug::GetCandidateNumber();
1295     Double_t chi2z = CalculateChi2Z(tracklets, z0, dzdx, xref);
1296     cstreamer << "FitRiemanTilt"
1297         << "EventNumber="                       << eventNumber
1298         << "CandidateNumber="   << candidateNumber
1299         << "xref="                                              << xref
1300         << "Chi2Z="                                             << chi2z
1301         << "\n";
1302   }*/
1303   return chi2;
1304 }
1305
1306
1307 //____________________________________________________________________
1308 Double_t AliTRDtrackerV1::FitKalman(AliTRDtrackV1 *track, AliTRDseedV1 *tracklets, Bool_t up, Int_t np, AliTrackPoint *points)
1309 {
1310 //   Kalman filter implementation for the TRD.
1311 //   It returns the positions of the fit in the array "points"
1312 // 
1313 //   Author : A.Bercuci@gsi.de
1314
1315   //printf("Start track @ x[%f]\n", track->GetX());
1316         
1317   //prepare marker points along the track
1318   Int_t ip = np ? 0 : 1;
1319   while(ip<np){
1320     if((up?-1:1) * (track->GetX() - points[ip].GetX()) > 0.) break;
1321     //printf("AliTRDtrackerV1::FitKalman() : Skip track marker x[%d] = %7.3f. Before track start ( %7.3f ).\n", ip, points[ip].GetX(), track->GetX());
1322     ip++;
1323   }
1324   //if(points) printf("First marker point @ x[%d] = %f\n", ip, points[ip].GetX());
1325
1326
1327   AliTRDseedV1 tracklet, *ptrTracklet = 0x0;
1328
1329   //Loop through the TRD planes
1330   for (Int_t jplane = 0; jplane < kNPlanes; jplane++) {
1331     // GET TRACKLET OR BUILT IT         
1332     Int_t iplane = up ? jplane : kNPlanes - 1 - jplane;
1333     if(tracklets){ 
1334       if(!(ptrTracklet = &tracklets[iplane])) continue;
1335     }else{
1336       if(!(ptrTracklet  = track->GetTracklet(iplane))){ 
1337       /*AliTRDtrackerV1 *tracker = 0x0;
1338         if(!(tracker = dynamic_cast<AliTRDtrackerV1*>( AliTRDReconstructor::Tracker()))) continue;
1339         ptrTracklet = new(&tracklet) AliTRDseedV1(iplane);
1340         if(!tracker->MakeTracklet(ptrTracklet, track)) */
1341         continue;
1342       }
1343     }
1344     if(!ptrTracklet->IsOK()) continue;
1345
1346     Double_t x = ptrTracklet->GetX0();
1347
1348     while(ip < np){
1349       //don't do anything if next marker is after next update point.
1350       if((up?-1:1) * (points[ip].GetX() - x) - fgkMaxStep < 0) break;
1351
1352       //printf("Propagate to x[%d] = %f\n", ip, points[ip].GetX());
1353
1354       if(((up?-1:1) * (points[ip].GetX() - track->GetX()) < 0) && !PropagateToX(*track, points[ip].GetX(), fgkMaxStep)) return -1.;
1355       
1356       Double_t xyz[3]; // should also get the covariance
1357       track->GetXYZ(xyz); points[ip].SetXYZ(xyz[0], xyz[1], xyz[2]);
1358       ip++;
1359     }
1360     //printf("plane[%d] tracklet[%p] x[%f]\n", iplane, ptrTracklet, x);
1361
1362     //Propagate closer to the next update point 
1363     if(((up?-1:1) * (x - track->GetX()) + fgkMaxStep < 0) && !PropagateToX(*track, x + (up?-1:1)*fgkMaxStep, fgkMaxStep)) return -1.;
1364
1365     if(!AdjustSector(track)) return -1;
1366     if(TMath::Abs(track->GetSnp()) > fgkMaxSnp) return -1;
1367     
1368     //load tracklet to the tracker and the track
1369 /*    Int_t index;
1370     if((index = FindTracklet(ptrTracklet)) < 0){
1371       ptrTracklet = SetTracklet(&tracklet);
1372       index = fTracklets->GetEntriesFast()-1;
1373     }
1374     track->SetTracklet(ptrTracklet, index);*/
1375
1376
1377     // register tracklet to track with tracklet creation !!
1378     // PropagateBack : loaded tracklet to the tracker and update index 
1379     // RefitInward : update index 
1380     // MakeTrack   : loaded tracklet to the tracker and update index 
1381     if(!tracklets) track->SetTracklet(ptrTracklet, -1);
1382     
1383   
1384     //Calculate the mean material budget along the path inside the chamber
1385     Double_t xyz0[3]; track->GetXYZ(xyz0);
1386     Double_t alpha = track->GetAlpha();
1387     Double_t xyz1[3], y, z;
1388     if(!track->GetProlongation(x, y, z)) return -1;
1389     xyz1[0] =  x * TMath::Cos(alpha) - y * TMath::Sin(alpha); 
1390     xyz1[1] = +x * TMath::Sin(alpha) + y * TMath::Cos(alpha);
1391     xyz1[2] =  z;
1392     Double_t param[7];
1393     AliTracker::MeanMaterialBudget(xyz0, xyz1, param);  
1394     Double_t xrho = param[0]*param[4]; // density*length
1395     Double_t xx0  = param[1]; // radiation length
1396     
1397     //Propagate the track
1398     track->PropagateTo(x, xx0, xrho);
1399     if (!AdjustSector(track)) break;
1400   
1401     //Update track
1402     Double_t chi2 = track->GetPredictedChi2(ptrTracklet);
1403     if(chi2<1e+10) track->Update(ptrTracklet, chi2);
1404
1405     if(!up) continue;
1406
1407                 //Reset material budget if 2 consecutive gold
1408                 if(iplane>0 && track->GetTracklet(iplane-1) && ptrTracklet->GetN() + track->GetTracklet(iplane-1)->GetN() > 20) track->SetBudget(2, 0.);
1409         } // end planes loop
1410
1411   // extrapolation
1412   while(ip < np){
1413     if(((up?-1:1) * (points[ip].GetX() - track->GetX()) < 0) && !PropagateToX(*track, points[ip].GetX(), fgkMaxStep)) return -1.;
1414     
1415     Double_t xyz[3]; // should also get the covariance
1416     track->GetXYZ(xyz); points[ip].SetXYZ(xyz[0], xyz[1], xyz[2]);
1417     ip++;
1418   }
1419
1420         return track->GetChi2();
1421 }
1422
1423 //_________________________________________________________________________
1424 Float_t AliTRDtrackerV1::CalculateChi2Z(AliTRDseedV1 *tracklets, Double_t offset, Double_t slope, Double_t xref)
1425 {
1426   //
1427   // Calculates the chi2-value of the track in z-Direction including tilting pad correction.
1428   // A linear dependence on the x-value serves as a model.
1429   // The parameters are related to the tilted Riemann fit.
1430   // Parameters: - Array of tracklets (AliTRDseedV1) related to the track candidate
1431   //             - the offset for the reference x
1432   //             - the slope
1433   //             - the reference x position
1434   // Output:     - The Chi2 value of the track in z-Direction
1435   //
1436   Float_t chi2Z = 0, nLayers = 0;
1437   for (Int_t iLayer = 0; iLayer < AliTRDgeometry::kNlayer; iLayer++) {
1438     if(!tracklets[iLayer].IsOK()) continue;
1439     Double_t z = offset + slope * (tracklets[iLayer].GetX0() - xref);
1440     chi2Z += TMath::Abs(tracklets[iLayer].GetMeanz() - z);
1441     nLayers++;
1442   }
1443   chi2Z /= TMath::Max((nLayers - 3.0),1.0);
1444   return chi2Z;
1445 }
1446
1447 //_____________________________________________________________________________
1448 Int_t AliTRDtrackerV1::PropagateToX(AliTRDtrackV1 &t, Double_t xToGo, Double_t maxStep)
1449 {
1450   //
1451   // Starting from current X-position of track <t> this function
1452   // extrapolates the track up to radial position <xToGo>. 
1453   // Returns 1 if track reaches the plane, and 0 otherwise 
1454   //
1455
1456   const Double_t kEpsilon = 0.00001;
1457
1458   // Current track X-position
1459   Double_t xpos = t.GetX();
1460
1461   // Direction: inward or outward
1462   Double_t dir  = (xpos < xToGo) ? 1.0 : -1.0;
1463
1464   while (((xToGo - xpos) * dir) > kEpsilon) {
1465
1466     Double_t xyz0[3];
1467     Double_t xyz1[3];
1468     Double_t param[7];
1469     Double_t x;
1470     Double_t y;
1471     Double_t z;
1472
1473     // The next step size
1474     Double_t step = dir * TMath::Min(TMath::Abs(xToGo-xpos),maxStep);
1475
1476     // Get the global position of the starting point
1477     t.GetXYZ(xyz0);
1478
1479     // X-position after next step
1480     x = xpos + step;
1481
1482     // Get local Y and Z at the X-position of the next step
1483     if (!t.GetProlongation(x,y,z)) {
1484       return 0; // No prolongation possible
1485     }
1486
1487     // The global position of the end point of this prolongation step
1488     xyz1[0] =  x * TMath::Cos(t.GetAlpha()) - y * TMath::Sin(t.GetAlpha()); 
1489     xyz1[1] = +x * TMath::Sin(t.GetAlpha()) + y * TMath::Cos(t.GetAlpha());
1490     xyz1[2] =  z;
1491
1492     // Calculate the mean material budget between start and
1493     // end point of this prolongation step
1494     AliTracker::MeanMaterialBudget(xyz0, xyz1, param);
1495
1496     // Propagate the track to the X-position after the next step
1497     if (!t.PropagateTo(x,param[1],param[0]*param[4])) {
1498       return 0;
1499     }
1500
1501     // Rotate the track if necessary
1502     AdjustSector(&t);
1503
1504     // New track X-position
1505     xpos = t.GetX();
1506
1507   }
1508
1509   return 1;
1510
1511 }
1512
1513
1514 //_____________________________________________________________________________
1515 Int_t AliTRDtrackerV1::ReadClusters(TClonesArray* &array, TTree *clusterTree) const
1516 {
1517   //
1518   // Reads AliTRDclusters from the file. 
1519   // The names of the cluster tree and branches 
1520   // should match the ones used in AliTRDclusterizer::WriteClusters()
1521   //
1522
1523   Int_t nsize = Int_t(clusterTree->GetTotBytes() / (sizeof(AliTRDcluster))); 
1524   TObjArray *clusterArray = new TObjArray(nsize+1000); 
1525   
1526   TBranch *branch = clusterTree->GetBranch("TRDcluster");
1527   if (!branch) {
1528     AliError("Can't get the branch !");
1529     return 1;
1530   }
1531   branch->SetAddress(&clusterArray); 
1532   
1533   if(!fClusters){ 
1534     array = new TClonesArray("AliTRDcluster", nsize);
1535     array->SetOwner(kTRUE);
1536   }
1537   
1538   // Loop through all entries in the tree
1539   Int_t nEntries   = (Int_t) clusterTree->GetEntries();
1540   Int_t nbytes     = 0;
1541   Int_t ncl        = 0;
1542   AliTRDcluster *c = 0x0;
1543   for (Int_t iEntry = 0; iEntry < nEntries; iEntry++) {
1544     // Import the tree
1545     nbytes += clusterTree->GetEvent(iEntry);  
1546     
1547     // Get the number of points in the detector
1548     Int_t nCluster = clusterArray->GetEntriesFast();  
1549     for (Int_t iCluster = 0; iCluster < nCluster; iCluster++) { 
1550       if(!(c = (AliTRDcluster *) clusterArray->UncheckedAt(iCluster))) continue;
1551       c->SetInChamber();
1552       new((*fClusters)[ncl++]) AliTRDcluster(*c);
1553       delete (clusterArray->RemoveAt(iCluster)); 
1554     }
1555
1556   }
1557   delete clusterArray;
1558
1559   return 0;
1560 }
1561
1562 //_____________________________________________________________________________
1563 Int_t AliTRDtrackerV1::LoadClusters(TTree *cTree)
1564 {
1565   //
1566   // Fills clusters into TRD tracking sectors
1567   //
1568   
1569   if(!(fClusters = AliTRDReconstructor::GetClusters())){
1570     if (ReadClusters(fClusters, cTree)) {
1571       AliError("Problem with reading the clusters !");
1572       return 1;
1573     }
1574   }
1575   SetClustersOwner();
1576
1577   if(!fClusters->GetEntriesFast()){ 
1578     AliInfo("No TRD clusters");
1579     return 1;
1580   }
1581
1582   //Int_t nin = 
1583   BuildTrackingContainers();  
1584
1585   //Int_t ncl  = fClusters->GetEntriesFast();
1586   //AliInfo(Form("Clusters %d [%6.2f %% in the active volume]", ncl, 100.*float(nin)/ncl));
1587
1588   return 0;
1589 }
1590
1591 //_____________________________________________________________________________
1592 Int_t AliTRDtrackerV1::LoadClusters(TClonesArray *clusters)
1593 {
1594   //
1595   // Fills clusters into TRD tracking sectors
1596   // Function for use in the HLT
1597   
1598   if(!clusters || !clusters->GetEntriesFast()){ 
1599     AliInfo("No TRD clusters");
1600     return 1;
1601   }
1602
1603   fClusters = clusters;
1604   SetClustersOwner();
1605
1606   //Int_t nin = 
1607   BuildTrackingContainers();  
1608
1609   //Int_t ncl  = fClusters->GetEntriesFast();
1610   //AliInfo(Form("Clusters %d [%6.2f %% in the active volume]", ncl, 100.*float(nin)/ncl));
1611
1612   return 0;
1613 }
1614
1615
1616 //____________________________________________________________________
1617 Int_t AliTRDtrackerV1::BuildTrackingContainers()
1618 {
1619 // Building tracking containers for clusters
1620
1621   Int_t nin =0, icl = fClusters->GetEntriesFast();
1622   while (icl--) {
1623     AliTRDcluster *c = (AliTRDcluster *) fClusters->UncheckedAt(icl);
1624     if(c->IsInChamber()) nin++;
1625     Int_t detector       = c->GetDetector();
1626     Int_t sector         = fGeom->GetSector(detector);
1627     Int_t stack          = fGeom->GetStack(detector);
1628     Int_t layer          = fGeom->GetLayer(detector);
1629     
1630     fTrSec[sector].GetChamber(stack, layer, kTRUE)->InsertCluster(c, icl);
1631   }
1632   
1633   for(int isector =0; isector<AliTRDgeometry::kNsector; isector++){ 
1634     if(!fTrSec[isector].GetNChambers()) continue;
1635     fTrSec[isector].Init(fReconstructor);
1636   }
1637
1638   return nin;
1639 }
1640
1641
1642
1643 //____________________________________________________________________
1644 void AliTRDtrackerV1::UnloadClusters() 
1645
1646   //
1647   // Clears the arrays of clusters and tracks. Resets sectors and timebins 
1648   //
1649
1650   if(fTracks) fTracks->Delete(); 
1651   if(fTracklets) fTracklets->Delete();
1652   if(fClusters && IsClustersOwner()) fClusters->Delete();
1653
1654   for (int i = 0; i < AliTRDgeometry::kNsector; i++) fTrSec[i].Clear();
1655
1656   // Increment the Event Number
1657   AliTRDtrackerDebug::SetEventNumber(AliTRDtrackerDebug::GetEventNumber()  + 1);
1658 }
1659
1660 //_____________________________________________________________________________
1661 Bool_t AliTRDtrackerV1::AdjustSector(AliTRDtrackV1 *track) 
1662 {
1663   //
1664   // Rotates the track when necessary
1665   //
1666
1667   Double_t alpha = AliTRDgeometry::GetAlpha(); 
1668   Double_t y     = track->GetY();
1669   Double_t ymax  = track->GetX()*TMath::Tan(0.5*alpha);
1670
1671   if      (y >  ymax) {
1672     if (!track->Rotate( alpha)) {
1673       return kFALSE;
1674     }
1675   } 
1676   else if (y < -ymax) {
1677     if (!track->Rotate(-alpha)) {
1678       return kFALSE;   
1679     }
1680   } 
1681
1682   return kTRUE;
1683
1684 }
1685
1686
1687 //____________________________________________________________________
1688 AliTRDseedV1* AliTRDtrackerV1::GetTracklet(AliTRDtrackV1 *track, Int_t p, Int_t &idx)
1689 {
1690   // Find tracklet for TRD track <track>
1691   // Parameters
1692   // - track
1693   // - sector
1694   // - plane
1695   // - index
1696   // Output
1697   // tracklet
1698   // index
1699   // Detailed description
1700   //
1701   idx = track->GetTrackletIndex(p);
1702   AliTRDseedV1 *tracklet = (idx==0xffff) ? 0x0 : (AliTRDseedV1*)fTracklets->UncheckedAt(idx);
1703
1704   return tracklet;
1705 }
1706
1707 //____________________________________________________________________
1708 AliTRDseedV1* AliTRDtrackerV1::SetTracklet(AliTRDseedV1 *tracklet)
1709 {
1710   // Add this tracklet to the list of tracklets stored in the tracker
1711   //
1712   // Parameters
1713   //   - tracklet : pointer to the tracklet to be added to the list
1714   //
1715   // Output
1716   //   - the index of the new tracklet in the tracker tracklets list
1717   //
1718   // Detailed description
1719   // Build the tracklets list if it is not yet created (late initialization)
1720   // and adds the new tracklet to the list.
1721   //
1722   if(!fTracklets){
1723     fTracklets = new TClonesArray("AliTRDseedV1", AliTRDgeometry::Nsector()*kMaxTracksStack);
1724     fTracklets->SetOwner(kTRUE);
1725   }
1726   Int_t nentries = fTracklets->GetEntriesFast();
1727   return new ((*fTracklets)[nentries]) AliTRDseedV1(*tracklet);
1728 }
1729
1730 //____________________________________________________________________
1731 AliTRDtrackV1* AliTRDtrackerV1::SetTrack(AliTRDtrackV1 *track)
1732 {
1733   // Add this track to the list of tracks stored in the tracker
1734   //
1735   // Parameters
1736   //   - track : pointer to the track to be added to the list
1737   //
1738   // Output
1739   //   - the pointer added
1740   //
1741   // Detailed description
1742   // Build the tracks list if it is not yet created (late initialization)
1743   // and adds the new track to the list.
1744   //
1745   if(!fTracks){
1746     fTracks = new TClonesArray("AliTRDtrackV1", AliTRDgeometry::Nsector()*kMaxTracksStack);
1747     fTracks->SetOwner(kTRUE);
1748   }
1749   Int_t nentries = fTracks->GetEntriesFast();
1750   return new ((*fTracks)[nentries]) AliTRDtrackV1(*track);
1751 }
1752
1753
1754
1755 //____________________________________________________________________
1756 Int_t AliTRDtrackerV1::Clusters2TracksSM(Int_t sector, AliESDEvent *esd)
1757 {
1758   //
1759   // Steer tracking for one SM.
1760   //
1761   // Parameters :
1762   //   sector  : Array of (SM) propagation layers containing clusters
1763   //   esd     : The current ESD event. On output it contains the also
1764   //             the ESD (TRD) tracks found in this SM. 
1765   //
1766   // Output :
1767   //   Number of tracks found in this TRD supermodule.
1768   // 
1769   // Detailed description
1770   //
1771   // 1. Unpack AliTRDpropagationLayers objects for each stack.
1772   // 2. Launch stack tracking. 
1773   //    See AliTRDtrackerV1::Clusters2TracksStack() for details.
1774   // 3. Pack results in the ESD event.
1775   //
1776   
1777   // allocate space for esd tracks in this SM
1778   TClonesArray esdTrackList("AliESDtrack", 2*kMaxTracksStack);
1779   esdTrackList.SetOwner();
1780   
1781   Int_t nTracks   = 0;
1782   Int_t nChambers = 0;
1783   AliTRDtrackingChamber **stack = 0x0, *chamber = 0x0;
1784   for(int istack = 0; istack<AliTRDgeometry::kNstack; istack++){
1785     if(!(stack = fTrSec[sector].GetStack(istack))) continue;
1786     nChambers = 0;
1787     for(int ilayer=0; ilayer<AliTRDgeometry::kNlayer; ilayer++){
1788       if(!(chamber = stack[ilayer])) continue;
1789       if(chamber->GetNClusters() < fgNTimeBins * fReconstructor->GetRecoParam() ->GetFindableClusters()) continue;
1790       nChambers++;
1791       //AliInfo(Form("sector %d stack %d layer %d clusters %d", sector, istack, ilayer, chamber->GetNClusters()));
1792     }
1793     if(nChambers < 4) continue;
1794     //AliInfo(Form("Doing stack %d", istack));
1795     nTracks += Clusters2TracksStack(stack, &esdTrackList);
1796   }
1797   //AliInfo(Form("Found %d tracks in SM %d [%d]\n", nTracks, sector, esd->GetNumberOfTracks()));
1798   
1799   for(int itrack=0; itrack<nTracks; itrack++)
1800     esd->AddTrack((AliESDtrack*)esdTrackList[itrack]);
1801
1802   // Reset Track and Candidate Number
1803   AliTRDtrackerDebug::SetCandidateNumber(0);
1804   AliTRDtrackerDebug::SetTrackNumber(0);
1805   return nTracks;
1806 }
1807
1808 //____________________________________________________________________
1809 Int_t AliTRDtrackerV1::Clusters2TracksStack(AliTRDtrackingChamber **stack, TClonesArray *esdTrackList)
1810 {
1811   //
1812   // Make tracks in one TRD stack.
1813   //
1814   // Parameters :
1815   //   layer  : Array of stack propagation layers containing clusters
1816   //   esdTrackList  : Array of ESD tracks found by the stand alone tracker. 
1817   //                   On exit the tracks found in this stack are appended.
1818   //
1819   // Output :
1820   //   Number of tracks found in this stack.
1821   // 
1822   // Detailed description
1823   //
1824   // 1. Find the 3 most useful seeding chambers. See BuildSeedingConfigs() for details.
1825   // 2. Steer AliTRDtrackerV1::MakeSeeds() for 3 seeding layer configurations. 
1826   //    See AliTRDtrackerV1::MakeSeeds() for more details.
1827   // 3. Arrange track candidates in decreasing order of their quality
1828   // 4. Classify tracks in 5 categories according to:
1829   //    a) number of layers crossed
1830   //    b) track quality 
1831   // 5. Sign clusters by tracks in decreasing order of track quality
1832   // 6. Build AliTRDtrack out of seeding tracklets
1833   // 7. Cook MC label
1834   // 8. Build ESD track and register it to the output list
1835   //
1836
1837   AliTRDtrackingChamber *chamber = 0x0;
1838   AliTRDseedV1 sseed[kMaxTracksStack*6]; // to be initialized
1839   Int_t pars[4]; // MakeSeeds parameters
1840
1841   //Double_t alpha = AliTRDgeometry::GetAlpha();
1842   //Double_t shift = .5 * alpha;
1843   Int_t configs[kNConfigs];
1844   
1845   // Build initial seeding configurations
1846   Double_t quality = BuildSeedingConfigs(stack, configs);
1847   if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 1){
1848     AliInfo(Form("Plane config %d %d %d Quality %f"
1849     , configs[0], configs[1], configs[2], quality));
1850   }
1851   
1852   // Initialize contors
1853   Int_t ntracks,      // number of TRD track candidates
1854     ntracks1,     // number of registered TRD tracks/iter
1855     ntracks2 = 0; // number of all registered TRD tracks in stack
1856   fSieveSeeding = 0;
1857   do{
1858     // Loop over seeding configurations
1859     ntracks = 0; ntracks1 = 0;
1860     for (Int_t iconf = 0; iconf<3; iconf++) {
1861       pars[0] = configs[iconf];
1862       pars[1] = ntracks;
1863       ntracks = MakeSeeds(stack, &sseed[6*ntracks], pars);
1864       if(ntracks == kMaxTracksStack) break;
1865     }
1866     if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 1) AliInfo(Form("Candidate TRD tracks %d in iteration %d.", ntracks, fSieveSeeding));
1867     
1868     if(!ntracks) break;
1869     
1870     // Sort the seeds according to their quality
1871     Int_t sort[kMaxTracksStack];
1872     TMath::Sort(ntracks, fTrackQuality, sort, kTRUE);
1873   
1874     // Initialize number of tracks so far and logic switches
1875     Int_t ntracks0 = esdTrackList->GetEntriesFast();
1876     Bool_t signedTrack[kMaxTracksStack];
1877     Bool_t fakeTrack[kMaxTracksStack];
1878     for (Int_t i=0; i<ntracks; i++){
1879       signedTrack[i] = kFALSE;
1880       fakeTrack[i] = kFALSE;
1881     }
1882     //AliInfo("Selecting track candidates ...");
1883     
1884     // Sieve clusters in decreasing order of track quality
1885     Double_t trackParams[7];
1886     //          AliTRDseedV1 *lseed = 0x0;
1887     Int_t jSieve = 0, candidates;
1888     do{
1889       //AliInfo(Form("\t\tITER = %i ", jSieve));
1890
1891       // Check track candidates
1892       candidates = 0;
1893       for (Int_t itrack = 0; itrack < ntracks; itrack++) {
1894         Int_t trackIndex = sort[itrack];
1895         if (signedTrack[trackIndex] || fakeTrack[trackIndex]) continue;
1896   
1897         
1898         // Calculate track parameters from tracklets seeds
1899         Int_t labelsall[1000];
1900         Int_t nlabelsall = 0;
1901         Int_t naccepted  = 0;
1902         Int_t ncl        = 0;
1903         Int_t nused      = 0;
1904         Int_t nlayers    = 0;
1905         Int_t findable   = 0;
1906         for (Int_t jLayer = 0; jLayer < kNPlanes; jLayer++) {
1907           Int_t jseed = kNPlanes*trackIndex+jLayer;
1908           if(!sseed[jseed].IsOK()) continue;
1909           if (TMath::Abs(sseed[jseed].GetYref(0) / sseed[jseed].GetX0()) < 0.15) findable++;
1910         
1911           sseed[jseed].UpdateUsed();
1912           ncl   += sseed[jseed].GetN2();
1913           nused += sseed[jseed].GetNUsed();
1914           nlayers++;
1915         
1916 //           // Cooking label
1917 //           for (Int_t itime = 0; itime < fgNTimeBins; itime++) {
1918 //             if(!sseed[jseed].IsUsable(itime)) continue;
1919 //             naccepted++;
1920 //             Int_t tindex = 0, ilab = 0;
1921 //             while(ilab<3 && (tindex = sseed[jseed].GetClusters(itime)->GetLabel(ilab)) >= 0){
1922 //               labelsall[nlabelsall++] = tindex;
1923 //               ilab++;
1924 //             }
1925 //           }
1926         }
1927
1928   // Filter duplicated tracks
1929   if (nused > 30){
1930     //printf("Skip %d nused %d\n", trackIndex, nused);
1931     fakeTrack[trackIndex] = kTRUE;
1932     continue;
1933   }
1934   if (Float_t(nused)/ncl >= .25){
1935     //printf("Skip %d nused/ncl >= .25\n", trackIndex);
1936     fakeTrack[trackIndex] = kTRUE;
1937     continue;
1938   }
1939         
1940   // Classify tracks
1941   Bool_t skip = kFALSE;
1942   switch(jSieve){
1943   case 0:
1944     if(nlayers < 6) {skip = kTRUE; break;}
1945     if(TMath::Log(1.E-9+fTrackQuality[trackIndex]) < -5.){skip = kTRUE; break;}
1946     break;
1947   
1948   case 1:
1949     if(nlayers < findable){skip = kTRUE; break;}
1950     if(TMath::Log(1.E-9+fTrackQuality[trackIndex]) < -4.){skip = kTRUE; break;}
1951     break;
1952   
1953   case 2:
1954     if ((nlayers == findable) || (nlayers == 6)) { skip = kTRUE; break;}
1955     if (TMath::Log(1.E-9+fTrackQuality[trackIndex]) < -6.0){skip = kTRUE; break;}
1956     break;
1957   
1958   case 3:
1959     if (TMath::Log(1.E-9+fTrackQuality[trackIndex]) < -5.){skip = kTRUE; break;}
1960     break;
1961   
1962   case 4:
1963     if (nlayers == 3){skip = kTRUE; break;}
1964     //if (TMath::Log(1.E-9+fTrackQuality[trackIndex]) - nused/(nlayers-3.0) < -15.0){skip = kTRUE; break;}
1965     break;
1966   }
1967   if(skip){
1968     candidates++;
1969     //printf("REJECTED : %d [%d] nlayers %d trackQuality = %e nused %d\n", itrack, trackIndex, nlayers, fTrackQuality[trackIndex], nused);
1970     continue;
1971   }
1972   signedTrack[trackIndex] = kTRUE;
1973             
1974         
1975   // Sign clusters
1976   AliTRDcluster *cl = 0x0; Int_t clusterIndex = -1;
1977   for (Int_t jLayer = 0; jLayer < kNPlanes; jLayer++) {
1978     Int_t jseed = kNPlanes*trackIndex+jLayer;
1979     if(!sseed[jseed].IsOK()) continue;
1980     if(TMath::Abs(sseed[jseed].GetYfit(1) - sseed[jseed].GetYfit(1)) >= .2) continue; // check this condition with Marian
1981     sseed[jseed].UseClusters();
1982     if(!cl){
1983       Int_t ic = 0;
1984       while(!(cl = sseed[jseed].GetClusters(ic))) ic++;
1985       clusterIndex =  sseed[jseed].GetIndexes(ic);
1986     }
1987   }
1988   if(!cl) continue;
1989
1990         
1991   // Build track parameters
1992   AliTRDseedV1 *lseed =&sseed[trackIndex*6];
1993 /*  Int_t idx = 0;
1994   while(idx<3 && !lseed->IsOK()) {
1995     idx++;
1996     lseed++;
1997   }*/
1998   Double_t x = lseed->GetX0();// - 3.5;
1999   trackParams[0] = x; //NEW AB
2000   trackParams[1] = lseed->GetYref(0); // lseed->GetYat(x);  
2001   trackParams[2] = lseed->GetZref(0); // lseed->GetZat(x); 
2002   trackParams[3] = TMath::Sin(TMath::ATan(lseed->GetYref(1)));
2003   trackParams[4] = lseed->GetZref(1) / TMath::Sqrt(1. + lseed->GetYref(1) * lseed->GetYref(1));
2004   trackParams[5] = lseed->GetC();
2005   Int_t ich = 0; while(!(chamber = stack[ich])) ich++;
2006   trackParams[6] = fGeom->GetSector(chamber->GetDetector());/* *alpha+shift;    // Supermodule*/
2007
2008   if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 1){
2009     AliInfo(Form("Track %d [%d] nlayers %d trackQuality = %e nused %d, yref = %3.3f", itrack, trackIndex, nlayers, fTrackQuality[trackIndex], nused, trackParams[1]));
2010           
2011     Int_t nclusters = 0;
2012     AliTRDseedV1 *dseed[6];
2013
2014     // Build track label - what happens if measured data ???
2015     Int_t labels[1000];
2016     Int_t outlab[1000];
2017     Int_t nlab = 0;
2018     for (Int_t iLayer = 0; iLayer < kNPlanes; iLayer++) {
2019       Int_t jseed = kNPlanes*trackIndex+iLayer;
2020       dseed[iLayer] = new AliTRDseedV1(sseed[jseed]);
2021       dseed[iLayer]->SetOwner();
2022       nclusters += sseed[jseed].GetN2();
2023       if(!sseed[jseed].IsOK()) continue;
2024       for(int ilab=0; ilab<2; ilab++){
2025         if(sseed[jseed].GetLabels(ilab) < 0) continue;
2026         labels[nlab] = sseed[jseed].GetLabels(ilab);
2027         nlab++;
2028       }
2029     }
2030     Freq(nlab,labels,outlab,kFALSE);
2031     Int_t   label     = outlab[0];
2032     Int_t   frequency = outlab[1];
2033     Freq(nlabelsall,labelsall,outlab,kFALSE);
2034     Int_t   label1    = outlab[0];
2035     Int_t   label2    = outlab[2];
2036     Float_t fakeratio = (naccepted - outlab[1]) / Float_t(naccepted);
2037
2038     //Int_t eventNrInFile = esd->GetEventNumberInFile();
2039     //AliInfo(Form("Number of clusters %d.", nclusters));
2040     Int_t eventNumber = AliTRDtrackerDebug::GetEventNumber();
2041     Int_t trackNumber = AliTRDtrackerDebug::GetTrackNumber();
2042     Int_t candidateNumber = AliTRDtrackerDebug::GetCandidateNumber();
2043     TTreeSRedirector &cstreamer = *fgDebugStreamer;
2044     cstreamer << "Clusters2TracksStack"
2045         << "EventNumber="               << eventNumber
2046         << "TrackNumber="               << trackNumber
2047         << "CandidateNumber="   << candidateNumber
2048         << "Iter="                              << fSieveSeeding
2049         << "Like="                              << fTrackQuality[trackIndex]
2050         << "S0.="                               << dseed[0]
2051         << "S1.="                               << dseed[1]
2052         << "S2.="                               << dseed[2]
2053         << "S3.="                               << dseed[3]
2054         << "S4.="                               << dseed[4]
2055         << "S5.="                               << dseed[5]
2056         << "p0="                                << trackParams[0]
2057         << "p1="                                << trackParams[1]
2058         << "p2="                                << trackParams[2]
2059         << "p3="                                << trackParams[3]
2060         << "p4="                                << trackParams[4]
2061         << "p5="                                << trackParams[5]
2062         << "p6="                                << trackParams[6]
2063         << "Label="                             << label
2064         << "Label1="                    << label1
2065         << "Label2="                    << label2
2066         << "FakeRatio="                 << fakeratio
2067         << "Freq="                              << frequency
2068         << "Ncl="                               << ncl
2069         << "NLayers="                   << nlayers
2070         << "Findable="                  << findable
2071         << "NUsed="                             << nused
2072         << "\n";
2073   }
2074       
2075   AliTRDtrackV1 *track = MakeTrack(&sseed[trackIndex*kNPlanes], trackParams);
2076   if(!track){
2077     AliWarning("Fail to build a TRD Track.");
2078     continue;
2079   }
2080   //AliInfo("End of MakeTrack()");
2081   AliESDtrack *esdTrack = new ((*esdTrackList)[ntracks0++]) AliESDtrack();
2082   esdTrack->UpdateTrackParams(track, AliESDtrack::kTRDout);
2083   esdTrack->SetLabel(track->GetLabel());
2084   track->UpdateESDtrack(esdTrack);
2085   // write ESD-friends if neccessary
2086   if (fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 0){
2087     AliTRDtrackV1 *calibTrack = new AliTRDtrackV1(*track);
2088     calibTrack->SetOwner();
2089     esdTrack->AddCalibObject(calibTrack);
2090   }
2091   ntracks1++;
2092   AliTRDtrackerDebug::SetTrackNumber(AliTRDtrackerDebug::GetTrackNumber() + 1);
2093       }
2094
2095       jSieve++;
2096     } while(jSieve<5 && candidates); // end track candidates sieve
2097     if(!ntracks1) break;
2098
2099     // increment counters
2100     ntracks2 += ntracks1;
2101
2102     if(fReconstructor->IsHLT()) break;
2103     fSieveSeeding++;
2104
2105     // Rebuild plane configurations and indices taking only unused clusters into account
2106     quality = BuildSeedingConfigs(stack, configs);
2107     if(quality < 1.E-7) break; //fReconstructor->GetRecoParam() ->GetPlaneQualityThreshold()) break;
2108     
2109     for(Int_t ip = 0; ip < kNPlanes; ip++){ 
2110       if(!(chamber = stack[ip])) continue;
2111       chamber->Build(fGeom);//Indices(fSieveSeeding);
2112     }
2113
2114     if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 1){ 
2115       AliInfo(Form("Sieve level %d Plane config %d %d %d Quality %f", fSieveSeeding, configs[0], configs[1], configs[2], quality));
2116     }
2117   } while(fSieveSeeding<10); // end stack clusters sieve
2118   
2119
2120
2121   //AliInfo(Form("Registered TRD tracks %d in stack %d.", ntracks2, pars[1]));
2122
2123   return ntracks2;
2124 }
2125
2126 //___________________________________________________________________
2127 Double_t AliTRDtrackerV1::BuildSeedingConfigs(AliTRDtrackingChamber **stack, Int_t *configs)
2128 {
2129   //
2130   // Assign probabilities to chambers according to their
2131   // capability of producing seeds.
2132   // 
2133   // Parameters :
2134   //
2135   //   layers : Array of stack propagation layers for all 6 chambers in one stack
2136   //   configs : On exit array of configuration indexes (see GetSeedingConfig()
2137   // for details) in the decreasing order of their seeding probabilities. 
2138   //
2139   // Output :
2140   //
2141   //  Return top configuration quality 
2142   //
2143   // Detailed description:
2144   //
2145   // To each chamber seeding configuration (see GetSeedingConfig() for
2146   // the list of all configurations) one defines 2 quality factors:
2147   //  - an apriori topological quality (see GetSeedingConfig() for details) and
2148   //  - a data quality based on the uniformity of the distribution of
2149   //    clusters over the x range (time bins population). See CookChamberQA() for details.
2150   // The overall chamber quality is given by the product of this 2 contributions.
2151   // 
2152
2153   Double_t chamberQ[kNPlanes];
2154   AliTRDtrackingChamber *chamber = 0x0;
2155   for(int iplane=0; iplane<kNPlanes; iplane++){
2156     if(!(chamber = stack[iplane])) continue;
2157     chamberQ[iplane] = (chamber = stack[iplane]) ?  chamber->GetQuality() : 0.;
2158   }
2159
2160   Double_t tconfig[kNConfigs];
2161   Int_t planes[4];
2162   for(int iconf=0; iconf<kNConfigs; iconf++){
2163     GetSeedingConfig(iconf, planes);
2164     tconfig[iconf] = fgTopologicQA[iconf];
2165     for(int iplane=0; iplane<4; iplane++) tconfig[iconf] *= chamberQ[planes[iplane]]; 
2166   }
2167   
2168   TMath::Sort((Int_t)kNConfigs, tconfig, configs, kTRUE);
2169   //    AliInfo(Form("q[%d] = %f", configs[0], tconfig[configs[0]]));
2170   //    AliInfo(Form("q[%d] = %f", configs[1], tconfig[configs[1]]));
2171   //    AliInfo(Form("q[%d] = %f", configs[2], tconfig[configs[2]]));
2172   
2173   return tconfig[configs[0]];
2174 }
2175
2176 //____________________________________________________________________
2177 Int_t AliTRDtrackerV1::MakeSeeds(AliTRDtrackingChamber **stack, AliTRDseedV1 *sseed, Int_t *ipar)
2178 {
2179   //
2180   // Make tracklet seeds in the TRD stack.
2181   //
2182   // Parameters :
2183   //   layers : Array of stack propagation layers containing clusters
2184   //   sseed  : Array of empty tracklet seeds. On exit they are filled.
2185   //   ipar   : Control parameters:
2186   //       ipar[0] -> seeding chambers configuration
2187   //       ipar[1] -> stack index
2188   //       ipar[2] -> number of track candidates found so far
2189   //
2190   // Output :
2191   //   Number of tracks candidates found.
2192   // 
2193   // Detailed description
2194   //
2195   // The following steps are performed:
2196   // 1. Select seeding layers from seeding chambers
2197   // 2. Select seeding clusters from the seeding AliTRDpropagationLayerStack.
2198   //   The clusters are taken from layer 3, layer 0, layer 1 and layer 2, in
2199   //   this order. The parameters controling the range of accepted clusters in
2200   //   layer 0, 1, and 2 are defined in AliTRDchamberTimeBin::BuildCond().
2201   // 3. Helix fit of the cluster set. (see AliTRDtrackerFitter::FitRieman(AliTRDcluster**))
2202   // 4. Initialize seeding tracklets in the seeding chambers.
2203   // 5. Filter 0.
2204   //   Chi2 in the Y direction less than threshold ... (1./(3. - sLayer))
2205   //   Chi2 in the Z direction less than threshold ... (1./(3. - sLayer))
2206   // 6. Attach clusters to seeding tracklets and find linear approximation of
2207   //   the tracklet (see AliTRDseedV1::AttachClustersIter()). The number of used
2208   //   clusters used by current seeds should not exceed ... (25).
2209   // 7. Filter 1.
2210   //   All 4 seeding tracklets should be correctly constructed (see
2211   //   AliTRDseedV1::AttachClustersIter())
2212   // 8. Helix fit of the seeding tracklets
2213   // 9. Filter 2.
2214   //   Likelihood calculation of the fit. (See AliTRDtrackerV1::CookLikelihood() for details)
2215   // 10. Extrapolation of the helix fit to the other 2 chambers:
2216   //    a) Initialization of extrapolation tracklet with fit parameters
2217   //    b) Helix fit of tracklets
2218   //    c) Attach clusters and linear interpolation to extrapolated tracklets
2219   //    d) Helix fit of tracklets
2220   // 11. Improve seeding tracklets quality by reassigning clusters.
2221   //      See AliTRDtrackerV1::ImproveSeedQuality() for details.
2222   // 12. Helix fit of all 6 seeding tracklets and chi2 calculation
2223   // 13. Hyperplane fit and track quality calculation. See AliTRDtrackerFitter::FitHyperplane() for details.
2224   // 14. Cooking labels for tracklets. Should be done only for MC
2225   // 15. Register seeds.
2226   //
2227
2228   AliTRDtrackingChamber *chamber = 0x0;
2229   AliTRDcluster *c[kNSeedPlanes] = {0x0, 0x0, 0x0, 0x0}; // initilize seeding clusters
2230   AliTRDseedV1 *cseed = &sseed[0]; // initialize tracklets for first track
2231   Int_t ncl, mcl; // working variable for looping over clusters
2232   Int_t index[AliTRDchamberTimeBin::kMaxClustersLayer], jndex[AliTRDchamberTimeBin::kMaxClustersLayer];
2233   // chi2 storage
2234   // chi2[0] = tracklet chi2 on the Z direction
2235   // chi2[1] = tracklet chi2 on the R direction
2236   Double_t chi2[4];
2237
2238         // Default positions for the anode wire in all 6 Layers in case of a stack with missing clusters
2239         // Positions taken using cosmic data taken with SM3 after rebuild
2240   Double_t x_def[kNPlanes] = {300.2, 312.8, 325.4, 338, 350.6, 363.2};
2241
2242   // this should be data member of AliTRDtrack
2243   Double_t seedQuality[kMaxTracksStack];
2244   
2245   // unpack control parameters
2246   Int_t config  = ipar[0];
2247   Int_t ntracks = ipar[1];
2248   Int_t planes[kNSeedPlanes]; GetSeedingConfig(config, planes); 
2249   Int_t planesExt[kNPlanes-kNSeedPlanes];         GetExtrapolationConfig(config, planesExt);
2250
2251
2252   // Init chambers geometry
2253   Int_t ic = 0; while(!(chamber = stack[ic])) ic++;
2254   Int_t istack = fGeom->GetStack(chamber->GetDetector());
2255   Double_t hL[kNPlanes];       // Tilting angle
2256   Float_t padlength[kNPlanes]; // pad lenghts
2257   AliTRDpadPlane *pp = 0x0;
2258   for(int iplane=0; iplane<kNPlanes; iplane++){
2259     pp                = fGeom->GetPadPlane(iplane, istack);
2260     hL[iplane]        = TMath::Tan(TMath::DegToRad()*pp->GetTiltingAngle());
2261     padlength[iplane] = pp->GetLengthIPad();
2262   }
2263   
2264   if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 1){
2265     AliInfo(Form("Making seeds Stack[%d] Config[%d] Tracks[%d]...", istack, config, ntracks));
2266   }
2267
2268   ResetSeedTB();
2269   Int_t nlayers = 0;
2270   for(int isl=0; isl<kNSeedPlanes; isl++){ 
2271     if(!(chamber = stack[planes[isl]])) continue;
2272     if(!chamber->GetSeedingLayer(fSeedTB[isl], fGeom, fReconstructor)) continue;
2273     nlayers++;
2274   }
2275   if(nlayers < 4) return 0;
2276   
2277   
2278   // Start finding seeds
2279   Double_t cond0[4], cond1[4], cond2[4];
2280   Int_t icl = 0;
2281   while((c[3] = (*fSeedTB[3])[icl++])){
2282     if(!c[3]) continue;
2283     fSeedTB[0]->BuildCond(c[3], cond0, 0);
2284     fSeedTB[0]->GetClusters(cond0, index, ncl);
2285     //printf("Found c[3] candidates 0 %d\n", ncl);
2286     Int_t jcl = 0;
2287     while(jcl<ncl) {
2288       c[0] = (*fSeedTB[0])[index[jcl++]];
2289       if(!c[0]) continue;
2290       Double_t dx    = c[3]->GetX() - c[0]->GetX();
2291       Double_t theta = (c[3]->GetZ() - c[0]->GetZ())/dx;
2292       Double_t phi   = (c[3]->GetY() - c[0]->GetY())/dx;
2293       fSeedTB[1]->BuildCond(c[0], cond1, 1, theta, phi);
2294       fSeedTB[1]->GetClusters(cond1, jndex, mcl);
2295       //printf("Found c[0] candidates 1 %d\n", mcl);
2296
2297       Int_t kcl = 0;
2298       while(kcl<mcl) {
2299         c[1] = (*fSeedTB[1])[jndex[kcl++]];
2300         if(!c[1]) continue;
2301         fSeedTB[2]->BuildCond(c[1], cond2, 2, theta, phi);
2302         c[2] = fSeedTB[2]->GetNearestCluster(cond2);
2303         //printf("Found c[1] candidate 2 %p\n", c[2]);
2304         if(!c[2]) continue;
2305               
2306         //                              AliInfo("Seeding clusters found. Building seeds ...");
2307         //                              for(Int_t i = 0; i < kNSeedPlanes; i++) printf("%i. coordinates: x = %6.3f, y = %6.3f, z = %6.3f\n", i, c[i]->GetX(), c[i]->GetY(), c[i]->GetZ());
2308               
2309         for (Int_t il = 0; il < kNPlanes; il++) cseed[il].Reset();
2310       
2311         FitRieman(c, chi2);
2312       
2313         AliTRDseedV1 *tseed = 0x0;
2314         for(int iLayer=0; iLayer<kNPlanes; iLayer++){
2315           tseed = &cseed[iLayer];
2316           tseed->SetPlane(iLayer);
2317           tseed->SetTilt(hL[iLayer]);
2318           tseed->SetPadLength(padlength[iLayer]);
2319           tseed->SetReconstructor(fReconstructor);
2320           Double_t x_anode = stack[iLayer] ? stack[iLayer]->GetX() : x_def[iLayer];
2321           tseed->SetX0(x_anode);
2322           tseed->Init(GetRiemanFitter());
2323         }
2324       
2325         Bool_t isFake = kFALSE;
2326         if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) >= 2){
2327           if (c[0]->GetLabel(0) != c[3]->GetLabel(0)) isFake = kTRUE;
2328           if (c[1]->GetLabel(0) != c[3]->GetLabel(0)) isFake = kTRUE;
2329           if (c[2]->GetLabel(0) != c[3]->GetLabel(0)) isFake = kTRUE;
2330       
2331           Double_t xpos[4];
2332           for(Int_t l = 0; l < kNSeedPlanes; l++) xpos[l] = fSeedTB[l]->GetX();
2333           Float_t yref[4];
2334           for(int il=0; il<4; il++) yref[il] = cseed[planes[il]].GetYref(0);
2335           Int_t ll = c[3]->GetLabel(0);
2336           Int_t eventNumber = AliTRDtrackerDebug::GetEventNumber();
2337           Int_t candidateNumber = AliTRDtrackerDebug::GetCandidateNumber();
2338           AliRieman *rim = GetRiemanFitter();
2339           TTreeSRedirector &cs0 = *fgDebugStreamer;
2340           cs0 << "MakeSeeds0"
2341               <<"EventNumber="          << eventNumber
2342               <<"CandidateNumber="      << candidateNumber
2343               <<"isFake="                               << isFake
2344               <<"config="                               << config
2345               <<"label="                                << ll
2346               <<"chi2z="                                << chi2[0]
2347               <<"chi2y="                                << chi2[1]
2348               <<"Y2exp="                                << cond2[0]     
2349               <<"Z2exp="                                << cond2[1]
2350               <<"X0="                                   << xpos[0] //layer[sLayer]->GetX()
2351               <<"X1="                                   << xpos[1] //layer[sLayer + 1]->GetX()
2352               <<"X2="                                   << xpos[2] //layer[sLayer + 2]->GetX()
2353               <<"X3="                                   << xpos[3] //layer[sLayer + 3]->GetX()
2354               <<"yref0="                                << yref[0]
2355               <<"yref1="                                << yref[1]
2356               <<"yref2="                                << yref[2]
2357               <<"yref3="                                << yref[3]
2358               <<"c0.="                          << c[0]
2359               <<"c1.="                          << c[1]
2360               <<"c2.="                          << c[2]
2361               <<"c3.="                          << c[3]
2362               <<"Seed0.="                               << &cseed[planes[0]]
2363               <<"Seed1.="                               << &cseed[planes[1]]
2364               <<"Seed2.="                               << &cseed[planes[2]]
2365               <<"Seed3.="                               << &cseed[planes[3]]
2366               <<"RiemanFitter.="                << rim
2367               <<"\n";
2368         }
2369       
2370         if(chi2[0] > fReconstructor->GetRecoParam() ->GetChi2Z()/*7./(3. - sLayer)*//*iter*/){
2371           //AliInfo(Form("Failed chi2 filter on chi2Z [%f].", chi2[0]));
2372           AliTRDtrackerDebug::SetCandidateNumber(AliTRDtrackerDebug::GetCandidateNumber() + 1);
2373           continue;
2374         }
2375         if(chi2[1] > fReconstructor->GetRecoParam() ->GetChi2Y()/*1./(3. - sLayer)*//*iter*/){
2376           //AliInfo(Form("Failed chi2 filter on chi2Y [%f].", chi2[1]));
2377           AliTRDtrackerDebug::SetCandidateNumber(AliTRDtrackerDebug::GetCandidateNumber() + 1);
2378           continue;
2379         }
2380         //AliInfo("Passed chi2 filter.");
2381       
2382         // try attaching clusters to tracklets
2383         Int_t nUsedCl = 0;
2384         Int_t mlayers = 0;
2385         for(int iLayer=0; iLayer<kNSeedPlanes; iLayer++){
2386           Int_t jLayer = planes[iLayer];
2387           if(!cseed[jLayer].AttachClustersIter(stack[jLayer], 5., kFALSE, c[iLayer])) continue;
2388           nUsedCl += cseed[jLayer].GetNUsed();
2389           if(nUsedCl > 25) break;
2390           mlayers++;
2391         }
2392
2393         if(mlayers < kNSeedPlanes){ 
2394           //AliInfo(Form("Failed updating all seeds %d [%d].", mlayers, kNSeedPlanes));
2395           AliTRDtrackerDebug::SetCandidateNumber(AliTRDtrackerDebug::GetCandidateNumber() + 1);
2396           continue;
2397         }
2398
2399         // temporary exit door for the HLT
2400         if(fReconstructor->IsHLT()){ 
2401           // attach clusters to extrapolation chambers
2402           for(int iLayer=0; iLayer<kNPlanes-kNSeedPlanes; iLayer++){
2403             Int_t jLayer = planesExt[iLayer];
2404             if(!(chamber = stack[jLayer])) continue;
2405             cseed[jLayer].AttachClustersIter(chamber, 1000.);
2406           }
2407           fTrackQuality[ntracks] = 1.; // dummy value
2408           ntracks++;
2409           if(ntracks == kMaxTracksStack){
2410             AliWarning(Form("Number of seeds reached maximum allowed (%d) in stack.", kMaxTracksStack));
2411             return ntracks;
2412           }
2413           cseed += 6; 
2414           continue;
2415         }
2416
2417
2418         // fit tracklets and cook likelihood
2419         FitTiltedRieman(&cseed[0], kTRUE);// Update Seeds and calculate Likelihood
2420         chi2[0] = GetChi2Y(&cseed[0]);
2421         chi2[1] = GetChi2Z(&cseed[0]);
2422         //Chi2 definitions in testing stage
2423         //chi2[0] = GetChi2YTest(&cseed[0]);
2424         //chi2[1] = GetChi2ZTest(&cseed[0]);
2425         Double_t like = CookLikelihood(&cseed[0], planes, chi2); // to be checked
2426       
2427         if (TMath::Log(1.E-9 + like) < fReconstructor->GetRecoParam() ->GetTrackLikelihood()){
2428           //AliInfo(Form("Failed likelihood %f[%e].", TMath::Log(1.E-9 + like), like));
2429           AliTRDtrackerDebug::SetCandidateNumber(AliTRDtrackerDebug::GetCandidateNumber() + 1);
2430           continue;
2431         }
2432         //AliInfo(Form("Passed likelihood %f[%e].", TMath::Log(1.E-9 + like), like));
2433       
2434         // book preliminary results
2435         seedQuality[ntracks] = like;
2436         fSeedLayer[ntracks]  = config;/*sLayer;*/
2437       
2438         // attach clusters to the extrapolation seeds
2439         Int_t nusedf   = 0; // debug value
2440         for(int iLayer=0; iLayer<kNPlanes-kNSeedPlanes; iLayer++){
2441           Int_t jLayer = planesExt[iLayer];
2442           if(!(chamber = stack[jLayer])) continue;
2443       
2444           // fit extrapolated seed
2445           if ((jLayer == 0) && !(cseed[1].IsOK())) continue;
2446           if ((jLayer == 5) && !(cseed[4].IsOK())) continue;
2447           AliTRDseedV1 pseed = cseed[jLayer];
2448           if(!pseed.AttachClustersIter(chamber, 1000.)) continue;
2449           cseed[jLayer] = pseed;
2450           nusedf += cseed[jLayer].GetNUsed(); // debug value
2451           FitTiltedRieman(cseed,  kTRUE);
2452         }
2453       
2454         // AliInfo("Extrapolation done.");
2455         // Debug Stream containing all the 6 tracklets
2456         if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) >= 2){
2457           TTreeSRedirector &cstreamer = *fgDebugStreamer;
2458           TLinearFitter *tiltedRieman = GetTiltedRiemanFitter();
2459           Int_t eventNumber             = AliTRDtrackerDebug::GetEventNumber();
2460           Int_t candidateNumber = AliTRDtrackerDebug::GetCandidateNumber();
2461           cstreamer << "MakeSeeds1"
2462               << "EventNumber="         << eventNumber
2463               << "CandidateNumber="     << candidateNumber
2464               << "S0.="                                 << &cseed[0]
2465               << "S1.="                                 << &cseed[1]
2466               << "S2.="                                 << &cseed[2]
2467               << "S3.="                                 << &cseed[3]
2468               << "S4.="                                 << &cseed[4]
2469               << "S5.="                                 << &cseed[5]
2470               << "FitterT.="                    << tiltedRieman
2471               << "\n";
2472         }
2473               
2474         if(fReconstructor->GetRecoParam()->HasImproveTracklets() && ImproveSeedQuality(stack, cseed) < 4){
2475           AliTRDtrackerDebug::SetCandidateNumber(AliTRDtrackerDebug::GetCandidateNumber() + 1);
2476           continue;
2477         }
2478         //AliInfo("Improve seed quality done.");
2479       
2480         // fit full track and cook likelihoods
2481         //                              Double_t curv = FitRieman(&cseed[0], chi2);
2482         //                              Double_t chi2ZF = chi2[0] / TMath::Max((mlayers - 3.), 1.);
2483         //                              Double_t chi2RF = chi2[1] / TMath::Max((mlayers - 3.), 1.);
2484       
2485         // do the final track fitting (Once with vertex constraint and once without vertex constraint)
2486         Double_t chi2Vals[3];
2487         chi2Vals[0] = FitTiltedRieman(&cseed[0], kFALSE);
2488         if(fReconstructor->GetRecoParam() ->IsVertexConstrained())
2489           chi2Vals[1] = FitTiltedRiemanConstraint(&cseed[0], GetZ()); // Do Vertex Constrained fit if desired
2490         else
2491           chi2Vals[1] = 1.;
2492         chi2Vals[2] = GetChi2Z(&cseed[0]) / TMath::Max((mlayers - 3.), 1.);
2493         // Chi2 definitions in testing stage
2494         //chi2Vals[2] = GetChi2ZTest(&cseed[0]);
2495         fTrackQuality[ntracks] = CalculateTrackLikelihood(&cseed[0], &chi2Vals[0]);
2496         //AliInfo("Hyperplane fit done\n");
2497       
2498         // finalize tracklets
2499         Int_t labels[12];
2500         Int_t outlab[24];
2501         Int_t nlab = 0;
2502         for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
2503           if (!cseed[iLayer].IsOK()) continue;
2504       
2505           if (cseed[iLayer].GetLabels(0) >= 0) {
2506             labels[nlab] = cseed[iLayer].GetLabels(0);
2507             nlab++;
2508           }
2509       
2510           if (cseed[iLayer].GetLabels(1) >= 0) {
2511             labels[nlab] = cseed[iLayer].GetLabels(1);
2512             nlab++;
2513           }
2514         }
2515         Freq(nlab,labels,outlab,kFALSE);
2516         Int_t label     = outlab[0];
2517         Int_t frequency = outlab[1];
2518         for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
2519           cseed[iLayer].SetFreq(frequency);
2520           cseed[iLayer].SetChi2Z(chi2[1]);
2521         }
2522             
2523         if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) >= 2){
2524           TTreeSRedirector &cstreamer = *fgDebugStreamer;
2525           Int_t eventNumber = AliTRDtrackerDebug::GetEventNumber();
2526           Int_t candidateNumber = AliTRDtrackerDebug::GetCandidateNumber();
2527           TLinearFitter *fitterTC = GetTiltedRiemanFitterConstraint();
2528           TLinearFitter *fitterT = GetTiltedRiemanFitter();
2529           cstreamer << "MakeSeeds2"
2530               << "EventNumber="                 << eventNumber
2531               << "CandidateNumber="     << candidateNumber
2532               << "Chi2TR="                      << chi2Vals[0]
2533               << "Chi2TC="                      << chi2Vals[1]
2534               << "Nlayers="                     << mlayers
2535               << "NUsedS="                      << nUsedCl
2536               << "NUsed="                               << nusedf
2537               << "Like="                                << like
2538               << "S0.="                         << &cseed[0]
2539               << "S1.="                         << &cseed[1]
2540               << "S2.="                         << &cseed[2]
2541               << "S3.="                         << &cseed[3]
2542               << "S4.="                         << &cseed[4]
2543               << "S5.="                         << &cseed[5]
2544               << "Label="                               << label
2545               << "Freq="                                << frequency
2546               << "FitterT.="                    << fitterT
2547               << "FitterTC.="                   << fitterTC
2548               << "\n";
2549         }
2550               
2551         ntracks++;
2552         AliTRDtrackerDebug::SetCandidateNumber(AliTRDtrackerDebug::GetCandidateNumber() + 1);
2553         if(ntracks == kMaxTracksStack){
2554           AliWarning(Form("Number of seeds reached maximum allowed (%d) in stack.", kMaxTracksStack));
2555           return ntracks;
2556         }
2557         cseed += 6;
2558       }
2559     }
2560   }
2561   
2562   return ntracks;
2563 }
2564
2565 //_____________________________________________________________________________
2566 AliTRDtrackV1* AliTRDtrackerV1::MakeTrack(AliTRDseedV1 *seeds, Double_t *params)
2567 {
2568   //
2569   // Build a TRD track out of tracklet candidates
2570   //
2571   // Parameters :
2572   //   seeds  : array of tracklets
2573   //   params : track parameters (see MakeSeeds() function body for a detailed description)
2574   //
2575   // Output :
2576   //   The TRD track.
2577   //
2578   // Detailed description
2579   //
2580   // To be discussed with Marian !!
2581   //
2582
2583   AliTRDCalibraFillHisto *calibra = AliTRDCalibraFillHisto::Instance();
2584   if (!calibra) AliInfo("Could not get Calibra instance\n");
2585
2586   Double_t alpha = AliTRDgeometry::GetAlpha();
2587   Double_t shift = AliTRDgeometry::GetAlpha()/2.0;
2588   Double_t c[15];
2589
2590   c[ 0] = 0.2;
2591   c[ 1] = 0.0; c[ 2] = 2.0;
2592   c[ 3] = 0.0; c[ 4] = 0.0; c[ 5] = 0.02;
2593   c[ 6] = 0.0; c[ 7] = 0.0; c[ 8] = 0.0;  c[ 9] = 0.1;
2594   c[10] = 0.0; c[11] = 0.0; c[12] = 0.0;  c[13] = 0.0; c[14] = params[5]*params[5]*0.01;
2595
2596   AliTRDtrackV1 track(seeds, &params[1], c, params[0], params[6]*alpha+shift);
2597   track.PropagateTo(params[0]-5.0);
2598   track.ResetCovariance(1);
2599   Int_t nc = TMath::Abs(FollowBackProlongation(track));
2600   if (nc < 30) return 0x0;
2601
2602   AliTRDtrackV1 *ptrTrack = SetTrack(&track);
2603   ptrTrack->CookLabel(.9);
2604   // computes PID for track
2605   ptrTrack->CookPID();
2606   // update calibration references using this track
2607   if(calibra->GetHisto2d()) calibra->UpdateHistogramsV1(ptrTrack);
2608
2609   return ptrTrack;
2610 }
2611
2612
2613 //____________________________________________________________________
2614 Int_t AliTRDtrackerV1::ImproveSeedQuality(AliTRDtrackingChamber **stack, AliTRDseedV1 *cseed)
2615 {
2616   //
2617   // Sort tracklets according to "quality" and try to "improve" the first 4 worst
2618   //
2619   // Parameters :
2620   //  layers : Array of propagation layers for a stack/supermodule
2621   //  cseed  : Array of 6 seeding tracklets which has to be improved
2622   // 
2623   // Output :
2624   //   cssed : Improved seeds
2625   // 
2626   // Detailed description
2627   //
2628   // Iterative procedure in which new clusters are searched for each
2629   // tracklet seed such that the seed quality (see AliTRDseed::GetQuality())
2630   // can be maximized. If some optimization is found the old seeds are replaced.
2631   //
2632   // debug level: 7
2633   //
2634   
2635   // make a local working copy
2636   AliTRDtrackingChamber *chamber = 0x0;
2637   AliTRDseedV1 bseed[6];
2638   Int_t nLayers = 0;
2639   for (Int_t jLayer = 0; jLayer < 6; jLayer++) bseed[jLayer] = cseed[jLayer];
2640   
2641   Float_t lastquality = 10000.0;
2642   Float_t lastchi2    = 10000.0;
2643   Float_t chi2        =  1000.0;
2644
2645   for (Int_t iter = 0; iter < 4; iter++) {
2646     Float_t sumquality = 0.0;
2647     Float_t squality[6];
2648     Int_t   sortindexes[6];
2649
2650     for (Int_t jLayer = 0; jLayer < 6; jLayer++) {
2651       squality[jLayer]  = bseed[jLayer].IsOK() ? bseed[jLayer].GetQuality(kTRUE) : 1000.;
2652       sumquality += squality[jLayer];
2653     }
2654     if ((sumquality >= lastquality) || (chi2       >     lastchi2)) break;
2655
2656     nLayers = 0;
2657     lastquality = sumquality;
2658     lastchi2    = chi2;
2659     if (iter > 0) for (Int_t jLayer = 0; jLayer < 6; jLayer++) cseed[jLayer] = bseed[jLayer];
2660
2661     TMath::Sort(6, squality, sortindexes, kFALSE);
2662     for (Int_t jLayer = 5; jLayer > 1; jLayer--) {
2663       Int_t bLayer = sortindexes[jLayer];
2664       if(!(chamber = stack[bLayer])) continue;
2665       bseed[bLayer].AttachClustersIter(chamber, squality[bLayer], kTRUE);
2666       if(bseed[bLayer].IsOK()) nLayers++;
2667     }
2668
2669     chi2 = FitTiltedRieman(bseed, kTRUE);
2670     if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) >= 7){
2671       Int_t eventNumber                 = AliTRDtrackerDebug::GetEventNumber();
2672       Int_t candidateNumber = AliTRDtrackerDebug::GetCandidateNumber();
2673       TLinearFitter *tiltedRieman = GetTiltedRiemanFitter();
2674       TTreeSRedirector &cstreamer = *fgDebugStreamer;
2675       cstreamer << "ImproveSeedQuality"
2676     << "EventNumber="           << eventNumber
2677     << "CandidateNumber="       << candidateNumber
2678     << "Iteration="                             << iter
2679     << "S0.="                                                   << &bseed[0]
2680     << "S1.="                                                   << &bseed[1]
2681     << "S2.="                                                   << &bseed[2]
2682     << "S3.="                                                   << &bseed[3]
2683     << "S4.="                                                   << &bseed[4]
2684     << "S5.="                                                   << &bseed[5]
2685     << "FitterT.="                              << tiltedRieman
2686     << "\n";
2687     }
2688   } // Loop: iter
2689   
2690   // we are sure that at least 2 tracklets are OK !
2691   return nLayers+2;
2692 }
2693
2694 //_________________________________________________________________________
2695 Double_t AliTRDtrackerV1::CalculateTrackLikelihood(AliTRDseedV1 *tracklets, Double_t *chi2){
2696   //
2697   // Calculates the Track Likelihood value. This parameter serves as main quality criterion for 
2698   // the track selection
2699   // The likelihood value containes:
2700   //    - The chi2 values from the both fitters and the chi2 values in z-direction from a linear fit
2701   //    - The Sum of the Parameter  |slope_ref - slope_fit|/Sigma of the tracklets
2702   // For all Parameters an exponential dependency is used
2703   //
2704   // Parameters: - Array of tracklets (AliTRDseedV1) related to the track candidate
2705   //             - Array of chi2 values: 
2706   //                 * Non-Constrained Tilted Riemann fit
2707   //                 * Vertex-Constrained Tilted Riemann fit
2708   //                 * z-Direction from Linear fit
2709   // Output:     - The calculated track likelihood
2710   //
2711   // debug level 2
2712   //
2713
2714   Double_t sumdaf = 0, nLayers = 0;
2715   for (Int_t iLayer = 0; iLayer < kNPlanes; iLayer++) {
2716     if(!tracklets[iLayer].IsOK()) continue;
2717     sumdaf += TMath::Abs((tracklets[iLayer].GetYfit(1) - tracklets[iLayer].GetYref(1))/ tracklets[iLayer].GetSigmaY2());
2718     nLayers++;
2719   }
2720   sumdaf /= Float_t (nLayers - 2.0);
2721   
2722   Double_t likeChi2Z  = TMath::Exp(-chi2[2] * 0.14);                    // Chi2Z 
2723   Double_t likeChi2TC = (fReconstructor->GetRecoParam() ->IsVertexConstrained()) ? 
2724                                                                                         TMath::Exp(-chi2[1] * 0.677) : 1;                       // Constrained Tilted Riemann
2725   Double_t likeChi2TR = TMath::Exp(-chi2[0] * 0.78);                    // Non-constrained Tilted Riemann
2726   Double_t likeAF     = TMath::Exp(-sumdaf * 3.23);
2727   Double_t trackLikelihood     = likeChi2Z * likeChi2TR * likeAF;
2728
2729   if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) >= 2){
2730     Int_t eventNumber = AliTRDtrackerDebug::GetEventNumber();
2731     Int_t candidateNumber = AliTRDtrackerDebug::GetCandidateNumber();
2732     TTreeSRedirector &cstreamer = *fgDebugStreamer;
2733     cstreamer << "CalculateTrackLikelihood0"
2734         << "EventNumber="                       << eventNumber
2735         << "CandidateNumber="   << candidateNumber
2736         << "LikeChi2Z="                         << likeChi2Z
2737         << "LikeChi2TR="                        << likeChi2TR
2738         << "LikeChi2TC="                        << likeChi2TC
2739         << "LikeAF="                                    << likeAF
2740         << "TrackLikelihood=" << trackLikelihood
2741         << "\n";
2742   }
2743
2744   return trackLikelihood;
2745 }
2746
2747 //____________________________________________________________________
2748 Double_t AliTRDtrackerV1::CookLikelihood(AliTRDseedV1 *cseed, Int_t planes[4]
2749           , Double_t *chi2)
2750 {
2751   //
2752   // Calculate the probability of this track candidate.
2753   //
2754   // Parameters :
2755   //   cseeds : array of candidate tracklets
2756   //   planes : array of seeding planes (see seeding configuration)
2757   //   chi2   : chi2 values (on the Z and Y direction) from the rieman fit of the track.
2758   //
2759   // Output :
2760   //   likelihood value
2761   // 
2762   // Detailed description
2763   //
2764   // The track quality is estimated based on the following 4 criteria:
2765   //  1. precision of the rieman fit on the Y direction (likea)
2766   //  2. chi2 on the Y direction (likechi2y)
2767   //  3. chi2 on the Z direction (likechi2z)
2768   //  4. number of attached clusters compared to a reference value 
2769   //     (see AliTRDrecoParam::fkFindable) (likeN)
2770   //
2771   // The distributions for each type of probabilities are given below as of
2772   // (date). They have to be checked to assure consistency of estimation.
2773   //
2774
2775   // ratio of the total number of clusters/track which are expected to be found by the tracker.
2776   Float_t fgFindable = fReconstructor->GetRecoParam() ->GetFindableClusters();
2777
2778   
2779   Int_t nclusters = 0;
2780   Double_t sumda = 0.;
2781   for(UChar_t ilayer = 0; ilayer < 4; ilayer++){
2782     Int_t jlayer = planes[ilayer];
2783     nclusters += cseed[jlayer].GetN2();
2784     sumda += TMath::Abs(cseed[jlayer].GetYfitR(1) - cseed[jlayer].GetYref(1));
2785   }
2786   Double_t likea     = TMath::Exp(-sumda*10.6);
2787   Double_t likechi2y  = 0.0000000001;
2788   if (chi2[0] < 0.5) likechi2y += TMath::Exp(-TMath::Sqrt(chi2[0]) * 7.73);
2789   Double_t likechi2z = TMath::Exp(-chi2[1] * 0.088) / TMath::Exp(-chi2[1] * 0.019);
2790   Int_t enc = Int_t(fgFindable*4.*fgNTimeBins);         // Expected Number Of Clusters, normally 72
2791   Double_t likeN     = TMath::Exp(-(enc - nclusters) * 0.19);
2792   
2793   Double_t like      = likea * likechi2y * likechi2z * likeN;
2794
2795   //    AliInfo(Form("sumda(%f) chi2[0](%f) chi2[1](%f) likea(%f) likechi2y(%f) likechi2z(%f) nclusters(%d) likeN(%f)", sumda, chi2[0], chi2[1], likea, likechi2y, likechi2z, nclusters, likeN));
2796   if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) >= 2){
2797     Int_t eventNumber = AliTRDtrackerDebug::GetEventNumber();
2798     Int_t candidateNumber = AliTRDtrackerDebug::GetCandidateNumber();
2799     // The Debug Stream contains the seed 
2800     TTreeSRedirector &cstreamer = *fgDebugStreamer;
2801     cstreamer << "CookLikelihood"
2802         << "EventNumber="                       << eventNumber
2803         << "CandidateNumber=" << candidateNumber
2804         << "tracklet0.="                        << &cseed[0]
2805         << "tracklet1.="                        << &cseed[1]
2806         << "tracklet2.="                        << &cseed[2]
2807         << "tracklet3.="                        << &cseed[3]
2808         << "tracklet4.="                        << &cseed[4]
2809         << "tracklet5.="                        << &cseed[5]
2810         << "sumda="                                             << sumda
2811         << "chi0="                                              << chi2[0]
2812         << "chi1="                                              << chi2[1]
2813         << "likea="                                             << likea
2814         << "likechi2y="                         << likechi2y
2815         << "likechi2z="                         << likechi2z
2816         << "nclusters="                         << nclusters
2817         << "likeN="                                             << likeN
2818         << "like="                                              << like
2819         << "\n";
2820   }
2821
2822   return like;
2823 }
2824
2825
2826
2827 //____________________________________________________________________
2828 void AliTRDtrackerV1::GetSeedingConfig(Int_t iconfig, Int_t planes[4])
2829 {
2830   //
2831   // Map seeding configurations to detector planes.
2832   //
2833   // Parameters :
2834   //   iconfig : configuration index
2835   //   planes  : member planes of this configuration. On input empty.
2836   //
2837   // Output :
2838   //   planes : contains the planes which are defining the configuration
2839   // 
2840   // Detailed description
2841   //
2842   // Here is the list of seeding planes configurations together with
2843   // their topological classification:
2844   //
2845   //  0 - 5432 TQ 0
2846   //  1 - 4321 TQ 0
2847   //  2 - 3210 TQ 0
2848   //  3 - 5321 TQ 1
2849   //  4 - 4210 TQ 1
2850   //  5 - 5431 TQ 1
2851   //  6 - 4320 TQ 1
2852   //  7 - 5430 TQ 2
2853   //  8 - 5210 TQ 2
2854   //  9 - 5421 TQ 3
2855   // 10 - 4310 TQ 3
2856   // 11 - 5410 TQ 4
2857   // 12 - 5420 TQ 5
2858   // 13 - 5320 TQ 5
2859   // 14 - 5310 TQ 5
2860   //
2861   // The topologic quality is modeled as follows:
2862   // 1. The general model is define by the equation:
2863   //  p(conf) = exp(-conf/2)
2864   // 2. According to the topologic classification, configurations from the same
2865   //    class are assigned the agerage value over the model values.
2866   // 3. Quality values are normalized.
2867   // 
2868   // The topologic quality distribution as function of configuration is given below:
2869   //Begin_Html
2870   // <img src="gif/topologicQA.gif">
2871   //End_Html
2872   //
2873
2874   switch(iconfig){
2875   case 0: // 5432 TQ 0
2876     planes[0] = 2;
2877     planes[1] = 3;
2878     planes[2] = 4;
2879     planes[3] = 5;
2880     break;
2881   case 1: // 4321 TQ 0
2882     planes[0] = 1;
2883     planes[1] = 2;
2884     planes[2] = 3;
2885     planes[3] = 4;
2886     break;
2887   case 2: // 3210 TQ 0
2888     planes[0] = 0;
2889     planes[1] = 1;
2890     planes[2] = 2;
2891     planes[3] = 3;
2892     break;
2893   case 3: // 5321 TQ 1
2894     planes[0] = 1;
2895     planes[1] = 2;
2896     planes[2] = 3;
2897     planes[3] = 5;
2898     break;
2899   case 4: // 4210 TQ 1
2900     planes[0] = 0;
2901     planes[1] = 1;
2902     planes[2] = 2;
2903     planes[3] = 4;
2904     break;
2905   case 5: // 5431 TQ 1
2906     planes[0] = 1;
2907     planes[1] = 3;
2908     planes[2] = 4;
2909     planes[3] = 5;
2910     break;
2911   case 6: // 4320 TQ 1
2912     planes[0] = 0;
2913     planes[1] = 2;
2914     planes[2] = 3;
2915     planes[3] = 4;
2916     break;
2917   case 7: // 5430 TQ 2
2918     planes[0] = 0;
2919     planes[1] = 3;
2920     planes[2] = 4;
2921     planes[3] = 5;
2922     break;
2923   case 8: // 5210 TQ 2
2924     planes[0] = 0;
2925     planes[1] = 1;
2926     planes[2] = 2;
2927     planes[3] = 5;
2928     break;
2929   case 9: // 5421 TQ 3
2930     planes[0] = 1;
2931     planes[1] = 2;
2932     planes[2] = 4;
2933     planes[3] = 5;
2934     break;
2935   case 10: // 4310 TQ 3
2936     planes[0] = 0;
2937     planes[1] = 1;
2938     planes[2] = 3;
2939     planes[3] = 4;
2940     break;
2941   case 11: // 5410 TQ 4
2942     planes[0] = 0;
2943     planes[1] = 1;
2944     planes[2] = 4;
2945     planes[3] = 5;
2946     break;
2947   case 12: // 5420 TQ 5
2948     planes[0] = 0;
2949     planes[1] = 2;
2950     planes[2] = 4;
2951     planes[3] = 5;
2952     break;
2953   case 13: // 5320 TQ 5
2954     planes[0] = 0;
2955     planes[1] = 2;
2956     planes[2] = 3;
2957     planes[3] = 5;
2958     break;
2959   case 14: // 5310 TQ 5
2960     planes[0] = 0;
2961     planes[1] = 1;
2962     planes[2] = 3;
2963     planes[3] = 5;
2964     break;
2965   }
2966 }
2967
2968 //____________________________________________________________________
2969 void AliTRDtrackerV1::GetExtrapolationConfig(Int_t iconfig, Int_t planes[2])
2970 {
2971   //
2972   // Returns the extrapolation planes for a seeding configuration.
2973   //
2974   // Parameters :
2975   //   iconfig : configuration index
2976   //   planes  : planes which are not in this configuration. On input empty.
2977   //
2978   // Output :
2979   //   planes : contains the planes which are not in the configuration
2980   // 
2981   // Detailed description
2982   //
2983
2984   switch(iconfig){
2985   case 0: // 5432 TQ 0
2986     planes[0] = 1;
2987     planes[1] = 0;
2988     break;
2989   case 1: // 4321 TQ 0
2990     planes[0] = 5;
2991     planes[1] = 0;
2992     break;
2993   case 2: // 3210 TQ 0
2994     planes[0] = 4;
2995     planes[1] = 5;
2996     break;
2997   case 3: // 5321 TQ 1
2998     planes[0] = 4;
2999     planes[1] = 0;
3000     break;
3001   case 4: // 4210 TQ 1
3002     planes[0] = 5;
3003     planes[1] = 3;
3004     break;
3005   case 5: // 5431 TQ 1
3006     planes[0] = 2;
3007     planes[1] = 0;
3008     break;
3009   case 6: // 4320 TQ 1
3010     planes[0] = 5;
3011     planes[1] = 1;
3012     break;
3013   case 7: // 5430 TQ 2
3014     planes[0] = 2;
3015     planes[1] = 1;
3016     break;
3017   case 8: // 5210 TQ 2
3018     planes[0] = 4;
3019     planes[1] = 3;
3020     break;
3021   case 9: // 5421 TQ 3
3022     planes[0] = 3;
3023     planes[1] = 0;
3024     break;
3025   case 10: // 4310 TQ 3
3026     planes[0] = 5;
3027     planes[1] = 2;
3028     break;
3029   case 11: // 5410 TQ 4
3030     planes[0] = 3;
3031     planes[1] = 2;
3032     break;
3033   case 12: // 5420 TQ 5
3034     planes[0] = 3;
3035     planes[1] = 1;
3036     break;
3037   case 13: // 5320 TQ 5
3038     planes[0] = 4;
3039     planes[1] = 1;
3040     break;
3041   case 14: // 5310 TQ 5
3042     planes[0] = 4;
3043     planes[1] = 2;
3044     break;
3045   }
3046 }
3047
3048 //____________________________________________________________________
3049 AliCluster* AliTRDtrackerV1::GetCluster(Int_t idx) const
3050 {
3051   Int_t ncls = fClusters->GetEntriesFast();
3052   return idx >= 0 && idx < ncls ? (AliCluster*)fClusters->UncheckedAt(idx) : 0x0;
3053 }
3054
3055 //____________________________________________________________________
3056 AliTRDseedV1* AliTRDtrackerV1::GetTracklet(Int_t idx) const
3057 {
3058   Int_t ntrklt = fTracklets->GetEntriesFast();
3059   return idx >= 0 && idx < ntrklt ? (AliTRDseedV1*)fTracklets->UncheckedAt(idx) : 0x0;
3060 }
3061
3062 //____________________________________________________________________
3063 AliKalmanTrack* AliTRDtrackerV1::GetTrack(Int_t idx) const
3064 {
3065   Int_t ntrk = fTracks->GetEntriesFast();
3066   return idx >= 0 && idx < ntrk ? (AliKalmanTrack*)fTracks->UncheckedAt(idx) : 0x0;
3067 }
3068
3069 //____________________________________________________________________
3070 Float_t AliTRDtrackerV1::CalculateReferenceX(AliTRDseedV1 *tracklets){
3071   //
3072   // Calculates the reference x-position for the tilted Rieman fit defined as middle
3073   // of the stack (middle between layers 2 and 3). For the calculation all the tracklets
3074   // are taken into account
3075   // 
3076   // Parameters:        - Array of tracklets(AliTRDseedV1)
3077   //
3078   // Output:            - The reference x-position(Float_t)
3079   //
3080   Int_t nDistances = 0;
3081   Float_t meanDistance = 0.;
3082   Int_t startIndex = 5;
3083   for(Int_t il =5; il > 0; il--){
3084     if(tracklets[il].IsOK() && tracklets[il -1].IsOK()){
3085       Float_t xdiff = tracklets[il].GetX0() - tracklets[il -1].GetX0();
3086       meanDistance += xdiff;
3087       nDistances++;
3088     }
3089     if(tracklets[il].IsOK()) startIndex = il;
3090   }
3091   if(tracklets[0].IsOK()) startIndex = 0;
3092   if(!nDistances){
3093     // We should normally never get here
3094     Float_t xpos[2]; memset(xpos, 0, sizeof(Float_t) * 2);
3095     Int_t iok = 0, idiff = 0;
3096     // This attempt is worse and should be avoided:
3097     // check for two chambers which are OK and repeat this without taking the mean value
3098     // Strategy avoids a division by 0;
3099     for(Int_t il = 5; il >= 0; il--){
3100       if(tracklets[il].IsOK()){
3101   xpos[iok] = tracklets[il].GetX0();
3102   iok++;
3103   startIndex = il;
3104       }
3105       if(iok) idiff++;  // to get the right difference;
3106       if(iok > 1) break;
3107     }
3108     if(iok > 1){
3109       meanDistance = (xpos[0] - xpos[1])/idiff;
3110     }
3111     else{
3112       // we have do not even have 2 layers which are OK? The we do not need to fit at all
3113       return 331.;
3114     }
3115   }
3116   else{
3117     meanDistance /= nDistances;
3118   }
3119   return tracklets[startIndex].GetX0() + (2.5 - startIndex) * meanDistance - 0.5 * (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick());
3120 }
3121
3122 //_____________________________________________________________________________
3123 Int_t AliTRDtrackerV1::Freq(Int_t n, const Int_t *inlist
3124           , Int_t *outlist, Bool_t down)
3125 {    
3126   //
3127   // Sort eleements according occurancy 
3128   // The size of output array has is 2*n 
3129   //
3130
3131   if (n <= 0) {
3132     return 0;
3133   }
3134
3135   Int_t *sindexS = new Int_t[n];   // Temporary array for sorting
3136   Int_t *sindexF = new Int_t[2*n];   
3137   for (Int_t i = 0; i < n; i++) {
3138     sindexF[i] = 0;
3139   }
3140
3141   TMath::Sort(n,inlist,sindexS,down); 
3142
3143   Int_t last     = inlist[sindexS[0]];
3144   Int_t val      = last;
3145   sindexF[0]     = 1;
3146   sindexF[0+n]   = last;
3147   Int_t countPos = 0;
3148
3149   // Find frequency
3150   for (Int_t i = 1; i < n; i++) {
3151     val = inlist[sindexS[i]];
3152     if (last == val) {
3153       sindexF[countPos]++;
3154     }
3155     else {      
3156       countPos++;
3157       sindexF[countPos+n] = val;
3158       sindexF[countPos]++;
3159       last                = val;
3160     }
3161   }
3162   if (last == val) {
3163     countPos++;
3164   }
3165
3166   // Sort according frequency
3167   TMath::Sort(countPos,sindexF,sindexS,kTRUE);
3168
3169   for (Int_t i = 0; i < countPos; i++) {
3170     outlist[2*i  ] = sindexF[sindexS[i]+n];
3171     outlist[2*i+1] = sindexF[sindexS[i]];
3172   }
3173
3174   delete [] sindexS;
3175   delete [] sindexF;
3176   
3177   return countPos;
3178
3179 }
3180
3181
3182 //____________________________________________________________________
3183 void AliTRDtrackerV1::SetReconstructor(const AliTRDReconstructor *rec)
3184 {
3185   fReconstructor = rec;
3186   if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 1){
3187     if(!fgDebugStreamer){
3188       TDirectory *savedir = gDirectory;
3189       fgDebugStreamer = new TTreeSRedirector("TRD.TrackerDebug.root");
3190       savedir->cd();
3191     }
3192   }     
3193 }
3194
3195 //_____________________________________________________________________________
3196 Float_t AliTRDtrackerV1::GetChi2Y(AliTRDseedV1 *tracklets) const
3197 {
3198   //    Chi2 definition on y-direction
3199
3200   Float_t chi2 = 0;
3201   for(Int_t ipl = 0; ipl < kNPlanes; ipl++){
3202     if(!tracklets[ipl].IsOK()) continue;
3203     Double_t distLayer = tracklets[ipl].GetYfit(0) - tracklets[ipl].GetYref(0); 
3204     chi2 += distLayer * distLayer;
3205   }
3206   return chi2;
3207 }
3208
3209 //____________________________________________________________________
3210 void AliTRDtrackerV1::ResetSeedTB()
3211 {
3212 // reset buffer for seeding time bin layers. If the time bin 
3213 // layers are not allocated this function allocates them  
3214
3215   for(Int_t isl=0; isl<kNSeedPlanes; isl++){
3216     if(!fSeedTB[isl]) fSeedTB[isl] = new AliTRDchamberTimeBin();
3217     else fSeedTB[isl]->Clear();
3218   }
3219 }
3220
3221 //_____________________________________________________________________________
3222 Float_t AliTRDtrackerV1::GetChi2Z(AliTRDseedV1 *tracklets) const 
3223 {
3224   //    Chi2 definition on z-direction
3225
3226   Float_t chi2 = 0;
3227   for(Int_t ipl = 0; ipl < kNPlanes; ipl++){
3228     if(!tracklets[ipl].IsOK()) continue;
3229     Double_t distLayer = tracklets[ipl].GetMeanz() - tracklets[ipl].GetZref(0); 
3230     chi2 += distLayer * distLayer;
3231   }
3232   return chi2;
3233 }
3234
3235 ///////////////////////////////////////////////////////
3236 //                                                   //
3237 // Resources of class AliTRDLeastSquare              //
3238 //                                                   //
3239 ///////////////////////////////////////////////////////
3240
3241 //_____________________________________________________________________________
3242 AliTRDtrackerV1::AliTRDLeastSquare::AliTRDLeastSquare(){
3243   //
3244   // Constructor of the nested class AliTRDtrackFitterLeastSquare
3245   //
3246   memset(fParams, 0, sizeof(Double_t) * 2);
3247   memset(fSums, 0, sizeof(Double_t) * 5);
3248   memset(fCovarianceMatrix, 0, sizeof(Double_t) * 3);
3249
3250 }
3251
3252 //_____________________________________________________________________________
3253 void AliTRDtrackerV1::AliTRDLeastSquare::AddPoint(Double_t *x, Double_t y, Double_t sigmaY){
3254   //
3255   // Adding Point to the fitter
3256   //
3257   Double_t weight = 1/(sigmaY * sigmaY);
3258   Double_t &xpt = *x;
3259   //    printf("Adding point x = %f, y = %f, sigma = %f\n", xpt, y, sigmaY);
3260   fSums[0] += weight;
3261   fSums[1] += weight * xpt;
3262   fSums[2] += weight * y;
3263   fSums[3] += weight * xpt * y;
3264   fSums[4] += weight * xpt * xpt;
3265   fSums[5] += weight * y * y;
3266 }
3267
3268 //_____________________________________________________________________________
3269 void AliTRDtrackerV1::AliTRDLeastSquare::RemovePoint(Double_t *x, Double_t y, Double_t sigmaY){
3270   //
3271   // Remove Point from the sample
3272   //
3273   Double_t weight = 1/(sigmaY * sigmaY);
3274   Double_t &xpt = *x; 
3275   fSums[0] -= weight;
3276   fSums[1] -= weight * xpt;
3277   fSums[2] -= weight * y;
3278   fSums[3] -= weight * xpt * y;
3279   fSums[4] -= weight * xpt * xpt;
3280   fSums[5] -= weight * y * y;
3281 }
3282
3283 //_____________________________________________________________________________
3284 void AliTRDtrackerV1::AliTRDLeastSquare::Eval(){
3285   //
3286   // Evaluation of the fit:
3287   // Calculation of the parameters
3288   // Calculation of the covariance matrix
3289   //
3290   
3291   Double_t denominator = fSums[0] * fSums[4] - fSums[1] *fSums[1];
3292   if(denominator==0) return;
3293
3294   //    for(Int_t isum = 0; isum < 5; isum++)
3295   //            printf("fSums[%d] = %f\n", isum, fSums[isum]);
3296   //    printf("denominator = %f\n", denominator);
3297   fParams[0] = (fSums[2] * fSums[4] - fSums[1] * fSums[3])/ denominator;
3298   fParams[1] = (fSums[0] * fSums[3] - fSums[1] * fSums[2]) / denominator;
3299   //    printf("fParams[0] = %f, fParams[1] = %f\n", fParams[0], fParams[1]);
3300   
3301   // Covariance matrix
3302   fCovarianceMatrix[0] = fSums[4] - fSums[1] * fSums[1] / fSums[0];
3303   fCovarianceMatrix[1] = fSums[5] - fSums[2] * fSums[2] / fSums[0];
3304   fCovarianceMatrix[2] = fSums[3] - fSums[1] * fSums[2] / fSums[0];
3305 }
3306
3307 //_____________________________________________________________________________
3308 Double_t AliTRDtrackerV1::AliTRDLeastSquare::GetFunctionValue(Double_t *xpos) const {
3309   //
3310   // Returns the Function value of the fitted function at a given x-position
3311   //
3312   return fParams[0] + fParams[1] * (*xpos);
3313 }
3314
3315 //_____________________________________________________________________________
3316 void AliTRDtrackerV1::AliTRDLeastSquare::GetCovarianceMatrix(Double_t *storage) const {
3317   //
3318   // Copies the values of the covariance matrix into the storage
3319   //
3320   memcpy(storage, fCovarianceMatrix, sizeof(Double_t) * 3);
3321 }
3322