]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/AliTPCtrackerMI.cxx
Second round of cleaning the AliESDv0 class (Yuri)
[u/mrichter/AliRoot.git] / TPC / AliTPCtrackerMI.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16
17 //-------------------------------------------------------
18 //          Implementation of the TPC tracker
19 //
20 //   Origin: Marian Ivanov   Marian.Ivanov@cern.ch
21 // 
22 //  AliTPC parallel tracker
23 //-------------------------------------------------------
24
25
26 /* $Id$ */
27
28 #include "Riostream.h"
29 #include <TClonesArray.h>
30 #include <TFile.h>
31 #include <TObjArray.h>
32 #include <TTree.h>
33 #include "AliLog.h"
34
35 #include "AliComplexCluster.h"
36 #include "AliESD.h"
37 #include "AliKink.h"
38 #include "AliV0.h"
39 #include "AliHelix.h"
40 #include "AliRunLoader.h"
41 #include "AliTPCClustersRow.h"
42 #include "AliTPCParam.h"
43 #include "AliTPCReconstructor.h"
44 #include "AliTPCpolyTrack.h"
45 #include "AliTPCreco.h"
46 #include "AliTPCseed.h" 
47 #include "AliTPCtrackerMI.h"
48 #include "TStopwatch.h"
49 #include "AliTPCReconstructor.h"
50 #include "AliPID.h"
51 #include "TTreeStream.h"
52 #include "AliAlignObj.h"
53 #include "AliTrackPointArray.h"
54
55 //
56
57 ClassImp(AliTPCtrackerMI)
58
59
60 class AliTPCFastMath {
61 public:
62   AliTPCFastMath();  
63   static Double_t FastAsin(Double_t x);   
64  private: 
65   static Double_t fgFastAsin[20000];  //lookup table for fast asin computation
66 };
67
68 Double_t AliTPCFastMath::fgFastAsin[20000];
69 AliTPCFastMath gAliTPCFastMath; // needed to fill the LUT
70
71 AliTPCFastMath::AliTPCFastMath(){
72   //
73   // initialized lookup table;
74   for (Int_t i=0;i<10000;i++){
75     fgFastAsin[2*i] = TMath::ASin(i/10000.);
76     fgFastAsin[2*i+1] = (TMath::ASin((i+1)/10000.)-fgFastAsin[2*i]);
77   }
78 }
79
80 Double_t AliTPCFastMath::FastAsin(Double_t x){
81   //
82   // return asin using lookup table
83   if (x>0){
84     Int_t index = int(x*10000);
85     return fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1];
86   }
87   x*=-1;
88   Int_t index = int(x*10000);
89   return -(fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1]);
90 }
91 //__________________________________________________________________
92 AliTPCtrackerMI::AliTPCtrackerMI()
93                 :AliTracker(),
94                  fkNIS(0),
95                  fInnerSec(0),
96                  fkNOS(0),
97                  fOuterSec(0),
98                  fN(0),
99                  fSectors(0),
100                  fInput(0),
101                  fOutput(0),
102                  fSeedTree(0),
103                  fTreeDebug(0),
104                  fEvent(0),
105                  fDebug(0),
106                  fNewIO(kFALSE),
107                  fNtracks(0),
108                  fSeeds(0),
109                  fIteration(0),
110                  fParam(0),
111                  fDebugStreamer(0)
112 {
113   //
114   // default constructor
115   //
116 }
117 //_____________________________________________________________________
118
119
120
121 Int_t AliTPCtrackerMI::UpdateTrack(AliTPCseed * track, Int_t accept){
122   //
123   //update track information using current cluster - track->fCurrentCluster
124
125
126   AliTPCclusterMI* c =track->GetCurrentCluster();
127   if (accept>0) track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);  //sign not accepted clusters
128
129   UInt_t i = track->GetCurrentClusterIndex1();
130
131   Int_t sec=(i&0xff000000)>>24; 
132   //Int_t row = (i&0x00ff0000)>>16; 
133   track->SetRow((i&0x00ff0000)>>16);
134   track->SetSector(sec);
135   //  Int_t index = i&0xFFFF;
136   if (sec>=fParam->GetNInnerSector()) track->SetRow(track->GetRow()+fParam->GetNRowLow()); 
137   track->SetClusterIndex2(track->GetRow(), i);  
138   //track->fFirstPoint = row;
139   //if ( track->fLastPoint<row) track->fLastPoint =row;
140   //  if (track->fRow<0 || track->fRow>160) {
141   //  printf("problem\n");
142   //}
143   if (track->GetFirstPoint()>track->GetRow()) 
144     track->SetFirstPoint(track->GetRow());
145   if (track->GetLastPoint()<track->GetRow()) 
146     track->SetLastPoint(track->GetRow());
147   
148
149   track->SetClusterPointer(track->GetRow(),c);  
150   //
151
152   Double_t angle2 = track->GetSnp()*track->GetSnp();
153   //
154   //SET NEW Track Point
155   //
156   if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
157   {
158     angle2 = TMath::Sqrt(angle2/(1-angle2)); 
159     AliTPCTrackerPoint   &point =*(track->GetTrackPoint(track->GetRow()));
160     //
161     point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
162     point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
163     point.SetErrY(sqrt(track->GetErrorY2()));
164     point.SetErrZ(sqrt(track->GetErrorZ2()));
165     //
166     point.SetX(track->GetX());
167     point.SetY(track->GetY());
168     point.SetZ(track->GetZ());
169     point.SetAngleY(angle2);
170     point.SetAngleZ(track->GetTgl());
171     if (point.IsShared()){
172       track->SetErrorY2(track->GetErrorY2()*4);
173       track->SetErrorZ2(track->GetErrorZ2()*4);
174     }
175   }  
176
177   Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
178   //
179   track->SetErrorY2(track->GetErrorY2()*1.3);
180   track->SetErrorY2(track->GetErrorY2()+0.01);    
181   track->SetErrorZ2(track->GetErrorZ2()*1.3);   
182   track->SetErrorZ2(track->GetErrorZ2()+0.005);      
183     //}
184   if (accept>0) return 0;
185   if (track->GetNumberOfClusters()%20==0){
186     //    if (track->fHelixIn){
187     //  TClonesArray & larr = *(track->fHelixIn);    
188     //  Int_t ihelix = larr.GetEntriesFast();
189     //  new(larr[ihelix]) AliHelix(*track) ;    
190     //}
191   }
192   track->SetNoCluster(0);
193   return track->Update(c,chi2,i);
194 }
195
196
197
198 Int_t AliTPCtrackerMI::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster, Float_t factor, 
199                                       Float_t cory, Float_t corz)
200 {
201   //
202   // decide according desired precision to accept given 
203   // cluster for tracking
204   Double_t sy2=ErrY2(seed,cluster)*cory;
205   Double_t sz2=ErrZ2(seed,cluster)*corz;
206   //sy2=ErrY2(seed,cluster)*cory;
207   //sz2=ErrZ2(seed,cluster)*cory;
208   
209   Double_t sdistancey2 = sy2+seed->GetSigmaY2();
210   Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
211   
212   Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-seed->GetY())*
213     (seed->GetCurrentCluster()->GetY()-seed->GetY())/sdistancey2;
214   Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-seed->GetZ())*
215     (seed->GetCurrentCluster()->GetZ()-seed->GetZ())/sdistancez2;
216   
217   Double_t rdistance2  = rdistancey2+rdistancez2;
218   //Int_t  accept =0;
219   
220   if (rdistance2>16) return 3;
221   
222   
223   if ((rdistancey2>9.*factor || rdistancez2>9.*factor) && cluster->GetType()==0)  
224     return 2;  //suspisiouce - will be changed
225   
226   if ((rdistancey2>6.25*factor || rdistancez2>6.25*factor) && cluster->GetType()>0)  
227     // strict cut on overlaped cluster
228     return  2;  //suspisiouce - will be changed
229   
230   if ( (rdistancey2>1.*factor || rdistancez2>6.25*factor ) 
231        && cluster->GetType()<0){
232     seed->SetNFoundable(seed->GetNFoundable()-1);
233     return 2;    
234   }
235   return 0;
236 }
237
238
239
240
241 //_____________________________________________________________________________
242 AliTPCtrackerMI::AliTPCtrackerMI(const AliTPCParam *par): 
243 AliTracker(), 
244                  fkNIS(par->GetNInnerSector()/2),
245                  fInnerSec(0),
246                  fkNOS(par->GetNOuterSector()/2),
247                  fOuterSec(0),
248                  fN(0),
249                  fSectors(0),
250                  fInput(0),
251                  fOutput(0),
252                  fSeedTree(0),
253                  fTreeDebug(0),
254                  fEvent(0),
255                  fDebug(0),
256                  fNewIO(0),
257                  fNtracks(0),
258                  fSeeds(0),
259                  fIteration(0),
260                  fParam(0),
261                  fDebugStreamer(0)
262 {
263   //---------------------------------------------------------------------
264   // The main TPC tracker constructor
265   //---------------------------------------------------------------------
266   fInnerSec=new AliTPCSector[fkNIS];         
267   fOuterSec=new AliTPCSector[fkNOS];
268  
269   Int_t i;
270   for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
271   for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
272
273   fParam = par;  
274   Int_t nrowlow = par->GetNRowLow();
275   Int_t nrowup = par->GetNRowUp();
276
277   
278   for (Int_t i=0;i<nrowlow;i++){
279     fXRow[i]     = par->GetPadRowRadiiLow(i);
280     fPadLength[i]= par->GetPadPitchLength(0,i);
281     fYMax[i]     = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
282   }
283
284   
285   for (Int_t i=0;i<nrowup;i++){
286     fXRow[i+nrowlow]      = par->GetPadRowRadiiUp(i);
287     fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
288     fYMax[i+nrowlow]      = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
289   }
290
291   fDebugStreamer = new TTreeSRedirector("TPCdebug.root");
292 }
293 //________________________________________________________________________
294 AliTPCtrackerMI::AliTPCtrackerMI(const AliTPCtrackerMI &t):
295   AliTracker(t),
296                  fkNIS(t.fkNIS),
297                  fInnerSec(0),
298                  fkNOS(t.fkNOS),
299                  fOuterSec(0),
300                  fN(0),
301                  fSectors(0),
302                  fInput(0),
303                  fOutput(0),
304                  fSeedTree(0),
305                  fTreeDebug(0),
306                  fEvent(0),
307                  fDebug(0),
308                  fNewIO(kFALSE),
309                  fNtracks(0),
310                  fSeeds(0),
311                  fIteration(0),
312                  fParam(0),
313                  fDebugStreamer(0)
314 {
315   //------------------------------------
316   // dummy copy constructor
317   //------------------------------------------------------------------
318   fOutput=t.fOutput;
319 }
320 AliTPCtrackerMI & AliTPCtrackerMI::operator=(const AliTPCtrackerMI& /*r*/){
321   //------------------------------
322   // dummy 
323   //--------------------------------------------------------------
324   return *this;
325 }
326 //_____________________________________________________________________________
327 AliTPCtrackerMI::~AliTPCtrackerMI() {
328   //------------------------------------------------------------------
329   // TPC tracker destructor
330   //------------------------------------------------------------------
331   delete[] fInnerSec;
332   delete[] fOuterSec;
333   if (fSeeds) {
334     fSeeds->Delete(); 
335     delete fSeeds;
336   }
337   if (fDebugStreamer) delete fDebugStreamer;
338 }
339
340 void AliTPCtrackerMI::SetIO()
341 {
342   //
343   fNewIO   =  kTRUE;
344   fInput   =  AliRunLoader::GetTreeR("TPC", kFALSE,AliConfig::GetDefaultEventFolderName());
345   
346   fOutput  =  AliRunLoader::GetTreeT("TPC", kTRUE,AliConfig::GetDefaultEventFolderName());
347   if (fOutput){
348     AliTPCtrack *iotrack= new AliTPCtrack;
349     fOutput->Branch("tracks","AliTPCtrack",&iotrack,32000,100);
350     delete iotrack;
351   }
352 }
353
354
355 void AliTPCtrackerMI::SetIO(TTree * input, TTree * output, AliESD * event)
356 {
357
358   // set input
359   fNewIO = kFALSE;
360   fInput    = 0;
361   fOutput   = 0;
362   fSeedTree = 0;
363   fTreeDebug =0;
364   fInput = input;
365   if (input==0){
366     return;
367   }  
368   //set output
369   fOutput = output;
370   if (output){
371     AliTPCtrack *iotrack= new AliTPCtrack;
372     //    iotrack->fHelixIn   = new TClonesArray("AliHelix");
373     //iotrack->fHelixOut  = new TClonesArray("AliHelix");    
374     fOutput->Branch("tracks","AliTPCtrack",&iotrack,32000,100);
375     delete iotrack;
376   }
377   if (output && (fDebug&2)){
378     //write the full seed information if specified in debug mode
379     //
380     fSeedTree =  new TTree("Seeds","Seeds");
381     AliTPCseed * vseed = new AliTPCseed;
382     //
383     TClonesArray * arrtr = new TClonesArray("AliTPCTrackPoint",160);
384     arrtr->ExpandCreateFast(160);
385     TClonesArray * arre = new TClonesArray("AliTPCExactPoint",160);
386     //
387     vseed->SetPoints(arrtr);
388     vseed->SetEPoints(arre);
389     //    vseed->fClusterPoints = arrcl;
390     fSeedTree->Branch("seeds","AliTPCseed",&vseed,32000,99);
391     delete arrtr;
392     delete arre;    
393     fTreeDebug = new TTree("trackDebug","trackDebug");
394     TClonesArray * arrd = new TClonesArray("AliTPCTrackPoint2",0);
395     fTreeDebug->Branch("debug",&arrd,32000,99);
396   }
397
398
399   //set ESD event  
400   fEvent  = event;  
401 }
402
403 void AliTPCtrackerMI::FillESD(TObjArray* arr)
404 {
405   //
406   //
407   //fill esds using updated tracks
408   if (fEvent){
409     // write tracks to the event
410     // store index of the track
411     Int_t nseed=arr->GetEntriesFast();
412     //FindKinks(arr,fEvent);
413     for (Int_t i=0; i<nseed; i++) {
414       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
415       if (!pt) continue; 
416       pt->UpdatePoints();
417       //      pt->PropagateTo(fParam->GetInnerRadiusLow());
418       if (pt->GetKinkIndex(0)<=0){  //don't propagate daughter tracks 
419         pt->PropagateTo(fParam->GetInnerRadiusLow());
420       }
421  
422       if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
423         AliESDtrack iotrack;
424         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
425         iotrack.SetTPCPoints(pt->GetPoints());
426         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
427         iotrack.SetV0Indexes(pt->GetV0Indexes());
428         //      iotrack.SetTPCpid(pt->fTPCr);
429         //iotrack.SetTPCindex(i);
430         fEvent->AddTrack(&iotrack);
431         continue;
432       }
433        
434       if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
435         AliESDtrack iotrack;
436         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
437         iotrack.SetTPCPoints(pt->GetPoints());
438         //iotrack.SetTPCindex(i);
439         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
440         iotrack.SetV0Indexes(pt->GetV0Indexes());
441         //      iotrack.SetTPCpid(pt->fTPCr);
442         fEvent->AddTrack(&iotrack);
443         continue;
444       } 
445       //
446       // short tracks  - maybe decays
447
448       if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
449         Int_t found,foundable,shared;
450         pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
451         if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
452           AliESDtrack iotrack;
453           iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);    
454           //iotrack.SetTPCindex(i);
455           iotrack.SetTPCPoints(pt->GetPoints());
456           iotrack.SetKinkIndexes(pt->GetKinkIndexes());
457           iotrack.SetV0Indexes(pt->GetV0Indexes());
458           //iotrack.SetTPCpid(pt->fTPCr);
459           fEvent->AddTrack(&iotrack);
460           continue;
461         }
462       }       
463       
464       if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
465         Int_t found,foundable,shared;
466         pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
467         if (found<20) continue;
468         if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
469         //
470         AliESDtrack iotrack;
471         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);      
472         iotrack.SetTPCPoints(pt->GetPoints());
473         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
474         iotrack.SetV0Indexes(pt->GetV0Indexes());
475         //iotrack.SetTPCpid(pt->fTPCr);
476         //iotrack.SetTPCindex(i);
477         fEvent->AddTrack(&iotrack);
478         continue;
479       }   
480       // short tracks  - secondaties
481       //
482       if ( (pt->GetNumberOfClusters()>30) ) {
483         Int_t found,foundable,shared;
484         pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
485         if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
486           AliESDtrack iotrack;
487           iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);    
488           iotrack.SetTPCPoints(pt->GetPoints());
489           iotrack.SetKinkIndexes(pt->GetKinkIndexes());
490           iotrack.SetV0Indexes(pt->GetV0Indexes());
491           //iotrack.SetTPCpid(pt->fTPCr);       
492           //iotrack.SetTPCindex(i);
493           fEvent->AddTrack(&iotrack);
494           continue;
495         }
496       }       
497       
498       if ( (pt->GetNumberOfClusters()>15)) {
499         Int_t found,foundable,shared;
500         pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
501         if (found<15) continue;
502         if (foundable<=0) continue;
503         if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
504         if (float(found)/float(foundable)<0.8) continue;
505         //
506         AliESDtrack iotrack;
507         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);      
508         iotrack.SetTPCPoints(pt->GetPoints());
509         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
510         iotrack.SetV0Indexes(pt->GetV0Indexes());
511         //      iotrack.SetTPCpid(pt->fTPCr);
512         //iotrack.SetTPCindex(i);
513         fEvent->AddTrack(&iotrack);
514         continue;
515       }   
516     }
517   }
518   printf("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks());
519 }
520
521 void AliTPCtrackerMI::WriteTracks(TTree * tree)
522 {
523   //
524   // write tracks from seed array to selected tree
525   //
526   fOutput  = tree;
527   if (fOutput){
528     AliTPCtrack *iotrack= new AliTPCtrack;
529     fOutput->Branch("tracks","AliTPCtrack",&iotrack,32000,100);
530   }
531   WriteTracks();
532 }
533
534 void AliTPCtrackerMI::WriteTracks()
535 {
536   //
537   // write tracks to the given output tree -
538   // output specified with SetIO routine
539   if (!fSeeds)  return;
540   if (!fOutput){
541     SetIO();
542   }
543
544   if (fOutput){
545     AliTPCtrack *iotrack= 0;
546     Int_t nseed=fSeeds->GetEntriesFast();
547     //for (Int_t i=0; i<nseed; i++) {
548     //  iotrack= (AliTPCtrack*)fSeeds->UncheckedAt(i);
549     //  if (iotrack) break;      
550     //}    
551     //TBranch * br = fOutput->Branch("tracks","AliTPCtrack",&iotrack,32000,100);
552     TBranch * br = fOutput->GetBranch("tracks");
553     br->SetAddress(&iotrack);
554     //
555     for (Int_t i=0; i<nseed; i++) {
556       AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i);    
557       if (!pt) continue;    
558       AliTPCtrack * track = new AliTPCtrack(*pt);
559       iotrack = track;
560       pt->SetLab2(i); 
561       //      br->SetAddress(&iotrack);
562       fOutput->Fill();
563       delete track;
564       iotrack =0;
565     }
566     //fOutput->GetDirectory()->cd();
567     //fOutput->Write();
568   }
569   // delete iotrack;
570   //
571   if (fSeedTree){
572     //write the full seed information if specified in debug mode
573       
574     AliTPCseed * vseed = new AliTPCseed;
575     //
576     TClonesArray * arrtr = new TClonesArray("AliTPCTrackPoint",160);
577     arrtr->ExpandCreateFast(160);
578     //TClonesArray * arrcl = new TClonesArray("AliTPCclusterMI",160);
579     //arrcl->ExpandCreateFast(160);
580     TClonesArray * arre = new TClonesArray("AliTPCExactPoint",160);
581     //
582     vseed->SetPoints(arrtr);
583     vseed->SetEPoints(arre);
584     //    vseed->fClusterPoints = arrcl;
585     //TBranch * brseed = seedtree->Branch("seeds","AliTPCseed",&vseed,32000,99);
586     TBranch * brseed = fSeedTree->GetBranch("seeds");
587     
588     Int_t nseed=fSeeds->GetEntriesFast();
589     
590     for (Int_t i=0; i<nseed; i++) {
591       AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i);    
592       if (!pt) continue;     
593       pt->SetPoints(arrtr);
594       //      pt->fClusterPoints = arrcl;
595       pt->SetEPoints(arre);
596       pt->RebuildSeed();
597       vseed = pt;
598       brseed->SetAddress(&vseed);
599       fSeedTree->Fill();
600       pt->SetPoints(0);
601       pt->SetEPoints(0);
602       //      pt->fClusterPoints = 0;
603     }
604     fSeedTree->Write();
605     if (fTreeDebug) fTreeDebug->Write();
606   }
607
608 }
609   
610
611
612
613 Double_t AliTPCtrackerMI::ErrY2(AliTPCseed* seed, AliTPCclusterMI * cl){
614   //
615   //
616   //seed->SetErrorY2(0.1);
617   //return 0.1;
618   //calculate look-up table at the beginning
619   static Bool_t  ginit = kFALSE;
620   static Float_t gnoise1,gnoise2,gnoise3;
621   static Float_t ggg1[10000];
622   static Float_t ggg2[10000];
623   static Float_t ggg3[10000];
624   static Float_t glandau1[10000];
625   static Float_t glandau2[10000];
626   static Float_t glandau3[10000];
627   //
628   static Float_t gcor01[500];
629   static Float_t gcor02[500];
630   static Float_t gcorp[500];
631   //
632
633   //
634   if (ginit==kFALSE){
635     for (Int_t i=1;i<500;i++){
636       Float_t rsigma = float(i)/100.;
637       gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
638       gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
639       gcorp[i]  = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
640     }
641
642     //
643     for (Int_t i=3;i<10000;i++){
644       //
645       //
646       // inner sector
647       Float_t amp = float(i);
648       Float_t padlength =0.75;
649       gnoise1 = 0.0004/padlength;
650       Float_t nel     = 0.268*amp;
651       Float_t nprim   = 0.155*amp;
652       ggg1[i]          = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
653       glandau1[i]      = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
654       if (glandau1[i]>1) glandau1[i]=1;
655       glandau1[i]*=padlength*padlength/12.;      
656       //
657       // outer short
658       padlength =1.;
659       gnoise2   = 0.0004/padlength;
660       nel       = 0.3*amp;
661       nprim     = 0.133*amp;
662       ggg2[i]      = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
663       glandau2[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
664       if (glandau2[i]>1) glandau2[i]=1;
665       glandau2[i]*=padlength*padlength/12.;
666       //
667       //
668       // outer long
669       padlength =1.5;
670       gnoise3   = 0.0004/padlength;
671       nel       = 0.3*amp;
672       nprim     = 0.133*amp;
673       ggg3[i]      = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
674       glandau3[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
675       if (glandau3[i]>1) glandau3[i]=1;
676       glandau3[i]*=padlength*padlength/12.;
677       //
678     }
679     ginit = kTRUE;
680   }
681   //
682   //
683   //
684   Int_t amp = int(TMath::Abs(cl->GetQ()));  
685   if (amp>9999) {
686     seed->SetErrorY2(1.);
687     return 1.;
688   }
689   Float_t snoise2;
690   Float_t z = TMath::Abs(fParam->GetZLength()-TMath::Abs(seed->GetZ()));
691   Int_t ctype = cl->GetType();  
692   Float_t padlength= GetPadPitchLength(seed->GetRow());
693   Double_t angle2 = seed->GetSnp()*seed->GetSnp();
694   angle2 = angle2/(1-angle2); 
695   //
696   //cluster "quality"
697   Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
698   Float_t res;
699   //
700   if (fSectors==fInnerSec){
701     snoise2 = gnoise1;
702     res     = ggg1[amp]*z+glandau1[amp]*angle2;     
703     if (ctype==0) res *= gcor01[rsigmay];
704     if ((ctype>0)){
705       res+=0.002;
706       res*= gcorp[rsigmay];
707     }
708   }
709   else {
710     if (padlength<1.1){
711       snoise2 = gnoise2;
712       res     = ggg2[amp]*z+glandau2[amp]*angle2; 
713       if (ctype==0) res *= gcor02[rsigmay];      
714       if ((ctype>0)){
715         res+=0.002;
716         res*= gcorp[rsigmay];
717       }
718     }
719     else{
720       snoise2 = gnoise3;      
721       res     = ggg3[amp]*z+glandau3[amp]*angle2; 
722       if (ctype==0) res *= gcor02[rsigmay];
723       if ((ctype>0)){
724         res+=0.002;
725         res*= gcorp[rsigmay];
726       }
727     }
728   }  
729
730   if (ctype<0){
731     res+=0.005;
732     res*=2.4;  // overestimate error 2 times
733   }
734   res+= snoise2;
735  
736   if (res<2*snoise2)
737     res = 2*snoise2;
738   
739   seed->SetErrorY2(res);
740   return res;
741
742
743 }
744
745
746
747 Double_t AliTPCtrackerMI::ErrZ2(AliTPCseed* seed, AliTPCclusterMI * cl){
748   //
749   //
750   //seed->SetErrorY2(0.1);
751   //return 0.1;
752   //calculate look-up table at the beginning
753   static Bool_t  ginit = kFALSE;
754   static Float_t gnoise1,gnoise2,gnoise3;
755   static Float_t ggg1[10000];
756   static Float_t ggg2[10000];
757   static Float_t ggg3[10000];
758   static Float_t glandau1[10000];
759   static Float_t glandau2[10000];
760   static Float_t glandau3[10000];
761   //
762   static Float_t gcor01[1000];
763   static Float_t gcor02[1000];
764   static Float_t gcorp[1000];
765   //
766
767   //
768   if (ginit==kFALSE){
769     for (Int_t i=1;i<1000;i++){
770       Float_t rsigma = float(i)/100.;
771       gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
772       gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
773       gcorp[i]  = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
774     }
775
776     //
777     for (Int_t i=3;i<10000;i++){
778       //
779       //
780       // inner sector
781       Float_t amp = float(i);
782       Float_t padlength =0.75;
783       gnoise1 = 0.0004/padlength;
784       Float_t nel     = 0.268*amp;
785       Float_t nprim   = 0.155*amp;
786       ggg1[i]          = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
787       glandau1[i]      = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
788       if (glandau1[i]>1) glandau1[i]=1;
789       glandau1[i]*=padlength*padlength/12.;      
790       //
791       // outer short
792       padlength =1.;
793       gnoise2   = 0.0004/padlength;
794       nel       = 0.3*amp;
795       nprim     = 0.133*amp;
796       ggg2[i]      = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
797       glandau2[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
798       if (glandau2[i]>1) glandau2[i]=1;
799       glandau2[i]*=padlength*padlength/12.;
800       //
801       //
802       // outer long
803       padlength =1.5;
804       gnoise3   = 0.0004/padlength;
805       nel       = 0.3*amp;
806       nprim     = 0.133*amp;
807       ggg3[i]      = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
808       glandau3[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
809       if (glandau3[i]>1) glandau3[i]=1;
810       glandau3[i]*=padlength*padlength/12.;
811       //
812     }
813     ginit = kTRUE;
814   }
815   //
816   //
817   //
818   Int_t amp = int(TMath::Abs(cl->GetQ()));  
819   if (amp>9999) {
820     seed->SetErrorY2(1.);
821     return 1.;
822   }
823   Float_t snoise2;
824   Float_t z = TMath::Abs(fParam->GetZLength()-TMath::Abs(seed->GetZ()));
825   Int_t ctype = cl->GetType();  
826   Float_t padlength= GetPadPitchLength(seed->GetRow());
827   //
828   Double_t angle2 = seed->GetSnp()*seed->GetSnp();
829   //  if (angle2<0.6) angle2 = 0.6;
830   angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2)); 
831   //
832   //cluster "quality"
833   Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
834   Float_t res;
835   //
836   if (fSectors==fInnerSec){
837     snoise2 = gnoise1;
838     res     = ggg1[amp]*z+glandau1[amp]*angle2;     
839     if (ctype==0) res *= gcor01[rsigmaz];
840     if ((ctype>0)){
841       res+=0.002;
842       res*= gcorp[rsigmaz];
843     }
844   }
845   else {
846     if (padlength<1.1){
847       snoise2 = gnoise2;
848       res     = ggg2[amp]*z+glandau2[amp]*angle2; 
849       if (ctype==0) res *= gcor02[rsigmaz];      
850       if ((ctype>0)){
851         res+=0.002;
852         res*= gcorp[rsigmaz];
853       }
854     }
855     else{
856       snoise2 = gnoise3;      
857       res     = ggg3[amp]*z+glandau3[amp]*angle2; 
858       if (ctype==0) res *= gcor02[rsigmaz];
859       if ((ctype>0)){
860         res+=0.002;
861         res*= gcorp[rsigmaz];
862       }
863     }
864   }  
865
866   if (ctype<0){
867     res+=0.002;
868     res*=1.3;
869   }
870   if ((ctype<0) &&amp<70){
871     res+=0.002;
872     res*=1.3;  
873   }
874   res += snoise2;
875   if (res<2*snoise2)
876      res = 2*snoise2;
877   if (res>3) res =3;
878   seed->SetErrorZ2(res);
879   return res;
880 }
881
882
883
884 /*
885 Double_t AliTPCtrackerMI::ErrZ2(AliTPCseed* seed, AliTPCclusterMI * cl){
886   //
887   //
888   //seed->SetErrorZ2(0.1);
889   //return 0.1;
890
891   Float_t snoise2;
892   Float_t z = TMath::Abs(fParam->GetZLength()-TMath::Abs(seed->GetZ()));
893   //
894   Float_t rsigmaz = cl->GetSigmaZ2()/(seed->fCurrentSigmaZ2);
895   Int_t ctype = cl->GetType();
896   Float_t amp = TMath::Abs(cl->GetQ());
897   
898   Float_t nel;
899   Float_t nprim;
900   //
901   Float_t landau=2 ;    //landau fluctuation part
902   Float_t gg=2;         // gg fluctuation part
903   Float_t padlength= GetPadPitchLength(seed->GetX());
904  
905   if (fSectors==fInnerSec){
906     snoise2 = 0.0004/padlength;
907     nel     = 0.268*amp;
908     nprim   = 0.155*amp;
909     gg      = (2+0.001*nel/(padlength*padlength))/nel;
910     landau  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
911     if (landau>1) landau=1;
912   }
913   else {
914     snoise2 = 0.0004/padlength;
915     nel     = 0.3*amp;
916     nprim   = 0.133*amp;
917     gg      = (2+0.0008*nel/(padlength*padlength))/nel;
918     landau  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
919     if (landau>1) landau=1;
920   }
921   Float_t sdiff = gg*fParam->GetDiffT()*fParam->GetDiffT()*z;
922
923   //
924   Float_t angle2 = seed->GetSnp()*seed->GetSnp();
925   angle2 = TMath::Sqrt((1-angle2));
926   if (angle2<0.6) angle2 = 0.6;
927   //angle2 = 1;
928
929   Float_t angle = seed->GetTgl()/angle2;
930   Float_t angular = landau*angle*angle*padlength*padlength/12.;
931   Float_t res = sdiff + angular;
932
933   
934   if ((ctype==0) && (fSectors ==fOuterSec))
935     res *= 0.81 +TMath::Exp(6.8*(rsigmaz-1.2));
936
937   if ((ctype==0) && (fSectors ==fInnerSec))
938     res *= 0.72 +TMath::Exp(2.04*(rsigmaz-1.2));
939   
940   if ((ctype>0)){
941     res+=0.005;
942     res*= TMath::Power(rsigmaz+0.5,1.5);  //0.31+0.147*ctype;
943   }
944   if (ctype<0){
945     res+=0.002;
946     res*=1.3;
947   }
948   if ((ctype<0) &&amp<70){
949     res+=0.002;
950     res*=1.3;  
951   }
952   res += snoise2;
953   if (res<2*snoise2)
954      res = 2*snoise2;
955
956   seed->SetErrorZ2(res);
957   return res;
958 }
959 */
960
961
962
963
964 void AliTPCtrackerMI::RotateToLocal(AliTPCseed *seed)
965 {
966   //rotate to track "local coordinata
967   Float_t x = seed->GetX();
968   Float_t y = seed->GetY();
969   Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
970   
971   if (y > ymax) {
972     seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
973     if (!seed->Rotate(fSectors->GetAlpha())) 
974       return;
975   } else if (y <-ymax) {
976     seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
977     if (!seed->Rotate(-fSectors->GetAlpha())) 
978       return;
979   }   
980
981 }
982
983
984
985 //_____________________________________________________________________________
986 Double_t AliTPCtrackerMI::F1old(Double_t x1,Double_t y1,
987                    Double_t x2,Double_t y2,
988                    Double_t x3,Double_t y3) 
989 {
990   //-----------------------------------------------------------------
991   // Initial approximation of the track curvature
992   //-----------------------------------------------------------------
993   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
994   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
995                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
996   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
997                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
998
999   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1000   if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1001   return -xr*yr/sqrt(xr*xr+yr*yr); 
1002 }
1003
1004
1005
1006 //_____________________________________________________________________________
1007 Double_t AliTPCtrackerMI::F1(Double_t x1,Double_t y1,
1008                    Double_t x2,Double_t y2,
1009                    Double_t x3,Double_t y3) 
1010 {
1011   //-----------------------------------------------------------------
1012   // Initial approximation of the track curvature
1013   //-----------------------------------------------------------------
1014   x3 -=x1;
1015   x2 -=x1;
1016   y3 -=y1;
1017   y2 -=y1;
1018   //  
1019   Double_t det = x3*y2-x2*y3;
1020   if (det==0) {
1021     return 100;
1022   }
1023   //
1024   Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1025   Double_t x0 = x3*0.5-y3*u;
1026   Double_t y0 = y3*0.5+x3*u;
1027   Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1028   if (det<0) c2*=-1;
1029   return c2;
1030 }
1031
1032
1033 Double_t AliTPCtrackerMI::F2(Double_t x1,Double_t y1,
1034                    Double_t x2,Double_t y2,
1035                    Double_t x3,Double_t y3) 
1036 {
1037   //-----------------------------------------------------------------
1038   // Initial approximation of the track curvature
1039   //-----------------------------------------------------------------
1040   x3 -=x1;
1041   x2 -=x1;
1042   y3 -=y1;
1043   y2 -=y1;
1044   //  
1045   Double_t det = x3*y2-x2*y3;
1046   if (det==0) {
1047     return 100;
1048   }
1049   //
1050   Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1051   Double_t x0 = x3*0.5-y3*u; 
1052   Double_t y0 = y3*0.5+x3*u;
1053   Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1054   if (det<0) c2*=-1;
1055   x0+=x1;
1056   x0*=c2;  
1057   return x0;
1058 }
1059
1060
1061
1062 //_____________________________________________________________________________
1063 Double_t AliTPCtrackerMI::F2old(Double_t x1,Double_t y1,
1064                    Double_t x2,Double_t y2,
1065                    Double_t x3,Double_t y3) 
1066 {
1067   //-----------------------------------------------------------------
1068   // Initial approximation of the track curvature times center of curvature
1069   //-----------------------------------------------------------------
1070   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1071   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1072                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1073   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1074                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1075
1076   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1077   
1078   return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1079 }
1080
1081 //_____________________________________________________________________________
1082 Double_t AliTPCtrackerMI::F3(Double_t x1,Double_t y1, 
1083                    Double_t x2,Double_t y2,
1084                    Double_t z1,Double_t z2) 
1085 {
1086   //-----------------------------------------------------------------
1087   // Initial approximation of the tangent of the track dip angle
1088   //-----------------------------------------------------------------
1089   return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1090 }
1091
1092
1093 Double_t AliTPCtrackerMI::F3n(Double_t x1,Double_t y1, 
1094                    Double_t x2,Double_t y2,
1095                    Double_t z1,Double_t z2, Double_t c) 
1096 {
1097   //-----------------------------------------------------------------
1098   // Initial approximation of the tangent of the track dip angle
1099   //-----------------------------------------------------------------
1100
1101   //  Double_t angle1;
1102   
1103   //angle1    =  (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1104   //
1105   Double_t d  =  TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1106   if (TMath::Abs(d*c*0.5)>1) return 0;
1107   //  Double_t   angle2    =  TMath::ASin(d*c*0.5);
1108   //  Double_t   angle2    =  AliTPCFastMath::FastAsin(d*c*0.5);
1109   Double_t   angle2    = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1110
1111   angle2  = (z1-z2)*c/(angle2*2.);
1112   return angle2;
1113 }
1114
1115 Bool_t   AliTPCtrackerMI::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z)
1116 {//-----------------------------------------------------------------
1117   // This function find proloncation of a track to a reference plane x=x2.
1118   //-----------------------------------------------------------------
1119   
1120   Double_t dx=x2-x1;
1121
1122   if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {   
1123     return kFALSE;
1124   }
1125
1126   Double_t c1=x[4]*x1 - x[2], r1=sqrt(1.- c1*c1);
1127   Double_t c2=x[4]*x2 - x[2], r2=sqrt(1.- c2*c2);  
1128   y = x[0];
1129   z = x[1];
1130   
1131   Double_t dy = dx*(c1+c2)/(r1+r2);
1132   Double_t dz = 0;
1133   //
1134   Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1135   
1136   if (TMath::Abs(delta)>0.01){
1137     dz = x[3]*TMath::ASin(delta)/x[4];
1138   }else{
1139     dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1140   }
1141   
1142   //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1143
1144   y+=dy;
1145   z+=dz;
1146   
1147   return kTRUE;  
1148 }
1149
1150 Int_t  AliTPCtrackerMI::LoadClusters (TTree *tree)
1151 {
1152   //
1153   //
1154   fInput = tree;
1155   return LoadClusters();
1156 }
1157
1158 Int_t  AliTPCtrackerMI::LoadClusters()
1159 {
1160   //
1161   // load clusters to the memory
1162   AliTPCClustersRow *clrow= new AliTPCClustersRow;
1163   clrow->SetClass("AliTPCclusterMI");
1164   clrow->SetArray(0);
1165   clrow->GetArray()->ExpandCreateFast(10000);
1166   //
1167   //  TTree * tree = fClustersArray.GetTree();
1168
1169   TTree * tree = fInput;
1170   TBranch * br = tree->GetBranch("Segment");
1171   br->SetAddress(&clrow);
1172   //
1173   Int_t j=Int_t(tree->GetEntries());
1174   for (Int_t i=0; i<j; i++) {
1175     br->GetEntry(i);
1176     //  
1177     Int_t sec,row;
1178     fParam->AdjustSectorRow(clrow->GetID(),sec,row);
1179     for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1180       Transform((AliCluster*)(clrow->GetArray()->At(icl)));
1181     }
1182     //
1183     AliTPCRow * tpcrow=0;
1184     Int_t left=0;
1185     if (sec<fkNIS*2){
1186       tpcrow = &(fInnerSec[sec%fkNIS][row]);    
1187       left = sec/fkNIS;
1188     }
1189     else{
1190       tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1191       left = (sec-fkNIS*2)/fkNOS;
1192     }
1193     if (left ==0){
1194       tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1195       tpcrow->SetClusters1(new AliTPCclusterMI[tpcrow->GetN1()]);
1196       for (Int_t i=0;i<tpcrow->GetN1();i++) 
1197         tpcrow->SetCluster1(i, *(AliTPCclusterMI*)(clrow->GetArray()->At(i)));
1198     }
1199     if (left ==1){
1200       tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1201       tpcrow->SetClusters2(new AliTPCclusterMI[tpcrow->GetN2()]);
1202       for (Int_t i=0;i<tpcrow->GetN2();i++) 
1203         tpcrow->SetCluster2(i,*(AliTPCclusterMI*)(clrow->GetArray()->At(i)));
1204     }
1205   }
1206   //
1207   delete clrow;
1208   LoadOuterSectors();
1209   LoadInnerSectors();
1210   return 0;
1211 }
1212
1213
1214 void AliTPCtrackerMI::UnloadClusters()
1215 {
1216   //
1217   // unload clusters from the memory
1218   //
1219   Int_t nrows = fOuterSec->GetNRows();
1220   for (Int_t sec = 0;sec<fkNOS;sec++)
1221     for (Int_t row = 0;row<nrows;row++){
1222       AliTPCRow*  tpcrow = &(fOuterSec[sec%fkNOS][row]);
1223       //      if (tpcrow){
1224       //        if (tpcrow->fClusters1) delete []tpcrow->fClusters1; 
1225       //        if (tpcrow->fClusters2) delete []tpcrow->fClusters2; 
1226       //}
1227       tpcrow->ResetClusters();
1228     }
1229   //
1230   nrows = fInnerSec->GetNRows();
1231   for (Int_t sec = 0;sec<fkNIS;sec++)
1232     for (Int_t row = 0;row<nrows;row++){
1233       AliTPCRow*  tpcrow = &(fInnerSec[sec%fkNIS][row]);
1234       //if (tpcrow){
1235       //        if (tpcrow->fClusters1) delete []tpcrow->fClusters1; 
1236       //if (tpcrow->fClusters2) delete []tpcrow->fClusters2; 
1237       //}
1238       tpcrow->ResetClusters();
1239     }
1240
1241   return ;
1242 }
1243
1244 void   AliTPCtrackerMI::Transform(AliCluster * cluster){
1245   //
1246   // 
1247   //
1248   //if (!fParam->IsGeoRead()) fParam->ReadGeoMatrices();
1249   TGeoHMatrix  *mat = fParam->GetClusterMatrix(cluster->GetDetector());
1250   //TGeoHMatrix  mat;
1251   Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1252   Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1253   if (mat) mat->LocalToMaster(pos,posC);
1254   else{
1255     // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1256   }
1257   cluster->SetX(posC[0]);
1258   cluster->SetY(posC[1]);
1259   cluster->SetZ(posC[2]);
1260 }
1261
1262 //_____________________________________________________________________________
1263 Int_t AliTPCtrackerMI::LoadOuterSectors() {
1264   //-----------------------------------------------------------------
1265   // This function fills outer TPC sectors with clusters.
1266   //-----------------------------------------------------------------
1267   Int_t nrows = fOuterSec->GetNRows();
1268   UInt_t index=0;
1269   for (Int_t sec = 0;sec<fkNOS;sec++)
1270     for (Int_t row = 0;row<nrows;row++){
1271       AliTPCRow*  tpcrow = &(fOuterSec[sec%fkNOS][row]);  
1272       Int_t sec2 = sec+2*fkNIS;
1273       //left
1274       Int_t ncl = tpcrow->GetN1();
1275       while (ncl--) {
1276         AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1277         index=(((sec2<<8)+row)<<16)+ncl;
1278         tpcrow->InsertCluster(c,index);
1279       }
1280       //right
1281       ncl = tpcrow->GetN2();
1282       while (ncl--) {
1283         AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1284         index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
1285         tpcrow->InsertCluster(c,index);
1286       }
1287       //
1288       // write indexes for fast acces
1289       //
1290       for (Int_t i=0;i<510;i++)
1291         tpcrow->SetFastCluster(i,-1);
1292       for (Int_t i=0;i<tpcrow->GetN();i++){
1293         Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1294         tpcrow->SetFastCluster(zi,i);  // write index
1295       }
1296       Int_t last = 0;
1297       for (Int_t i=0;i<510;i++){
1298         if (tpcrow->GetFastCluster(i)<0)
1299           tpcrow->SetFastCluster(i,last);
1300         else
1301           last = tpcrow->GetFastCluster(i);
1302       }
1303     }  
1304   fN=fkNOS;
1305   fSectors=fOuterSec;
1306   return 0;
1307 }
1308
1309
1310 //_____________________________________________________________________________
1311 Int_t  AliTPCtrackerMI::LoadInnerSectors() {
1312   //-----------------------------------------------------------------
1313   // This function fills inner TPC sectors with clusters.
1314   //-----------------------------------------------------------------
1315   Int_t nrows = fInnerSec->GetNRows();
1316   UInt_t index=0;
1317   for (Int_t sec = 0;sec<fkNIS;sec++)
1318     for (Int_t row = 0;row<nrows;row++){
1319       AliTPCRow*  tpcrow = &(fInnerSec[sec%fkNIS][row]);
1320       //
1321       //left
1322       Int_t ncl = tpcrow->GetN1();
1323       while (ncl--) {
1324         AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1325         index=(((sec<<8)+row)<<16)+ncl;
1326         tpcrow->InsertCluster(c,index);
1327       }
1328       //right
1329       ncl = tpcrow->GetN2();
1330       while (ncl--) {
1331         AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1332         index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
1333         tpcrow->InsertCluster(c,index);
1334       }
1335       //
1336       // write indexes for fast acces
1337       //
1338       for (Int_t i=0;i<510;i++)
1339         tpcrow->SetFastCluster(i,-1);
1340       for (Int_t i=0;i<tpcrow->GetN();i++){
1341         Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1342         tpcrow->SetFastCluster(zi,i);  // write index
1343       }
1344       Int_t last = 0;
1345       for (Int_t i=0;i<510;i++){
1346         if (tpcrow->GetFastCluster(i)<0)
1347           tpcrow->SetFastCluster(i,last);
1348         else
1349           last = tpcrow->GetFastCluster(i);
1350       }
1351
1352     }  
1353    
1354   fN=fkNIS;
1355   fSectors=fInnerSec;
1356   return 0;
1357 }
1358
1359
1360
1361 //_________________________________________________________________________
1362 AliTPCclusterMI *AliTPCtrackerMI::GetClusterMI(Int_t index) const {
1363   //--------------------------------------------------------------------
1364   //       Return pointer to a given cluster
1365   //--------------------------------------------------------------------
1366   if (index<0) return 0; // no cluster
1367   Int_t sec=(index&0xff000000)>>24; 
1368   Int_t row=(index&0x00ff0000)>>16; 
1369   Int_t ncl=(index&0x00007fff)>>00;
1370
1371   const AliTPCRow * tpcrow=0;
1372   AliTPCclusterMI * clrow =0;
1373
1374   if (sec<0 || sec>=fkNIS*4) {
1375     AliWarning(Form("Wrong sector %d",sec));
1376     return 0x0;
1377   }
1378
1379   if (sec<fkNIS*2){
1380     tpcrow = &(fInnerSec[sec%fkNIS][row]);
1381     if (tpcrow==0) return 0;
1382
1383     if (sec<fkNIS) {
1384       if (tpcrow->GetN1()<=ncl) return 0;
1385       clrow = tpcrow->GetClusters1();
1386     }
1387     else {
1388       if (tpcrow->GetN2()<=ncl) return 0;
1389       clrow = tpcrow->GetClusters2();
1390     }
1391   }
1392   else {
1393     tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1394     if (tpcrow==0) return 0;
1395
1396     if (sec-2*fkNIS<fkNOS) {
1397       if (tpcrow->GetN1()<=ncl) return 0;
1398       clrow = tpcrow->GetClusters1();
1399     }
1400     else {
1401       if (tpcrow->GetN2()<=ncl) return 0;
1402       clrow = tpcrow->GetClusters2();
1403     }
1404   }
1405
1406   return &(clrow[ncl]);      
1407   
1408 }
1409
1410
1411
1412 Int_t AliTPCtrackerMI::FollowToNext(AliTPCseed& t, Int_t nr) {
1413   //-----------------------------------------------------------------
1414   // This function tries to find a track prolongation to next pad row
1415   //-----------------------------------------------------------------
1416   //
1417   Double_t  x= GetXrow(nr), ymax=GetMaxY(nr);
1418   AliTPCclusterMI *cl=0;
1419   Int_t tpcindex= t.GetClusterIndex2(nr);
1420   //
1421   // update current shape info every 5 pad-row
1422   //  if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
1423     GetShape(&t,nr);    
1424     //}
1425   //  
1426   if (fIteration>0 && tpcindex>=-1){  //if we have already clusters 
1427     //        
1428     if (tpcindex==-1) return 0; //track in dead zone
1429     if (tpcindex>0){     //
1430       cl = t.GetClusterPointer(nr);
1431       if ( (cl==0) ) cl = GetClusterMI(tpcindex);
1432       t.SetCurrentClusterIndex1(tpcindex); 
1433     }
1434     if (cl){      
1435       Int_t relativesector = ((tpcindex&0xff000000)>>24)%18;  // if previously accepted cluster in different sector
1436       Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
1437       //
1438       if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
1439       if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
1440       
1441       if (TMath::Abs(angle-t.GetAlpha())>0.001){
1442         Double_t rotation = angle-t.GetAlpha();
1443         t.SetRelativeSector(relativesector);
1444         if (!t.Rotate(rotation)) return 0;      
1445       }
1446       if (!t.PropagateTo(x)) return 0;
1447       //
1448       t.SetCurrentCluster(cl); 
1449       t.SetRow(nr);
1450       Int_t accept = AcceptCluster(&t,t.GetCurrentCluster(),1.);
1451       if ((tpcindex&0x8000)==0) accept =0;
1452       if (accept<3) { 
1453         //if founded cluster is acceptible
1454         if (cl->IsUsed(11)) {  // id cluster is shared inrease uncertainty
1455           t.SetErrorY2(t.GetErrorY2()+0.03);
1456           t.SetErrorZ2(t.GetErrorZ2()+0.03); 
1457           t.SetErrorY2(t.GetErrorY2()*3);
1458           t.SetErrorZ2(t.GetErrorZ2()*3); 
1459         }
1460         t.SetNFoundable(t.GetNFoundable()+1);
1461         UpdateTrack(&t,accept);
1462         return 1;
1463       }    
1464     }
1465   }
1466   if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;  // cut on angle
1467   if (fIteration>1){
1468     // not look for new cluster during refitting    
1469     t.SetNFoundable(t.GetNFoundable()+1);
1470     return 0;
1471   }
1472   //
1473   UInt_t index=0;
1474   //  if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
1475   Double_t  y=t.GetYat(x);
1476   if (TMath::Abs(y)>ymax){
1477     if (y > ymax) {
1478       t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1479       if (!t.Rotate(fSectors->GetAlpha())) 
1480         return 0;
1481     } else if (y <-ymax) {
1482       t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1483       if (!t.Rotate(-fSectors->GetAlpha())) 
1484         return 0;
1485     }
1486     //return 1;
1487   }
1488   //
1489   if (!t.PropagateTo(x)) {
1490     if (fIteration==0) t.SetRemoval(10);
1491     return 0;
1492   }
1493   y=t.GetY(); 
1494   Double_t z=t.GetZ();
1495   //
1496
1497   if (!IsActive(t.GetRelativeSector(),nr)) {
1498     t.SetInDead(kTRUE);
1499     t.SetClusterIndex2(nr,-1); 
1500     return 0;
1501   }
1502   //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1503   Bool_t isActive  = IsActive(t.GetRelativeSector(),nr);
1504   Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
1505   
1506   if (!isActive || !isActive2) return 0;
1507
1508   const AliTPCRow &krow=GetRow(t.GetRelativeSector(),nr);
1509   if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
1510   Double_t  roady  =1.;
1511   Double_t  roadz = 1.;
1512   //
1513   if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1514     t.SetInDead(kTRUE);
1515     t.SetClusterIndex2(nr,-1); 
1516     return 0;
1517   } 
1518   else
1519     {
1520       if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fParam->GetZLength() && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker())) 
1521         t.SetNFoundable(t.GetNFoundable()+1);
1522       else
1523         return 0;
1524     }   
1525   //calculate 
1526   if (krow) {
1527     //    cl = krow.FindNearest2(y+10.,z,roady,roadz,index);    
1528     cl = krow.FindNearest2(y,z,roady,roadz,index);    
1529     if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));       
1530   }  
1531   if (cl) {
1532     t.SetCurrentCluster(cl); 
1533     t.SetRow(nr);
1534     if (fIteration==2&&cl->IsUsed(10)) return 0; 
1535     Int_t accept = AcceptCluster(&t,t.GetCurrentCluster(),1.);
1536     if (fIteration==2&&cl->IsUsed(11)) {
1537       t.SetErrorY2(t.GetErrorY2()+0.03);
1538       t.SetErrorZ2(t.GetErrorZ2()+0.03); 
1539       t.SetErrorY2(t.GetErrorY2()*3);
1540       t.SetErrorZ2(t.GetErrorZ2()*3); 
1541     }
1542     /*    
1543     if (t.fCurrentCluster->IsUsed(10)){
1544       //
1545       //     
1546
1547       t.fNShared++;
1548       if (t.fNShared>0.7*t.GetNumberOfClusters()) {
1549         t.fRemoval =10;
1550         return 0;
1551       }
1552     }
1553     */
1554     if (accept<3) UpdateTrack(&t,accept);
1555
1556   } else {  
1557     if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
1558     
1559   }
1560   return 1;
1561 }
1562
1563 Int_t AliTPCtrackerMI::FollowToNextFast(AliTPCseed& t, Int_t nr) {
1564   //-----------------------------------------------------------------
1565   // This function tries to find a track prolongation to next pad row
1566   //-----------------------------------------------------------------
1567   //
1568   Double_t  x= GetXrow(nr), ymax=GetMaxY(nr);
1569   Double_t y,z; 
1570   if (!t.GetProlongation(x,y,z)) {
1571     t.SetRemoval(10);
1572     return 0;
1573   }
1574   //
1575   //
1576   if (TMath::Abs(y)>ymax){
1577     
1578     if (y > ymax) {
1579       t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1580       if (!t.Rotate(fSectors->GetAlpha())) 
1581         return 0;
1582     } else if (y <-ymax) {
1583       t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1584       if (!t.Rotate(-fSectors->GetAlpha())) 
1585         return 0;
1586     }
1587     if (!t.PropagateTo(x)) {
1588       return 0;
1589     } 
1590     t.GetProlongation(x,y,z);
1591   }
1592   //
1593   // update current shape info every 3 pad-row
1594   if ( (nr%6==0) || t.GetNumberOfClusters()<2 || (t.GetCurrentSigmaY2()<0.0001) ){
1595     //    t.fCurrentSigmaY = GetSigmaY(&t);
1596     //t.fCurrentSigmaZ = GetSigmaZ(&t);
1597     GetShape(&t,nr);
1598   }
1599   //  
1600   AliTPCclusterMI *cl=0;
1601   UInt_t index=0;
1602   
1603   
1604   //Int_t nr2 = nr;
1605   const AliTPCRow &krow=GetRow(t.GetRelativeSector(),nr);
1606   if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
1607   Double_t  roady  =1.;
1608   Double_t  roadz = 1.;
1609   //
1610   Int_t row = nr;
1611   if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1612     t.SetInDead(kTRUE);
1613     t.SetClusterIndex2(row,-1); 
1614     return 0;
1615   } 
1616   else
1617     {
1618       if (TMath::Abs(z)>(AliTPCReconstructor::GetCtgRange()*x+10)) t.SetClusterIndex2(row,-1);
1619     }   
1620   //calculate 
1621   
1622   if ((cl==0)&&(krow)) {
1623     //    cl = krow.FindNearest2(y+10,z,roady,roadz,index);    
1624     cl = krow.FindNearest2(y,z,roady,roadz,index);    
1625
1626     if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));       
1627   }  
1628
1629   if (cl) {
1630     t.SetCurrentCluster(cl); 
1631     //    Int_t accept = AcceptCluster(&t,t.fCurrentCluster,1.);        
1632     //if (accept<3){
1633       t.SetClusterIndex2(row,index);
1634       t.SetClusterPointer(row, cl);
1635       //}
1636   }
1637   return 1;
1638 }
1639
1640
1641
1642 //_________________________________________________________________________
1643 Bool_t AliTPCtrackerMI::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
1644 {
1645   // Get track space point by index
1646   // return false in case the cluster doesn't exist
1647   AliTPCclusterMI *cl = GetClusterMI(index);
1648   if (!cl) return kFALSE;
1649   Int_t sector = (index&0xff000000)>>24;
1650   //  Int_t row = (index&0x00ff0000)>>16;
1651   Float_t xyz[3];
1652   //  xyz[0] = fParam->GetPadRowRadii(sector,row);
1653   xyz[0] = cl->GetX();
1654   xyz[1] = cl->GetY();
1655   xyz[2] = cl->GetZ();
1656   Float_t sin,cos;
1657   fParam->AdjustCosSin(sector,cos,sin);
1658   Float_t x = cos*xyz[0]-sin*xyz[1];
1659   Float_t y = cos*xyz[1]+sin*xyz[0];
1660   Float_t cov[6];
1661   Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
1662   if (sector < fParam->GetNInnerSector()) sigmaY2 *= 2.07;
1663   Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
1664   if (sector < fParam->GetNInnerSector()) sigmaZ2 *= 1.77;
1665   cov[0] = sin*sin*sigmaY2;
1666   cov[1] = -sin*cos*sigmaY2;
1667   cov[2] = 0.;
1668   cov[3] = cos*cos*sigmaY2;
1669   cov[4] = 0.;
1670   cov[5] = sigmaZ2;
1671   p.SetXYZ(x,y,xyz[2],cov);
1672   AliAlignObj::ELayerID iLayer;
1673   Int_t idet;
1674   if (sector < fParam->GetNInnerSector()) {
1675     iLayer = AliAlignObj::kTPC1;
1676     idet = sector;
1677   }
1678   else {
1679     iLayer = AliAlignObj::kTPC2;
1680     idet = sector - fParam->GetNInnerSector();
1681   }
1682   UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,idet);
1683   p.SetVolumeID(volid);
1684   return kTRUE;
1685 }
1686
1687
1688
1689 Int_t AliTPCtrackerMI::UpdateClusters(AliTPCseed& t,  Int_t nr) {
1690   //-----------------------------------------------------------------
1691   // This function tries to find a track prolongation to next pad row
1692   //-----------------------------------------------------------------
1693   t.SetCurrentCluster(0);
1694   t.SetCurrentClusterIndex1(0);   
1695    
1696   Double_t xt=t.GetX();
1697   Int_t     row = GetRowNumber(xt)-1; 
1698   Double_t  ymax= GetMaxY(nr);
1699
1700   if (row < nr) return 1; // don't prolongate if not information until now -
1701 //   if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
1702 //     t.fRemoval =10;
1703 //     return 0;  // not prolongate strongly inclined tracks
1704 //   } 
1705 //   if (TMath::Abs(t.GetSnp())>0.95) {
1706 //     t.fRemoval =10;
1707 //     return 0;  // not prolongate strongly inclined tracks
1708 //   }// patch 28 fev 06
1709
1710   Double_t x= GetXrow(nr);
1711   Double_t y,z;
1712   //t.PropagateTo(x+0.02);
1713   //t.PropagateTo(x+0.01);
1714   if (!t.PropagateTo(x)){
1715     return 0;
1716   }
1717   //
1718   y=t.GetY();
1719   z=t.GetZ();
1720
1721   if (TMath::Abs(y)>ymax){
1722     if (y > ymax) {
1723       t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1724       if (!t.Rotate(fSectors->GetAlpha())) 
1725         return 0;
1726     } else if (y <-ymax) {
1727       t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1728       if (!t.Rotate(-fSectors->GetAlpha())) 
1729         return 0;
1730     }
1731     //    if (!t.PropagateTo(x)){
1732     //  return 0;
1733     //}
1734     return 1;
1735     //y = t.GetY();    
1736   }
1737   //
1738   if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
1739
1740   if (!IsActive(t.GetRelativeSector(),nr)) {
1741     t.SetInDead(kTRUE);
1742     t.SetClusterIndex2(nr,-1); 
1743     return 0;
1744   }
1745   //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1746
1747   AliTPCRow &krow=GetRow(t.GetRelativeSector(),nr);
1748
1749   if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1750     t.SetInDead(kTRUE);
1751     t.SetClusterIndex2(nr,-1); 
1752     return 0;
1753   } 
1754   else
1755     {
1756       if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker())) t.SetNFoundable(t.GetNFoundable()+1);
1757       else
1758         return 0;      
1759     }
1760
1761   // update current
1762   if ( (nr%6==0) || t.GetNumberOfClusters()<2){
1763     //    t.fCurrentSigmaY = GetSigmaY(&t);
1764     //t.fCurrentSigmaZ = GetSigmaZ(&t);
1765     GetShape(&t,nr);
1766   }
1767     
1768   AliTPCclusterMI *cl=0;
1769   Int_t index=0;
1770   //
1771   Double_t roady = 1.;
1772   Double_t roadz = 1.;
1773   //
1774
1775   if (!cl){
1776     index = t.GetClusterIndex2(nr);    
1777     if ( (index>0) && (index&0x8000)==0){
1778       cl = t.GetClusterPointer(nr);
1779       if ( (cl==0) && (index>0)) cl = GetClusterMI(index);
1780       t.SetCurrentClusterIndex1(index);
1781       if (cl) {
1782         t.SetCurrentCluster(cl);
1783         return 1;
1784       }
1785     }
1786   }
1787
1788   //  if (index<0) return 0;
1789   UInt_t uindex = TMath::Abs(index);
1790
1791   if (krow) {    
1792     //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);      
1793     cl = krow.FindNearest2(y,z,roady,roadz,uindex);      
1794   }
1795
1796   if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));   
1797   t.SetCurrentCluster(cl);
1798
1799   return 1;
1800 }
1801
1802
1803 Int_t AliTPCtrackerMI::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
1804   //-----------------------------------------------------------------
1805   // This function tries to find a track prolongation to next pad row
1806   //-----------------------------------------------------------------
1807
1808   //update error according neighborhoud
1809
1810   if (t.GetCurrentCluster()) {
1811     t.SetRow(nr); 
1812     Int_t accept = AcceptCluster(&t,t.GetCurrentCluster(),1.);
1813     
1814     if (t.GetCurrentCluster()->IsUsed(10)){
1815       //
1816       //
1817       //  t.fErrorZ2*=2;
1818       //  t.fErrorY2*=2;
1819       t.SetNShared(t.GetNShared()+1);
1820       if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
1821         t.SetRemoval(10);
1822         return 0;
1823       }
1824     }   
1825     if (fIteration>0) accept = 0;
1826     if (accept<3)  UpdateTrack(&t,accept);  
1827  
1828   } else {
1829     if (fIteration==0){
1830       if ( ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)&& t.GetNumberOfClusters()>18) t.SetRemoval(10);      
1831       if (  t.GetChi2()/t.GetNumberOfClusters()>6 &&t.GetNumberOfClusters()>18) t.SetRemoval(10);      
1832
1833       if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
1834     }
1835   }
1836   return 1;
1837 }
1838
1839
1840
1841 //_____________________________________________________________________________
1842 Int_t AliTPCtrackerMI::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step) {
1843   //-----------------------------------------------------------------
1844   // This function tries to find a track prolongation.
1845   //-----------------------------------------------------------------
1846   Double_t xt=t.GetX();
1847   //
1848   Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
1849   if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
1850   if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
1851   //
1852   t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
1853     
1854   Int_t first = GetRowNumber(xt)-1;
1855   for (Int_t nr= first; nr>=rf; nr-=step) {
1856     // update kink info
1857     if (t.GetKinkIndexes()[0]>0){
1858       for (Int_t i=0;i<3;i++){
1859         Int_t index = t.GetKinkIndexes()[i];
1860         if (index==0) break;
1861         if (index<0) continue;
1862         //
1863         AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
1864         if (!kink){
1865           printf("PROBLEM\n");
1866         }
1867         else{
1868           Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
1869           if (kinkrow==nr){
1870             AliExternalTrackParam paramd(t);
1871             kink->SetDaughter(paramd);
1872             kink->SetStatus(2,5);
1873             kink->Update();
1874           }
1875         }
1876       }
1877     }
1878
1879     if (nr==80) t.UpdateReference();
1880     if (nr<fInnerSec->GetNRows()) 
1881       fSectors = fInnerSec;
1882     else
1883       fSectors = fOuterSec;
1884     if (FollowToNext(t,nr)==0) 
1885       if (!t.IsActive()) 
1886         return 0;
1887     
1888   }   
1889   return 1;
1890 }
1891
1892
1893 //_____________________________________________________________________________
1894 Int_t AliTPCtrackerMI::FollowProlongationFast(AliTPCseed& t, Int_t rf, Int_t step) {
1895   //-----------------------------------------------------------------
1896   // This function tries to find a track prolongation.
1897   //-----------------------------------------------------------------
1898   Double_t xt=t.GetX();
1899   //
1900   Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
1901   if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
1902   if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
1903   t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
1904     
1905   for (Int_t nr=GetRowNumber(xt)-1; nr>=rf; nr-=step) {
1906     
1907     if (FollowToNextFast(t,nr)==0) 
1908       if (!t.IsActive()) return 0;
1909     
1910   }   
1911   return 1;
1912 }
1913
1914
1915
1916
1917
1918 Int_t AliTPCtrackerMI::FollowBackProlongation(AliTPCseed& t, Int_t rf) {
1919   //-----------------------------------------------------------------
1920   // This function tries to find a track prolongation.
1921   //-----------------------------------------------------------------
1922   //
1923   Double_t xt=t.GetX();  
1924   Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
1925   if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
1926   if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
1927   t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
1928     
1929   Int_t first = t.GetFirstPoint();
1930   if (first<GetRowNumber(xt)+1) first = GetRowNumber(xt)+1;
1931   //
1932   if (first<0) first=0;
1933   for (Int_t nr=first; nr<=rf; nr++) {
1934     //    if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
1935     if (t.GetKinkIndexes()[0]<0){
1936       for (Int_t i=0;i<3;i++){
1937         Int_t index = t.GetKinkIndexes()[i];
1938         if (index==0) break;
1939         if (index>0) continue;
1940         index = TMath::Abs(index);
1941         AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
1942         if (!kink){
1943           printf("PROBLEM\n");
1944         }
1945         else{
1946           Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
1947           if (kinkrow==nr){
1948             AliExternalTrackParam paramm(t);
1949             kink->SetMother(paramm);
1950             kink->SetStatus(2,1);
1951             kink->Update();
1952           }
1953         }
1954       }      
1955     }
1956     //
1957     if (nr<fInnerSec->GetNRows()) 
1958       fSectors = fInnerSec;
1959     else
1960       fSectors = fOuterSec;
1961
1962     FollowToNext(t,nr);                                                             
1963   }   
1964   return 1;
1965 }
1966
1967
1968
1969
1970    
1971 Float_t AliTPCtrackerMI::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
1972 {
1973   //
1974   //
1975   sum1=0;
1976   sum2=0;
1977   Int_t sum=0;
1978   //
1979   Float_t dz2 =(s1->GetZ() - s2->GetZ());
1980   dz2*=dz2;  
1981
1982   Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
1983   dy2*=dy2;
1984   Float_t distance = TMath::Sqrt(dz2+dy2);
1985   if (distance>4.) return 0; // if there are far away  - not overlap - to reduce combinatorics
1986  
1987   //  Int_t offset =0;
1988   Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
1989   Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
1990   if (lastpoint>160) 
1991     lastpoint =160;
1992   if (firstpoint<0) 
1993     firstpoint = 0;
1994   if (firstpoint>lastpoint) {
1995     firstpoint =lastpoint;
1996     //    lastpoint  =160;
1997   }
1998     
1999   
2000   for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2001     if (s1->GetClusterIndex2(i)>0) sum1++;
2002     if (s2->GetClusterIndex2(i)>0) sum2++;
2003     if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2004       sum++;
2005     }
2006   }
2007   if (sum<5) return 0;
2008
2009   Float_t summin = TMath::Min(sum1+1,sum2+1);
2010   Float_t ratio = (sum+1)/Float_t(summin);
2011   return ratio;
2012 }
2013
2014 void  AliTPCtrackerMI::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2015 {
2016   //
2017   //
2018   if (TMath::Abs(s1->GetC()-s2->GetC())>0.004) return;
2019   if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>0.6) return;
2020
2021   Float_t dz2 =(s1->GetZ() - s2->GetZ());
2022   dz2*=dz2;
2023   Float_t dy2 =(s1->GetY() - s2->GetY());
2024   dy2*=dy2;
2025   Float_t distance = dz2+dy2;
2026   if (distance>325.) return ; // if there are far away  - not overlap - to reduce combinatorics
2027   
2028   //
2029   Int_t sumshared=0;
2030   //
2031   Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2032   Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2033   //
2034   if (firstpoint>=lastpoint-5) return;;
2035
2036   for (Int_t i=firstpoint;i<lastpoint;i++){
2037     //    if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2038     if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2039       sumshared++;
2040     }
2041   }
2042   if (sumshared>4){
2043     // sign clusters
2044     //
2045     for (Int_t i=firstpoint;i<lastpoint;i++){
2046       //      if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2047       if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2048         AliTPCTrackerPoint *p1  = s1->GetTrackPoint(i);
2049         AliTPCTrackerPoint *p2  = s2->GetTrackPoint(i);; 
2050         if (s1->IsActive()&&s2->IsActive()){
2051           p1->SetShared(kTRUE);
2052           p2->SetShared(kTRUE);
2053         }       
2054       }
2055     }
2056   }
2057   //  
2058   if (sumshared>10){
2059     for (Int_t i=0;i<4;i++){
2060       if (s1->GetOverlapLabel(3*i)==0){
2061         s1->SetOverlapLabel(3*i,  s2->GetLabel());
2062         s1->SetOverlapLabel(3*i+1,sumshared);
2063         s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2064         break;
2065       } 
2066     }
2067     for (Int_t i=0;i<4;i++){
2068       if (s2->GetOverlapLabel(3*i)==0){
2069         s2->SetOverlapLabel(3*i,  s1->GetLabel());
2070         s2->SetOverlapLabel(3*i+1,sumshared);
2071         s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2072         break;
2073       } 
2074     }    
2075   }
2076   
2077 }
2078
2079 void  AliTPCtrackerMI::SignShared(TObjArray * arr)
2080 {
2081   //
2082   //sort trackss according sectors
2083   //  
2084   for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2085     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2086     if (!pt) continue;
2087     //if (pt) RotateToLocal(pt);
2088     pt->SetSort(0);
2089   }
2090   arr->UnSort();
2091   arr->Sort();  // sorting according z
2092   arr->Expand(arr->GetEntries());
2093   //
2094   //
2095   Int_t nseed=arr->GetEntriesFast();
2096   for (Int_t i=0; i<nseed; i++) {
2097     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2098     if (!pt) continue;
2099     for (Int_t j=0;j<=12;j++){
2100       pt->SetOverlapLabel(j,0);
2101     }
2102   }
2103   for (Int_t i=0; i<nseed; i++) {
2104     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2105     if (!pt) continue;
2106     if (pt->GetRemoval()>10) continue;
2107     for (Int_t j=i+1; j<nseed; j++){
2108       AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2109       //      if (pt2){
2110       if (pt2->GetRemoval()<=10) {
2111         if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2112         SignShared(pt,pt2);
2113       }
2114     }  
2115   }
2116 }
2117
2118 void  AliTPCtrackerMI::RemoveDouble(TObjArray * arr, Float_t factor1, Float_t factor2,  Int_t removalindex)
2119 {
2120   //
2121   //sort trackss according sectors
2122   //
2123   if (fDebug&1) {
2124     Info("RemoveDouble","Number of tracks before double removal- %d\n",arr->GetEntries());
2125   }
2126   //
2127   for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2128     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2129     if (!pt) continue;
2130     pt->SetSort(0);
2131   }
2132   arr->UnSort();
2133   arr->Sort();  // sorting according z
2134   arr->Expand(arr->GetEntries());
2135   //
2136   //reset overlap labels
2137   //
2138   Int_t nseed=arr->GetEntriesFast();
2139   for (Int_t i=0; i<nseed; i++) {
2140     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2141     if (!pt) continue;
2142     pt->SetUniqueID(i);
2143     for (Int_t j=0;j<=12;j++){
2144       pt->SetOverlapLabel(j,0);
2145     }
2146   }
2147   //
2148   //sign shared tracks
2149   for (Int_t i=0; i<nseed; i++) {
2150     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2151     if (!pt) continue;
2152     if (pt->GetRemoval()>10) continue;
2153     Float_t deltac = pt->GetC()*0.1;
2154     for (Int_t j=i+1; j<nseed; j++){
2155       AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2156       //      if (pt2){
2157       if (pt2->GetRemoval()<=10) {
2158         if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2159         if (TMath::Abs(pt->GetC()  -pt2->GetC())>deltac) continue;
2160         if (TMath::Abs(pt->GetTgl()-pt2->GetTgl())>0.05) continue;
2161         //
2162         SignShared(pt,pt2);
2163       }
2164     }
2165   }
2166   //
2167   // remove highly shared tracks
2168   for (Int_t i=0; i<nseed; i++) {
2169     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2170     if (!pt) continue;
2171     if (pt->GetRemoval()>10) continue;
2172     //
2173     Int_t sumshared =0;
2174     for (Int_t j=0;j<4;j++){
2175       sumshared = pt->GetOverlapLabel(j*3+1);      
2176     }
2177     Float_t factor = factor1;
2178     if (pt->GetRemoval()>0) factor = factor2;
2179     if (sumshared/pt->GetNumberOfClusters()>factor){
2180       for (Int_t j=0;j<4;j++){
2181         if (pt->GetOverlapLabel(3*j)==0) continue;
2182         if (pt->GetOverlapLabel(3*j+1)<5) continue; 
2183         if (pt->GetRemoval()==removalindex) continue;      
2184         AliTPCseed * pt2 = (AliTPCseed*)arr->UncheckedAt(pt->GetOverlapLabel(3*j+2));
2185         if (!pt2) continue;
2186         if (pt2->GetSigma2C()<pt->GetSigma2C()){
2187           //      pt->fRemoval = removalindex;
2188           delete arr->RemoveAt(i);        
2189           break;
2190         }
2191       }      
2192     }
2193   }
2194   arr->Compress();
2195   if (fDebug&1) {
2196     Info("RemoveDouble","Number of tracks after double removal- %d\n",arr->GetEntries());
2197   }
2198 }
2199
2200
2201
2202
2203
2204
2205 void AliTPCtrackerMI::SortTracks(TObjArray * arr, Int_t mode) const
2206 {
2207   //
2208   //sort tracks in array according mode criteria
2209   Int_t nseed = arr->GetEntriesFast();    
2210   for (Int_t i=0; i<nseed; i++) {
2211     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2212     if (!pt) {
2213       continue;
2214     }
2215     pt->SetSort(mode);
2216   }
2217   arr->UnSort();
2218   arr->Sort();
2219 }
2220
2221 void AliTPCtrackerMI::RemoveUsed(TObjArray * arr, Float_t factor1,  Float_t factor2, Int_t removalindex)
2222 {
2223
2224   //Loop over all tracks and remove "overlaps"
2225   //
2226   //
2227   Int_t nseed = arr->GetEntriesFast();  
2228   Int_t good =0;
2229
2230   for (Int_t i=0; i<nseed; i++) {
2231     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2232     if (!pt) {
2233       delete arr->RemoveAt(i);
2234     }
2235     else{
2236       pt->SetSort(1);
2237       pt->SetBSigned(kFALSE);
2238     }
2239   }
2240   arr->Compress();
2241   nseed = arr->GetEntriesFast();
2242   arr->UnSort();
2243   arr->Sort();
2244   //
2245   //unsign used
2246   UnsignClusters();
2247   //
2248   for (Int_t i=0; i<nseed; i++) {
2249     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2250     if (!pt) {
2251       continue;
2252     }    
2253     Int_t found,foundable,shared;
2254     if (pt->IsActive()) 
2255       pt->GetClusterStatistic(0,160,found, foundable,shared,kFALSE);
2256     else
2257       pt->GetClusterStatistic(0,160,found, foundable,shared,kTRUE); 
2258     //
2259     Double_t factor = factor2;
2260     if (pt->GetBConstrain()) factor = factor1;
2261
2262     if ((Float_t(shared)/Float_t(found))>factor){
2263       pt->Desactivate(removalindex);
2264       continue;
2265     }
2266
2267     good++;
2268     for (Int_t i=0; i<160; i++) {
2269       Int_t index=pt->GetClusterIndex2(i);
2270       if (index<0 || index&0x8000 ) continue;
2271       AliTPCclusterMI *c= pt->GetClusterPointer(i);        
2272       if (!c) continue;
2273       //      if (!c->IsUsed(10)) c->Use(10);
2274       //if (pt->IsActive()) 
2275       c->Use(10);  
2276       //else
2277       //        c->Use(5);
2278     }
2279     
2280   }
2281   fNtracks = good;
2282   if (fDebug>0){
2283     Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2284   }
2285 }
2286
2287
2288 void AliTPCtrackerMI::RemoveUsed2(TObjArray * arr, Float_t factor1,  Float_t factor2, Int_t minimal)
2289 {
2290
2291   //Loop over all tracks and remove "overlaps"
2292   //
2293   //
2294   UnsignClusters();
2295   //
2296   Int_t nseed = arr->GetEntriesFast();  
2297   Float_t * quality = new Float_t[nseed];
2298   Int_t   * indexes = new Int_t[nseed];
2299   Int_t good =0;
2300   //
2301   //
2302   for (Int_t i=0; i<nseed; i++) {
2303     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2304     if (!pt){
2305       quality[i]=-1;
2306       continue;
2307     }
2308     pt->UpdatePoints();    //select first last max dens points
2309     Float_t * points = pt->GetPoints();
2310     if (points[3]<0.8) quality[i] =-1;
2311     //
2312     quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
2313   }
2314   TMath::Sort(nseed,quality,indexes);
2315   //
2316   //
2317   for (Int_t itrack=0; itrack<nseed; itrack++) {
2318     Int_t trackindex = indexes[itrack];
2319     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);    
2320     if (quality[trackindex]<0){
2321       if (pt) {
2322         delete arr->RemoveAt(trackindex);
2323       }
2324       else{
2325         arr->RemoveAt(trackindex);
2326       }
2327       continue;
2328     }
2329     //
2330     Int_t first = Int_t(pt->GetPoints()[0]);
2331     Int_t last  = Int_t(pt->GetPoints()[2]);
2332     Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
2333     //
2334     Int_t found,foundable,shared;
2335     pt->GetClusterStatistic(first,last, found, foundable,shared,kFALSE);
2336     Float_t sharedfactor = Float_t(shared+1)/Float_t(found+1);
2337     Bool_t itsgold =kFALSE;
2338     if (pt->GetESD()){
2339       Int_t dummy[12];
2340       if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
2341     }
2342     if (!itsgold){
2343       //
2344       if (Float_t(shared+1)/Float_t(found+1)>factor){
2345         if (pt->GetKinkIndexes()[0]!=0) continue;  //don't remove tracks  - part of the kinks
2346         delete arr->RemoveAt(trackindex);
2347         continue;
2348       }      
2349       if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){  //remove short tracks
2350         if (pt->GetKinkIndexes()[0]!=0) continue;  //don't remove tracks  - part of the kinks
2351         delete arr->RemoveAt(trackindex);
2352         continue;
2353       }
2354     }
2355
2356     good++;
2357     if (sharedfactor>0.4) continue;
2358     if (pt->GetKinkIndexes()[0]>0) continue;
2359     for (Int_t i=first; i<last; i++) {
2360       Int_t index=pt->GetClusterIndex2(i);
2361       // if (index<0 || index&0x8000 ) continue;
2362       if (index<0 || index&0x8000 ) continue;
2363       AliTPCclusterMI *c= pt->GetClusterPointer(i);        
2364       if (!c) continue;
2365       c->Use(10);  
2366     }    
2367   }
2368   fNtracks = good;
2369   if (fDebug>0){
2370     Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2371   }
2372   delete []quality;
2373   delete []indexes;
2374 }
2375
2376 void AliTPCtrackerMI::UnsignClusters() 
2377 {
2378   //
2379   // loop over all clusters and unsign them
2380   //
2381   
2382   for (Int_t sec=0;sec<fkNIS;sec++){
2383     for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2384       AliTPCclusterMI *cl = fInnerSec[sec][row].GetClusters1();
2385       for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
2386         //      if (cl[icl].IsUsed(10))         
2387         cl[icl].Use(-1);
2388       cl = fInnerSec[sec][row].GetClusters2();
2389       for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
2390         //if (cl[icl].IsUsed(10))       
2391           cl[icl].Use(-1);      
2392     }
2393   }
2394   
2395   for (Int_t sec=0;sec<fkNOS;sec++){
2396     for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2397       AliTPCclusterMI *cl = fOuterSec[sec][row].GetClusters1();
2398       for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
2399         //if (cl[icl].IsUsed(10))       
2400           cl[icl].Use(-1);
2401       cl = fOuterSec[sec][row].GetClusters2();
2402       for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
2403         //if (cl[icl].IsUsed(10))       
2404         cl[icl].Use(-1);      
2405     }
2406   }
2407   
2408 }
2409
2410
2411
2412 void AliTPCtrackerMI::SignClusters(TObjArray * arr, Float_t fnumber, Float_t fdensity)
2413 {
2414   //
2415   //sign clusters to be "used"
2416   //
2417   // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
2418   // loop over "primaries"
2419   
2420   Float_t sumdens=0;
2421   Float_t sumdens2=0;
2422   Float_t sumn   =0;
2423   Float_t sumn2  =0;
2424   Float_t sumchi =0;
2425   Float_t sumchi2 =0;
2426
2427   Float_t sum    =0;
2428
2429   TStopwatch timer;
2430   timer.Start();
2431
2432   Int_t nseed = arr->GetEntriesFast();
2433   for (Int_t i=0; i<nseed; i++) {
2434     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2435     if (!pt) {
2436       continue;
2437     }    
2438     if (!(pt->IsActive())) continue;
2439     Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2440     if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
2441       sumdens += dens;
2442       sumdens2+= dens*dens;
2443       sumn    += pt->GetNumberOfClusters();
2444       sumn2   += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
2445       Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
2446       if (chi2>5) chi2=5;
2447       sumchi  +=chi2;
2448       sumchi2 +=chi2*chi2;
2449       sum++;
2450     }
2451   }
2452
2453   Float_t mdensity = 0.9;
2454   Float_t meann    = 130;
2455   Float_t meanchi  = 1;
2456   Float_t sdensity = 0.1;
2457   Float_t smeann    = 10;
2458   Float_t smeanchi  =0.4;
2459   
2460
2461   if (sum>20){
2462     mdensity = sumdens/sum;
2463     meann    = sumn/sum;
2464     meanchi  = sumchi/sum;
2465     //
2466     sdensity = sumdens2/sum-mdensity*mdensity;
2467     sdensity = TMath::Sqrt(sdensity);
2468     //
2469     smeann   = sumn2/sum-meann*meann;
2470     smeann   = TMath::Sqrt(smeann);
2471     //
2472     smeanchi = sumchi2/sum - meanchi*meanchi;
2473     smeanchi = TMath::Sqrt(smeanchi);
2474   }
2475
2476
2477   //REMOVE  SHORT DELTAS or tracks going out of sensitive volume of TPC
2478   //
2479   for (Int_t i=0; i<nseed; i++) {
2480     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2481     if (!pt) {
2482       continue;
2483     }
2484     if (pt->GetBSigned()) continue;
2485     if (pt->GetBConstrain()) continue;    
2486     //if (!(pt->IsActive())) continue;
2487     /*
2488     Int_t found,foundable,shared;    
2489     pt->GetClusterStatistic(0,160,found, foundable,shared);
2490     if (shared/float(found)>0.3) {
2491       if (shared/float(found)>0.9 ){
2492         //delete arr->RemoveAt(i);
2493       }
2494       continue;
2495     }
2496     */
2497     Bool_t isok =kFALSE;
2498     if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
2499       isok = kTRUE;
2500     if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
2501       isok =kTRUE;
2502     if  (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
2503       isok =kTRUE;
2504     if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
2505       isok =kTRUE;
2506     
2507     if (isok)     
2508       for (Int_t i=0; i<160; i++) {     
2509         Int_t index=pt->GetClusterIndex2(i);
2510         if (index<0) continue;
2511         AliTPCclusterMI *c= pt->GetClusterPointer(i);
2512         if (!c) continue;
2513         //if (!(c->IsUsed(10))) c->Use();  
2514         c->Use(10);  
2515       }
2516   }
2517   
2518   
2519   //
2520   Double_t maxchi  = meanchi+2.*smeanchi;
2521
2522   for (Int_t i=0; i<nseed; i++) {
2523     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2524     if (!pt) {
2525       continue;
2526     }    
2527     //if (!(pt->IsActive())) continue;
2528     if (pt->GetBSigned()) continue;
2529     Double_t chi     = pt->GetChi2()/pt->GetNumberOfClusters();
2530     if (chi>maxchi) continue;
2531
2532     Float_t bfactor=1;
2533     Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2534    
2535     //sign only tracks with enoug big density at the beginning
2536     
2537     if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue; 
2538     
2539     
2540     Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
2541     Double_t minn    = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
2542    
2543     //    if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
2544     if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
2545       minn=0;
2546
2547     if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
2548       //Int_t noc=pt->GetNumberOfClusters();
2549       pt->SetBSigned(kTRUE);
2550       for (Int_t i=0; i<160; i++) {
2551
2552         Int_t index=pt->GetClusterIndex2(i);
2553         if (index<0) continue;
2554         AliTPCclusterMI *c= pt->GetClusterPointer(i);
2555         if (!c) continue;
2556         //      if (!(c->IsUsed(10))) c->Use();  
2557         c->Use(10);  
2558       }
2559     }
2560   }
2561   //  gLastCheck = nseed;
2562   //  arr->Compress();
2563   if (fDebug>0){
2564     timer.Print();
2565   }
2566 }
2567
2568
2569 void  AliTPCtrackerMI::StopNotActive(TObjArray * arr, Int_t row0, Float_t th0, Float_t th1, Float_t th2) const
2570 {
2571   // stop not active tracks
2572   // take th1 as threshold for number of founded to number of foundable on last 10 active rows
2573   // take th2 as threshold for number of founded to number of foundable on last 20 active rows 
2574   Int_t nseed = arr->GetEntriesFast();  
2575   //
2576   for (Int_t i=0; i<nseed; i++) {
2577     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2578     if (!pt) {
2579       continue;
2580     }
2581     if (!(pt->IsActive())) continue;
2582     StopNotActive(pt,row0,th0, th1,th2);
2583   }
2584 }
2585
2586
2587
2588 void  AliTPCtrackerMI::StopNotActive(AliTPCseed * seed, Int_t row0, Float_t th0, Float_t th1,
2589  Float_t th2) const
2590 {
2591   // stop not active tracks
2592   // take th1 as threshold for number of founded to number of foundable on last 10 active rows
2593   // take th2 as threshold for number of founded to number of foundable on last 20 active rows 
2594   Int_t sumgood1  = 0;
2595   Int_t sumgood2  = 0;
2596   Int_t foundable = 0;
2597   Int_t maxindex = seed->GetLastPoint();  //last foundable row
2598   if (seed->GetNFoundable()*th0 > seed->GetNumberOfClusters()) {
2599     seed->Desactivate(10) ;
2600     return;
2601   }
2602
2603   for (Int_t i=row0; i<maxindex; i++){
2604     Int_t index = seed->GetClusterIndex2(i);
2605     if (index!=-1) foundable++;
2606     //if (!c) continue;
2607     if (foundable<=30) sumgood1++;
2608     if (foundable<=50) {
2609       sumgood2++;
2610     }
2611     else{ 
2612       break;
2613     }        
2614   }
2615   if (foundable>=30.){ 
2616      if (sumgood1<(th1*30.)) seed->Desactivate(10);
2617   }
2618   if (foundable>=50)
2619     if (sumgood2<(th2*50.)) seed->Desactivate(10);
2620 }
2621
2622
2623 Int_t AliTPCtrackerMI::RefitInward(AliESD *event)
2624 {
2625   //
2626   // back propagation of ESD tracks
2627   //
2628   //return 0;
2629   fEvent = event;
2630   ReadSeeds(event,2);
2631   fIteration=2;
2632   //PrepareForProlongation(fSeeds,1);
2633   PropagateForward2(fSeeds);
2634
2635   Int_t ntracks=0;
2636   Int_t nseed = fSeeds->GetEntriesFast();
2637   for (Int_t i=0;i<nseed;i++){
2638     AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
2639     if (!seed) continue;
2640     if (seed->GetKinkIndex(0)>0)  UpdateKinkQualityD(seed);  // update quality informations for kinks
2641
2642     seed->PropagateTo(fParam->GetInnerRadiusLow());
2643     seed->UpdatePoints();
2644     AliESDtrack *esd=event->GetTrack(i);
2645     seed->CookdEdx(0.02,0.6);
2646     CookLabel(seed,0.1); //For comparison only
2647     //
2648     if (AliTPCReconstructor::StreamLevel()>0 && seed!=0&&esd!=0) {
2649       TTreeSRedirector &cstream = *fDebugStreamer;
2650       cstream<<"Crefit"<<
2651         "Esd.="<<esd<<
2652         "Track.="<<seed<<
2653         "\n"; 
2654     }
2655
2656     if (seed->GetNumberOfClusters()>15){
2657       esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit); 
2658       esd->SetTPCPoints(seed->GetPoints());
2659       esd->SetTPCPointsF(seed->GetNFoundable());
2660       Int_t ndedx   = seed->GetNCDEDX(0)+seed->GetNCDEDX(1)+seed->GetNCDEDX(2)+seed->GetNCDEDX(3);
2661       Float_t sdedx = (seed->GetSDEDX(0)+seed->GetSDEDX(1)+seed->GetSDEDX(2)+seed->GetSDEDX(3))*0.25;
2662       Float_t dedx  = seed->GetdEdx();
2663       esd->SetTPCsignal(dedx, sdedx, ndedx);
2664       //
2665       // add seed to the esd track in Calib level
2666       //
2667       if (AliTPCReconstructor::StreamLevel()>0){
2668         AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE); 
2669         esd->AddCalibObject(seedCopy);
2670       }
2671       ntracks++;
2672     }
2673     else{
2674       //printf("problem\n");
2675     }
2676   }
2677   //FindKinks(fSeeds,event);
2678   Info("RefitInward","Number of refitted tracks %d",ntracks);
2679   fEvent =0;
2680   //WriteTracks();
2681   return 0;
2682 }
2683
2684
2685 Int_t AliTPCtrackerMI::PropagateBack(AliESD *event)
2686 {
2687   //
2688   // back propagation of ESD tracks
2689   //
2690
2691   fEvent = event;
2692   fIteration = 1;
2693   ReadSeeds(event,1);
2694   PropagateBack(fSeeds); 
2695   RemoveUsed2(fSeeds,0.4,0.4,20);
2696   //
2697   Int_t nseed = fSeeds->GetEntriesFast();
2698   Int_t ntracks=0;
2699   for (Int_t i=0;i<nseed;i++){
2700     AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
2701     if (!seed) continue;
2702     if (seed->GetKinkIndex(0)<0)  UpdateKinkQualityM(seed);  // update quality informations for kinks
2703     seed->UpdatePoints();
2704     AliESDtrack *esd=event->GetTrack(i);
2705     seed->CookdEdx(0.02,0.6);
2706     CookLabel(seed,0.1); //For comparison only
2707     if (seed->GetNumberOfClusters()>15){
2708       esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
2709       esd->SetTPCPoints(seed->GetPoints());
2710       esd->SetTPCPointsF(seed->GetNFoundable());
2711       Int_t ndedx   = seed->GetNCDEDX(0)+seed->GetNCDEDX(1)+seed->GetNCDEDX(2)+seed->GetNCDEDX(3);
2712       Float_t sdedx = (seed->GetSDEDX(0)+seed->GetSDEDX(1)+seed->GetSDEDX(2)+seed->GetSDEDX(3))*0.25;
2713       Float_t dedx  = seed->GetdEdx();
2714       esd->SetTPCsignal(dedx, sdedx, ndedx);
2715       ntracks++;
2716       Int_t eventnumber = event->GetEventNumber();// patch 28 fev 06
2717       (*fDebugStreamer)<<"Cback"<<
2718         "Tr0.="<<seed<<
2719         "EventNr="<<eventnumber<<
2720         "\n"; // patch 28 fev 06   
2721     }
2722   }
2723   //FindKinks(fSeeds,event);
2724   Info("PropagateBack","Number of back propagated tracks %d",ntracks);
2725   fEvent =0;
2726   //WriteTracks();
2727
2728   return 0;
2729 }
2730
2731
2732 void AliTPCtrackerMI::DeleteSeeds()
2733 {
2734   //
2735   //delete Seeds
2736
2737   Int_t nseed = fSeeds->GetEntriesFast();
2738   for (Int_t i=0;i<nseed;i++){
2739     AliTPCseed * seed = (AliTPCseed*)fSeeds->At(i);
2740     if (seed) delete fSeeds->RemoveAt(i);
2741   }
2742   delete fSeeds;
2743
2744   fSeeds =0;
2745 }
2746
2747 void AliTPCtrackerMI::ReadSeeds(AliESD *event, Int_t direction)
2748 {
2749   //
2750   //read seeds from the event
2751   
2752   Int_t nentr=event->GetNumberOfTracks();
2753   if (fDebug>0){
2754     Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
2755   }
2756   if (fSeeds) 
2757     DeleteSeeds();
2758   if (!fSeeds){   
2759     fSeeds = new TObjArray(nentr);
2760   }
2761   UnsignClusters();
2762   //  Int_t ntrk=0;  
2763   for (Int_t i=0; i<nentr; i++) {
2764     AliESDtrack *esd=event->GetTrack(i);
2765     ULong_t status=esd->GetStatus();
2766     if (!(status&AliESDtrack::kTPCin)) continue;
2767     AliTPCtrack t(*esd);
2768     t.SetNumberOfClusters(0);
2769     //    AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
2770     AliTPCseed *seed = new AliTPCseed(t/*,t.GetAlpha()*/);
2771     for (Int_t ikink=0;ikink<3;ikink++) {
2772       Int_t index = esd->GetKinkIndex(ikink);
2773       seed->GetKinkIndexes()[ikink] = index;
2774       if (index==0) continue;
2775       index = TMath::Abs(index);
2776       AliESDkink * kink = fEvent->GetKink(index-1);
2777       if (kink&&esd->GetKinkIndex(ikink)<0){
2778         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
2779         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,0);
2780       }
2781       if (kink&&esd->GetKinkIndex(ikink)>0){
2782         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
2783         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,4);
2784       }
2785
2786     }
2787     if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.); 
2788     if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
2789     if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
2790       fSeeds->AddAt(0,i);
2791       delete seed;
2792       continue;    
2793     }
2794     if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) > 0 )  {
2795       Double_t par0[5],par1[5],alpha,x;
2796       esd->GetInnerExternalParameters(alpha,x,par0);
2797       esd->GetExternalParameters(x,par1);
2798       Double_t delta1 = TMath::Abs(par0[4]-par1[4])/(0.000000001+TMath::Abs(par0[4]+par1[4]));
2799       Double_t delta2 = TMath::Abs(par0[3]-par1[3]);
2800       Double_t trdchi2=0;
2801       if (esd->GetTRDncls()>0) trdchi2 = esd->GetTRDchi2()/esd->GetTRDncls();
2802       //reset covariance if suspicious 
2803       if ( (delta1>0.1) || (delta2>0.006) ||trdchi2>7.)
2804         seed->ResetCovariance(10.);
2805     }
2806
2807     //
2808     //
2809     // rotate to the local coordinate system
2810     //   
2811     fSectors=fInnerSec; fN=fkNIS;    
2812     Double_t alpha=seed->GetAlpha() - fSectors->GetAlphaShift();
2813     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2814     if (alpha < 0.            ) alpha += 2.*TMath::Pi();
2815     Int_t ns=Int_t(alpha/fSectors->GetAlpha())%fN;
2816     alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
2817     if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
2818     if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
2819     alpha-=seed->GetAlpha();  
2820     if (!seed->Rotate(alpha)) {
2821       delete seed;
2822       continue;
2823     }
2824     seed->SetESD(esd);
2825     // sign clusters
2826     if (esd->GetKinkIndex(0)<=0){
2827       for (Int_t irow=0;irow<160;irow++){
2828         Int_t index = seed->GetClusterIndex2(irow);    
2829         if (index>0){ 
2830           //
2831           AliTPCclusterMI * cl = GetClusterMI(index);
2832           seed->SetClusterPointer(irow,cl);
2833           if (cl){
2834             if ((index & 0x8000)==0){
2835               cl->Use(10);  // accepted cluster   
2836             }else{
2837               cl->Use(6);   // close cluster not accepted
2838             }   
2839           }else{
2840             Info("ReadSeeds","Not found cluster");
2841           }
2842         }
2843       }
2844     }
2845     fSeeds->AddAt(seed,i);
2846   }
2847 }
2848
2849
2850
2851 //_____________________________________________________________________________
2852 void AliTPCtrackerMI::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
2853                                  Float_t deltay, Int_t ddsec) {
2854   //-----------------------------------------------------------------
2855   // This function creates track seeds.
2856   // SEEDING WITH VERTEX CONSTRAIN 
2857   //-----------------------------------------------------------------
2858   // cuts[0]   - fP4 cut
2859   // cuts[1]   - tan(phi)  cut
2860   // cuts[2]   - zvertex cut
2861   // cuts[3]   - fP3 cut
2862   Int_t nin0  = 0;
2863   Int_t nin1  = 0;
2864   Int_t nin2  = 0;
2865   Int_t nin   = 0;
2866   Int_t nout1 = 0;
2867   Int_t nout2 = 0;
2868
2869   Double_t x[5], c[15];
2870   //  Int_t di = i1-i2;
2871   //
2872   AliTPCseed * seed = new AliTPCseed;
2873   Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
2874   Double_t cs=cos(alpha), sn=sin(alpha);
2875   //
2876   //  Double_t x1 =fOuterSec->GetX(i1);
2877   //Double_t xx2=fOuterSec->GetX(i2);
2878   
2879   Double_t x1 =GetXrow(i1);
2880   Double_t xx2=GetXrow(i2);
2881
2882   Double_t x3=GetX(), y3=GetY(), z3=GetZ();
2883
2884   Int_t imiddle = (i2+i1)/2;    //middle pad row index
2885   Double_t xm = GetXrow(imiddle); // radius of middle pad-row
2886   const AliTPCRow& krm=GetRow(sec,imiddle); //middle pad -row
2887   //
2888   Int_t ns =sec;   
2889
2890   const AliTPCRow& kr1=GetRow(ns,i1);
2891   Double_t ymax  = GetMaxY(i1)-kr1.GetDeadZone()-1.5;  
2892   Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;  
2893
2894   //
2895   // change cut on curvature if it can't reach this layer
2896   // maximal curvature set to reach it
2897   Double_t dvertexmax  = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
2898   if (dvertexmax*0.5*cuts[0]>0.85){
2899     cuts[0] = 0.85/(dvertexmax*0.5+1.);
2900   }
2901   Double_t r2min = 1/(cuts[0]*cuts[0]);  //minimal square of radius given by cut
2902
2903   //  Int_t ddsec = 1;
2904   if (deltay>0) ddsec = 0; 
2905   // loop over clusters  
2906   for (Int_t is=0; is < kr1; is++) {
2907     //
2908     if (kr1[is]->IsUsed(10)) continue;
2909     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
2910     //if (TMath::Abs(y1)>ymax) continue;
2911
2912     if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge
2913
2914     // find possible directions    
2915     Float_t anglez = (z1-z3)/(x1-x3); 
2916     Float_t extraz = z1 - anglez*(x1-xx2);  // extrapolated z      
2917     //
2918     //
2919     //find   rotation angles relative to line given by vertex and point 1
2920     Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
2921     Double_t dvertex  = TMath::Sqrt(dvertex2);
2922     Double_t angle13  = TMath::ATan((y1-y3)/(x1-x3));
2923     Double_t cs13     = cos(-angle13), sn13 = sin(-angle13);            
2924     
2925     //
2926     // loop over 2 sectors
2927     Int_t dsec1=-ddsec;
2928     Int_t dsec2= ddsec;
2929     if (y1<0)  dsec2= 0;
2930     if (y1>0)  dsec1= 0;
2931     
2932     Double_t dddz1=0;  // direction of delta inclination in z axis
2933     Double_t dddz2=0;
2934     if ( (z1-z3)>0)
2935       dddz1 =1;    
2936     else
2937       dddz2 =1;
2938     //
2939     for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
2940       Int_t sec2 = sec + dsec;
2941       // 
2942       //      AliTPCRow&  kr2  = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
2943       //AliTPCRow&  kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
2944       AliTPCRow&  kr2  = GetRow((sec2+fkNOS)%fkNOS,i2);
2945       AliTPCRow&  kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
2946       Int_t  index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
2947       Int_t  index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
2948
2949       // rotation angles to p1-p3
2950       Double_t cs13r     = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;            
2951       Double_t x2,   y2,   z2; 
2952       //
2953       //      Double_t dymax = maxangle*TMath::Abs(x1-xx2);
2954
2955       //
2956       Double_t dxx0 =  (xx2-x3)*cs13r;
2957       Double_t dyy0 =  (xx2-x3)*sn13r;
2958       for (Int_t js=index1; js < index2; js++) {
2959         const AliTPCclusterMI *kcl = kr2[js];
2960         if (kcl->IsUsed(10)) continue;  
2961         //
2962         //calcutate parameters
2963         //      
2964         Double_t yy0 =  dyy0 +(kcl->GetY()-y3)*cs13r;
2965         // stright track
2966         if (TMath::Abs(yy0)<0.000001) continue;
2967         Double_t xx0 =  dxx0 -(kcl->GetY()-y3)*sn13r;
2968         Double_t y0  =  0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
2969         Double_t r02 = (0.25+y0*y0)*dvertex2;   
2970         //curvature (radius) cut
2971         if (r02<r2min) continue;                
2972        
2973         nin0++; 
2974         //
2975         Double_t c0  = 1/TMath::Sqrt(r02);
2976         if (yy0>0) c0*=-1.;     
2977                
2978        
2979         //Double_t dfi0   = 2.*TMath::ASin(dvertex*c0*0.5);
2980         //Double_t dfi1   = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
2981         Double_t dfi0   = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
2982         Double_t dfi1   = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);  
2983         //
2984         //
2985         Double_t z0  =  kcl->GetZ();  
2986         Double_t zzzz2    = z1-(z1-z3)*dfi1/dfi0;
2987         if (TMath::Abs(zzzz2-z0)>0.5) continue;       
2988         nin1++;              
2989         //      
2990         Double_t dip    = (z1-z0)*c0/dfi1;        
2991         Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
2992         //
2993         y2 = kcl->GetY(); 
2994         if (dsec==0){
2995           x2 = xx2; 
2996           z2 = kcl->GetZ();       
2997         }
2998         else
2999           {
3000             // rotation 
3001             z2 = kcl->GetZ();  
3002             x2= xx2*cs-y2*sn*dsec;
3003             y2=+xx2*sn*dsec+y2*cs;
3004           }
3005         
3006         x[0] = y1;
3007         x[1] = z1;
3008         x[2] = x0;
3009         x[3] = dip;
3010         x[4] = c0;
3011         //
3012         //
3013         // do we have cluster at the middle ?
3014         Double_t ym,zm;
3015         GetProlongation(x1,xm,x,ym,zm);
3016         UInt_t dummy; 
3017         AliTPCclusterMI * cm=0;
3018         if (TMath::Abs(ym)-ymaxm<0){      
3019           cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3020           if ((!cm) || (cm->IsUsed(10))) {        
3021             continue;
3022           }
3023         }
3024         else{     
3025           // rotate y1 to system 0
3026           // get state vector in rotated system 
3027           Double_t yr1  = (-0.5*sn13+y0*cs13)*dvertex*c0;
3028           Double_t xr2  =  x0*cs+yr1*sn*dsec;
3029           Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3030           //
3031           GetProlongation(xx2,xm,xr,ym,zm);
3032           if (TMath::Abs(ym)-ymaxm<0){
3033             cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3034             if ((!cm) || (cm->IsUsed(10))) {      
3035               continue;
3036             }
3037           }
3038         }
3039        
3040
3041         Double_t dym = 0;
3042         Double_t dzm = 0;
3043         if (cm){
3044           dym = ym - cm->GetY();
3045           dzm = zm - cm->GetZ();
3046         }
3047         nin2++;
3048
3049
3050         //
3051         //
3052         Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3053         Double_t sy2=kcl->GetSigmaY2()*2.,     sz2=kcl->GetSigmaZ2()*2.;
3054         //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3055         Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3056         //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3057
3058         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3059         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3060         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3061         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3062         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3063         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3064         
3065         Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3066         Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3067         Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3068         Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3069         
3070         c[0]=sy1;
3071         c[1]=0.;       c[2]=sz1;
3072         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3073         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3074                        c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3075         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3076         c[13]=f30*sy1*f40+f32*sy2*f42;
3077         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3078         
3079         //      if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3080         
3081         UInt_t index=kr1.GetIndex(is);
3082         AliTPCseed *track=new(seed) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3083         
3084         track->SetIsSeeding(kTRUE);
3085         track->SetSeed1(i1);
3086         track->SetSeed2(i2);
3087         track->SetSeedType(3);
3088
3089        
3090         //if (dsec==0) {
3091           FollowProlongation(*track, (i1+i2)/2,1);
3092           Int_t foundable,found,shared;
3093           track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3094           if ((found<0.55*foundable)  || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3095             seed->Reset();
3096             seed->~AliTPCseed();
3097             continue;
3098           }
3099           //}
3100         
3101         nin++;
3102         FollowProlongation(*track, i2,1);
3103         
3104         
3105         //Int_t rc = 1;
3106         track->SetBConstrain(1);
3107         //      track->fLastPoint = i1+fInnerSec->GetNRows();  // first cluster in track position
3108         track->SetLastPoint(i1);  // first cluster in track position
3109         track->SetFirstPoint(track->GetLastPoint());
3110         
3111         if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
3112             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
3113             track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3114           seed->Reset();
3115           seed->~AliTPCseed();
3116           continue;
3117         }
3118         nout1++;
3119         // Z VERTEX CONDITION
3120         Double_t zv, bz=GetBz();
3121         if ( !track->GetZAt(0.,bz,zv) ) continue;
3122         if (TMath::Abs(zv-z3)>cuts[2]) {
3123           FollowProlongation(*track, TMath::Max(i2-20,0));
3124           if ( !track->GetZAt(0.,bz,zv) ) continue;
3125           if (TMath::Abs(zv-z3)>cuts[2]){
3126             FollowProlongation(*track, TMath::Max(i2-40,0));
3127             if ( !track->GetZAt(0.,bz,zv) ) continue;
3128             if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3129               // make seed without constrain
3130               AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3131               FollowProlongation(*track2, i2,1);
3132               track2->SetBConstrain(kFALSE);
3133               track2->SetSeedType(1);
3134               arr->AddLast(track2); 
3135               seed->Reset();
3136               seed->~AliTPCseed();
3137               continue;         
3138             }
3139             else{
3140               seed->Reset();
3141               seed->~AliTPCseed();
3142               continue;
3143             
3144             }
3145           }
3146         }
3147         
3148         track->SetSeedType(0);
3149         arr->AddLast(track); 
3150         seed = new AliTPCseed;  
3151         nout2++;
3152         // don't consider other combinations
3153         if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3154           break;
3155       }
3156     }
3157   }
3158   if (fDebug>3){
3159     Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3160   }
3161   delete seed;
3162 }
3163
3164
3165 void AliTPCtrackerMI::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
3166                                  Float_t deltay) {
3167   
3168
3169
3170   //-----------------------------------------------------------------
3171   // This function creates track seeds.
3172   //-----------------------------------------------------------------
3173   // cuts[0]   - fP4 cut
3174   // cuts[1]   - tan(phi)  cut
3175   // cuts[2]   - zvertex cut
3176   // cuts[3]   - fP3 cut
3177
3178
3179   Int_t nin0  = 0;
3180   Int_t nin1  = 0;
3181   Int_t nin2  = 0;
3182   Int_t nin   = 0;
3183   Int_t nout1 = 0;
3184   Int_t nout2 = 0;
3185   Int_t nout3 =0;
3186   Double_t x[5], c[15];
3187   //
3188   // make temporary seed
3189   AliTPCseed * seed = new AliTPCseed;
3190   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3191   //  Double_t cs=cos(alpha), sn=sin(alpha);
3192   //
3193   //
3194
3195   // first 3 padrows
3196   Double_t x1 = GetXrow(i1-1);
3197   const    AliTPCRow& kr1=GetRow(sec,i1-1);
3198   Double_t y1max  = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;  
3199   //
3200   Double_t x1p = GetXrow(i1);
3201   const    AliTPCRow& kr1p=GetRow(sec,i1);
3202   //
3203   Double_t x1m = GetXrow(i1-2);
3204   const    AliTPCRow& kr1m=GetRow(sec,i1-2);
3205
3206   //
3207   //last 3 padrow for seeding
3208   AliTPCRow&  kr3  = GetRow((sec+fkNOS)%fkNOS,i1-7);
3209   Double_t    x3   =  GetXrow(i1-7);
3210   //  Double_t    y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;  
3211   //
3212   AliTPCRow&  kr3p  = GetRow((sec+fkNOS)%fkNOS,i1-6);
3213   Double_t    x3p   = GetXrow(i1-6);
3214   //
3215   AliTPCRow&  kr3m  = GetRow((sec+fkNOS)%fkNOS,i1-8);
3216   Double_t    x3m   = GetXrow(i1-8);
3217
3218   //
3219   //
3220   // middle padrow
3221   Int_t im = i1-4;                           //middle pad row index
3222   Double_t xm         = GetXrow(im);         // radius of middle pad-row
3223   const AliTPCRow& krm=GetRow(sec,im);   //middle pad -row
3224   //  Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;  
3225   //
3226   //
3227   Double_t deltax  = x1-x3;
3228   Double_t dymax   = deltax*cuts[1];
3229   Double_t dzmax   = deltax*cuts[3];
3230   //
3231   // loop over clusters  
3232   for (Int_t is=0; is < kr1; is++) {
3233     //
3234     if (kr1[is]->IsUsed(10)) continue;
3235     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
3236     //
3237     if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge    
3238     // 
3239     Int_t  index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3240     Int_t  index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3241     //    
3242     Double_t y3,   z3;
3243     //
3244     //
3245     UInt_t index;
3246     for (Int_t js=index1; js < index2; js++) {
3247       const AliTPCclusterMI *kcl = kr3[js];
3248       if (kcl->IsUsed(10)) continue;
3249       y3 = kcl->GetY(); 
3250       // apply angular cuts
3251       if (TMath::Abs(y1-y3)>dymax) continue;
3252       x3 = x3; 
3253       z3 = kcl->GetZ(); 
3254       if (TMath::Abs(z1-z3)>dzmax) continue;
3255       //
3256       Double_t angley = (y1-y3)/(x1-x3);
3257       Double_t anglez = (z1-z3)/(x1-x3);
3258       //
3259       Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3260       Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3261       //
3262       Double_t yyym = angley*(xm-x1)+y1;
3263       Double_t zzzm = anglez*(xm-x1)+z1;
3264
3265       const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3266       if (!kcm) continue;
3267       if (kcm->IsUsed(10)) continue;
3268       
3269       erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3270       errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3271       //
3272       //
3273       //
3274       Int_t used  =0;
3275       Int_t found =0;
3276       //
3277       // look around first
3278       const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3279                                                       anglez*(x1m-x1)+z1,
3280                                                       erry,errz,index);
3281       //
3282       if (kc1m){
3283         found++;
3284         if (kc1m->IsUsed(10)) used++;
3285       }
3286       const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3287                                                       anglez*(x1p-x1)+z1,
3288                                                       erry,errz,index);
3289       //
3290       if (kc1p){
3291         found++;
3292         if (kc1p->IsUsed(10)) used++;
3293       }
3294       if (used>1)  continue;
3295       if (found<1) continue; 
3296
3297       //
3298       // look around last
3299       const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3300                                                       anglez*(x3m-x3)+z3,
3301                                                       erry,errz,index);
3302       //
3303       if (kc3m){
3304         found++;
3305         if (kc3m->IsUsed(10)) used++;
3306       }
3307       else 
3308         continue;
3309       const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3310                                                       anglez*(x3p-x3)+z3,
3311                                                       erry,errz,index);
3312       //
3313       if (kc3p){
3314         found++;
3315         if (kc3p->IsUsed(10)) used++;
3316       }
3317       else 
3318         continue;
3319       if (used>1)  continue;
3320       if (found<3) continue;       
3321       //
3322       Double_t x2,y2,z2;
3323       x2 = xm;
3324       y2 = kcm->GetY();
3325       z2 = kcm->GetZ();
3326       //
3327                         
3328       x[0]=y1;
3329       x[1]=z1;
3330       x[4]=F1(x1,y1,x2,y2,x3,y3);
3331       //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3332       nin0++;
3333       //
3334       x[2]=F2(x1,y1,x2,y2,x3,y3);
3335       nin1++;
3336       //
3337       x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3338       //if (TMath::Abs(x[3]) > cuts[3]) continue;
3339       nin2++;
3340       //
3341       //
3342       Double_t sy1=0.1,  sz1=0.1;
3343       Double_t sy2=0.1,  sz2=0.1;
3344       Double_t sy3=0.1,  sy=0.1, sz=0.1;
3345       
3346       Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3347       Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3348       Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3349       Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3350       Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3351       Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3352       
3353       Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3354       Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3355       Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3356       Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3357       
3358       c[0]=sy1;
3359       c[1]=0.;       c[2]=sz1; 
3360       c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3361       c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3362       c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3363       c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3364       c[13]=f30*sy1*f40+f32*sy2*f42;
3365       c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3366       
3367       //        if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3368       
3369       UInt_t index=kr1.GetIndex(is);
3370       AliTPCseed *track=new(seed) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3371       
3372       track->SetIsSeeding(kTRUE);
3373
3374       nin++;      
3375       FollowProlongation(*track, i1-7,1);
3376       if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 || 
3377           track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3378         seed->Reset();
3379         seed->~AliTPCseed();
3380         continue;
3381       }
3382       nout1++;
3383       nout2++;  
3384       //Int_t rc = 1;
3385       FollowProlongation(*track, i2,1);
3386       track->SetBConstrain(0);
3387       track->SetLastPoint(i1+fInnerSec->GetNRows());  // first cluster in track position
3388       track->SetFirstPoint(track->GetLastPoint());
3389       
3390       if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
3391           track->GetNumberOfClusters()<track->GetNFoundable()*0.7 || 
3392           track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3393         seed->Reset();
3394         seed->~AliTPCseed();
3395         continue;
3396       }
3397    
3398       {
3399         FollowProlongation(*track, TMath::Max(i2-10,0),1);
3400         AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3401         FollowProlongation(*track2, i2,1);
3402         track2->SetBConstrain(kFALSE);
3403         track2->SetSeedType(4);
3404         arr->AddLast(track2); 
3405         seed->Reset();
3406         seed->~AliTPCseed();
3407       }
3408       
3409    
3410       //arr->AddLast(track); 
3411       //seed = new AliTPCseed;  
3412       nout3++;
3413     }
3414   }
3415   
3416   if (fDebug>3){
3417     Info("MakeSeeds5","\nSeeding statiistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2,nout3);
3418   }
3419   delete seed;
3420 }
3421
3422
3423 //_____________________________________________________________________________
3424 void AliTPCtrackerMI::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3425                                  Float_t deltay, Bool_t /*bconstrain*/) {
3426   //-----------------------------------------------------------------
3427   // This function creates track seeds - without vertex constraint
3428   //-----------------------------------------------------------------
3429   // cuts[0]   - fP4 cut        - not applied
3430   // cuts[1]   - tan(phi)  cut
3431   // cuts[2]   - zvertex cut    - not applied 
3432   // cuts[3]   - fP3 cut
3433   Int_t nin0=0;
3434   Int_t nin1=0;
3435   Int_t nin2=0;
3436   Int_t nin3=0;
3437   //  Int_t nin4=0;
3438   //Int_t nin5=0;
3439
3440   
3441
3442   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3443   //  Double_t cs=cos(alpha), sn=sin(alpha);
3444   Int_t row0 = (i1+i2)/2;
3445   Int_t drow = (i1-i2)/2;
3446   const AliTPCRow& kr0=fSectors[sec][row0];
3447   AliTPCRow * kr=0;
3448
3449   AliTPCpolyTrack polytrack;
3450   Int_t nclusters=fSectors[sec][row0];
3451   AliTPCseed * seed = new AliTPCseed;
3452
3453   Int_t sumused=0;
3454   Int_t cused=0;
3455   Int_t cnused=0;
3456   for (Int_t is=0; is < nclusters; is++) {  //LOOP over clusters
3457     Int_t nfound =0;
3458     Int_t nfoundable =0;
3459     for (Int_t iter =1; iter<2; iter++){   //iterations
3460       const AliTPCRow& krm=fSectors[sec][row0-iter];
3461       const AliTPCRow& krp=fSectors[sec][row0+iter];      
3462       const AliTPCclusterMI * cl= kr0[is];
3463       
3464       if (cl->IsUsed(10)) {
3465         cused++;
3466       }
3467       else{
3468         cnused++;
3469       }
3470       Double_t x = kr0.GetX();
3471       // Initialization of the polytrack
3472       nfound =0;
3473       nfoundable =0;
3474       polytrack.Reset();
3475       //
3476       Double_t y0= cl->GetY();
3477       Double_t z0= cl->GetZ();
3478       Float_t erry = 0;
3479       Float_t errz = 0;
3480       
3481       Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3482       if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue;  // seed only at the edge
3483       
3484       erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;      
3485       errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;      
3486       polytrack.AddPoint(x,y0,z0,erry, errz);
3487
3488       sumused=0;
3489       if (cl->IsUsed(10)) sumused++;
3490
3491
3492       Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3493       Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3494       //
3495       x = krm.GetX();
3496       AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3497       if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3498         erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;          
3499         errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3500         if (cl1->IsUsed(10))  sumused++;
3501         polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3502       }
3503       //
3504       x = krp.GetX();
3505       AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3506       if (cl2) {
3507         erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;          
3508         errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3509         if (cl2->IsUsed(10)) sumused++;  
3510         polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3511       }
3512       //
3513       if (sumused>0) continue;
3514       nin0++;
3515       polytrack.UpdateParameters();
3516       // follow polytrack
3517       roadz = 1.2;
3518       roady = 1.2;
3519       //
3520       Double_t yn,zn;
3521       nfoundable = polytrack.GetN();
3522       nfound     = nfoundable; 
3523       //
3524       for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
3525         Float_t maxdist = 0.8*(1.+3./(ddrow));
3526         for (Int_t delta = -1;delta<=1;delta+=2){
3527           Int_t row = row0+ddrow*delta;
3528           kr = &(fSectors[sec][row]);
3529           Double_t xn = kr->GetX();
3530           Double_t ymax = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
3531           polytrack.GetFitPoint(xn,yn,zn);
3532           if (TMath::Abs(yn)>ymax) continue;
3533           nfoundable++;
3534           AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
3535           if (cln) {
3536             Float_t dist =  TMath::Sqrt(  (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
3537             if (dist<maxdist){
3538               /*
3539               erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));         
3540               errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3541               if (cln->IsUsed(10)) {
3542                 //      printf("used\n");
3543                 sumused++;
3544                 erry*=2;
3545                 errz*=2;
3546               }
3547               */
3548               erry=0.1;
3549               errz=0.1;
3550               polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
3551               nfound++;
3552             }
3553           }
3554         }
3555         if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable))  break;     
3556         polytrack.UpdateParameters();
3557       }           
3558     }
3559     if ( (sumused>3) || (sumused>0.5*nfound))  {
3560       //printf("sumused   %d\n",sumused);
3561       continue;
3562     }
3563     nin1++;
3564     Double_t dy,dz;
3565     polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
3566     AliTPCpolyTrack track2;
3567     
3568     polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
3569     if (track2.GetN()<0.5*nfoundable) continue;
3570     nin2++;
3571
3572     if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
3573       //
3574       // test seed with and without constrain
3575       for (Int_t constrain=0; constrain<=0;constrain++){
3576         // add polytrack candidate
3577
3578         Double_t x[5], c[15];
3579         Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
3580         track2.GetBoundaries(x3,x1);    
3581         x2 = (x1+x3)/2.;
3582         track2.GetFitPoint(x1,y1,z1);
3583         track2.GetFitPoint(x2,y2,z2);
3584         track2.GetFitPoint(x3,y3,z3);
3585         //
3586         //is track pointing to the vertex ?
3587         Double_t x0,y0,z0;
3588         x0=0;
3589         polytrack.GetFitPoint(x0,y0,z0);
3590
3591         if (constrain) {
3592           x2 = x3;
3593           y2 = y3;
3594           z2 = z3;
3595           
3596           x3 = 0;
3597           y3 = 0;
3598           z3 = 0;
3599         }
3600         x[0]=y1;
3601         x[1]=z1;
3602         x[4]=F1(x1,y1,x2,y2,x3,y3);
3603                 
3604         //      if (TMath::Abs(x[4]) >= cuts[0]) continue;  //
3605         x[2]=F2(x1,y1,x2,y2,x3,y3);
3606         
3607         //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
3608         //x[3]=F3(x1,y1,x2,y2,z1,z2);
3609         x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
3610         //if (TMath::Abs(x[3]) > cuts[3]) continue;
3611
3612         
3613         Double_t sy =0.1, sz =0.1;
3614         Double_t sy1=0.02, sz1=0.02;
3615         Double_t sy2=0.02, sz2=0.02;
3616         Double_t sy3=0.02;
3617
3618         if (constrain){
3619           sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3620         }
3621         
3622         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3623         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3624         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3625         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3626         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3627         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3628
3629         Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
3630         Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
3631         Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
3632         Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
3633
3634         
3635         c[0]=sy1;
3636         c[1]=0.;       c[2]=sz1;
3637         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3638         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3639         c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3640         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3641         c[13]=f30*sy1*f40+f32*sy2*f42;
3642         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3643         
3644         //Int_t row1 = fSectors->GetRowNumber(x1);
3645         Int_t row1 = GetRowNumber(x1);
3646
3647         UInt_t index=0;
3648         //kr0.GetIndex(is);
3649         AliTPCseed *track=new (seed) AliTPCseed(x1,sec*alpha+shift,x,c,index);
3650         track->SetIsSeeding(kTRUE);
3651         Int_t rc=FollowProlongation(*track, i2);        
3652         if (constrain) track->SetBConstrain(1);
3653         else
3654           track->SetBConstrain(0);
3655         track->SetLastPoint(row1+fInnerSec->GetNRows());  // first cluster in track position
3656         track->SetFirstPoint(track->GetLastPoint());
3657
3658         if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 || 
3659             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
3660             track->GetNShared()>0.4*track->GetNumberOfClusters()) {
3661           //delete track;
3662           seed->Reset();
3663           seed->~AliTPCseed();
3664         }
3665         else {
3666           arr->AddLast(track);
3667           seed = new AliTPCseed;
3668         }
3669         nin3++;
3670       }
3671     }  // if accepted seed
3672   }
3673   if (fDebug>3){
3674     Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
3675   }
3676   delete seed;
3677 }
3678
3679
3680 AliTPCseed *AliTPCtrackerMI::MakeSeed(AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
3681 {
3682   //
3683   //
3684   //reseed using track points
3685   Int_t p0 = int(r0*track->GetNumberOfClusters());     // point 0 
3686   Int_t p1 = int(r1*track->GetNumberOfClusters());
3687   Int_t p2 = int(r2*track->GetNumberOfClusters());   // last point
3688   Int_t pp2=0;
3689   Double_t  x0[3],x1[3],x2[3];
3690   for (Int_t i=0;i<3;i++){
3691     x0[i]=-1;
3692     x1[i]=-1;
3693     x2[i]=-1;
3694   }
3695
3696   // find track position at given ratio of the length
3697   Int_t  sec0=0, sec1=0, sec2=0;
3698   Int_t index=-1;
3699   Int_t clindex;
3700   for (Int_t i=0;i<160;i++){
3701     if (track->GetClusterPointer(i)){
3702       index++;
3703       AliTPCTrackerPoint   *trpoint =track->GetTrackPoint(i);
3704       if ( (index<p0) || x0[0]<0 ){
3705         if (trpoint->GetX()>1){
3706           clindex = track->GetClusterIndex2(i);
3707           if (clindex>0){       
3708             x0[0] = trpoint->GetX();
3709             x0[1] = trpoint->GetY();
3710             x0[2] = trpoint->GetZ();
3711             sec0  = ((clindex&0xff000000)>>24)%18;
3712           }
3713         }
3714       }
3715
3716       if ( (index<p1) &&(trpoint->GetX()>1)){
3717         clindex = track->GetClusterIndex2(i);
3718         if (clindex>0){
3719           x1[0] = trpoint->GetX();
3720           x1[1] = trpoint->GetY();
3721           x1[2] = trpoint->GetZ();
3722           sec1  = ((clindex&0xff000000)>>24)%18;
3723         }
3724       }
3725       if ( (index<p2) &&(trpoint->GetX()>1)){
3726         clindex = track->GetClusterIndex2(i);
3727         if (clindex>0){
3728           x2[0] = trpoint->GetX();
3729           x2[1] = trpoint->GetY();
3730           x2[2] = trpoint->GetZ(); 
3731           sec2  = ((clindex&0xff000000)>>24)%18;
3732           pp2 = i;
3733         }
3734       }
3735     }
3736   }
3737   
3738   Double_t alpha, cs,sn, xx2,yy2;
3739   //
3740   alpha = (sec1-sec2)*fSectors->GetAlpha();
3741   cs = TMath::Cos(alpha);
3742   sn = TMath::Sin(alpha); 
3743   xx2= x1[0]*cs-x1[1]*sn;
3744   yy2= x1[0]*sn+x1[1]*cs;
3745   x1[0] = xx2;
3746   x1[1] = yy2;
3747   //
3748   alpha = (sec0-sec2)*fSectors->GetAlpha();
3749   cs = TMath::Cos(alpha);
3750   sn = TMath::Sin(alpha); 
3751   xx2= x0[0]*cs-x0[1]*sn;
3752   yy2= x0[0]*sn+x0[1]*cs;
3753   x0[0] = xx2;
3754   x0[1] = yy2;
3755   //
3756   //
3757   //
3758   Double_t x[5],c[15];
3759   //
3760   x[0]=x2[1];
3761   x[1]=x2[2];
3762   x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
3763   //  if (x[4]>1) return 0;
3764   x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
3765   x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
3766   //if (TMath::Abs(x[3]) > 2.2)  return 0;
3767   //if (TMath::Abs(x[2]) > 1.99) return 0;
3768   //  
3769   Double_t sy =0.1,  sz =0.1;
3770   //
3771   Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
3772   Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
3773   Double_t sy3=0.01+track->GetSigmaY2();
3774   //
3775   Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
3776   Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
3777   Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
3778   Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
3779   Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
3780   Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
3781   //
3782   Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
3783   Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
3784   Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
3785   Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
3786   
3787   
3788   c[0]=sy1;
3789   c[1]=0.;       c[2]=sz1;
3790   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3791   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3792   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3793   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3794   c[13]=f30*sy1*f40+f32*sy2*f42;
3795   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3796   
3797   //  Int_t row1 = fSectors->GetRowNumber(x2[0]);
3798   AliTPCseed *seed=new  AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
3799   //  Double_t y0,z0,y1,z1, y2,z2;
3800   //seed->GetProlongation(x0[0],y0,z0);
3801   // seed->GetProlongation(x1[0],y1,z1);
3802   //seed->GetProlongation(x2[0],y2,z2);
3803   //  seed =0;
3804   seed->SetLastPoint(pp2);
3805   seed->SetFirstPoint(pp2);
3806   
3807
3808   return seed;
3809 }
3810
3811
3812 AliTPCseed *AliTPCtrackerMI::ReSeed(AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
3813 {
3814   //
3815   //
3816   //reseed using founded clusters 
3817   //
3818   // Find the number of clusters
3819   Int_t nclusters = 0;
3820   for (Int_t irow=0;irow<160;irow++){
3821     if (track->GetClusterIndex(irow)>0) nclusters++;
3822   }
3823   //
3824   Int_t ipos[3];
3825   ipos[0] = TMath::Max(int(r0*nclusters),0);             // point 0 cluster
3826   ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1);   // 
3827   ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1);   // last point
3828   //
3829   //
3830   Double_t  xyz[3][3];
3831   Int_t     row[3],sec[3]={0,0,0};
3832   //
3833   // find track row position at given ratio of the length
3834   Int_t index=-1;
3835   for (Int_t irow=0;irow<160;irow++){    
3836     if (track->GetClusterIndex2(irow)<0) continue;
3837     index++;
3838     for (Int_t ipoint=0;ipoint<3;ipoint++){
3839       if (index<=ipos[ipoint]) row[ipoint] = irow;
3840     }        
3841   }
3842   //
3843   //Get cluster and sector position
3844   for (Int_t ipoint=0;ipoint<3;ipoint++){
3845     Int_t clindex = track->GetClusterIndex2(row[ipoint]);
3846     AliTPCclusterMI * cl = GetClusterMI(clindex);
3847     if (cl==0) {
3848       //Error("Bug\n");
3849       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
3850       return 0;
3851     }
3852     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
3853     xyz[ipoint][0]  = GetXrow(row[ipoint]);
3854     xyz[ipoint][1]  = cl->GetY();
3855     xyz[ipoint][2]  = cl->GetZ();
3856   }
3857   //
3858   //
3859   // Calculate seed state vector and covariance matrix
3860
3861   Double_t alpha, cs,sn, xx2,yy2;
3862   //
3863   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
3864   cs = TMath::Cos(alpha);
3865   sn = TMath::Sin(alpha); 
3866   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
3867   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
3868   xyz[1][0] = xx2;
3869   xyz[1][1] = yy2;
3870   //
3871   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
3872   cs = TMath::Cos(alpha);
3873   sn = TMath::Sin(alpha); 
3874   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
3875   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
3876   xyz[0][0] = xx2;
3877   xyz[0][1] = yy2;
3878   //
3879   //
3880   //
3881   Double_t x[5],c[15];
3882   //
3883   x[0]=xyz[2][1];
3884   x[1]=xyz[2][2];
3885   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
3886   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
3887   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
3888   //  
3889   Double_t sy =0.1,  sz =0.1;
3890   //
3891   Double_t sy1=0.2, sz1=0.2;
3892   Double_t sy2=0.2, sz2=0.2;
3893   Double_t sy3=0.2;
3894   //
3895   Double_t f40=(F1(xyz[2][0],xyz[2][1]+sy,xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1])-x[4])/sy;
3896   Double_t f42=(F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1]+sy,xyz[0][0],xyz[0][1])-x[4])/sy;
3897   Double_t f43=(F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]+sy)-x[4])/sy;
3898   Double_t f20=(F2(xyz[2][0],xyz[2][1]+sy,xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1])-x[2])/sy;
3899   Double_t f22=(F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1]+sy,xyz[0][0],xyz[0][1])-x[2])/sy;
3900   Double_t f23=(F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]+sy)-x[2])/sy;
3901   //
3902   Double_t f30=(F3(xyz[2][0],xyz[2][1]+sy,xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2])-x[3])/sy;
3903   Double_t f31=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2]+sz,xyz[0][2])-x[3])/sz;
3904   Double_t f32=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1]+sy,xyz[2][2],xyz[0][2])-x[3])/sy;
3905   Double_t f34=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2]+sz)-x[3])/sz;
3906   
3907   
3908   c[0]=sy1;
3909   c[1]=0.;       c[2]=sz1;
3910   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3911   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3912   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3913   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3914   c[13]=f30*sy1*f40+f32*sy2*f42;
3915   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3916   
3917   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
3918   AliTPCseed *seed=new  AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
3919   seed->SetLastPoint(row[2]);
3920   seed->SetFirstPoint(row[2]);  
3921   return seed;
3922 }
3923
3924
3925 AliTPCseed *AliTPCtrackerMI::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
3926 {
3927   //
3928   //
3929   //reseed using founded clusters 
3930   //
3931   Double_t  xyz[3][3];
3932   Int_t     row[3]={0,0,0};
3933   Int_t     sec[3]={0,0,0};
3934   //
3935   // forward direction
3936   if (forward){
3937     for (Int_t irow=r0;irow<160;irow++){
3938       if (track->GetClusterIndex(irow)>0){
3939         row[0] = irow;
3940         break;
3941       }
3942     }
3943     for (Int_t irow=160;irow>r0;irow--){
3944       if (track->GetClusterIndex(irow)>0){
3945         row[2] = irow;
3946         break;
3947       }
3948     }
3949     for (Int_t irow=row[2]-15;irow>row[0];irow--){
3950       if (track->GetClusterIndex(irow)>0){
3951         row[1] = irow;
3952         break;
3953       }
3954     }
3955     //
3956   }
3957   if (!forward){
3958     for (Int_t irow=0;irow<r0;irow++){
3959       if (track->GetClusterIndex(irow)>0){
3960         row[0] = irow;
3961         break;
3962       }
3963     }
3964     for (Int_t irow=r0;irow>0;irow--){
3965       if (track->GetClusterIndex(irow)>0){
3966         row[2] = irow;
3967         break;
3968       }
3969     }    
3970     for (Int_t irow=row[2]-15;irow>row[0];irow--){
3971       if (track->GetClusterIndex(irow)>0){
3972         row[1] = irow;
3973         break;
3974       }
3975     } 
3976   }
3977   //
3978   if ((row[2]-row[0])<20) return 0;
3979   if (row[1]==0) return 0;
3980   //
3981   //
3982   //Get cluster and sector position
3983   for (Int_t ipoint=0;ipoint<3;ipoint++){
3984     Int_t clindex = track->GetClusterIndex2(row[ipoint]);
3985     AliTPCclusterMI * cl = GetClusterMI(clindex);
3986     if (cl==0) {
3987       //Error("Bug\n");
3988       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
3989       return 0;
3990     }
3991     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
3992     xyz[ipoint][0]  = GetXrow(row[ipoint]);
3993     AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);    
3994     if (point&&ipoint<2){
3995       //
3996        xyz[ipoint][1]  = point->GetY();
3997        xyz[ipoint][2]  = point->GetZ();
3998     }
3999     else{
4000       xyz[ipoint][1]  = cl->GetY();
4001       xyz[ipoint][2]  = cl->GetZ();
4002     }
4003   }
4004   //
4005   //
4006   //
4007   //
4008   // Calculate seed state vector and covariance matrix
4009
4010   Double_t alpha, cs,sn, xx2,yy2;
4011   //
4012   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4013   cs = TMath::Cos(alpha);
4014   sn = TMath::Sin(alpha); 
4015   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4016   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4017   xyz[1][0] = xx2;
4018   xyz[1][1] = yy2;
4019   //
4020   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4021   cs = TMath::Cos(alpha);
4022   sn = TMath::Sin(alpha); 
4023   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4024   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4025   xyz[0][0] = xx2;
4026   xyz[0][1] = yy2;
4027   //
4028   //
4029   //
4030   Double_t x[5],c[15];
4031   //
4032   x[0]=xyz[2][1];
4033   x[1]=xyz[2][2];
4034   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4035   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4036   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4037   //  
4038   Double_t sy =0.1,  sz =0.1;
4039   //
4040   Double_t sy1=0.2, sz1=0.2;
4041   Double_t sy2=0.2, sz2=0.2;
4042   Double_t sy3=0.2;
4043   //
4044   Double_t f40=(F1(xyz[2][0],xyz[2][1]+sy,xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1])-x[4])/sy;
4045   Double_t f42=(F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1]+sy,xyz[0][0],xyz[0][1])-x[4])/sy;
4046   Double_t f43=(F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]+sy)-x[4])/sy;
4047   Double_t f20=(F2(xyz[2][0],xyz[2][1]+sy,xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1])-x[2])/sy;
4048   Double_t f22=(F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1]+sy,xyz[0][0],xyz[0][1])-x[2])/sy;
4049   Double_t f23=(F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]+sy)-x[2])/sy;
4050   //
4051   Double_t f30=(F3(xyz[2][0],xyz[2][1]+sy,xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2])-x[3])/sy;
4052   Double_t f31=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2]+sz,xyz[0][2])-x[3])/sz;
4053   Double_t f32=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1]+sy,xyz[2][2],xyz[0][2])-x[3])/sy;
4054   Double_t f34=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2]+sz)-x[3])/sz;
4055   
4056   
4057   c[0]=sy1;
4058   c[1]=0.;       c[2]=sz1;
4059   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4060   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
4061   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4062   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4063   c[13]=f30*sy1*f40+f32*sy2*f42;
4064   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4065   
4066   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4067   AliTPCseed *seed=new  AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4068   seed->SetLastPoint(row[2]);
4069   seed->SetFirstPoint(row[2]);  
4070   for (Int_t i=row[0];i<row[2];i++){
4071     seed->SetClusterIndex(i, track->GetClusterIndex(i));
4072   }
4073
4074   return seed;
4075 }
4076
4077 void  AliTPCtrackerMI::FindKinks(TObjArray * array, AliESD *esd)
4078 {
4079   //
4080   //  find kinks
4081   //
4082   //
4083
4084   TObjArray *kinks= new TObjArray(10000);
4085   //  TObjArray *v0s= new TObjArray(10000);
4086   Int_t nentries = array->GetEntriesFast();
4087   AliHelix *helixes      = new AliHelix[nentries];
4088   Int_t    *sign         = new Int_t[nentries];
4089   Int_t    *nclusters    = new Int_t[nentries];
4090   Float_t  *alpha        = new Float_t[nentries];
4091   AliKink  *kink         = new AliKink();
4092   Int_t      * usage     = new Int_t[nentries];
4093   Float_t  *zm           = new Float_t[nentries];
4094   Float_t  *z0           = new Float_t[nentries]; 
4095   Float_t  *fim          = new Float_t[nentries];
4096   Float_t  *shared       = new Float_t[nentries];
4097   Bool_t   *circular     = new Bool_t[nentries];
4098   Float_t *dca          = new Float_t[nentries];
4099   //const AliESDVertex * primvertex = esd->GetVertex();
4100   //
4101   //  nentries = array->GetEntriesFast();
4102   //
4103   
4104   //
4105   //
4106   for (Int_t i=0;i<nentries;i++){
4107     sign[i]=0;
4108     usage[i]=0;
4109     AliTPCseed* track = (AliTPCseed*)array->At(i);    
4110     if (!track) continue;
4111     track->SetCircular(0);
4112     shared[i] = kFALSE;
4113     track->UpdatePoints();
4114     if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
4115     }
4116     nclusters[i]=track->GetNumberOfClusters();
4117     alpha[i] = track->GetAlpha();
4118     new (&helixes[i]) AliHelix(*track);
4119     Double_t xyz[3];
4120     helixes[i].Evaluate(0,xyz);
4121     sign[i] = (track->GetC()>0) ? -1:1;
4122     Double_t x,y,z;
4123     x=160;
4124     if (track->GetProlongation(x,y,z)){
4125       zm[i]  = z;
4126       fim[i] = alpha[i]+TMath::ATan2(y,x);
4127     }
4128     else{
4129       zm[i]  = track->GetZ();
4130       fim[i] = alpha[i];
4131     }   
4132     z0[i]=1000;
4133     circular[i]= kFALSE;
4134     if (track->GetProlongation(0,y,z))  z0[i] = z;
4135     dca[i] = track->GetD(0,0);    
4136   }
4137   //
4138   //
4139   TStopwatch timer;
4140   timer.Start();
4141   Int_t ncandidates =0;
4142   Int_t nall =0;
4143   Int_t ntracks=0; 
4144   Double_t phase[2][2],radius[2];
4145
4146   //
4147   // Find circling track
4148   TTreeSRedirector &cstream = *fDebugStreamer;
4149   //
4150   for (Int_t i0=0;i0<nentries;i0++){
4151     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4152     if (!track0) continue;    
4153     if (track0->GetNumberOfClusters()<40) continue;
4154     if (TMath::Abs(1./track0->GetC())>200) continue;
4155     for (Int_t i1=i0+1;i1<nentries;i1++){
4156       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4157       if (!track1) continue;
4158       if (track1->GetNumberOfClusters()<40)                  continue;
4159       if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
4160       if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
4161       if (TMath::Abs(1./track1->GetC())>200) continue;
4162       if (track1->Get1Pt()*track0->Get1Pt()>0)      continue;
4163       if (track1->GetTgl()*track0->GetTgl()>0)      continue;
4164       if (max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
4165       if (track0->GetBConstrain()&&TMath::Abs(track1->Get1Pt())<TMath::Abs(track0->Get1Pt())) continue; //returning - lower momenta
4166       if (track1->GetBConstrain()&&TMath::Abs(track0->Get1Pt())<TMath::Abs(track1->Get1Pt())) continue; //returning - lower momenta
4167       //
4168       Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
4169       if (mindcar<5)   continue;
4170       Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
4171       if (mindcaz<5) continue;
4172       if (mindcar+mindcaz<20) continue;
4173       //
4174       //
4175       Float_t xc0 = helixes[i0].GetHelix(6);
4176       Float_t yc0 = helixes[i0].GetHelix(7);
4177       Float_t r0  = helixes[i0].GetHelix(8);
4178       Float_t xc1 = helixes[i1].GetHelix(6);
4179       Float_t yc1 = helixes[i1].GetHelix(7);
4180       Float_t r1  = helixes[i1].GetHelix(8);
4181         
4182       Float_t rmean = (r0+r1)*0.5;
4183       Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
4184       //if (delta>30) continue;
4185       if (delta>rmean*0.25) continue;
4186       if (TMath::Abs(r0-r1)/rmean>0.3) continue; 
4187       //
4188       Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4189       if (npoints==0) continue;
4190       helixes[i0].GetClosestPhases(helixes[i1], phase);
4191       //
4192       Double_t xyz0[3];
4193       Double_t xyz1[3];
4194       Double_t hangles[3];
4195       helixes[i0].Evaluate(phase[0][0],xyz0);
4196       helixes[i1].Evaluate(phase[0][1],xyz1);
4197
4198       helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4199       Double_t deltah[2],deltabest;
4200       if (hangles[2]<2.8) continue;
4201       /*
4202       cstream<<"C"<<track0->fLab<<track1->fLab<<
4203         track0->fP3<<track1->fP3<<
4204         track0->fP4<<track1->fP4<<
4205         delta<<rmean<<npoints<<
4206         hangles[0]<<hangles[2]<<
4207         xyz0[2]<<xyz1[2]<<radius[0]<<"\n"; 
4208       */
4209       if (npoints>0){
4210         Int_t ibest=0;
4211         helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
4212         if (npoints==2){
4213           helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
4214           if (deltah[1]<deltah[0]) ibest=1;
4215         }
4216         deltabest  = TMath::Sqrt(deltah[ibest]);
4217         helixes[i0].Evaluate(phase[ibest][0],xyz0);
4218         helixes[i1].Evaluate(phase[ibest][1],xyz1);
4219         helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
4220         Double_t radiusbest = TMath::Sqrt(radius[ibest]);
4221         //
4222         if (deltabest>6) continue;
4223         if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
4224         Bool_t sign =kFALSE;
4225         if (hangles[2]>3.06) sign =kTRUE;
4226         //
4227         if (sign){
4228           circular[i0] = kTRUE;
4229           circular[i1] = kTRUE;
4230           if (TMath::Abs(track0->Get1Pt())<TMath::Abs(track1->Get1Pt())){
4231             track0->SetCircular(track0->GetCircular()+1);
4232             track1->SetCircular(track1->GetCircular()+2);
4233           }
4234           else{
4235             track1->SetCircular(track1->GetCircular()+1);
4236             track0->SetCircular(track0->GetCircular()+2);
4237           }
4238         }               
4239         if (sign&&AliTPCReconstructor::StreamLevel()>1){          
4240           //debug stream          
4241           Int_t lab0=track0->GetLabel();
4242           Int_t lab1=track1->GetLabel();
4243           cstream<<"Curling"<<
4244             "lab0="<<lab0<<
4245             "lab1="<<lab1<<   
4246             "Tr0.="<<track0<<
4247             "Tr1.="<<track1<<      
4248             "dca0="<<dca[i0]<<
4249             "dca1="<<dca[i1]<<
4250             "mindcar="<<mindcar<<
4251             "mindcaz="<<mindcaz<<
4252             "delta="<<delta<<
4253             "rmean="<<rmean<<
4254             "npoints="<<npoints<<                      
4255             "hangles0="<<hangles[0]<<
4256             "hangles2="<<hangles[2]<<                    
4257             "xyz0="<<xyz0[2]<<
4258             "xyzz1="<<xyz1[2]<<
4259             "z0="<<z0[i0]<<
4260             "z1="<<z0[i1]<<
4261             "radius="<<radiusbest<<
4262             "deltabest="<<deltabest<< 
4263             "phase0="<<phase[ibest][0]<<
4264             "phase1="<<phase[ibest][1]<<
4265             "\n";                 
4266         }
4267       }
4268     }
4269   }
4270   //
4271   //  Finf kinks loop
4272   // 
4273   //
4274   for (Int_t i =0;i<nentries;i++){
4275     if (sign[i]==0) continue;
4276     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4277     ntracks++;
4278     //
4279     Double_t cradius0 = 40*40;
4280     Double_t cradius1 = 270*270;
4281     Double_t cdist1=8.;
4282     Double_t cdist2=8.;
4283     Double_t cdist3=0.55; 
4284     for (Int_t j =i+1;j<nentries;j++){
4285       nall++;
4286       if (sign[j]*sign[i]<1) continue;
4287       if ( (nclusters[i]+nclusters[j])>200) continue;
4288       if ( (nclusters[i]+nclusters[j])<80) continue;
4289       if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
4290       if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
4291       //AliTPCseed * track1 = (AliTPCseed*)array->At(j);  Double_t phase[2][2],radius[2];    
4292       Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
4293       if (npoints<1) continue;
4294       // cuts on radius      
4295       if (npoints==1){
4296         if (radius[0]<cradius0||radius[0]>cradius1) continue;
4297       }
4298       else{
4299         if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
4300       }
4301       //      
4302       Double_t delta1=10000,delta2=10000;
4303       // cuts on the intersection radius
4304       helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
4305       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
4306       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
4307       if (npoints==2){ 
4308         helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
4309         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
4310         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
4311       }
4312       //
4313       Double_t distance1 = TMath::Min(delta1,delta2);
4314       if (distance1>cdist1) continue;  // cut on DCA linear approximation
4315       //
4316       npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
4317       helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
4318       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
4319       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
4320       //
4321       if (npoints==2){ 
4322         helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);   
4323         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
4324         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
4325       }            
4326       distance1 = TMath::Min(delta1,delta2);
4327       Float_t rkink =0;
4328       if (delta1<delta2){
4329         rkink = TMath::Sqrt(radius[0]);
4330       }
4331       else{
4332         rkink = TMath::Sqrt(radius[1]);
4333       }
4334       if (distance1>cdist2) continue;
4335       //
4336       //
4337       AliTPCseed * track1 = (AliTPCseed*)array->At(j);
4338       //
4339       //
4340       Int_t row0 = GetRowNumber(rkink); 
4341       if (row0<10)  continue;
4342       if (row0>150) continue;
4343       //
4344       //
4345       Float_t dens00=-1,dens01=-1;
4346       Float_t dens10=-1,dens11=-1;
4347       //
4348       Int_t found,foundable,shared;
4349       track0->GetClusterStatistic(0,row0-5, found, foundable,shared,kFALSE);
4350       if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
4351       track0->GetClusterStatistic(row0+5,155, found, foundable,shared,kFALSE);
4352       if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
4353       //
4354       track1->GetClusterStatistic(0,row0-5, found, foundable,shared,kFALSE);
4355       if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
4356       track1->GetClusterStatistic(row0+5,155, found, foundable,shared,kFALSE);
4357       if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
4358       //     
4359       if (dens00<dens10 && dens01<dens11) continue;
4360       if (dens00>dens10 && dens01>dens11) continue;
4361       if (TMath::Max(dens00,dens10)<0.1)  continue;
4362       if (TMath::Max(dens01,dens11)<0.3)  continue;
4363       //
4364       if (TMath::Min(dens00,dens10)>0.6)  continue;
4365       if (TMath::Min(dens01,dens11)>0.6)  continue;
4366
4367       //
4368       AliTPCseed * ktrack0, *ktrack1;
4369       if (dens00>dens10){
4370         ktrack0 = track0;
4371         ktrack1 = track1;
4372       }
4373       else{
4374         ktrack0 = track1;
4375         ktrack1 = track0;
4376       }
4377       if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
4378       AliExternalTrackParam paramm(*ktrack0);
4379       AliExternalTrackParam paramd(*ktrack1);
4380       if (row0>60&&ktrack1->GetReference().GetX()>90.) new (&paramd) AliExternalTrackParam(ktrack1->GetReference()); 
4381       //
4382       //
4383       kink->SetMother(paramm);
4384       kink->SetDaughter(paramd);
4385       kink->Update();
4386
4387       Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
4388       Int_t index[4];
4389       fParam->Transform0to1(x,index);
4390       fParam->Transform1to2(x,index);
4391       row0 = GetRowNumber(x[0]); 
4392
4393       if (kink->GetR()<100) continue;
4394       if (kink->GetR()>240) continue;
4395       if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue;  //out of fiducial volume
4396       if (kink->GetDistance()>cdist3) continue;
4397       Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1];  // rough direction estimate
4398       if (dird<0) continue;
4399
4400       Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1];  // rough direction estimate
4401       if (dirm<0) continue;
4402       Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
4403       if (mpt<0.2) continue;
4404
4405       if (mpt<1){
4406         //for high momenta momentum not defined well in first iteration
4407         Double_t qt   =  TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
4408         if (qt>0.35) continue; 
4409       }
4410       
4411       kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
4412       kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
4413       if (dens00>dens10){
4414         kink->SetTPCDensity(dens00,0,0);
4415         kink->SetTPCDensity(dens01,0,1);
4416         kink->SetTPCDensity(dens10,1,0);
4417         kink->SetTPCDensity(dens11,1,1);
4418         kink->SetIndex(i,0);
4419         kink->SetIndex(j,1);
4420       }
4421       else{
4422         kink->SetTPCDensity(dens10,0,0);
4423         kink->SetTPCDensity(dens11,0,1);
4424         kink->SetTPCDensity(dens00,1,0);
4425         kink->SetTPCDensity(dens01,1,1);
4426         kink->SetIndex(j,0);
4427         kink->SetIndex(i,1);
4428       }
4429
4430       if (mpt<1||kink->GetAngle(2)>0.1){
4431         //      angle and densities  not defined yet
4432         if (kink->GetTPCDensityFactor()<0.8) continue;
4433         if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
4434         if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
4435         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
4436         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
4437
4438         Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
4439         criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
4440         criticalangle= 3*TMath::Sqrt(criticalangle);
4441         if (criticalangle>0.02) criticalangle=0.02;
4442         if (kink->GetAngle(2)<criticalangle) continue;
4443       }
4444       //
4445       Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2)));  // overlap region defined
4446       Float_t shapesum =0;
4447       Float_t sum = 0;
4448       for ( Int_t row = row0-drow; row<row0+drow;row++){
4449         if (row<0) continue;
4450         if (row>155) continue;
4451         if (ktrack0->GetClusterPointer(row)){
4452           AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
4453           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
4454           sum++;
4455         }
4456         if (ktrack1->GetClusterPointer(row)){
4457           AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
4458           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
4459           sum++;
4460         }       
4461       }
4462       if (sum<4){
4463         kink->SetShapeFactor(-1.);
4464       }
4465       else{
4466         kink->SetShapeFactor(shapesum/sum);
4467       }      
4468       //      esd->AddKink(kink);
4469       kinks->AddLast(kink);
4470       kink = new AliKink;
4471       ncandidates++;
4472     }
4473   }
4474   //
4475   // sort the kinks according quality - and refit them towards vertex
4476   //
4477   Int_t       nkinks    = kinks->GetEntriesFast();
4478   Float_t    *quality   = new Float_t[nkinks];
4479   Int_t      *indexes   = new Int_t[nkinks];
4480   AliTPCseed *mothers   = new AliTPCseed[nkinks];
4481   AliTPCseed *daughters = new AliTPCseed[nkinks];
4482   //
4483   //
4484   for (Int_t i=0;i<nkinks;i++){
4485     quality[i] =100000;
4486     AliKink *kink = (AliKink*)kinks->At(i);
4487     //
4488     // refit kinks towards vertex
4489     // 
4490     Int_t index0 = kink->GetIndex(0);
4491     Int_t index1 = kink->GetIndex(1);
4492     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
4493     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
4494     //
4495     Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
4496     //
4497     // Refit Kink under if too small angle
4498     //
4499     if (kink->GetAngle(2)<0.05){
4500       kink->SetTPCRow0(GetRowNumber(kink->GetR()));
4501       Int_t row0 = kink->GetTPCRow0();
4502       Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2)));
4503       //
4504       //
4505       Int_t last  = row0-drow;
4506       if (last<40) last=40;
4507       if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
4508       AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
4509       //
4510       //
4511       Int_t first = row0+drow;
4512       if (first>130) first=130;
4513       if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
4514       AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
4515       //
4516       if (seed0 && seed1){
4517         kink->SetStatus(1,8);
4518         if (RefitKink(*seed0,*seed1,*kink)) kink->SetStatus(1,9);
4519         row0 = GetRowNumber(kink->GetR());
4520         sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
4521         new (&mothers[i])   AliTPCseed(*seed0);
4522         new (&daughters[i]) AliTPCseed(*seed1); 
4523       }
4524       else{
4525         delete kinks->RemoveAt(i);
4526         if (seed0) delete seed0;
4527         if (seed1) delete seed1;
4528         continue;
4529       }
4530       if (kink->GetDistance()>0.5 || kink->GetR()<110 || kink->GetR()>240) {
4531         delete kinks->RemoveAt(i);
4532         if (seed0) delete seed0;
4533         if (seed1) delete seed1;
4534         continue;
4535       }
4536       //
4537       delete seed0;
4538       delete seed1;            
4539     }
4540     //
4541     if (kink) quality[i] = 160*((0.1+kink->GetDistance())*(2.-kink->GetTPCDensityFactor()))/(sumn+40.);  //the longest -clossest will win
4542   }
4543   TMath::Sort(nkinks,quality,indexes,kFALSE);
4544   //
4545   //remove double find kinks
4546   //
4547   for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
4548     AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
4549     if (!kink0) continue;
4550     //
4551     for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
4552       if (!kink0) continue;
4553       AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
4554       if (!kink1) continue;
4555       // if not close kink continue
4556       if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
4557       if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
4558       if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
4559       //
4560       AliTPCseed &mother0   = mothers[indexes[ikink0]];
4561       AliTPCseed &daughter0 = daughters[indexes[ikink0]];
4562       AliTPCseed &mother1   = mothers[indexes[ikink1]];
4563       AliTPCseed &daughter1 = daughters[indexes[ikink1]];
4564       Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
4565       //
4566       Int_t same  = 0;
4567       Int_t both  = 0;
4568       Int_t samem = 0;
4569       Int_t bothm = 0;
4570       Int_t samed = 0;
4571       Int_t bothd = 0;
4572       //
4573       for (Int_t i=0;i<row0;i++){
4574         if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
4575           both++;
4576           bothm++;
4577           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
4578             same++;
4579             samem++;
4580           }
4581         }
4582       }
4583
4584       for (Int_t i=row0;i<158;i++){
4585         if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){
4586           both++;
4587           bothd++;
4588           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
4589             same++;
4590             samed++;
4591           }
4592         }
4593       }
4594       Float_t ratio = Float_t(same+1)/Float_t(both+1);
4595       Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
4596       Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
4597       if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
4598         Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
4599         Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
4600         if (sum1>sum0){
4601           shared[kink0->GetIndex(0)]= kTRUE;
4602           shared[kink0->GetIndex(1)]= kTRUE;      
4603           delete kinks->RemoveAt(indexes[ikink0]);
4604         }
4605         else{
4606           shared[kink1->GetIndex(0)]= kTRUE;
4607           shared[kink1->GetIndex(1)]= kTRUE;      
4608           delete kinks->RemoveAt(indexes[ikink1]);
4609         }
4610       }
4611     }
4612   }
4613
4614
4615   for (Int_t i=0;i<nkinks;i++){
4616     AliKink * kink = (AliKink*) kinks->At(indexes[i]);
4617     if (!kink) continue;
4618     kink->SetTPCRow0(GetRowNumber(kink->GetR()));
4619     Int_t index0 = kink->GetIndex(0);
4620     Int_t index1 = kink->GetIndex(1);
4621     if (circular[index0]||circular[index1]&&kink->GetDistance()>0.2) continue;
4622     kink->SetMultiple(usage[index0],0);
4623     kink->SetMultiple(usage[index1],1);
4624     if (kink->GetMultiple()[0]+kink->GetMultiple()[1]>2) continue;
4625     if (kink->GetMultiple()[0]+kink->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
4626     if (kink->GetMultiple()[0]+kink->GetMultiple()[1]>0 && kink->GetDistance()>0.2) continue;
4627     if (circular[index0]||circular[index1]&&kink->GetDistance()>0.1) continue;
4628
4629     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
4630     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
4631     if (!ktrack0 || !ktrack1) continue;
4632     Int_t index = esd->AddKink(kink);
4633     //
4634     //
4635     if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) {  //best kink
4636       if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
4637         new (ktrack0) AliTPCseed(mothers[indexes[i]]);
4638         new (ktrack1) AliTPCseed(daughters[indexes[i]]);
4639       }
4640     }
4641     //
4642     ktrack0->SetKinkIndex(usage[index0],-(index+1));
4643     ktrack1->SetKinkIndex(usage[index1], (index+1));
4644     usage[index0]++;
4645     usage[index1]++;
4646   }
4647   //
4648   // Remove tracks corresponding to shared kink's
4649   //
4650   for (Int_t i=0;i<nentries;i++){
4651     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4652     if (!track0) continue;
4653     if (track0->GetKinkIndex(0)!=0) continue;
4654     if (shared[i]) delete array->RemoveAt(i);
4655   }
4656
4657   //
4658   //
4659   RemoveUsed2(array,0.5,0.4,30);
4660   UnsignClusters();
4661   for (Int_t i=0;i<nentries;i++){
4662     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4663     if (!track0) continue;
4664     track0->CookdEdx(0.02,0.6);
4665     track0->CookPID();
4666   }
4667   //
4668   for (Int_t i=0;i<nentries;i++){
4669     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4670     if (!track0) continue;
4671     if (track0->GetPt()<1.4) continue;
4672     //remove double high momenta tracks - overlapped with kink candidates
4673     Int_t shared=0;
4674     Int_t all   =0;
4675     for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
4676       if (track0->GetClusterPointer(icl)!=0){
4677         all++;
4678         if (track0->GetClusterPointer(icl)->IsUsed(10)) shared++;
4679       }
4680     }
4681     if (Float_t(shared+1)/Float_t(nall+1)>0.5) {
4682       delete array->RemoveAt(i);
4683       continue;
4684     }
4685     //
4686     if (track0->GetKinkIndex(0)!=0) continue;
4687     if (track0->GetNumberOfClusters()<80) continue;
4688
4689     AliTPCseed *pmother = new AliTPCseed();
4690     AliTPCseed *pdaughter = new AliTPCseed();
4691     AliKink *pkink = new AliKink;
4692
4693     AliTPCseed & mother = *pmother;
4694     AliTPCseed & daughter = *pdaughter;
4695     AliKink & kink = *pkink;
4696     if (CheckKinkPoint(track0,mother,daughter, kink)){
4697       if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
4698         delete pmother;
4699         delete pdaughter;
4700         delete pkink;
4701         continue;  //too short tracks
4702       }
4703       if (mother.GetPt()<1.4) {
4704         delete pmother;
4705         delete pdaughter;
4706         delete pkink;
4707         continue;
4708       }
4709       Int_t row0= kink.GetTPCRow0();
4710       if (kink.GetDistance()>0.5 || kink.GetR()<110. || kink.GetR()>240.) {
4711         delete pmother;
4712         delete pdaughter;
4713         delete pkink;
4714         continue;
4715       }
4716       //
4717       Int_t index = esd->AddKink(&kink);      
4718       mother.SetKinkIndex(0,-(index+1));
4719       daughter.SetKinkIndex(0,index+1);
4720       if (mother.GetNumberOfClusters()>50) {
4721         delete array->RemoveAt(i);
4722         array->AddAt(new AliTPCseed(mother),i);
4723       }
4724       else{
4725         array->AddLast(new AliTPCseed(mother));
4726       }
4727       array->AddLast(new AliTPCseed(daughter));      
4728       for (Int_t icl=0;icl<row0;icl++) {
4729         if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
4730       }
4731       //
4732       for (Int_t icl=row0;icl<158;icl++) {
4733         if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
4734       }
4735       //
4736     }
4737     delete pmother;
4738     delete pdaughter;
4739     delete pkink;
4740   }
4741
4742   delete [] daughters;
4743   delete [] mothers;
4744   //
4745   //
4746   delete [] dca;
4747   delete []circular;
4748   delete []shared;
4749   delete []quality;
4750   delete []indexes;
4751   //
4752   delete kink;
4753   delete[]fim;
4754   delete[] zm;
4755   delete[] z0;
4756   delete [] usage;
4757   delete[] alpha;
4758   delete[] nclusters;
4759   delete[] sign;
4760   delete[] helixes;
4761   kinks->Delete();
4762   delete kinks;
4763
4764   printf("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall);
4765   timer.Print();
4766 }
4767
4768 void  AliTPCtrackerMI::FindV0s(TObjArray * array, AliESD *esd)
4769 {
4770   //
4771   //  find V0s
4772   //
4773   //
4774   TObjArray *tpcv0s      = new TObjArray(100000);
4775   Int_t     nentries     = array->GetEntriesFast();
4776   AliHelix *helixes      = new AliHelix[nentries];
4777   Int_t    *sign         = new Int_t[nentries];
4778   Float_t  *alpha        = new Float_t[nentries];
4779   Float_t  *z0           = new Float_t[nentries]; 
4780   Float_t  *dca          = new Float_t[nentries];
4781   Float_t  *sdcar        = new Float_t[nentries];
4782   Float_t  *cdcar        = new Float_t[nentries];
4783   Float_t  *pulldcar     = new Float_t[nentries];
4784   Float_t  *pulldcaz     = new Float_t[nentries];
4785   Float_t  *pulldca      = new Float_t[nentries];
4786   Bool_t   *isPrim       = new Bool_t[nentries];  
4787   const AliESDVertex * primvertex = esd->GetVertex();
4788   Double_t             zvertex = primvertex->GetZv(); 
4789   //
4790   //  nentries = array->GetEntriesFast();
4791   //
4792   for (Int_t i=0;i<nentries;i++){
4793     sign[i]=0;
4794     isPrim[i]=0;
4795     AliTPCseed* track = (AliTPCseed*)array->At(i);    
4796     if (!track) continue;
4797     track->GetV0Indexes()[0] = 0;  //rest v0 indexes
4798     track->GetV0Indexes()[1] = 0;  //rest v0 indexes
4799     track->GetV0Indexes()[2] = 0;  //rest v0 indexes
4800     //
4801     alpha[i] = track->GetAlpha();
4802     new (&helixes[i]) AliHelix(*track);
4803     Double_t xyz[3];
4804     helixes[i].Evaluate(0,xyz);
4805     sign[i] = (track->GetC()>0) ? -1:1;
4806     Double_t x,y,z;
4807     x=160;
4808     z0[i]=1000;
4809     if (track->GetProlongation(0,y,z))  z0[i] = z;
4810     dca[i] = track->GetD(0,0);
4811     // 
4812     // dca error parrameterezation + pulls
4813     //
4814     sdcar[i]      = TMath::Sqrt(0.150*0.150+(100*track->GetC())*(100*track->GetC()));
4815     if (TMath::Abs(track->GetTgl())>1) sdcar[i]*=2.5;
4816     cdcar[i]      = TMath::Exp((TMath::Abs(track->GetC())-0.0106)*525.3);
4817     pulldcar[i]   = (dca[i]-cdcar[i])/sdcar[i];
4818     pulldcaz[i]   = (z0[i]-zvertex)/sdcar[i];
4819     pulldca[i]    = TMath::Sqrt(pulldcar[i]*pulldcar[i]+pulldcaz[i]*pulldcaz[i]);
4820     if (track->TPCrPID(1)+track->TPCrPID(2)+track->TPCrPID(3)>0.5) {
4821       if (pulldca[i]<3.) isPrim[i]=kTRUE;  //pion, muon and Kaon  3 sigma cut
4822     }
4823     if (track->TPCrPID(4)>0.5) {
4824       if (pulldca[i]<0.5) isPrim[i]=kTRUE;  //proton 0.5 sigma cut
4825     }
4826     if (track->TPCrPID(0)>0.4) {
4827       isPrim[i]=kFALSE;  //electron no  sigma cut
4828     }
4829   }
4830   //
4831   //
4832   TStopwatch timer;
4833   timer.Start();
4834   Int_t ncandidates =0;
4835   Int_t nall =0;
4836   Int_t ntracks=0; 
4837   Double_t phase[2][2],radius[2];
4838   //
4839   //  Finf V0s loop
4840   // 
4841   //
4842   // //  
4843   TTreeSRedirector &cstream = *fDebugStreamer; 
4844   Float_t fprimvertex[3]={GetX(),GetY(),GetZ()};
4845   AliV0 vertex; 
4846   Double_t cradius0 = 10*10;
4847   Double_t cradius1 = 200*200;
4848   Double_t cdist1=3.;
4849   Double_t cdist2=4.;
4850   Double_t cpointAngle = 0.95;
4851   //
4852   Double_t delta[2]={10000,10000};
4853   for (Int_t i =0;i<nentries;i++){
4854     if (sign[i]==0) continue;
4855     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4856     if (!track0) continue;
4857     if (AliTPCReconstructor::StreamLevel()>0){
4858       cstream<<"Tracks"<<
4859         "Tr0.="<<track0<<
4860         "dca="<<dca[i]<<
4861         "z0="<<z0[i]<<
4862         "zvertex="<<zvertex<<
4863         "sdcar0="<<sdcar[i]<<
4864         "cdcar0="<<cdcar[i]<<
4865         "pulldcar0="<<pulldcar[i]<<
4866         "pulldcaz0="<<pulldcaz[i]<<
4867         "pulldca0="<<pulldca[i]<<
4868         "isPrim="<<isPrim[i]<<
4869         "\n";
4870     }
4871     //
4872     if (track0->Get1Pt()<0) continue;
4873     if (track0->GetKinkIndex(0)>0||isPrim[i]) continue;   //daughter kink
4874     //
4875     if (TMath::Abs(helixes[i].GetHelix(4))<0.000000001) continue;
4876     ntracks++;
4877     // debug output
4878     
4879     
4880     for (Int_t j =0;j<nentries;j++){
4881       AliTPCseed * track1 = (AliTPCseed*)array->At(j);
4882       if (!track1) continue;
4883       if (track1->GetKinkIndex(0)>0 || isPrim[j]) continue; //daughter kink
4884       if (sign[j]*sign[i]>0) continue; 
4885       if (TMath::Abs(helixes[j].GetHelix(4))<0.000001) continue;
4886       if (track0->GetCircular()+track1->GetCircular()>1) continue;    //circling -returning track
4887       nall++;
4888       //
4889       // DCA to prim vertex cut
4890       //
4891       //
4892       delta[0]=10000;
4893       delta[1]=10000;
4894
4895       Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,cdist2);
4896       if (npoints<1) continue;
4897       Int_t iclosest=0;
4898       // cuts on radius      
4899       if (npoints==1){
4900         if (radius[0]<cradius0||radius[0]>cradius1) continue;
4901         helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta[0]);
4902         if (delta[0]>cdist1) continue;
4903       }
4904       else{
4905         if (TMath::Max(radius[0],radius[1])<cradius0|| TMath::Min(radius[0],radius[1])>cradius1) continue;      
4906         helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta[0]);    
4907         helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta[1]);
4908         if (delta[1]<delta[0]) iclosest=1;
4909         if (delta[iclosest]>cdist1) continue;
4910       }
4911       helixes[i].ParabolicDCA(helixes[j],phase[iclosest][0],phase[iclosest][1],radius[iclosest],delta[iclosest]);
4912       if (radius[iclosest]<cradius0 || radius[iclosest]>cradius1 || delta[iclosest]>cdist1) continue;
4913       //
4914       Double_t pointAngle = helixes[i].GetPointAngle(helixes[j],phase[iclosest],fprimvertex);
4915       if (pointAngle<cpointAngle) continue;
4916       //
4917       Bool_t isGamma = kFALSE;
4918       vertex.SetParamP(*track0); //track0 - plus
4919       vertex.SetParamN(*track1); //track1 - minus
4920       vertex.Update(fprimvertex);
4921       if (track0->TPCrPID(0)>0.3&&track1->TPCrPID(0)>0.3&&vertex.GetAnglep()[2]<0.15) isGamma=kTRUE;              // gamma conversion candidate
4922       Double_t pointAngle2 = vertex.GetV0CosineOfPointingAngle();
4923       //continue;
4924       if (vertex.GetV0CosineOfPointingAngle()<cpointAngle && (!isGamma)) continue;// point angle cut
4925       //Bo:      if (vertex.GetDist2()>2&&(!isGamma)) continue;      // point angle cut
4926       if (vertex.GetDcaV0Daughters()>2&&(!isGamma)) continue;//Bo:   // point angle cut
4927       Float_t sigmae     = 0.15*0.15;
4928       if (vertex.GetRr()<80) 
4929         sigmae += (sdcar[i]*sdcar[i]+sdcar[j]*sdcar[j])*(1.-vertex.GetRr()/80.)*(1.-vertex.GetRr()/80.);
4930       sigmae+= TMath::Sqrt(sigmae);
4931       //Bo:      if (vertex.GetDist2()/sigmae>3.&&(!isGamma)) continue; 
4932       if (vertex.GetDcaV0Daughters()/sigmae>3.&&(!isGamma)) continue; 
4933       Float_t densb0=0,densb1=0,densa0=0,densa1=0;
4934       Int_t row0 = GetRowNumber(vertex.GetRr());
4935       if (row0>15){
4936         //Bo:   if (vertex.GetDist2()>0.2) continue;             
4937         if (vertex.GetDcaV0Daughters()>0.2) continue;             
4938         densb0     = track0->Density2(0,row0-5);          
4939         densb1     = track1->Density2(0,row0-5);         
4940         if (densb0>0.3|| densb1>0.3) continue;            //clusters before vertex
4941         densa0     = track0->Density2(row0+5,row0+40);    
4942         densa1     = track1->Density2(row0+5,row0+40);    
4943         if ((densa0<0.4|| densa1<0.4)&&(!isGamma)) continue;            //missing clusters after vertex
4944       }
4945       else{
4946         densa0     = track0->Density2(0,40);  //cluster density
4947         densa1     = track1->Density2(0,40);  //cluster density
4948         if ((vertex.GetRr()<80&&densa0+densa1<1.)&&(!isGamma)) continue;
4949       }
4950 //Bo:        vertex.SetLab(0,track0->GetLabel());
4951 //Bo:        vertex.SetLab(1,track1->GetLabel());
4952       vertex.SetChi2After((densa0+densa1)*0.5);
4953       vertex.SetChi2Before((densb0+densb1)*0.5);
4954       vertex.SetIndex(0,i);
4955       vertex.SetIndex(1,j);
4956 //Bo:      vertex.SetStatus(1); // TPC v0 candidate
4957       vertex.SetOnFlyStatus(2);//Bo: // TPC v0 candidate
4958 //Bo:        vertex.SetRp(track0->TPCrPIDs());
4959 //Bo:        vertex.SetRm(track1->TPCrPIDs());
4960       tpcv0s->AddLast(new AliESDv0(vertex));      
4961       ncandidates++;
4962       {
4963         Int_t eventNr = esd->GetEventNumber();
4964         Double_t radiusm= (delta[0]<delta[1])? TMath::Sqrt(radius[0]):TMath::Sqrt(radius[1]);  
4965         Double_t deltam= (delta[0]<delta[1])? TMath::Sqrt(delta[0]):TMath::Sqrt(delta[1]);  
4966         if (AliTPCReconstructor::StreamLevel()>0) {
4967           Int_t lab0=track0->GetLabel();
4968           Int_t lab1=track1->GetLabel();
4969           Char_t c0=track0->GetCircular();
4970           Char_t c1=track1->GetCircular();
4971           cstream<<"V0"<<
4972           "Event="<<eventNr<<
4973           "vertex.="<<&vertex<<
4974           "Tr0.="<<track0<<
4975           "lab0="<<lab0<<
4976           "Helix0.="<<&helixes[i]<<     
4977           "Tr1.="<<track1<<
4978           "lab1="<<lab1<<
4979           "Helix1.="<<&helixes[j]<<
4980           "pointAngle="<<pointAngle<<
4981           "pointAngle2="<<pointAngle2<<
4982           "dca0="<<dca[i]<<
4983           "dca1="<<dca[j]<<
4984           "z0="<<z0[i]<<
4985           "z1="<<z0[j]<<
4986           "zvertex="<<zvertex<<
4987           "circular0="<<c0<<
4988           "circular1="<<c1<<
4989           "npoints="<<npoints<<
4990           "radius0="<<radius[0]<<
4991           "delta0="<<delta[0]<<
4992           "radius1="<<radius[1]<<
4993           "delta1="<<delta[1]<<
4994           "radiusm="<<radiusm<<
4995           "deltam="<<deltam<<
4996           "sdcar0="<<sdcar[i]<<
4997           "sdcar1="<<sdcar[j]<<
4998           "cdcar0="<<cdcar[i]<<
4999           "cdcar1="<<cdcar[j]<<
5000           "pulldcar0="<<pulldcar[i]<<
5001           "pulldcar1="<<pulldcar[j]<<
5002           "pulldcaz0="<<pulldcaz[i]<<
5003           "pulldcaz1="<<pulldcaz[j]<<
5004           "pulldca0="<<pulldca[i]<<
5005           "pulldca1="<<pulldca[j]<<
5006           "densb0="<<densb0<<
5007           "densb1="<<densb1<<
5008           "densa0="<<densa0<<
5009           "densa1="<<densa1<<
5010           "sigmae="<<sigmae<<
5011             "\n";}
5012       }
5013     }
5014   }    
5015   Float_t *quality = new Float_t[ncandidates];
5016   Int_t *indexes = new Int_t[ncandidates];
5017   Int_t naccepted =0;
5018   for (Int_t i=0;i<ncandidates;i++){
5019     quality[i]     = 0; 
5020     AliESDv0 *v0 = (AliESDv0*)tpcv0s->At(i);
5021     quality[i]     = 1./(1.00001-v0->GetV0CosineOfPointingAngle());   //base point angle
5022     // quality[i]    /= (0.5+v0->GetDist2());  
5023     // quality[i]    *= v0->GetChi2After();               //density factor
5024
5025     Int_t index0 = v0->GetIndex(0);
5026     Int_t index1 = v0->GetIndex(1);
5027     //Bo:    Double_t minpulldca = TMath::Min(2.+pulldca[v0->GetIndex(0)],(2.+pulldca[v0->GetIndex(1)]) );     //pull
5028     Double_t minpulldca = TMath::Min(2.+pulldca[index0],(2.+pulldca[index1]) );//Bo:
5029
5030
5031
5032     AliTPCseed * track0 = (AliTPCseed*)array->At(index0);
5033     AliTPCseed * track1 = (AliTPCseed*)array->At(index1);
5034     if (track0->TPCrPID(0)>0.3&&track1->TPCrPID(0)>0.3&&v0->GetAnglep()[2]<0.15) quality[i]+=1000000;              // gamma conversion candidate
5035     if (track0->TPCrPID(4)>0.9||track1->TPCrPID(4)>0.9&&minpulldca>4) quality[i]*=10;    // lambda candidate candidate
5036   }
5037
5038   TMath::Sort(ncandidates,quality,indexes,kTRUE);
5039   //
5040   //
5041   for (Int_t i=0;i<ncandidates;i++){
5042     AliESDv0 * v0 = (AliESDv0*)tpcv0s->At(indexes[i]);
5043     if (!v0) continue;
5044     Int_t index0 = v0->GetIndex(0);
5045     Int_t index1 = v0->GetIndex(1);
5046     AliTPCseed * track0 = (AliTPCseed*)array->At(index0);
5047     AliTPCseed * track1 = (AliTPCseed*)array->At(index1);
5048     if (!track0||!track1) {
5049       printf("Bug\n");
5050       continue;
5051     }
5052     Bool_t accept =kTRUE;  //default accept
5053     Int_t *v0indexes0 = track0->GetV0Indexes();
5054     Int_t *v0indexes1 = track1->GetV0Indexes();
5055     //
5056     Int_t order0 = (v0indexes0[0]!=0) ? 1:0;
5057     Int_t order1 = (v0indexes1[0]!=0) ? 1:0;    
5058     if (v0indexes0[1]!=0) order0 =2;
5059     if (v0indexes1[1]!=0) order1 =2;      
5060     //
5061     if (v0indexes0[2]!=0) {order0=3; accept=kFALSE;}
5062     if (v0indexes0[2]!=0) {order1=3; accept=kFALSE;}
5063     //
5064     AliESDv0 * v02 = v0;
5065     if (accept){
5066       //Bo:      v0->SetOrder(0,order0);
5067       //Bo:      v0->SetOrder(1,order1);
5068       //Bo:      v0->SetOrder(1,order0+order1);     
5069       v0->SetOnFlyStatus(kTRUE);
5070       Int_t index = esd->AddV0(v0);
5071       v02 = esd->GetV0(index);
5072       v0indexes0[order0]=index;
5073       v0indexes1[order1]=index;
5074       naccepted++;
5075     }
5076     {
5077       Int_t eventNr = esd->GetEventNumber();
5078       if (AliTPCReconstructor::StreamLevel()>0) {
5079         Int_t lab0=track0->GetLabel();
5080         Int_t lab1=track1->GetLabel();
5081         cstream<<"V02"<<
5082         "Event="<<eventNr<<
5083         "vertex.="<<v0<<        
5084         "vertex2.="<<v02<<
5085         "Tr0.="<<track0<<
5086         "lab0="<<lab0<<
5087         "Tr1.="<<track1<<
5088         "lab1="<<lab1<<
5089         "dca0="<<dca[index0]<<
5090         "dca1="<<dca[index1]<<
5091         "order0="<<order0<<
5092         "order1="<<order1<<
5093         "accept="<<accept<<
5094         "quality="<<quality[i]<<
5095         "pulldca0="<<pulldca[index0]<<
5096         "pulldca1="<<pulldca[index1]<<
5097         "index="<<i<<
5098           "\n";}
5099     }
5100   }    
5101
5102
5103   //
5104   //
5105   delete []quality;
5106   delete []indexes;
5107 //
5108   delete [] isPrim;
5109   delete [] pulldca;
5110   delete [] pulldcaz;
5111   delete [] pulldcar;
5112   delete [] cdcar;
5113   delete [] sdcar;
5114   delete [] dca;
5115   //
5116   delete[] z0;
5117   delete[] alpha;
5118   delete[] sign;
5119   delete[] helixes;
5120   printf("TPC V0 finder : naccepted\t%d\tncandidates\t%d\tntracks\t%d\tnall\t%d\n",naccepted,ncandidates,ntracks,nall);
5121   timer.Print();
5122 }
5123
5124 Int_t AliTPCtrackerMI::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, AliESDkink &knk)
5125 {
5126   //
5127   // refit kink towards to the vertex
5128   //
5129   //
5130   AliKink &kink=(AliKink &)knk;
5131
5132   Int_t row0 = GetRowNumber(kink.GetR());
5133   FollowProlongation(mother,0);
5134   mother.Reset(kFALSE);
5135   //
5136   FollowProlongation(daughter,row0);
5137   daughter.Reset(kFALSE);
5138   FollowBackProlongation(daughter,158);
5139   daughter.Reset(kFALSE);
5140   Int_t first = TMath::Max(row0-20,30); 
5141   Int_t last  = TMath::Min(row0+20,140);
5142   //
5143   const Int_t kNdiv =5;
5144   AliTPCseed  param0[kNdiv];  // parameters along the track
5145   AliTPCseed  param1[kNdiv];  // parameters along the track
5146   AliKink     kinks[kNdiv];   // corresponding kink parameters
5147   //
5148   Int_t rows[kNdiv];
5149   for (Int_t irow=0; irow<kNdiv;irow++){
5150     rows[irow] = first +((last-first)*irow)/(kNdiv-1);
5151   }
5152   // store parameters along the track
5153   //
5154   for (Int_t irow=0;irow<kNdiv;irow++){
5155     FollowBackProlongation(mother, rows[irow]);
5156     FollowProlongation(daughter,rows[kNdiv-1-irow]);       
5157     new(&param0[irow])     AliTPCseed(mother);
5158     new(&param1[kNdiv-1-irow])   AliTPCseed(daughter);
5159   }
5160   //
5161   // define kinks 
5162   for (Int_t irow=0; irow<kNdiv-1;irow++){
5163     if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
5164     kinks[irow].SetMother(param0[irow]);
5165     kinks[irow].SetDaughter(param1[irow]);
5166     kinks[irow].Update();
5167   }
5168   //
5169   // choose kink with best "quality"
5170   Int_t index =-1;
5171   Double_t mindist = 10000;
5172   for (Int_t irow=0;irow<kNdiv;irow++){
5173     if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
5174     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
5175     if (TMath::Abs(kinks[irow].GetR())<100.) continue;
5176     //
5177     Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
5178     normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
5179     if (normdist < mindist){
5180       mindist = normdist;
5181       index = irow;
5182     }
5183   }
5184   //
5185   if (index==-1) return 0;
5186   //
5187   //
5188   param0[index].Reset(kTRUE);
5189   FollowProlongation(param0[index],0);
5190   //
5191   new (&mother) AliTPCseed(param0[index]);
5192   new (&daughter) AliTPCseed(param1[index]);  // daughter in vertex
5193   //
5194   kink.SetMother(mother);
5195   kink.SetDaughter(daughter);
5196   kink.Update();
5197   kink.SetTPCRow0(GetRowNumber(kink.GetR()));
5198   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
5199   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
5200   kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
5201   kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
5202   mother.SetLabel(kink.GetLabel(0));
5203   daughter.SetLabel(kink.GetLabel(1));
5204
5205   return 1;
5206 }
5207
5208
5209 void AliTPCtrackerMI::UpdateKinkQualityM(AliTPCseed * seed){
5210   //
5211   // update Kink quality information for mother after back propagation
5212   //
5213   if (seed->GetKinkIndex(0)>=0) return; 
5214   for (Int_t ikink=0;ikink<3;ikink++){
5215     Int_t index = seed->GetKinkIndex(ikink);
5216     if (index>=0) break;
5217     index = TMath::Abs(index)-1;
5218     AliESDkink * kink = fEvent->GetKink(index);
5219     //kink->fTPCdensity2[0][0]=-1;
5220     //kink->fTPCdensity2[0][1]=-1;
5221     kink->SetTPCDensity2(-1,0,0);
5222     kink->SetTPCDensity2(1,0,1);
5223     //
5224     Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5225     if (row0<15) row0=15;
5226     //
5227     Int_t row1 = kink->GetTPCRow0() + 2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5228     if (row1>145) row1=145;
5229     //
5230     Int_t found,foundable,shared;
5231     seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
5232     if (foundable>5)   kink->SetTPCDensity2(Float_t(found)/Float_t(foundable),0,0);
5233     seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
5234     if (foundable>5)   kink->SetTPCDensity2(Float_t(found)/Float_t(foundable),0,1);
5235   }
5236     
5237 }
5238
5239 void AliTPCtrackerMI::UpdateKinkQualityD(AliTPCseed * seed){
5240   //
5241   // update Kink quality information for daughter after refit
5242   //
5243   if (seed->GetKinkIndex(0)<=0) return; 
5244   for (Int_t ikink=0;ikink<3;ikink++){
5245     Int_t index = seed->GetKinkIndex(ikink);
5246     if (index<=0) break;
5247     index = TMath::Abs(index)-1;
5248     AliESDkink * kink = fEvent->GetKink(index);
5249     kink->SetTPCDensity2(-1,1,0);
5250     kink->SetTPCDensity2(-1,1,1);
5251     //
5252     Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5253     if (row0<15) row0=15;
5254     //
5255     Int_t row1 = kink->GetTPCRow0() +2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5256     if (row1>145) row1=145;
5257     //
5258     Int_t found,foundable,shared;
5259     seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
5260     if (foundable>5)   kink->SetTPCDensity2(Float_t(found)/Float_t(foundable),1,0);
5261     seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
5262     if (foundable>5)   kink->SetTPCDensity2(Float_t(found)/Float_t(foundable),1,1);
5263   }
5264     
5265 }
5266
5267
5268 Int_t  AliTPCtrackerMI::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, AliESDkink &knk)
5269 {
5270   //
5271   // check kink point for given track
5272   // if return value=0 kink point not found
5273   // otherwise seed0 correspond to mother particle
5274   //           seed1 correspond to daughter particle
5275   //           kink  parameter of kink point
5276   AliKink &kink=(AliKink &)knk;
5277
5278   Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
5279   Int_t first = seed->GetFirstPoint(); 
5280   Int_t last  = seed->GetLastPoint();
5281   if (last-first<20) return 0;          // shortest length - 2*30 = 60 pad-rows
5282
5283   
5284   AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE);  //middle of chamber
5285   if (!seed1) return 0;
5286   FollowProlongation(*seed1,seed->GetLastPoint()-20);
5287   seed1->Reset(kTRUE);
5288   FollowProlongation(*seed1,158);
5289   seed1->Reset(kTRUE);  
5290   last = seed1->GetLastPoint();
5291   //
5292   AliTPCseed *seed0 = new AliTPCseed(*seed);
5293   seed0->Reset(kFALSE);
5294   seed0->Reset();
5295   //
5296   AliTPCseed  param0[20];  // parameters along the track
5297   AliTPCseed  param1[20];  // parameters along the track
5298   AliKink     kinks[20];   // corresponding kink parameters
5299   Int_t rows[20];
5300   for (Int_t irow=0; irow<20;irow++){
5301     rows[irow] = first +((last-first)*irow)/19;
5302   }
5303   // store parameters along the track
5304   //
5305   for (Int_t irow=0;irow<20;irow++){
5306     FollowBackProlongation(*seed0, rows[irow]);
5307     FollowProlongation(*seed1,rows[19-irow]);       
5308     new(&param0[irow])     AliTPCseed(*seed0);
5309     new(&param1[19-irow])   AliTPCseed(*seed1);
5310   }
5311   //
5312   // define kinks 
5313   for (Int_t irow=0; irow<19;irow++){
5314     kinks[irow].SetMother(param0[irow]);
5315     kinks[irow].SetDaughter(param1[irow]);
5316     kinks[irow].Update();
5317   }
5318   //
5319   // choose kink with biggest change of angle
5320   Int_t index =-1;
5321   Double_t maxchange= 0;
5322   for (Int_t irow=1;irow<19;irow++){
5323     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
5324     if (TMath::Abs(kinks[irow].GetR())<110.) continue;
5325     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
5326     if ( quality > maxchange){
5327       maxchange = quality;
5328       index = irow;
5329       //
5330     }
5331   }
5332   delete seed0;
5333   delete seed1;
5334   if (index<0) return 0;
5335   //
5336   Int_t row0    = GetRowNumber(kinks[index].GetR());   //row 0 estimate
5337   seed0 = new AliTPCseed(param0[index]);
5338   seed1 = new AliTPCseed(param1[index]);
5339   seed0->Reset(kFALSE);
5340   seed1->Reset(kFALSE);
5341   seed0->ResetCovariance(10.);
5342   seed1->ResetCovariance(10.);
5343   FollowProlongation(*seed0,0);
5344   FollowBackProlongation(*seed1,158);
5345   new (&mother) AliTPCseed(*seed0);  // backup mother at position 0
5346   seed0->Reset(kFALSE);  
5347   seed1->Reset(kFALSE);
5348   seed0->ResetCovariance(10.);
5349   seed1->ResetCovariance(10.);
5350   //
5351   first = TMath::Max(row0-20,0);
5352   last  = TMath::Min(row0+20,158);
5353   //
5354   for (Int_t irow=0; irow<20;irow++){
5355     rows[irow] = first +((last-first)*irow)/19;
5356   }
5357   // store parameters along the track
5358   //
5359   for (Int_t irow=0;irow<20;irow++){
5360     FollowBackProlongation(*seed0, rows[irow]);
5361     FollowProlongation(*seed1,rows[19-irow]);       
5362     new(&param0[irow])     AliTPCseed(*seed0);
5363     new(&param1[19-irow])   AliTPCseed(*seed1);
5364   }
5365   //
5366   // define kinks 
5367   for (Int_t irow=0; irow<19;irow++){
5368     kinks[irow].SetMother(param0[irow]);
5369     kinks[irow].SetDaughter(param1[irow]);
5370     //    param0[irow].Dump();
5371     //param1[irow].Dump();
5372     kinks[irow].Update();
5373   }
5374   //
5375   // choose kink with biggest change of angle
5376   index =-1;
5377   maxchange= 0;
5378   for (Int_t irow=0;irow<20;irow++){
5379     if (TMath::Abs(kinks[irow].GetR())>250.) continue;
5380     if (TMath::Abs(kinks[irow].GetR())<90.) continue;
5381     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
5382     if ( quality > maxchange){
5383       maxchange = quality;
5384       index = irow;
5385       //
5386     }
5387   }
5388   //
5389   //
5390   if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
5391     delete seed0;
5392     delete seed1;
5393     return 0;
5394   }
5395   //  Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
5396   
5397   kink.SetMother(param0[index]);
5398   kink.SetDaughter(param1[index]);
5399   kink.Update();
5400   row0    = GetRowNumber(kink.GetR());   
5401   kink.SetTPCRow0(row0);
5402   kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
5403   kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
5404   kink.SetIndex(-10,0);
5405   kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
5406   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
5407   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
5408   //
5409   //
5410   //  new (&mother) AliTPCseed(param0[index]);
5411   new (&daughter) AliTPCseed(param1[index]);
5412   daughter.SetLabel(kink.GetLabel(1));  
5413   param0[index].Reset(kTRUE);
5414   FollowProlongation(param0[index],0);  
5415   new (&mother) AliTPCseed(param0[index]);
5416   mother.SetLabel(kink.GetLabel(0));
5417   delete seed0;
5418   delete seed1;
5419   //
5420   return 1;
5421 }
5422
5423
5424
5425
5426 AliTPCseed*  AliTPCtrackerMI::ReSeed(AliTPCseed *t)
5427 {
5428   //
5429   // reseed - refit -  track
5430   //
5431   Int_t first = 0;
5432   //  Int_t last  = fSectors->GetNRows()-1;
5433   //
5434   if (fSectors == fOuterSec){
5435     first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
5436     //last  = 
5437   }
5438   else
5439     first = t->GetFirstPoint();
5440   //
5441   AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
5442   FollowBackProlongation(*t,fSectors->GetNRows()-1);
5443   t->Reset(kFALSE);
5444   FollowProlongation(*t,first);
5445   return seed;
5446 }
5447
5448
5449
5450
5451
5452
5453
5454 //_____________________________________________________________________________
5455 Int_t AliTPCtrackerMI::ReadSeeds(const TFile *inp) {
5456   //-----------------------------------------------------------------
5457   // This function reades track seeds.
5458   //-----------------------------------------------------------------
5459   TDirectory *savedir=gDirectory; 
5460
5461   TFile *in=(TFile*)inp;
5462   if (!in->IsOpen()) {
5463      cerr<<"AliTPCtrackerMI::ReadSeeds(): input file is not open !\n";
5464      return 1;
5465   }
5466
5467   in->cd();
5468   TTree *seedTree=(TTree*)in->Get("Seeds");
5469   if (!seedTree) {
5470      cerr<<"AliTPCtrackerMI::ReadSeeds(): ";
5471      cerr<<"can't get a tree with track seeds !\n";
5472      return 2;
5473   }
5474   AliTPCtrack *seed=new AliTPCtrack; 
5475   seedTree->SetBranchAddress("tracks",&seed);
5476   
5477   if (fSeeds==0) fSeeds=new TObjArray(15000);
5478
5479   Int_t n=(Int_t)seedTree->GetEntries();
5480   for (Int_t i=0; i<n; i++) {
5481      seedTree->GetEvent(i);
5482      fSeeds->AddLast(new AliTPCseed(*seed/*,seed->GetAlpha()*/));
5483   }
5484   
5485   delete seed;
5486   delete seedTree; 
5487   savedir->cd();
5488   return 0;
5489 }
5490
5491 Int_t AliTPCtrackerMI::Clusters2Tracks (AliESD *esd)
5492 {
5493   //
5494   if (fSeeds) DeleteSeeds();
5495   fEvent = esd;
5496   Clusters2Tracks();
5497   if (!fSeeds) return 1;
5498   FillESD(fSeeds);
5499   return 0;
5500   //
5501 }
5502
5503
5504 //_____________________________________________________________________________
5505 Int_t AliTPCtrackerMI::Clusters2Tracks() {
5506   //-----------------------------------------------------------------
5507   // This is a track finder.
5508   //-----------------------------------------------------------------
5509   TDirectory *savedir=gDirectory; 
5510   TStopwatch timer;
5511
5512   fIteration = 0;
5513   fSeeds = Tracking();
5514
5515   if (fDebug>0){
5516     Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
5517   }
5518   //activate again some tracks
5519   for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
5520     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5521     if (!pt) continue;    
5522     Int_t nc=t.GetNumberOfClusters();
5523     if (nc<20) {
5524       delete fSeeds->RemoveAt(i);
5525       continue;
5526     } 
5527     CookLabel(pt,0.1); 
5528     if (pt->GetRemoval()==10) {
5529       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
5530         pt->Desactivate(10);  // make track again active
5531       else{
5532         pt->Desactivate(20);    
5533         delete fSeeds->RemoveAt(i);
5534       }
5535     } 
5536   }
5537   //
5538   RemoveUsed2(fSeeds,0.85,0.85,0);
5539   if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
5540   RemoveUsed2(fSeeds,0.5,0.4,20);
5541  //  //
5542 //   // refit short tracks
5543 //   //
5544   Int_t nseed=fSeeds->GetEntriesFast();
5545 //   for (Int_t i=0; i<nseed; i++) {
5546 //     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5547 //     if (!pt) continue;    
5548 //     Int_t nc=t.GetNumberOfClusters();
5549 //     if (nc<15) {
5550 //       delete fSeeds->RemoveAt(i);
5551 //       continue;
5552 //     }
5553 //     if (pt->GetKinkIndexes()[0]!=0) continue; // ignore kink candidates
5554 //     if (nc>100) continue;                     // hopefully, enough for ITS
5555 //     AliTPCseed *seed2 = new AliTPCseed(*pt);
5556 //     //seed2->Reset(kFALSE);
5557 //     //pt->ResetCovariance();
5558 //     seed2->Modify(1);
5559 //     FollowBackProlongation(*seed2,158);
5560 //     //seed2->Reset(kFALSE);
5561 //     seed2->Modify(10);
5562 //     FollowProlongation(*seed2,0);
5563 //     TTreeSRedirector &cstream = *fDebugStreamer;
5564 //     cstream<<"Crefit"<<
5565 //       "Tr0.="<<pt<<
5566 //       "Tr1.="<<seed2<<
5567 //       "\n";     
5568 //     if (seed2->fN>pt->fN){
5569 //       delete fSeeds->RemoveAt(i);
5570 //       fSeeds->AddAt(seed2,i);
5571 //     }else{
5572 //       delete seed2;
5573 //     }
5574 //   }
5575 //   RemoveUsed2(fSeeds,0.6,0.6,50);
5576
5577 //  FindV0s(fSeeds,fEvent);  
5578   //RemoveDouble(fSeeds,0.2,0.6,11);
5579
5580   //
5581   Int_t found = 0;
5582   for (Int_t i=0; i<nseed; i++) {
5583     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5584     if (!pt) continue;    
5585     Int_t nc=t.GetNumberOfClusters();
5586     if (nc<15) {
5587       delete fSeeds->RemoveAt(i);
5588       continue;
5589     }
5590     CookLabel(pt,0.1); //For comparison only
5591     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
5592     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
5593       found++;      
5594       if (fDebug>0) cerr<<found<<'\r';      
5595       pt->SetLab2(i);
5596     }
5597     else
5598       delete fSeeds->RemoveAt(i);
5599   }
5600
5601   
5602   //RemoveOverlap(fSeeds,0.99,7,kTRUE);  
5603   SignShared(fSeeds);  
5604   //RemoveUsed(fSeeds,0.9,0.9,6);
5605   // 
5606   nseed=fSeeds->GetEntriesFast();
5607   found = 0;
5608   for (Int_t i=0; i<nseed; i++) {
5609     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5610     if (!pt) continue;    
5611     Int_t nc=t.GetNumberOfClusters();
5612     if (nc<15) {
5613       delete fSeeds->RemoveAt(i);
5614       continue;
5615     }
5616     t.SetUniqueID(i);
5617     t.CookdEdx(0.02,0.6);
5618     //    CheckKinkPoint(&t,0.05);
5619     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
5620     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
5621       found++;
5622       if (fDebug>0){
5623         cerr<<found<<'\r';      
5624       }
5625       pt->SetLab2(i);
5626     }
5627     else
5628       delete fSeeds->RemoveAt(i);
5629     //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
5630     //if (seed1){
5631     //  FollowProlongation(*seed1,0);
5632     //  Int_t n = seed1->GetNumberOfClusters();
5633     //  printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
5634     //  printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
5635     //
5636     //}
5637     //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
5638     
5639   }
5640
5641   SortTracks(fSeeds, 1);
5642   
5643   /*    
5644   fIteration = 1;
5645   PrepareForBackProlongation(fSeeds,5.);
5646   PropagateBack(fSeeds);
5647   printf("Time for back propagation: \t");timer.Print();timer.Start();
5648   
5649   fIteration = 2;
5650   
5651   PrepareForProlongation(fSeeds,5.);
5652   PropagateForward2(fSeeds);
5653    
5654   printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
5655   // RemoveUsed(fSeeds,0.7,0.7,6);
5656   //RemoveOverlap(fSeeds,0.9,7,kTRUE);
5657    
5658   nseed=fSeeds->GetEntriesFast();
5659   found = 0;
5660   for (Int_t i=0; i<nseed; i++) {
5661     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5662     if (!pt) continue;    
5663     Int_t nc=t.GetNumberOfClusters();
5664     if (nc<15) {
5665       delete fSeeds->RemoveAt(i);
5666       continue;
5667     }
5668     t.CookdEdx(0.02,0.6);
5669     //    CookLabel(pt,0.1); //For comparison only
5670     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
5671     if ((pt->IsActive() || (pt->fRemoval==10) )){
5672       cerr<<found++<<'\r';      
5673     }
5674     else
5675       delete fSeeds->RemoveAt(i);
5676     pt->fLab2 = i;
5677   }
5678   */
5679  
5680   //  fNTracks = found;
5681   if (fDebug>0){
5682     Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
5683   }
5684   //
5685   //  cerr<<"Number of found tracks : "<<"\t"<<found<<endl;  
5686   Info("Clusters2Tracks","Number of found tracks %d",found);  
5687   savedir->cd();
5688   //  UnloadClusters();
5689   //  
5690   return 0;
5691 }
5692
5693 void AliTPCtrackerMI::Tracking(TObjArray * arr)
5694 {
5695   //
5696   // tracking of the seeds
5697   //
5698
5699   fSectors = fOuterSec;
5700   ParallelTracking(arr,150,63);
5701   fSectors = fOuterSec;
5702   ParallelTracking(arr,63,0);
5703 }
5704
5705 TObjArray * AliTPCtrackerMI::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
5706 {
5707   //
5708   //
5709   //tracking routine
5710   TObjArray * arr = new TObjArray;
5711   // 
5712   fSectors = fOuterSec;
5713   TStopwatch timer;
5714   timer.Start();
5715   for (Int_t sec=0;sec<fkNOS;sec++){
5716     if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
5717     if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);    
5718     if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
5719   }
5720   if (fDebug>0){
5721     Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
5722     timer.Print();
5723     timer.Start();
5724   }
5725   Tracking(arr);  
5726   if (fDebug>0){
5727     timer.Print();
5728   }
5729
5730   return arr;
5731 }
5732
5733 TObjArray * AliTPCtrackerMI::Tracking()
5734 {
5735   //
5736   //
5737   if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
5738   TStopwatch timer;
5739   timer.Start();
5740   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
5741
5742   TObjArray * seeds = new TObjArray;
5743   TObjArray * arr=0;
5744   
5745   Int_t gap =20;
5746   Float_t cuts[4];
5747   cuts[0] = 0.002;
5748   cuts[1] = 1.5;
5749   cuts[2] = 3.;
5750   cuts[3] = 3.;
5751   Float_t fnumber  = 3.0;
5752   Float_t fdensity = 3.0;
5753   
5754   //  
5755   //find primaries  
5756   cuts[0]=0.0066;
5757   for (Int_t delta = 0; delta<18; delta+=6){
5758     //
5759     cuts[0]=0.0070;
5760     cuts[1] = 1.5;
5761     arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
5762     SumTracks(seeds,arr);   
5763     SignClusters(seeds,fnumber,fdensity); 
5764     //
5765     for (Int_t i=2;i<6;i+=2){
5766       // seed high pt tracks
5767       cuts[0]=0.0022;
5768       cuts[1]=0.3;
5769       arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
5770       SumTracks(seeds,arr);   
5771       SignClusters(seeds,fnumber,fdensity);        
5772     }
5773   }
5774   fnumber  = 4;
5775   fdensity = 4.;
5776   //  RemoveUsed(seeds,0.9,0.9,1);
5777   //  UnsignClusters();
5778   //  SignClusters(seeds,fnumber,fdensity);    
5779
5780   //find primaries  
5781   cuts[0]=0.0077;
5782   for (Int_t delta = 20; delta<120; delta+=10){
5783     //
5784     // seed high pt tracks
5785     cuts[0]=0.0060;
5786     cuts[1]=0.3;
5787     cuts[2]=6.;
5788     arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
5789     SumTracks(seeds,arr);   
5790     SignClusters(seeds,fnumber,fdensity);            
5791
5792     cuts[0]=0.003;
5793     cuts[1]=0.3;
5794     cuts[2]=6.;
5795     arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
5796     SumTracks(seeds,arr);   
5797     SignClusters(seeds,fnumber,fdensity);            
5798   }
5799
5800   cuts[0] = 0.01;
5801   cuts[1] = 2.0;
5802   cuts[2] = 3.;
5803   cuts[3] = 2.0;
5804   fnumber  = 2.;
5805   fdensity = 2.;
5806   
5807   if (fDebug>0){
5808     Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
5809     timer.Print();
5810     timer.Start();
5811   }
5812   //  RemoveUsed(seeds,0.75,0.75,1);
5813   //UnsignClusters();
5814   //SignClusters(seeds,fnumber,fdensity);
5815   
5816   // find secondaries
5817
5818   cuts[0] = 0.3;
5819   cuts[1] = 1.5;
5820   cuts[2] = 3.;
5821   cuts[3] = 1.5;
5822
5823   arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
5824   SumTracks(seeds,arr);   
5825   SignClusters(seeds,fnumber,fdensity);   
5826   //
5827   arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
5828   SumTracks(seeds,arr);   
5829   SignClusters(seeds,fnumber,fdensity);   
5830   //
5831   arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
5832   SumTracks(seeds,arr);   
5833   SignClusters(seeds,fnumber,fdensity);   
5834   //
5835
5836
5837   for (Int_t delta = 3; delta<30; delta+=5){
5838     //
5839     cuts[0] = 0.3;
5840     cuts[1] = 1.5;
5841     cuts[2] = 3.;
5842     cuts[3] = 1.5;
5843     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
5844     SumTracks(seeds,arr);   
5845     SignClusters(seeds,fnumber,fdensity);   
5846     //
5847     arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
5848     SumTracks(seeds,arr);   
5849     SignClusters(seeds,fnumber,fdensity); 
5850     //
5851   } 
5852   fnumber  = 1;
5853   fdensity = 1;
5854   //
5855   // change cuts
5856   fnumber  = 2.;
5857   fdensity = 2.;
5858   cuts[0]=0.0080;
5859
5860   // find secondaries
5861   for (Int_t delta = 30; delta<90; delta+=10){
5862     //
5863     cuts[0] = 0.3;
5864     cuts[1] = 3.5;
5865     cuts[2] = 3.;
5866     cuts[3] = 3.5;
5867     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
5868     SumTracks(seeds,arr);   
5869     SignClusters(seeds,fnumber,fdensity);   
5870     //
5871     arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
5872     SumTracks(seeds,arr);   
5873     SignClusters(seeds,fnumber,fdensity);   
5874   }
5875  
5876   if (fDebug>0){
5877     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
5878     timer.Print();
5879     timer.Start();
5880   }
5881
5882   return seeds;
5883   //
5884       
5885 }
5886
5887
5888 TObjArray * AliTPCtrackerMI::TrackingSpecial()
5889 {
5890   //
5891   // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
5892   // no primary vertex seeding tried
5893   //
5894   TStopwatch timer;
5895   timer.Start();
5896   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
5897
5898   TObjArray * seeds = new TObjArray;
5899   TObjArray * arr=0;
5900   
5901   Int_t   gap  = 15;
5902   Float_t cuts[4];
5903   Float_t fnumber  = 3.0;
5904   Float_t fdensity = 3.0;
5905   
5906   // find secondaries
5907   cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC();   // max curvature
5908   cuts[1] = 3.5;    // max tan(phi) angle for seeding
5909   cuts[2] = 3.;     // not used (cut on z primary vertex)     
5910   cuts[3] = 3.5;    // max tan(theta) angle for seeding
5911
5912   for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
5913     //
5914     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
5915     SumTracks(seeds,arr);   
5916     SignClusters(seeds,fnumber,fdensity);   
5917   } 
5918  
5919   if (fDebug>0){
5920     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
5921     timer.Print();
5922     timer.Start();
5923   }
5924
5925   return seeds;
5926   //
5927       
5928 }
5929
5930
5931 void AliTPCtrackerMI::SumTracks(TObjArray *arr1,TObjArray *arr2) const
5932 {
5933   //
5934   //sum tracks to common container
5935   //remove suspicious tracks
5936   Int_t nseed = arr2->GetEntriesFast();
5937   for (Int_t i=0;i<nseed;i++){
5938     AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);    
5939     if (pt){
5940       //
5941       // remove tracks with too big curvature
5942       //
5943       if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
5944         delete arr2->RemoveAt(i);
5945         continue;
5946       }
5947        // REMOVE VERY SHORT  TRACKS
5948       if (pt->GetNumberOfClusters()<20){ 
5949         delete arr2->RemoveAt(i);
5950         continue;
5951       }// patch 28 fev06
5952       // NORMAL ACTIVE TRACK
5953       if (pt->IsActive()){
5954         arr1->AddLast(arr2->RemoveAt(i));
5955         continue;
5956       }
5957       //remove not usable tracks
5958       if (pt->GetRemoval()!=10){
5959         delete arr2->RemoveAt(i);
5960         continue;
5961       }
5962      
5963       // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
5964       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
5965         arr1->AddLast(arr2->RemoveAt(i));
5966       else{      
5967         delete arr2->RemoveAt(i);
5968       }
5969     }
5970   }
5971   delete arr2;  
5972 }
5973
5974
5975
5976 void  AliTPCtrackerMI::ParallelTracking(TObjArray * arr, Int_t rfirst, Int_t rlast)
5977 {
5978   //
5979   // try to track in parralel
5980
5981   Int_t nseed=arr->GetEntriesFast();
5982   //prepare seeds for tracking
5983   for (Int_t i=0; i<nseed; i++) {
5984     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt; 
5985     if (!pt) continue;
5986     if (!t.IsActive()) continue;
5987     // follow prolongation to the first layer
5988     if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fParam->GetNRowLow()>rfirst+1) )  
5989       FollowProlongation(t, rfirst+1);
5990   }
5991
5992
5993   //
5994   for (Int_t nr=rfirst; nr>=rlast; nr--){ 
5995     if (nr<fInnerSec->GetNRows()) 
5996       fSectors = fInnerSec;
5997     else
5998       fSectors = fOuterSec;
5999     // make indexes with the cluster tracks for given       
6000
6001     // find nearest cluster
6002     for (Int_t i=0; i<nseed; i++) {
6003       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;       
6004       if (!pt) continue;
6005       if (nr==80) pt->UpdateReference();
6006       if (!pt->IsActive()) continue;
6007       //      if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fParam->GetNRowLow())<nr) continue;
6008       if (pt->GetRelativeSector()>17) {
6009         continue;
6010       }
6011       UpdateClusters(t,nr);
6012     }
6013     // prolonagate to the nearest cluster - if founded
6014     for (Int_t i=0; i<nseed; i++) {
6015       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i); 
6016       if (!pt) continue;
6017       if (!pt->IsActive()) continue; 
6018       // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fParam->GetNRowLow())<nr) continue;
6019       if (pt->GetRelativeSector()>17) {
6020         continue;
6021       }
6022       FollowToNextCluster(*pt,nr);
6023     }
6024   }    
6025 }
6026
6027 void AliTPCtrackerMI::PrepareForBackProlongation(TObjArray * arr,Float_t fac) const
6028 {
6029   //
6030   //
6031   // if we use TPC track itself we have to "update" covariance
6032   //
6033   Int_t nseed= arr->GetEntriesFast();
6034   for (Int_t i=0;i<nseed;i++){
6035     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6036     if (pt) {
6037       pt->Modify(fac);
6038       //
6039       //rotate to current local system at first accepted  point    
6040       Int_t index  = pt->GetClusterIndex2(pt->GetFirstPoint()); 
6041       Int_t sec    = (index&0xff000000)>>24;
6042       sec = sec%18;
6043       Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
6044       if (angle1>TMath::Pi()) 
6045         angle1-=2.*TMath::Pi();
6046       Float_t angle2 = pt->GetAlpha();
6047       
6048       if (TMath::Abs(angle1-angle2)>0.001){
6049         pt->Rotate(angle1-angle2);
6050         //angle2 = pt->GetAlpha();
6051         //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
6052         //if (pt->GetAlpha()<0) 
6053         //  pt->fRelativeSector+=18;
6054         //sec = pt->fRelativeSector;
6055       }
6056         
6057     }
6058     
6059   }
6060
6061
6062 }
6063 void AliTPCtrackerMI::PrepareForProlongation(TObjArray * arr, Float_t fac) const
6064 {
6065   //
6066   //
6067   // if we use TPC track itself we have to "update" covariance
6068   //
6069   Int_t nseed= arr->GetEntriesFast();
6070   for (Int_t i=0;i<nseed;i++){
6071     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6072     if (pt) {
6073       pt->Modify(fac);
6074       pt->SetFirstPoint(pt->GetLastPoint()); 
6075     }
6076     
6077   }
6078
6079
6080 }
6081
6082 Int_t AliTPCtrackerMI::PropagateBack(TObjArray * arr)
6083 {
6084   //
6085   // make back propagation
6086   //
6087   Int_t nseed= arr->GetEntriesFast();
6088   for (Int_t i=0;i<nseed;i++){
6089     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6090     if (pt&& pt->GetKinkIndex(0)<=0) { 
6091       //AliTPCseed *pt2 = new AliTPCseed(*pt);
6092       fSectors = fInnerSec;
6093       //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
6094       //fSectors = fOuterSec;
6095       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);     
6096       //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
6097       //        Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
6098       //        FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
6099       //}
6100     }
6101     if (pt&& pt->GetKinkIndex(0)>0) {
6102       AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
6103       pt->SetFirstPoint(kink->GetTPCRow0());
6104       fSectors = fInnerSec;
6105       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);  
6106     }
6107     
6108   }
6109   return 0;
6110 }
6111
6112
6113 Int_t AliTPCtrackerMI::PropagateForward2(TObjArray * arr)
6114 {
6115   //
6116   // make forward propagation
6117   //
6118   Int_t nseed= arr->GetEntriesFast();
6119   //
6120   for (Int_t i=0;i<nseed;i++){
6121     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6122     if (pt) { 
6123       FollowProlongation(*pt,0);
6124     }
6125   }
6126   return 0;
6127 }
6128
6129
6130 Int_t AliTPCtrackerMI::PropagateForward()
6131 {
6132   //
6133   // propagate track forward
6134   //UnsignClusters();
6135   Int_t nseed = fSeeds->GetEntriesFast();
6136   for (Int_t i=0;i<nseed;i++){
6137     AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
6138     if (pt){
6139       AliTPCseed &t = *pt;
6140       Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
6141       if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
6142       if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
6143       t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
6144     }
6145   }
6146   
6147   fSectors = fOuterSec;
6148   ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
6149   fSectors = fInnerSec;
6150   ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
6151   //WriteTracks();
6152   return 1;
6153 }
6154
6155
6156
6157
6158
6159
6160 Int_t AliTPCtrackerMI::PropagateBack(AliTPCseed * pt, Int_t row0, Int_t row1)
6161 {
6162   //
6163   // make back propagation, in between row0 and row1
6164   //
6165   
6166   if (pt) { 
6167     fSectors = fInnerSec;
6168     Int_t  r1;
6169     //
6170     if (row1<fSectors->GetNRows()) 
6171       r1 = row1;
6172     else 
6173       r1 = fSectors->GetNRows()-1;
6174
6175     if (row0<fSectors->GetNRows()&& r1>0 )
6176       FollowBackProlongation(*pt,r1);
6177     if (row1<=fSectors->GetNRows())
6178       return 0;
6179     //
6180     r1 = row1 - fSectors->GetNRows();
6181     if (r1<=0) return 0;
6182     if (r1>=fOuterSec->GetNRows()) return 0;
6183     fSectors = fOuterSec;
6184     return FollowBackProlongation(*pt,r1);
6185   }        
6186   return 0;
6187 }
6188
6189
6190
6191
6192 void  AliTPCtrackerMI::GetShape(AliTPCseed * seed, Int_t row)
6193 {
6194   //
6195   //
6196   Float_t sd2 = TMath::Abs((fParam->GetZLength()-TMath::Abs(seed->GetZ())))*fParam->GetDiffL()*fParam->GetDiffL();
6197   //  Float_t padlength =  fParam->GetPadPitchLength(seed->fSector);
6198   Float_t padlength =  GetPadPitchLength(row);
6199   //
6200   Float_t sresy = (seed->GetSector() < fParam->GetNSector()/2) ? 0.2 :0.3;
6201   Double_t angulary  = seed->GetSnp();
6202   angulary = angulary*angulary/(1-angulary*angulary);
6203   seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);  
6204   //
6205   Float_t sresz = fParam->GetZSigma();
6206   Float_t angularz  = seed->GetTgl();
6207   seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
6208   /*
6209   Float_t wy = GetSigmaY(seed);
6210   Float_t wz = GetSigmaZ(seed);
6211   wy*=wy;
6212   wz*=wz;
6213   if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
6214     printf("problem\n");
6215   }
6216   */
6217 }
6218
6219
6220 Float_t  AliTPCtrackerMI::GetSigmaY(AliTPCseed * seed)
6221 {
6222   //
6223   //  
6224   Float_t sd2 = TMath::Abs((fParam->GetZLength()-TMath::Abs(seed->GetZ())))*fParam->GetDiffL()*fParam->GetDiffL();
6225   Float_t padlength =  fParam->GetPadPitchLength(seed->GetSector());
6226   Float_t sres = (seed->GetSector() < fParam->GetNSector()/2) ? 0.2 :0.3;
6227   Float_t angular  = seed->GetSnp();
6228   angular = angular*angular/(1-angular*angular);
6229   //  angular*=angular;
6230   //angular  = TMath::Sqrt(angular/(1-angular));
6231   Float_t res = TMath::Sqrt(sd2+padlength*padlength*angular/12.+sres*sres);
6232   return res;
6233 }
6234 Float_t  AliTPCtrackerMI::GetSigmaZ(AliTPCseed * seed)
6235 {
6236   //
6237   //
6238   Float_t sd2 = TMath::Abs((fParam->GetZLength()-TMath::Abs(seed->GetZ())))*fParam->GetDiffL()*fParam->GetDiffL();
6239   Float_t padlength =  fParam->GetPadPitchLength(seed->GetSector());
6240   Float_t sres = fParam->GetZSigma();
6241   Float_t angular  = seed->GetTgl();
6242   Float_t res = TMath::Sqrt(sd2+padlength*padlength*angular*angular/12.+sres*sres);
6243   return res;
6244 }
6245
6246
6247 //__________________________________________________________________________
6248 void AliTPCtrackerMI::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
6249   //--------------------------------------------------------------------
6250   //This function "cooks" a track label. If label<0, this track is fake.
6251   //--------------------------------------------------------------------
6252   AliTPCseed * t = (AliTPCseed*)tk;
6253   Int_t noc=t->GetNumberOfClusters();
6254   if (noc<10){
6255     //printf("\nnot founded prolongation\n\n\n");
6256     //t->Dump();
6257     return ;
6258   }
6259   Int_t lb[160];
6260   Int_t mx[160];
6261   AliTPCclusterMI *clusters[160];
6262   //
6263   for (Int_t i=0;i<160;i++) {
6264     clusters[i]=0;
6265     lb[i]=mx[i]=0;
6266   }
6267
6268   Int_t i;
6269   Int_t current=0;
6270   for (i=0; i<160 && current<noc; i++) {
6271      
6272      Int_t index=t->GetClusterIndex2(i);
6273      if (index<=0) continue; 
6274      if (index&0x8000) continue;
6275      //     
6276      //clusters[current]=GetClusterMI(index);
6277      if (t->GetClusterPointer(i)){
6278        clusters[current]=t->GetClusterPointer(i);     
6279        current++;
6280      }
6281   }
6282   noc = current;
6283
6284   Int_t lab=123456789;
6285   for (i=0; i<noc; i++) {
6286     AliTPCclusterMI *c=clusters[i];
6287     if (!c) continue;
6288     lab=TMath::Abs(c->GetLabel(0));
6289     Int_t j;
6290     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
6291     lb[j]=lab;
6292     (mx[j])++;
6293   }
6294
6295   Int_t max=0;
6296   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
6297     
6298   for (i=0; i<noc; i++) {
6299     AliTPCclusterMI *c=clusters[i]; 
6300     if (!c) continue;
6301     if (TMath::Abs(c->GetLabel(1)) == lab ||
6302         TMath::Abs(c->GetLabel(2)) == lab ) max++;
6303   }
6304
6305   if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
6306
6307   else {
6308      Int_t tail=Int_t(0.10*noc);
6309      max=0;
6310      Int_t ind=0;
6311      for (i=1; i<=160&&ind<tail; i++) {
6312        //       AliTPCclusterMI *c=clusters[noc-i];
6313        AliTPCclusterMI *c=clusters[i];
6314        if (!c) continue;
6315        if (lab == TMath::Abs(c->GetLabel(0)) ||
6316            lab == TMath::Abs(c->GetLabel(1)) ||
6317            lab == TMath::Abs(c->GetLabel(2))) max++;
6318        ind++;
6319      }
6320      if (max < Int_t(0.5*tail)) lab=-lab;
6321   }
6322
6323   t->SetLabel(lab);
6324
6325   //  delete[] lb;
6326   //delete[] mx;
6327   //delete[] clusters;
6328 }
6329
6330
6331 //__________________________________________________________________________
6332 Int_t AliTPCtrackerMI::CookLabel(AliTPCseed *t, Float_t wrong,Int_t first, Int_t last) const {
6333   //--------------------------------------------------------------------
6334   //This function "cooks" a track label. If label<0, this track is fake.
6335   //--------------------------------------------------------------------
6336   Int_t noc=t->GetNumberOfClusters();
6337   if (noc<10){
6338     //printf("\nnot founded prolongation\n\n\n");
6339     //t->Dump();
6340     return -1;
6341   }
6342   Int_t lb[160];
6343   Int_t mx[160];
6344   AliTPCclusterMI *clusters[160];
6345   //
6346   for (Int_t i=0;i<160;i++) {
6347     clusters[i]=0;
6348     lb[i]=mx[i]=0;
6349   }
6350
6351   Int_t i;
6352   Int_t current=0;
6353   for (i=0; i<160 && current<noc; i++) {
6354     if (i<first) continue;
6355     if (i>last)  continue;
6356      Int_t index=t->GetClusterIndex2(i);
6357      if (index<=0) continue; 
6358      if (index&0x8000) continue;
6359      //     
6360      //clusters[current]=GetClusterMI(index);
6361      if (t->GetClusterPointer(i)){
6362        clusters[current]=t->GetClusterPointer(i);     
6363        current++;
6364      }
6365   }
6366   noc = current;
6367   if (noc<5) return -1;
6368   Int_t lab=123456789;
6369   for (i=0; i<noc; i++) {
6370     AliTPCclusterMI *c=clusters[i];
6371     if (!c) continue;
6372     lab=TMath::Abs(c->GetLabel(0));
6373     Int_t j;
6374     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
6375     lb[j]=lab;
6376     (mx[j])++;
6377   }
6378
6379   Int_t max=0;
6380   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
6381     
6382   for (i=0; i<noc; i++) {
6383     AliTPCclusterMI *c=clusters[i]; 
6384     if (!c) continue;
6385     if (TMath::Abs(c->GetLabel(1)) == lab ||
6386         TMath::Abs(c->GetLabel(2)) == lab ) max++;
6387   }
6388
6389   if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
6390
6391   else {
6392      Int_t tail=Int_t(0.10*noc);
6393      max=0;
6394      Int_t ind=0;
6395      for (i=1; i<=160&&ind<tail; i++) {
6396        //       AliTPCclusterMI *c=clusters[noc-i];
6397        AliTPCclusterMI *c=clusters[i];
6398        if (!c) continue;
6399        if (lab == TMath::Abs(c->GetLabel(0)) ||
6400            lab == TMath::Abs(c->GetLabel(1)) ||
6401            lab == TMath::Abs(c->GetLabel(2))) max++;
6402        ind++;
6403      }
6404      if (max < Int_t(0.5*tail)) lab=-lab;
6405   }
6406
6407   //  t->SetLabel(lab);
6408   return lab;
6409   //  delete[] lb;
6410   //delete[] mx;
6411   //delete[] clusters;
6412 }
6413
6414
6415 Int_t  AliTPCtrackerMI::AliTPCSector::GetRowNumber(Double_t x) const 
6416 {
6417   //return pad row number for this x
6418   Double_t r;
6419   if (fN < 64){
6420     r=fRow[fN-1].GetX();
6421     if (x > r) return fN;
6422     r=fRow[0].GetX();
6423     if (x < r) return -1;
6424     return Int_t((x-r)/fPadPitchLength + 0.5);}
6425   else{    
6426     r=fRow[fN-1].GetX();
6427     if (x > r) return fN;
6428     r=fRow[0].GetX();
6429     if (x < r) return -1;
6430     Double_t r1=fRow[64].GetX();
6431     if(x<r1){       
6432       return Int_t((x-r)/f1PadPitchLength + 0.5);}
6433     else{
6434       return (Int_t((x-r1)/f2PadPitchLength + 0.5)+64);} 
6435   }
6436 }
6437
6438 Int_t  AliTPCtrackerMI::GetRowNumber(Double_t x[3]) const 
6439 {
6440   //return pad row number for given x vector
6441   Float_t phi = TMath::ATan2(x[1],x[0]);
6442   if(phi<0) phi=2.*TMath::Pi()+phi;
6443   //  Get the local angle in the sector philoc
6444   const Float_t kRaddeg = 180/3.14159265358979312;
6445   Float_t phiangle   = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
6446   Double_t localx    = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
6447   return GetRowNumber(localx);
6448 }
6449
6450 //_________________________________________________________________________
6451 void AliTPCtrackerMI::AliTPCSector::Setup(const AliTPCParam *par, Int_t f) {
6452   //-----------------------------------------------------------------------
6453   // Setup inner sector
6454   //-----------------------------------------------------------------------
6455   if (f==0) {
6456      fAlpha=par->GetInnerAngle();
6457      fAlphaShift=par->GetInnerAngleShift();
6458      fPadPitchWidth=par->GetInnerPadPitchWidth();
6459      fPadPitchLength=par->GetInnerPadPitchLength();
6460      fN=par->GetNRowLow();
6461      fRow=new AliTPCRow[fN];
6462      for (Int_t i=0; i<fN; i++) {
6463        fRow[i].SetX(par->GetPadRowRadiiLow(i));
6464        fRow[i].SetDeadZone(1.5);  //1.5 cm of dead zone
6465      }
6466   } else {
6467      fAlpha=par->GetOuterAngle();
6468      fAlphaShift=par->GetOuterAngleShift();
6469      fPadPitchWidth  = par->GetOuterPadPitchWidth();
6470      fPadPitchLength = par->GetOuter1PadPitchLength();
6471      f1PadPitchLength = par->GetOuter1PadPitchLength();
6472      f2PadPitchLength = par->GetOuter2PadPitchLength();
6473
6474      fN=par->GetNRowUp();
6475      fRow=new AliTPCRow[fN];
6476      for (Int_t i=0; i<fN; i++) {
6477        fRow[i].SetX(par->GetPadRowRadiiUp(i)); 
6478        fRow[i].SetDeadZone(1.5);  // 1.5 cm of dead zone
6479      }
6480   } 
6481 }
6482
6483 AliTPCtrackerMI::AliTPCRow::AliTPCRow():
6484   fDeadZone(0.),
6485   fClusters1(0),
6486   fN1(0),
6487   fClusters2(0),
6488   fN2(0),
6489   fN(0),
6490   fX(0.)
6491 {
6492   //
6493   // default constructor
6494   //
6495 }
6496
6497 AliTPCtrackerMI::AliTPCRow::~AliTPCRow(){
6498   //
6499
6500 }
6501
6502
6503
6504 //_________________________________________________________________________
6505 void 
6506 AliTPCtrackerMI::AliTPCRow::InsertCluster(const AliTPCclusterMI* c, UInt_t index) {
6507   //-----------------------------------------------------------------------
6508   // Insert a cluster into this pad row in accordence with its y-coordinate
6509   //-----------------------------------------------------------------------
6510   if (fN==kMaxClusterPerRow) {
6511     cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return;
6512   }
6513   if (fN==0) {fIndex[0]=index; fClusters[fN++]=c; return;}
6514   Int_t i=Find(c->GetZ());
6515   memmove(fClusters+i+1 ,fClusters+i,(fN-i)*sizeof(AliTPCclusterMI*));
6516   memmove(fIndex   +i+1 ,fIndex   +i,(fN-i)*sizeof(UInt_t));
6517   fIndex[i]=index; fClusters[i]=c; fN++;
6518 }
6519
6520 void AliTPCtrackerMI::AliTPCRow::ResetClusters() {
6521    //
6522    // reset clusters
6523    fN  = 0; 
6524    fN1 = 0;
6525    fN2 = 0;
6526    //delete[] fClusterArray; 
6527    if (fClusters1) delete []fClusters1; 
6528    if (fClusters2) delete []fClusters2; 
6529    //fClusterArray=0;
6530    fClusters1 = 0;
6531    fClusters2 = 0;
6532 }
6533
6534
6535 //___________________________________________________________________
6536 Int_t AliTPCtrackerMI::AliTPCRow::Find(Double_t z) const {
6537   //-----------------------------------------------------------------------
6538   // Return the index of the nearest cluster 
6539   //-----------------------------------------------------------------------
6540   if (fN==0) return 0;
6541   if (z <= fClusters[0]->GetZ()) return 0;
6542   if (z > fClusters[fN-1]->GetZ()) return fN;
6543   Int_t b=0, e=fN-1, m=(b+e)/2;
6544   for (; b<e; m=(b+e)/2) {
6545     if (z > fClusters[m]->GetZ()) b=m+1;
6546     else e=m; 
6547   }
6548   return m;
6549 }
6550
6551
6552
6553 //___________________________________________________________________
6554 AliTPCclusterMI * AliTPCtrackerMI::AliTPCRow::FindNearest(Double_t y, Double_t z, Double_t roady, Double_t roadz) const {
6555   //-----------------------------------------------------------------------
6556   // Return the index of the nearest cluster in z y 
6557   //-----------------------------------------------------------------------
6558   Float_t maxdistance = roady*roady + roadz*roadz;
6559
6560   AliTPCclusterMI *cl =0;
6561   for (Int_t i=Find(z-roadz); i<fN; i++) {
6562       AliTPCclusterMI *c=(AliTPCclusterMI*)(fClusters[i]);
6563       if (c->GetZ() > z+roadz) break;
6564       if ( (c->GetY()-y) >  roady ) continue;
6565       Float_t distance = (c->GetZ()-z)*(c->GetZ()-z)+(c->GetY()-y)*(c->GetY()-y);
6566       if (maxdistance>distance) {
6567         maxdistance = distance;
6568         cl=c;       
6569       }
6570   }
6571   return cl;      
6572 }
6573
6574 AliTPCclusterMI * AliTPCtrackerMI::AliTPCRow::FindNearest2(Double_t y, Double_t z, Double_t roady, Double_t roadz,UInt_t & index) const 
6575 {
6576   //-----------------------------------------------------------------------
6577   // Return the index of the nearest cluster in z y 
6578   //-----------------------------------------------------------------------
6579   Float_t maxdistance = roady*roady + roadz*roadz;
6580   AliTPCclusterMI *cl =0;
6581
6582   //PH Check boundaries. 510 is the size of fFastCluster
6583   Int_t iz1 = Int_t(z-roadz+254.5);
6584   if (iz1<0 || iz1>=510) return cl;
6585   iz1 = TMath::Max(GetFastCluster(iz1)-1,0);
6586   Int_t iz2 = Int_t(z+roadz+255.5);
6587   if (iz2<0 || iz2>=510) return cl;
6588   iz2 = TMath::Min(GetFastCluster(iz2)+1,fN);
6589
6590   //FindNearest3(y,z,roady,roadz,index);
6591   //  for (Int_t i=Find(z-roadz); i<fN; i++) {
6592   for (Int_t i=iz1; i<iz2; i++) {
6593       AliTPCclusterMI *c=(AliTPCclusterMI*)(fClusters[i]);
6594       if (c->GetZ() > z+roadz) break;
6595       if ( c->GetY()-y >  roady ) continue;
6596       if ( y-c->GetY() >  roady ) continue;
6597       Float_t distance = (c->GetZ()-z)*(c->GetZ()-z)+(c->GetY()-y)*(c->GetY()-y);
6598       if (maxdistance>distance) {
6599         maxdistance = distance;
6600         cl=c;       
6601         index =i;
6602         //roady = TMath::Sqrt(maxdistance);
6603       }
6604   }
6605   return cl;      
6606 }
6607
6608
6609
6610 AliTPCclusterMI * AliTPCtrackerMI::AliTPCRow::FindNearest3(Double_t y, Double_t z, Double_t roady, Double_t roadz,UInt_t & index) const 
6611 {
6612   //-----------------------------------------------------------------------
6613   // Return the index of the nearest cluster in z y 
6614   //-----------------------------------------------------------------------
6615   Float_t maxdistance = roady*roady + roadz*roadz;
6616   //  Int_t iz = Int_t(z+255.);
6617   AliTPCclusterMI *cl =0;
6618   for (Int_t i=Find(z-roadz); i<fN; i++) {
6619     //for (Int_t i=fFastCluster[iz-2]; i<fFastCluster[iz+2]; i++) {
6620       AliTPCclusterMI *c=(AliTPCclusterMI*)(fClusters[i]);
6621       if (c->GetZ() > z+roadz) break;
6622       if ( c->GetY()-y >  roady ) continue;
6623       if ( y-c->GetY() >  roady ) continue;
6624       Float_t distance = (c->GetZ()-z)*(c->GetZ()-z)+(c->GetY()-y)*(c->GetY()-y);
6625       if (maxdistance>distance) {
6626         maxdistance = distance;
6627         cl=c;       
6628         index =i;
6629         //roady = TMath::Sqrt(maxdistance);
6630       }
6631   }
6632   return cl;      
6633 }
6634
6635
6636
6637
6638
6639 // AliTPCTrackerPoint * AliTPCseed::GetTrackPoint(Int_t i)
6640 // {
6641 //   //
6642 //   // 
6643 //   return &fTrackPoints[i];
6644 // }
6645
6646