]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/AliTPCtrackerMI.cxx
New base AliCluster class (Jouri+Cvetan)
[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((AliTPCclusterMI*)(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(AliTPCclusterMI * 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->GetEventNumberInFile();// patch 28 fev 06
2717       // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number      
2718       (*fDebugStreamer)<<"Cback"<<
2719         "Tr0.="<<seed<<
2720         "EventNrInFile="<<eventnumber<<
2721         "\n"; // patch 28 fev 06   
2722     }
2723   }
2724   //FindKinks(fSeeds,event);
2725   Info("PropagateBack","Number of back propagated tracks %d",ntracks);
2726   fEvent =0;
2727   //WriteTracks();
2728
2729   return 0;
2730 }
2731
2732
2733 void AliTPCtrackerMI::DeleteSeeds()
2734 {
2735   //
2736   //delete Seeds
2737
2738   Int_t nseed = fSeeds->GetEntriesFast();
2739   for (Int_t i=0;i<nseed;i++){
2740     AliTPCseed * seed = (AliTPCseed*)fSeeds->At(i);
2741     if (seed) delete fSeeds->RemoveAt(i);
2742   }
2743   delete fSeeds;
2744
2745   fSeeds =0;
2746 }
2747
2748 void AliTPCtrackerMI::ReadSeeds(AliESD *event, Int_t direction)
2749 {
2750   //
2751   //read seeds from the event
2752   
2753   Int_t nentr=event->GetNumberOfTracks();
2754   if (fDebug>0){
2755     Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
2756   }
2757   if (fSeeds) 
2758     DeleteSeeds();
2759   if (!fSeeds){   
2760     fSeeds = new TObjArray(nentr);
2761   }
2762   UnsignClusters();
2763   //  Int_t ntrk=0;  
2764   for (Int_t i=0; i<nentr; i++) {
2765     AliESDtrack *esd=event->GetTrack(i);
2766     ULong_t status=esd->GetStatus();
2767     if (!(status&AliESDtrack::kTPCin)) continue;
2768     AliTPCtrack t(*esd);
2769     t.SetNumberOfClusters(0);
2770     //    AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
2771     AliTPCseed *seed = new AliTPCseed(t/*,t.GetAlpha()*/);
2772     for (Int_t ikink=0;ikink<3;ikink++) {
2773       Int_t index = esd->GetKinkIndex(ikink);
2774       seed->GetKinkIndexes()[ikink] = index;
2775       if (index==0) continue;
2776       index = TMath::Abs(index);
2777       AliESDkink * kink = fEvent->GetKink(index-1);
2778       if (kink&&esd->GetKinkIndex(ikink)<0){
2779         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
2780         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,0);
2781       }
2782       if (kink&&esd->GetKinkIndex(ikink)>0){
2783         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
2784         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,4);
2785       }
2786
2787     }
2788     if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.); 
2789     if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
2790     if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
2791       fSeeds->AddAt(0,i);
2792       delete seed;
2793       continue;    
2794     }
2795     if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) > 0 )  {
2796       Double_t par0[5],par1[5],alpha,x;
2797       esd->GetInnerExternalParameters(alpha,x,par0);
2798       esd->GetExternalParameters(x,par1);
2799       Double_t delta1 = TMath::Abs(par0[4]-par1[4])/(0.000000001+TMath::Abs(par0[4]+par1[4]));
2800       Double_t delta2 = TMath::Abs(par0[3]-par1[3]);
2801       Double_t trdchi2=0;
2802       if (esd->GetTRDncls()>0) trdchi2 = esd->GetTRDchi2()/esd->GetTRDncls();
2803       //reset covariance if suspicious 
2804       if ( (delta1>0.1) || (delta2>0.006) ||trdchi2>7.)
2805         seed->ResetCovariance(10.);
2806     }
2807
2808     //
2809     //
2810     // rotate to the local coordinate system
2811     //   
2812     fSectors=fInnerSec; fN=fkNIS;    
2813     Double_t alpha=seed->GetAlpha() - fSectors->GetAlphaShift();
2814     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2815     if (alpha < 0.            ) alpha += 2.*TMath::Pi();
2816     Int_t ns=Int_t(alpha/fSectors->GetAlpha())%fN;
2817     alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
2818     if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
2819     if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
2820     alpha-=seed->GetAlpha();  
2821     if (!seed->Rotate(alpha)) {
2822       delete seed;
2823       continue;
2824     }
2825     seed->SetESD(esd);
2826     // sign clusters
2827     if (esd->GetKinkIndex(0)<=0){
2828       for (Int_t irow=0;irow<160;irow++){
2829         Int_t index = seed->GetClusterIndex2(irow);    
2830         if (index>0){ 
2831           //
2832           AliTPCclusterMI * cl = GetClusterMI(index);
2833           seed->SetClusterPointer(irow,cl);
2834           if (cl){
2835             if ((index & 0x8000)==0){
2836               cl->Use(10);  // accepted cluster   
2837             }else{
2838               cl->Use(6);   // close cluster not accepted
2839             }   
2840           }else{
2841             Info("ReadSeeds","Not found cluster");
2842           }
2843         }
2844       }
2845     }
2846     fSeeds->AddAt(seed,i);
2847   }
2848 }
2849
2850
2851
2852 //_____________________________________________________________________________
2853 void AliTPCtrackerMI::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
2854                                  Float_t deltay, Int_t ddsec) {
2855   //-----------------------------------------------------------------
2856   // This function creates track seeds.
2857   // SEEDING WITH VERTEX CONSTRAIN 
2858   //-----------------------------------------------------------------
2859   // cuts[0]   - fP4 cut
2860   // cuts[1]   - tan(phi)  cut
2861   // cuts[2]   - zvertex cut
2862   // cuts[3]   - fP3 cut
2863   Int_t nin0  = 0;
2864   Int_t nin1  = 0;
2865   Int_t nin2  = 0;
2866   Int_t nin   = 0;
2867   Int_t nout1 = 0;
2868   Int_t nout2 = 0;
2869
2870   Double_t x[5], c[15];
2871   //  Int_t di = i1-i2;
2872   //
2873   AliTPCseed * seed = new AliTPCseed;
2874   Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
2875   Double_t cs=cos(alpha), sn=sin(alpha);
2876   //
2877   //  Double_t x1 =fOuterSec->GetX(i1);
2878   //Double_t xx2=fOuterSec->GetX(i2);
2879   
2880   Double_t x1 =GetXrow(i1);
2881   Double_t xx2=GetXrow(i2);
2882
2883   Double_t x3=GetX(), y3=GetY(), z3=GetZ();
2884
2885   Int_t imiddle = (i2+i1)/2;    //middle pad row index
2886   Double_t xm = GetXrow(imiddle); // radius of middle pad-row
2887   const AliTPCRow& krm=GetRow(sec,imiddle); //middle pad -row
2888   //
2889   Int_t ns =sec;   
2890
2891   const AliTPCRow& kr1=GetRow(ns,i1);
2892   Double_t ymax  = GetMaxY(i1)-kr1.GetDeadZone()-1.5;  
2893   Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;  
2894
2895   //
2896   // change cut on curvature if it can't reach this layer
2897   // maximal curvature set to reach it
2898   Double_t dvertexmax  = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
2899   if (dvertexmax*0.5*cuts[0]>0.85){
2900     cuts[0] = 0.85/(dvertexmax*0.5+1.);
2901   }
2902   Double_t r2min = 1/(cuts[0]*cuts[0]);  //minimal square of radius given by cut
2903
2904   //  Int_t ddsec = 1;
2905   if (deltay>0) ddsec = 0; 
2906   // loop over clusters  
2907   for (Int_t is=0; is < kr1; is++) {
2908     //
2909     if (kr1[is]->IsUsed(10)) continue;
2910     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
2911     //if (TMath::Abs(y1)>ymax) continue;
2912
2913     if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge
2914
2915     // find possible directions    
2916     Float_t anglez = (z1-z3)/(x1-x3); 
2917     Float_t extraz = z1 - anglez*(x1-xx2);  // extrapolated z      
2918     //
2919     //
2920     //find   rotation angles relative to line given by vertex and point 1
2921     Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
2922     Double_t dvertex  = TMath::Sqrt(dvertex2);
2923     Double_t angle13  = TMath::ATan((y1-y3)/(x1-x3));
2924     Double_t cs13     = cos(-angle13), sn13 = sin(-angle13);            
2925     
2926     //
2927     // loop over 2 sectors
2928     Int_t dsec1=-ddsec;
2929     Int_t dsec2= ddsec;
2930     if (y1<0)  dsec2= 0;
2931     if (y1>0)  dsec1= 0;
2932     
2933     Double_t dddz1=0;  // direction of delta inclination in z axis
2934     Double_t dddz2=0;
2935     if ( (z1-z3)>0)
2936       dddz1 =1;    
2937     else
2938       dddz2 =1;
2939     //
2940     for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
2941       Int_t sec2 = sec + dsec;
2942       // 
2943       //      AliTPCRow&  kr2  = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
2944       //AliTPCRow&  kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
2945       AliTPCRow&  kr2  = GetRow((sec2+fkNOS)%fkNOS,i2);
2946       AliTPCRow&  kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
2947       Int_t  index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
2948       Int_t  index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
2949
2950       // rotation angles to p1-p3
2951       Double_t cs13r     = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;            
2952       Double_t x2,   y2,   z2; 
2953       //
2954       //      Double_t dymax = maxangle*TMath::Abs(x1-xx2);
2955
2956       //
2957       Double_t dxx0 =  (xx2-x3)*cs13r;
2958       Double_t dyy0 =  (xx2-x3)*sn13r;
2959       for (Int_t js=index1; js < index2; js++) {
2960         const AliTPCclusterMI *kcl = kr2[js];
2961         if (kcl->IsUsed(10)) continue;  
2962         //
2963         //calcutate parameters
2964         //      
2965         Double_t yy0 =  dyy0 +(kcl->GetY()-y3)*cs13r;
2966         // stright track
2967         if (TMath::Abs(yy0)<0.000001) continue;
2968         Double_t xx0 =  dxx0 -(kcl->GetY()-y3)*sn13r;
2969         Double_t y0  =  0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
2970         Double_t r02 = (0.25+y0*y0)*dvertex2;   
2971         //curvature (radius) cut
2972         if (r02<r2min) continue;                
2973        
2974         nin0++; 
2975         //
2976         Double_t c0  = 1/TMath::Sqrt(r02);
2977         if (yy0>0) c0*=-1.;     
2978                
2979        
2980         //Double_t dfi0   = 2.*TMath::ASin(dvertex*c0*0.5);
2981         //Double_t dfi1   = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
2982         Double_t dfi0   = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
2983         Double_t dfi1   = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);  
2984         //
2985         //
2986         Double_t z0  =  kcl->GetZ();  
2987         Double_t zzzz2    = z1-(z1-z3)*dfi1/dfi0;
2988         if (TMath::Abs(zzzz2-z0)>0.5) continue;       
2989         nin1++;              
2990         //      
2991         Double_t dip    = (z1-z0)*c0/dfi1;        
2992         Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
2993         //
2994         y2 = kcl->GetY(); 
2995         if (dsec==0){
2996           x2 = xx2; 
2997           z2 = kcl->GetZ();       
2998         }
2999         else
3000           {
3001             // rotation 
3002             z2 = kcl->GetZ();  
3003             x2= xx2*cs-y2*sn*dsec;
3004             y2=+xx2*sn*dsec+y2*cs;
3005           }
3006         
3007         x[0] = y1;
3008         x[1] = z1;
3009         x[2] = x0;
3010         x[3] = dip;
3011         x[4] = c0;
3012         //
3013         //
3014         // do we have cluster at the middle ?
3015         Double_t ym,zm;
3016         GetProlongation(x1,xm,x,ym,zm);
3017         UInt_t dummy; 
3018         AliTPCclusterMI * cm=0;
3019         if (TMath::Abs(ym)-ymaxm<0){      
3020           cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3021           if ((!cm) || (cm->IsUsed(10))) {        
3022             continue;
3023           }
3024         }
3025         else{     
3026           // rotate y1 to system 0
3027           // get state vector in rotated system 
3028           Double_t yr1  = (-0.5*sn13+y0*cs13)*dvertex*c0;
3029           Double_t xr2  =  x0*cs+yr1*sn*dsec;
3030           Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3031           //
3032           GetProlongation(xx2,xm,xr,ym,zm);
3033           if (TMath::Abs(ym)-ymaxm<0){
3034             cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3035             if ((!cm) || (cm->IsUsed(10))) {      
3036               continue;
3037             }
3038           }
3039         }
3040        
3041
3042         Double_t dym = 0;
3043         Double_t dzm = 0;
3044         if (cm){
3045           dym = ym - cm->GetY();
3046           dzm = zm - cm->GetZ();
3047         }
3048         nin2++;
3049
3050
3051         //
3052         //
3053         Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3054         Double_t sy2=kcl->GetSigmaY2()*2.,     sz2=kcl->GetSigmaZ2()*2.;
3055         //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3056         Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3057         //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3058
3059         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3060         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3061         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3062         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3063         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3064         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3065         
3066         Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3067         Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3068         Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3069         Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3070         
3071         c[0]=sy1;
3072         c[1]=0.;       c[2]=sz1;
3073         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3074         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3075                        c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3076         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3077         c[13]=f30*sy1*f40+f32*sy2*f42;
3078         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3079         
3080         //      if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3081         
3082         UInt_t index=kr1.GetIndex(is);
3083         AliTPCseed *track=new(seed) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3084         
3085         track->SetIsSeeding(kTRUE);
3086         track->SetSeed1(i1);
3087         track->SetSeed2(i2);
3088         track->SetSeedType(3);
3089
3090        
3091         //if (dsec==0) {
3092           FollowProlongation(*track, (i1+i2)/2,1);
3093           Int_t foundable,found,shared;
3094           track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3095           if ((found<0.55*foundable)  || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3096             seed->Reset();
3097             seed->~AliTPCseed();
3098             continue;
3099           }
3100           //}
3101         
3102         nin++;
3103         FollowProlongation(*track, i2,1);
3104         
3105         
3106         //Int_t rc = 1;
3107         track->SetBConstrain(1);
3108         //      track->fLastPoint = i1+fInnerSec->GetNRows();  // first cluster in track position
3109         track->SetLastPoint(i1);  // first cluster in track position
3110         track->SetFirstPoint(track->GetLastPoint());
3111         
3112         if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
3113             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
3114             track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3115           seed->Reset();
3116           seed->~AliTPCseed();
3117           continue;
3118         }
3119         nout1++;
3120         // Z VERTEX CONDITION
3121         Double_t zv, bz=GetBz();
3122         if ( !track->GetZAt(0.,bz,zv) ) continue;
3123         if (TMath::Abs(zv-z3)>cuts[2]) {
3124           FollowProlongation(*track, TMath::Max(i2-20,0));
3125           if ( !track->GetZAt(0.,bz,zv) ) continue;
3126           if (TMath::Abs(zv-z3)>cuts[2]){
3127             FollowProlongation(*track, TMath::Max(i2-40,0));
3128             if ( !track->GetZAt(0.,bz,zv) ) continue;
3129             if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3130               // make seed without constrain
3131               AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3132               FollowProlongation(*track2, i2,1);
3133               track2->SetBConstrain(kFALSE);
3134               track2->SetSeedType(1);
3135               arr->AddLast(track2); 
3136               seed->Reset();
3137               seed->~AliTPCseed();
3138               continue;         
3139             }
3140             else{
3141               seed->Reset();
3142               seed->~AliTPCseed();
3143               continue;
3144             
3145             }
3146           }
3147         }
3148         
3149         track->SetSeedType(0);
3150         arr->AddLast(track); 
3151         seed = new AliTPCseed;  
3152         nout2++;
3153         // don't consider other combinations
3154         if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3155           break;
3156       }
3157     }
3158   }
3159   if (fDebug>3){
3160     Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3161   }
3162   delete seed;
3163 }
3164
3165
3166 void AliTPCtrackerMI::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
3167                                  Float_t deltay) {
3168   
3169
3170
3171   //-----------------------------------------------------------------
3172   // This function creates track seeds.
3173   //-----------------------------------------------------------------
3174   // cuts[0]   - fP4 cut
3175   // cuts[1]   - tan(phi)  cut
3176   // cuts[2]   - zvertex cut
3177   // cuts[3]   - fP3 cut
3178
3179
3180   Int_t nin0  = 0;
3181   Int_t nin1  = 0;
3182   Int_t nin2  = 0;
3183   Int_t nin   = 0;
3184   Int_t nout1 = 0;
3185   Int_t nout2 = 0;
3186   Int_t nout3 =0;
3187   Double_t x[5], c[15];
3188   //
3189   // make temporary seed
3190   AliTPCseed * seed = new AliTPCseed;
3191   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3192   //  Double_t cs=cos(alpha), sn=sin(alpha);
3193   //
3194   //
3195
3196   // first 3 padrows
3197   Double_t x1 = GetXrow(i1-1);
3198   const    AliTPCRow& kr1=GetRow(sec,i1-1);
3199   Double_t y1max  = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;  
3200   //
3201   Double_t x1p = GetXrow(i1);
3202   const    AliTPCRow& kr1p=GetRow(sec,i1);
3203   //
3204   Double_t x1m = GetXrow(i1-2);
3205   const    AliTPCRow& kr1m=GetRow(sec,i1-2);
3206
3207   //
3208   //last 3 padrow for seeding
3209   AliTPCRow&  kr3  = GetRow((sec+fkNOS)%fkNOS,i1-7);
3210   Double_t    x3   =  GetXrow(i1-7);
3211   //  Double_t    y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;  
3212   //
3213   AliTPCRow&  kr3p  = GetRow((sec+fkNOS)%fkNOS,i1-6);
3214   Double_t    x3p   = GetXrow(i1-6);
3215   //
3216   AliTPCRow&  kr3m  = GetRow((sec+fkNOS)%fkNOS,i1-8);
3217   Double_t    x3m   = GetXrow(i1-8);
3218
3219   //
3220   //
3221   // middle padrow
3222   Int_t im = i1-4;                           //middle pad row index
3223   Double_t xm         = GetXrow(im);         // radius of middle pad-row
3224   const AliTPCRow& krm=GetRow(sec,im);   //middle pad -row
3225   //  Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;  
3226   //
3227   //
3228   Double_t deltax  = x1-x3;
3229   Double_t dymax   = deltax*cuts[1];
3230   Double_t dzmax   = deltax*cuts[3];
3231   //
3232   // loop over clusters  
3233   for (Int_t is=0; is < kr1; is++) {
3234     //
3235     if (kr1[is]->IsUsed(10)) continue;
3236     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
3237     //
3238     if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge    
3239     // 
3240     Int_t  index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3241     Int_t  index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3242     //    
3243     Double_t y3,   z3;
3244     //
3245     //
3246     UInt_t index;
3247     for (Int_t js=index1; js < index2; js++) {
3248       const AliTPCclusterMI *kcl = kr3[js];
3249       if (kcl->IsUsed(10)) continue;
3250       y3 = kcl->GetY(); 
3251       // apply angular cuts
3252       if (TMath::Abs(y1-y3)>dymax) continue;
3253       x3 = x3; 
3254       z3 = kcl->GetZ(); 
3255       if (TMath::Abs(z1-z3)>dzmax) continue;
3256       //
3257       Double_t angley = (y1-y3)/(x1-x3);
3258       Double_t anglez = (z1-z3)/(x1-x3);
3259       //
3260       Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3261       Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3262       //
3263       Double_t yyym = angley*(xm-x1)+y1;
3264       Double_t zzzm = anglez*(xm-x1)+z1;
3265
3266       const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3267       if (!kcm) continue;
3268       if (kcm->IsUsed(10)) continue;
3269       
3270       erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3271       errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3272       //
3273       //
3274       //
3275       Int_t used  =0;
3276       Int_t found =0;
3277       //
3278       // look around first
3279       const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3280                                                       anglez*(x1m-x1)+z1,
3281                                                       erry,errz,index);
3282       //
3283       if (kc1m){
3284         found++;
3285         if (kc1m->IsUsed(10)) used++;
3286       }
3287       const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3288                                                       anglez*(x1p-x1)+z1,
3289                                                       erry,errz,index);
3290       //
3291       if (kc1p){
3292         found++;
3293         if (kc1p->IsUsed(10)) used++;
3294       }
3295       if (used>1)  continue;
3296       if (found<1) continue; 
3297
3298       //
3299       // look around last
3300       const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3301                                                       anglez*(x3m-x3)+z3,
3302                                                       erry,errz,index);
3303       //
3304       if (kc3m){
3305         found++;
3306         if (kc3m->IsUsed(10)) used++;
3307       }
3308       else 
3309         continue;
3310       const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3311                                                       anglez*(x3p-x3)+z3,
3312                                                       erry,errz,index);
3313       //
3314       if (kc3p){
3315         found++;
3316         if (kc3p->IsUsed(10)) used++;
3317       }
3318       else 
3319         continue;
3320       if (used>1)  continue;
3321       if (found<3) continue;       
3322       //
3323       Double_t x2,y2,z2;
3324       x2 = xm;
3325       y2 = kcm->GetY();
3326       z2 = kcm->GetZ();
3327       //
3328                         
3329       x[0]=y1;
3330       x[1]=z1;
3331       x[4]=F1(x1,y1,x2,y2,x3,y3);
3332       //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3333       nin0++;
3334       //
3335       x[2]=F2(x1,y1,x2,y2,x3,y3);
3336       nin1++;
3337       //
3338       x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3339       //if (TMath::Abs(x[3]) > cuts[3]) continue;
3340       nin2++;
3341       //
3342       //
3343       Double_t sy1=0.1,  sz1=0.1;
3344       Double_t sy2=0.1,  sz2=0.1;
3345       Double_t sy3=0.1,  sy=0.1, sz=0.1;
3346       
3347       Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3348       Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3349       Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3350       Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3351       Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3352       Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3353       
3354       Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3355       Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3356       Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3357       Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3358       
3359       c[0]=sy1;
3360       c[1]=0.;       c[2]=sz1; 
3361       c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3362       c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3363       c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3364       c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3365       c[13]=f30*sy1*f40+f32*sy2*f42;
3366       c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3367       
3368       //        if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3369       
3370       UInt_t index=kr1.GetIndex(is);
3371       AliTPCseed *track=new(seed) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3372       
3373       track->SetIsSeeding(kTRUE);
3374
3375       nin++;      
3376       FollowProlongation(*track, i1-7,1);
3377       if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 || 
3378           track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3379         seed->Reset();
3380         seed->~AliTPCseed();
3381         continue;
3382       }
3383       nout1++;
3384       nout2++;  
3385       //Int_t rc = 1;
3386       FollowProlongation(*track, i2,1);
3387       track->SetBConstrain(0);
3388       track->SetLastPoint(i1+fInnerSec->GetNRows());  // first cluster in track position
3389       track->SetFirstPoint(track->GetLastPoint());
3390       
3391       if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
3392           track->GetNumberOfClusters()<track->GetNFoundable()*0.7 || 
3393           track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3394         seed->Reset();
3395         seed->~AliTPCseed();
3396         continue;
3397       }
3398    
3399       {
3400         FollowProlongation(*track, TMath::Max(i2-10,0),1);
3401         AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3402         FollowProlongation(*track2, i2,1);
3403         track2->SetBConstrain(kFALSE);
3404         track2->SetSeedType(4);
3405         arr->AddLast(track2); 
3406         seed->Reset();
3407         seed->~AliTPCseed();
3408       }
3409       
3410    
3411       //arr->AddLast(track); 
3412       //seed = new AliTPCseed;  
3413       nout3++;
3414     }
3415   }
3416   
3417   if (fDebug>3){
3418     Info("MakeSeeds5","\nSeeding statiistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2,nout3);
3419   }
3420   delete seed;
3421 }
3422
3423
3424 //_____________________________________________________________________________
3425 void AliTPCtrackerMI::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3426                                  Float_t deltay, Bool_t /*bconstrain*/) {
3427   //-----------------------------------------------------------------
3428   // This function creates track seeds - without vertex constraint
3429   //-----------------------------------------------------------------
3430   // cuts[0]   - fP4 cut        - not applied
3431   // cuts[1]   - tan(phi)  cut
3432   // cuts[2]   - zvertex cut    - not applied 
3433   // cuts[3]   - fP3 cut
3434   Int_t nin0=0;
3435   Int_t nin1=0;
3436   Int_t nin2=0;
3437   Int_t nin3=0;
3438   //  Int_t nin4=0;
3439   //Int_t nin5=0;
3440
3441   
3442
3443   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3444   //  Double_t cs=cos(alpha), sn=sin(alpha);
3445   Int_t row0 = (i1+i2)/2;
3446   Int_t drow = (i1-i2)/2;
3447   const AliTPCRow& kr0=fSectors[sec][row0];
3448   AliTPCRow * kr=0;
3449
3450   AliTPCpolyTrack polytrack;
3451   Int_t nclusters=fSectors[sec][row0];
3452   AliTPCseed * seed = new AliTPCseed;
3453
3454   Int_t sumused=0;
3455   Int_t cused=0;
3456   Int_t cnused=0;
3457   for (Int_t is=0; is < nclusters; is++) {  //LOOP over clusters
3458     Int_t nfound =0;
3459     Int_t nfoundable =0;
3460     for (Int_t iter =1; iter<2; iter++){   //iterations
3461       const AliTPCRow& krm=fSectors[sec][row0-iter];
3462       const AliTPCRow& krp=fSectors[sec][row0+iter];      
3463       const AliTPCclusterMI * cl= kr0[is];
3464       
3465       if (cl->IsUsed(10)) {
3466         cused++;
3467       }
3468       else{
3469         cnused++;
3470       }
3471       Double_t x = kr0.GetX();
3472       // Initialization of the polytrack
3473       nfound =0;
3474       nfoundable =0;
3475       polytrack.Reset();
3476       //
3477       Double_t y0= cl->GetY();
3478       Double_t z0= cl->GetZ();
3479       Float_t erry = 0;
3480       Float_t errz = 0;
3481       
3482       Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3483       if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue;  // seed only at the edge
3484       
3485       erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;      
3486       errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;      
3487       polytrack.AddPoint(x,y0,z0,erry, errz);
3488
3489       sumused=0;
3490       if (cl->IsUsed(10)) sumused++;
3491
3492
3493       Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3494       Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3495       //
3496       x = krm.GetX();
3497       AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3498       if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3499         erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;          
3500         errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3501         if (cl1->IsUsed(10))  sumused++;
3502         polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3503       }
3504       //
3505       x = krp.GetX();
3506       AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3507       if (cl2) {
3508         erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;          
3509         errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3510         if (cl2->IsUsed(10)) sumused++;  
3511         polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3512       }
3513       //
3514       if (sumused>0) continue;
3515       nin0++;
3516       polytrack.UpdateParameters();
3517       // follow polytrack
3518       roadz = 1.2;
3519       roady = 1.2;
3520       //
3521       Double_t yn,zn;
3522       nfoundable = polytrack.GetN();
3523       nfound     = nfoundable; 
3524       //
3525       for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
3526         Float_t maxdist = 0.8*(1.+3./(ddrow));
3527         for (Int_t delta = -1;delta<=1;delta+=2){
3528           Int_t row = row0+ddrow*delta;
3529           kr = &(fSectors[sec][row]);
3530           Double_t xn = kr->GetX();
3531           Double_t ymax = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
3532           polytrack.GetFitPoint(xn,yn,zn);
3533           if (TMath::Abs(yn)>ymax) continue;
3534           nfoundable++;
3535           AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
3536           if (cln) {
3537             Float_t dist =  TMath::Sqrt(  (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
3538             if (dist<maxdist){
3539               /*
3540               erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));         
3541               errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3542               if (cln->IsUsed(10)) {
3543                 //      printf("used\n");
3544                 sumused++;
3545                 erry*=2;
3546                 errz*=2;
3547               }
3548               */
3549               erry=0.1;
3550               errz=0.1;
3551               polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
3552               nfound++;
3553             }
3554           }
3555         }
3556         if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable))  break;     
3557         polytrack.UpdateParameters();
3558       }           
3559     }
3560     if ( (sumused>3) || (sumused>0.5*nfound))  {
3561       //printf("sumused   %d\n",sumused);
3562       continue;
3563     }
3564     nin1++;
3565     Double_t dy,dz;
3566     polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
3567     AliTPCpolyTrack track2;
3568     
3569     polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
3570     if (track2.GetN()<0.5*nfoundable) continue;
3571     nin2++;
3572
3573     if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
3574       //
3575       // test seed with and without constrain
3576       for (Int_t constrain=0; constrain<=0;constrain++){
3577         // add polytrack candidate
3578
3579         Double_t x[5], c[15];
3580         Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
3581         track2.GetBoundaries(x3,x1);    
3582         x2 = (x1+x3)/2.;
3583         track2.GetFitPoint(x1,y1,z1);
3584         track2.GetFitPoint(x2,y2,z2);
3585         track2.GetFitPoint(x3,y3,z3);
3586         //
3587         //is track pointing to the vertex ?
3588         Double_t x0,y0,z0;
3589         x0=0;
3590         polytrack.GetFitPoint(x0,y0,z0);
3591
3592         if (constrain) {
3593           x2 = x3;
3594           y2 = y3;
3595           z2 = z3;
3596           
3597           x3 = 0;
3598           y3 = 0;
3599           z3 = 0;
3600         }
3601         x[0]=y1;
3602         x[1]=z1;
3603         x[4]=F1(x1,y1,x2,y2,x3,y3);
3604                 
3605         //      if (TMath::Abs(x[4]) >= cuts[0]) continue;  //
3606         x[2]=F2(x1,y1,x2,y2,x3,y3);
3607         
3608         //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
3609         //x[3]=F3(x1,y1,x2,y2,z1,z2);
3610         x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
3611         //if (TMath::Abs(x[3]) > cuts[3]) continue;
3612
3613         
3614         Double_t sy =0.1, sz =0.1;
3615         Double_t sy1=0.02, sz1=0.02;
3616         Double_t sy2=0.02, sz2=0.02;
3617         Double_t sy3=0.02;
3618
3619         if (constrain){
3620           sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3621         }
3622         
3623         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3624         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3625         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3626         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3627         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3628         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3629
3630         Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
3631         Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
3632         Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
3633         Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
3634
3635         
3636         c[0]=sy1;
3637         c[1]=0.;       c[2]=sz1;
3638         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3639         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3640         c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3641         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3642         c[13]=f30*sy1*f40+f32*sy2*f42;
3643         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3644         
3645         //Int_t row1 = fSectors->GetRowNumber(x1);
3646         Int_t row1 = GetRowNumber(x1);
3647
3648         UInt_t index=0;
3649         //kr0.GetIndex(is);
3650         AliTPCseed *track=new (seed) AliTPCseed(x1,sec*alpha+shift,x,c,index);
3651         track->SetIsSeeding(kTRUE);
3652         Int_t rc=FollowProlongation(*track, i2);        
3653         if (constrain) track->SetBConstrain(1);
3654         else
3655           track->SetBConstrain(0);
3656         track->SetLastPoint(row1+fInnerSec->GetNRows());  // first cluster in track position
3657         track->SetFirstPoint(track->GetLastPoint());
3658
3659         if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 || 
3660             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
3661             track->GetNShared()>0.4*track->GetNumberOfClusters()) {
3662           //delete track;
3663           seed->Reset();
3664           seed->~AliTPCseed();
3665         }
3666         else {
3667           arr->AddLast(track);
3668           seed = new AliTPCseed;
3669         }
3670         nin3++;
3671       }
3672     }  // if accepted seed
3673   }
3674   if (fDebug>3){
3675     Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
3676   }
3677   delete seed;
3678 }
3679
3680
3681 AliTPCseed *AliTPCtrackerMI::MakeSeed(AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
3682 {
3683   //
3684   //
3685   //reseed using track points
3686   Int_t p0 = int(r0*track->GetNumberOfClusters());     // point 0 
3687   Int_t p1 = int(r1*track->GetNumberOfClusters());
3688   Int_t p2 = int(r2*track->GetNumberOfClusters());   // last point
3689   Int_t pp2=0;
3690   Double_t  x0[3],x1[3],x2[3];
3691   for (Int_t i=0;i<3;i++){
3692     x0[i]=-1;
3693     x1[i]=-1;
3694     x2[i]=-1;
3695   }
3696
3697   // find track position at given ratio of the length
3698   Int_t  sec0=0, sec1=0, sec2=0;
3699   Int_t index=-1;
3700   Int_t clindex;
3701   for (Int_t i=0;i<160;i++){
3702     if (track->GetClusterPointer(i)){
3703       index++;
3704       AliTPCTrackerPoint   *trpoint =track->GetTrackPoint(i);
3705       if ( (index<p0) || x0[0]<0 ){
3706         if (trpoint->GetX()>1){
3707           clindex = track->GetClusterIndex2(i);
3708           if (clindex>0){       
3709             x0[0] = trpoint->GetX();
3710             x0[1] = trpoint->GetY();
3711             x0[2] = trpoint->GetZ();
3712             sec0  = ((clindex&0xff000000)>>24)%18;
3713           }
3714         }
3715       }
3716
3717       if ( (index<p1) &&(trpoint->GetX()>1)){
3718         clindex = track->GetClusterIndex2(i);
3719         if (clindex>0){
3720           x1[0] = trpoint->GetX();
3721           x1[1] = trpoint->GetY();
3722           x1[2] = trpoint->GetZ();
3723           sec1  = ((clindex&0xff000000)>>24)%18;
3724         }
3725       }
3726       if ( (index<p2) &&(trpoint->GetX()>1)){
3727         clindex = track->GetClusterIndex2(i);
3728         if (clindex>0){
3729           x2[0] = trpoint->GetX();
3730           x2[1] = trpoint->GetY();
3731           x2[2] = trpoint->GetZ(); 
3732           sec2  = ((clindex&0xff000000)>>24)%18;
3733           pp2 = i;
3734         }
3735       }
3736     }
3737   }
3738   
3739   Double_t alpha, cs,sn, xx2,yy2;
3740   //
3741   alpha = (sec1-sec2)*fSectors->GetAlpha();
3742   cs = TMath::Cos(alpha);
3743   sn = TMath::Sin(alpha); 
3744   xx2= x1[0]*cs-x1[1]*sn;
3745   yy2= x1[0]*sn+x1[1]*cs;
3746   x1[0] = xx2;
3747   x1[1] = yy2;
3748   //
3749   alpha = (sec0-sec2)*fSectors->GetAlpha();
3750   cs = TMath::Cos(alpha);
3751   sn = TMath::Sin(alpha); 
3752   xx2= x0[0]*cs-x0[1]*sn;
3753   yy2= x0[0]*sn+x0[1]*cs;
3754   x0[0] = xx2;
3755   x0[1] = yy2;
3756   //
3757   //
3758   //
3759   Double_t x[5],c[15];
3760   //
3761   x[0]=x2[1];
3762   x[1]=x2[2];
3763   x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
3764   //  if (x[4]>1) return 0;
3765   x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
3766   x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
3767   //if (TMath::Abs(x[3]) > 2.2)  return 0;
3768   //if (TMath::Abs(x[2]) > 1.99) return 0;
3769   //  
3770   Double_t sy =0.1,  sz =0.1;
3771   //
3772   Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
3773   Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
3774   Double_t sy3=0.01+track->GetSigmaY2();
3775   //
3776   Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
3777   Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
3778   Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
3779   Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
3780   Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
3781   Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
3782   //
3783   Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
3784   Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
3785   Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
3786   Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
3787   
3788   
3789   c[0]=sy1;
3790   c[1]=0.;       c[2]=sz1;
3791   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3792   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3793   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3794   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3795   c[13]=f30*sy1*f40+f32*sy2*f42;
3796   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3797   
3798   //  Int_t row1 = fSectors->GetRowNumber(x2[0]);
3799   AliTPCseed *seed=new  AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
3800   //  Double_t y0,z0,y1,z1, y2,z2;
3801   //seed->GetProlongation(x0[0],y0,z0);
3802   // seed->GetProlongation(x1[0],y1,z1);
3803   //seed->GetProlongation(x2[0],y2,z2);
3804   //  seed =0;
3805   seed->SetLastPoint(pp2);
3806   seed->SetFirstPoint(pp2);
3807   
3808
3809   return seed;
3810 }
3811
3812
3813 AliTPCseed *AliTPCtrackerMI::ReSeed(AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
3814 {
3815   //
3816   //
3817   //reseed using founded clusters 
3818   //
3819   // Find the number of clusters
3820   Int_t nclusters = 0;
3821   for (Int_t irow=0;irow<160;irow++){
3822     if (track->GetClusterIndex(irow)>0) nclusters++;
3823   }
3824   //
3825   Int_t ipos[3];
3826   ipos[0] = TMath::Max(int(r0*nclusters),0);             // point 0 cluster
3827   ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1);   // 
3828   ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1);   // last point
3829   //
3830   //
3831   Double_t  xyz[3][3];
3832   Int_t     row[3],sec[3]={0,0,0};
3833   //
3834   // find track row position at given ratio of the length
3835   Int_t index=-1;
3836   for (Int_t irow=0;irow<160;irow++){    
3837     if (track->GetClusterIndex2(irow)<0) continue;
3838     index++;
3839     for (Int_t ipoint=0;ipoint<3;ipoint++){
3840       if (index<=ipos[ipoint]) row[ipoint] = irow;
3841     }        
3842   }
3843   //
3844   //Get cluster and sector position
3845   for (Int_t ipoint=0;ipoint<3;ipoint++){
3846     Int_t clindex = track->GetClusterIndex2(row[ipoint]);
3847     AliTPCclusterMI * cl = GetClusterMI(clindex);
3848     if (cl==0) {
3849       //Error("Bug\n");
3850       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
3851       return 0;
3852     }
3853     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
3854     xyz[ipoint][0]  = GetXrow(row[ipoint]);
3855     xyz[ipoint][1]  = cl->GetY();
3856     xyz[ipoint][2]  = cl->GetZ();
3857   }
3858   //
3859   //
3860   // Calculate seed state vector and covariance matrix
3861
3862   Double_t alpha, cs,sn, xx2,yy2;
3863   //
3864   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
3865   cs = TMath::Cos(alpha);
3866   sn = TMath::Sin(alpha); 
3867   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
3868   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
3869   xyz[1][0] = xx2;
3870   xyz[1][1] = yy2;
3871   //
3872   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
3873   cs = TMath::Cos(alpha);
3874   sn = TMath::Sin(alpha); 
3875   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
3876   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
3877   xyz[0][0] = xx2;
3878   xyz[0][1] = yy2;
3879   //
3880   //
3881   //
3882   Double_t x[5],c[15];
3883   //
3884   x[0]=xyz[2][1];
3885   x[1]=xyz[2][2];
3886   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
3887   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
3888   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
3889   //  
3890   Double_t sy =0.1,  sz =0.1;
3891   //
3892   Double_t sy1=0.2, sz1=0.2;
3893   Double_t sy2=0.2, sz2=0.2;
3894   Double_t sy3=0.2;
3895   //
3896   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;
3897   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;
3898   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;
3899   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;
3900   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;
3901   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;
3902   //
3903   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;
3904   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;
3905   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;
3906   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;
3907   
3908   
3909   c[0]=sy1;
3910   c[1]=0.;       c[2]=sz1;
3911   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3912   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3913   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3914   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3915   c[13]=f30*sy1*f40+f32*sy2*f42;
3916   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3917   
3918   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
3919   AliTPCseed *seed=new  AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
3920   seed->SetLastPoint(row[2]);
3921   seed->SetFirstPoint(row[2]);  
3922   return seed;
3923 }
3924
3925
3926 AliTPCseed *AliTPCtrackerMI::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
3927 {
3928   //
3929   //
3930   //reseed using founded clusters 
3931   //
3932   Double_t  xyz[3][3];
3933   Int_t     row[3]={0,0,0};
3934   Int_t     sec[3]={0,0,0};
3935   //
3936   // forward direction
3937   if (forward){
3938     for (Int_t irow=r0;irow<160;irow++){
3939       if (track->GetClusterIndex(irow)>0){
3940         row[0] = irow;
3941         break;
3942       }
3943     }
3944     for (Int_t irow=160;irow>r0;irow--){
3945       if (track->GetClusterIndex(irow)>0){
3946         row[2] = irow;
3947         break;
3948       }
3949     }
3950     for (Int_t irow=row[2]-15;irow>row[0];irow--){
3951       if (track->GetClusterIndex(irow)>0){
3952         row[1] = irow;
3953         break;
3954       }
3955     }
3956     //
3957   }
3958   if (!forward){
3959     for (Int_t irow=0;irow<r0;irow++){
3960       if (track->GetClusterIndex(irow)>0){
3961         row[0] = irow;
3962         break;
3963       }
3964     }
3965     for (Int_t irow=r0;irow>0;irow--){
3966       if (track->GetClusterIndex(irow)>0){
3967         row[2] = irow;
3968         break;
3969       }
3970     }    
3971     for (Int_t irow=row[2]-15;irow>row[0];irow--){
3972       if (track->GetClusterIndex(irow)>0){
3973         row[1] = irow;
3974         break;
3975       }
3976     } 
3977   }
3978   //
3979   if ((row[2]-row[0])<20) return 0;
3980   if (row[1]==0) return 0;
3981   //
3982   //
3983   //Get cluster and sector position
3984   for (Int_t ipoint=0;ipoint<3;ipoint++){
3985     Int_t clindex = track->GetClusterIndex2(row[ipoint]);
3986     AliTPCclusterMI * cl = GetClusterMI(clindex);
3987     if (cl==0) {
3988       //Error("Bug\n");
3989       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
3990       return 0;
3991     }
3992     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
3993     xyz[ipoint][0]  = GetXrow(row[ipoint]);
3994     AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);    
3995     if (point&&ipoint<2){
3996       //
3997        xyz[ipoint][1]  = point->GetY();
3998        xyz[ipoint][2]  = point->GetZ();
3999     }
4000     else{
4001       xyz[ipoint][1]  = cl->GetY();
4002       xyz[ipoint][2]  = cl->GetZ();
4003     }
4004   }
4005   //
4006   //
4007   //
4008   //
4009   // Calculate seed state vector and covariance matrix
4010
4011   Double_t alpha, cs,sn, xx2,yy2;
4012   //
4013   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4014   cs = TMath::Cos(alpha);
4015   sn = TMath::Sin(alpha); 
4016   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4017   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4018   xyz[1][0] = xx2;
4019   xyz[1][1] = yy2;
4020   //
4021   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4022   cs = TMath::Cos(alpha);
4023   sn = TMath::Sin(alpha); 
4024   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4025   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4026   xyz[0][0] = xx2;
4027   xyz[0][1] = yy2;
4028   //
4029   //
4030   //
4031   Double_t x[5],c[15];
4032   //
4033   x[0]=xyz[2][1];
4034   x[1]=xyz[2][2];
4035   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4036   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4037   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4038   //  
4039   Double_t sy =0.1,  sz =0.1;
4040   //
4041   Double_t sy1=0.2, sz1=0.2;
4042   Double_t sy2=0.2, sz2=0.2;
4043   Double_t sy3=0.2;
4044   //
4045   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;
4046   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;
4047   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;
4048   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;
4049   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;
4050   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;
4051   //
4052   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;
4053   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;
4054   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;
4055   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;
4056   
4057   
4058   c[0]=sy1;
4059   c[1]=0.;       c[2]=sz1;
4060   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4061   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
4062   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4063   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4064   c[13]=f30*sy1*f40+f32*sy2*f42;
4065   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4066   
4067   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4068   AliTPCseed *seed=new  AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4069   seed->SetLastPoint(row[2]);
4070   seed->SetFirstPoint(row[2]);  
4071   for (Int_t i=row[0];i<row[2];i++){
4072     seed->SetClusterIndex(i, track->GetClusterIndex(i));
4073   }
4074
4075   return seed;
4076 }
4077
4078 void  AliTPCtrackerMI::FindKinks(TObjArray * array, AliESD *esd)
4079 {
4080   //
4081   //  find kinks
4082   //
4083   //
4084
4085   TObjArray *kinks= new TObjArray(10000);
4086   //  TObjArray *v0s= new TObjArray(10000);
4087   Int_t nentries = array->GetEntriesFast();
4088   AliHelix *helixes      = new AliHelix[nentries];
4089   Int_t    *sign         = new Int_t[nentries];
4090   Int_t    *nclusters    = new Int_t[nentries];
4091   Float_t  *alpha        = new Float_t[nentries];
4092   AliKink  *kink         = new AliKink();
4093   Int_t      * usage     = new Int_t[nentries];
4094   Float_t  *zm           = new Float_t[nentries];
4095   Float_t  *z0           = new Float_t[nentries]; 
4096   Float_t  *fim          = new Float_t[nentries];
4097   Float_t  *shared       = new Float_t[nentries];
4098   Bool_t   *circular     = new Bool_t[nentries];
4099   Float_t *dca          = new Float_t[nentries];
4100   //const AliESDVertex * primvertex = esd->GetVertex();
4101   //
4102   //  nentries = array->GetEntriesFast();
4103   //
4104   
4105   //
4106   //
4107   for (Int_t i=0;i<nentries;i++){
4108     sign[i]=0;
4109     usage[i]=0;
4110     AliTPCseed* track = (AliTPCseed*)array->At(i);    
4111     if (!track) continue;
4112     track->SetCircular(0);
4113     shared[i] = kFALSE;
4114     track->UpdatePoints();
4115     if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
4116     }
4117     nclusters[i]=track->GetNumberOfClusters();
4118     alpha[i] = track->GetAlpha();
4119     new (&helixes[i]) AliHelix(*track);
4120     Double_t xyz[3];
4121     helixes[i].Evaluate(0,xyz);
4122     sign[i] = (track->GetC()>0) ? -1:1;
4123     Double_t x,y,z;
4124     x=160;
4125     if (track->GetProlongation(x,y,z)){
4126       zm[i]  = z;
4127       fim[i] = alpha[i]+TMath::ATan2(y,x);
4128     }
4129     else{
4130       zm[i]  = track->GetZ();
4131       fim[i] = alpha[i];
4132     }   
4133     z0[i]=1000;
4134     circular[i]= kFALSE;
4135     if (track->GetProlongation(0,y,z))  z0[i] = z;
4136     dca[i] = track->GetD(0,0);    
4137   }
4138   //
4139   //
4140   TStopwatch timer;
4141   timer.Start();
4142   Int_t ncandidates =0;
4143   Int_t nall =0;
4144   Int_t ntracks=0; 
4145   Double_t phase[2][2],radius[2];
4146
4147   //
4148   // Find circling track
4149   TTreeSRedirector &cstream = *fDebugStreamer;
4150   //
4151   for (Int_t i0=0;i0<nentries;i0++){
4152     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4153     if (!track0) continue;    
4154     if (track0->GetNumberOfClusters()<40) continue;
4155     if (TMath::Abs(1./track0->GetC())>200) continue;
4156     for (Int_t i1=i0+1;i1<nentries;i1++){
4157       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4158       if (!track1) continue;
4159       if (track1->GetNumberOfClusters()<40)                  continue;
4160       if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
4161       if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
4162       if (TMath::Abs(1./track1->GetC())>200) continue;
4163       if (track1->Get1Pt()*track0->Get1Pt()>0)      continue;
4164       if (track1->GetTgl()*track0->GetTgl()>0)      continue;
4165       if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
4166       if (track0->GetBConstrain()&&TMath::Abs(track1->Get1Pt())<TMath::Abs(track0->Get1Pt())) continue; //returning - lower momenta
4167       if (track1->GetBConstrain()&&TMath::Abs(track0->Get1Pt())<TMath::Abs(track1->Get1Pt())) continue; //returning - lower momenta
4168       //
4169       Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
4170       if (mindcar<5)   continue;
4171       Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
4172       if (mindcaz<5) continue;
4173       if (mindcar+mindcaz<20) continue;
4174       //
4175       //
4176       Float_t xc0 = helixes[i0].GetHelix(6);
4177       Float_t yc0 = helixes[i0].GetHelix(7);
4178       Float_t r0  = helixes[i0].GetHelix(8);
4179       Float_t xc1 = helixes[i1].GetHelix(6);
4180       Float_t yc1 = helixes[i1].GetHelix(7);
4181       Float_t r1  = helixes[i1].GetHelix(8);
4182         
4183       Float_t rmean = (r0+r1)*0.5;
4184       Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
4185       //if (delta>30) continue;
4186       if (delta>rmean*0.25) continue;
4187       if (TMath::Abs(r0-r1)/rmean>0.3) continue; 
4188       //
4189       Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4190       if (npoints==0) continue;
4191       helixes[i0].GetClosestPhases(helixes[i1], phase);
4192       //
4193       Double_t xyz0[3];
4194       Double_t xyz1[3];
4195       Double_t hangles[3];
4196       helixes[i0].Evaluate(phase[0][0],xyz0);
4197       helixes[i1].Evaluate(phase[0][1],xyz1);
4198
4199       helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4200       Double_t deltah[2],deltabest;
4201       if (hangles[2]<2.8) continue;
4202       /*
4203       cstream<<"C"<<track0->fLab<<track1->fLab<<
4204         track0->fP3<<track1->fP3<<
4205         track0->fP4<<track1->fP4<<
4206         delta<<rmean<<npoints<<
4207         hangles[0]<<hangles[2]<<
4208         xyz0[2]<<xyz1[2]<<radius[0]<<"\n"; 
4209       */
4210       if (npoints>0){
4211         Int_t ibest=0;
4212         helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
4213         if (npoints==2){
4214           helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
4215           if (deltah[1]<deltah[0]) ibest=1;
4216         }
4217         deltabest  = TMath::Sqrt(deltah[ibest]);
4218         helixes[i0].Evaluate(phase[ibest][0],xyz0);
4219         helixes[i1].Evaluate(phase[ibest][1],xyz1);
4220         helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
4221         Double_t radiusbest = TMath::Sqrt(radius[ibest]);
4222         //
4223         if (deltabest>6) continue;
4224         if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
4225         Bool_t sign =kFALSE;
4226         if (hangles[2]>3.06) sign =kTRUE;
4227         //
4228         if (sign){
4229           circular[i0] = kTRUE;
4230           circular[i1] = kTRUE;
4231           if (TMath::Abs(track0->Get1Pt())<TMath::Abs(track1->Get1Pt())){
4232             track0->SetCircular(track0->GetCircular()+1);
4233             track1->SetCircular(track1->GetCircular()+2);
4234           }
4235           else{
4236             track1->SetCircular(track1->GetCircular()+1);
4237             track0->SetCircular(track0->GetCircular()+2);
4238           }
4239         }               
4240         if (sign&&AliTPCReconstructor::StreamLevel()>1){          
4241           //debug stream          
4242           Int_t lab0=track0->GetLabel();
4243           Int_t lab1=track1->GetLabel();
4244           cstream<<"Curling"<<
4245             "lab0="<<lab0<<
4246             "lab1="<<lab1<<   
4247             "Tr0.="<<track0<<
4248             "Tr1.="<<track1<<      
4249             "dca0="<<dca[i0]<<
4250             "dca1="<<dca[i1]<<
4251             "mindcar="<<mindcar<<
4252             "mindcaz="<<mindcaz<<
4253             "delta="<<delta<<
4254             "rmean="<<rmean<<
4255             "npoints="<<npoints<<                      
4256             "hangles0="<<hangles[0]<<
4257             "hangles2="<<hangles[2]<<                    
4258             "xyz0="<<xyz0[2]<<
4259             "xyzz1="<<xyz1[2]<<
4260             "z0="<<z0[i0]<<
4261             "z1="<<z0[i1]<<
4262             "radius="<<radiusbest<<
4263             "deltabest="<<deltabest<< 
4264             "phase0="<<phase[ibest][0]<<
4265             "phase1="<<phase[ibest][1]<<
4266             "\n";                 
4267         }
4268       }
4269     }
4270   }
4271   //
4272   //  Finf kinks loop
4273   // 
4274   //
4275   for (Int_t i =0;i<nentries;i++){
4276     if (sign[i]==0) continue;
4277     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4278     ntracks++;
4279     //
4280     Double_t cradius0 = 40*40;
4281     Double_t cradius1 = 270*270;
4282     Double_t cdist1=8.;
4283     Double_t cdist2=8.;
4284     Double_t cdist3=0.55; 
4285     for (Int_t j =i+1;j<nentries;j++){
4286       nall++;
4287       if (sign[j]*sign[i]<1) continue;
4288       if ( (nclusters[i]+nclusters[j])>200) continue;
4289       if ( (nclusters[i]+nclusters[j])<80) continue;
4290       if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
4291       if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
4292       //AliTPCseed * track1 = (AliTPCseed*)array->At(j);  Double_t phase[2][2],radius[2];    
4293       Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
4294       if (npoints<1) continue;
4295       // cuts on radius      
4296       if (npoints==1){
4297         if (radius[0]<cradius0||radius[0]>cradius1) continue;
4298       }
4299       else{
4300         if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
4301       }
4302       //      
4303       Double_t delta1=10000,delta2=10000;
4304       // cuts on the intersection radius
4305       helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
4306       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
4307       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
4308       if (npoints==2){ 
4309         helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
4310         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
4311         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
4312       }
4313       //
4314       Double_t distance1 = TMath::Min(delta1,delta2);
4315       if (distance1>cdist1) continue;  // cut on DCA linear approximation
4316       //
4317       npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
4318       helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
4319       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
4320       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
4321       //
4322       if (npoints==2){ 
4323         helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);   
4324         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
4325         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
4326       }            
4327       distance1 = TMath::Min(delta1,delta2);
4328       Float_t rkink =0;
4329       if (delta1<delta2){
4330         rkink = TMath::Sqrt(radius[0]);
4331       }
4332       else{
4333         rkink = TMath::Sqrt(radius[1]);
4334       }
4335       if (distance1>cdist2) continue;
4336       //
4337       //
4338       AliTPCseed * track1 = (AliTPCseed*)array->At(j);
4339       //
4340       //
4341       Int_t row0 = GetRowNumber(rkink); 
4342       if (row0<10)  continue;
4343       if (row0>150) continue;
4344       //
4345       //
4346       Float_t dens00=-1,dens01=-1;
4347       Float_t dens10=-1,dens11=-1;
4348       //
4349       Int_t found,foundable,shared;
4350       track0->GetClusterStatistic(0,row0-5, found, foundable,shared,kFALSE);
4351       if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
4352       track0->GetClusterStatistic(row0+5,155, found, foundable,shared,kFALSE);
4353       if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
4354       //
4355       track1->GetClusterStatistic(0,row0-5, found, foundable,shared,kFALSE);
4356       if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
4357       track1->GetClusterStatistic(row0+5,155, found, foundable,shared,kFALSE);
4358       if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
4359       //     
4360       if (dens00<dens10 && dens01<dens11) continue;
4361       if (dens00>dens10 && dens01>dens11) continue;
4362       if (TMath::Max(dens00,dens10)<0.1)  continue;
4363       if (TMath::Max(dens01,dens11)<0.3)  continue;
4364       //
4365       if (TMath::Min(dens00,dens10)>0.6)  continue;
4366       if (TMath::Min(dens01,dens11)>0.6)  continue;
4367
4368       //
4369       AliTPCseed * ktrack0, *ktrack1;
4370       if (dens00>dens10){
4371         ktrack0 = track0;
4372         ktrack1 = track1;
4373       }
4374       else{
4375         ktrack0 = track1;
4376         ktrack1 = track0;
4377       }
4378       if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
4379       AliExternalTrackParam paramm(*ktrack0);
4380       AliExternalTrackParam paramd(*ktrack1);
4381       if (row0>60&&ktrack1->GetReference().GetX()>90.) new (&paramd) AliExternalTrackParam(ktrack1->GetReference()); 
4382       //
4383       //
4384       kink->SetMother(paramm);
4385       kink->SetDaughter(paramd);
4386       kink->Update();
4387
4388       Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
4389       Int_t index[4];
4390       fParam->Transform0to1(x,index);
4391       fParam->Transform1to2(x,index);
4392       row0 = GetRowNumber(x[0]); 
4393
4394       if (kink->GetR()<100) continue;
4395       if (kink->GetR()>240) continue;
4396       if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue;  //out of fiducial volume
4397       if (kink->GetDistance()>cdist3) continue;
4398       Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1];  // rough direction estimate
4399       if (dird<0) continue;
4400
4401       Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1];  // rough direction estimate
4402       if (dirm<0) continue;
4403       Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
4404       if (mpt<0.2) continue;
4405
4406       if (mpt<1){
4407         //for high momenta momentum not defined well in first iteration
4408         Double_t qt   =  TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
4409         if (qt>0.35) continue; 
4410       }
4411       
4412       kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
4413       kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
4414       if (dens00>dens10){
4415         kink->SetTPCDensity(dens00,0,0);
4416         kink->SetTPCDensity(dens01,0,1);
4417         kink->SetTPCDensity(dens10,1,0);
4418         kink->SetTPCDensity(dens11,1,1);
4419         kink->SetIndex(i,0);
4420         kink->SetIndex(j,1);
4421       }
4422       else{
4423         kink->SetTPCDensity(dens10,0,0);
4424         kink->SetTPCDensity(dens11,0,1);
4425         kink->SetTPCDensity(dens00,1,0);
4426         kink->SetTPCDensity(dens01,1,1);
4427         kink->SetIndex(j,0);
4428         kink->SetIndex(i,1);
4429       }
4430
4431       if (mpt<1||kink->GetAngle(2)>0.1){
4432         //      angle and densities  not defined yet
4433         if (kink->GetTPCDensityFactor()<0.8) continue;
4434         if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
4435         if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
4436         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
4437         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
4438
4439         Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
4440         criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
4441         criticalangle= 3*TMath::Sqrt(criticalangle);
4442         if (criticalangle>0.02) criticalangle=0.02;
4443         if (kink->GetAngle(2)<criticalangle) continue;
4444       }
4445       //
4446       Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2)));  // overlap region defined
4447       Float_t shapesum =0;
4448       Float_t sum = 0;
4449       for ( Int_t row = row0-drow; row<row0+drow;row++){
4450         if (row<0) continue;
4451         if (row>155) continue;
4452         if (ktrack0->GetClusterPointer(row)){
4453           AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
4454           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
4455           sum++;
4456         }
4457         if (ktrack1->GetClusterPointer(row)){
4458           AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
4459           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
4460           sum++;
4461         }       
4462       }
4463       if (sum<4){
4464         kink->SetShapeFactor(-1.);
4465       }
4466       else{
4467         kink->SetShapeFactor(shapesum/sum);
4468       }      
4469       //      esd->AddKink(kink);
4470       kinks->AddLast(kink);
4471       kink = new AliKink;
4472       ncandidates++;
4473     }
4474   }
4475   //
4476   // sort the kinks according quality - and refit them towards vertex
4477   //
4478   Int_t       nkinks    = kinks->GetEntriesFast();
4479   Float_t    *quality   = new Float_t[nkinks];
4480   Int_t      *indexes   = new Int_t[nkinks];
4481   AliTPCseed *mothers   = new AliTPCseed[nkinks];
4482   AliTPCseed *daughters = new AliTPCseed[nkinks];
4483   //
4484   //
4485   for (Int_t i=0;i<nkinks;i++){
4486     quality[i] =100000;
4487     AliKink *kink = (AliKink*)kinks->At(i);
4488     //
4489     // refit kinks towards vertex
4490     // 
4491     Int_t index0 = kink->GetIndex(0);
4492     Int_t index1 = kink->GetIndex(1);
4493     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
4494     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
4495     //
4496     Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
4497     //
4498     // Refit Kink under if too small angle
4499     //
4500     if (kink->GetAngle(2)<0.05){
4501       kink->SetTPCRow0(GetRowNumber(kink->GetR()));
4502       Int_t row0 = kink->GetTPCRow0();
4503       Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2)));
4504       //
4505       //
4506       Int_t last  = row0-drow;
4507       if (last<40) last=40;
4508       if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
4509       AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
4510       //
4511       //
4512       Int_t first = row0+drow;
4513       if (first>130) first=130;
4514       if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
4515       AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
4516       //
4517       if (seed0 && seed1){
4518         kink->SetStatus(1,8);
4519         if (RefitKink(*seed0,*seed1,*kink)) kink->SetStatus(1,9);
4520         row0 = GetRowNumber(kink->GetR());
4521         sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
4522         new (&mothers[i])   AliTPCseed(*seed0);
4523         new (&daughters[i]) AliTPCseed(*seed1); 
4524       }
4525       else{
4526         delete kinks->RemoveAt(i);
4527         if (seed0) delete seed0;
4528         if (seed1) delete seed1;
4529         continue;
4530       }
4531       if (kink->GetDistance()>0.5 || kink->GetR()<110 || kink->GetR()>240) {
4532         delete kinks->RemoveAt(i);
4533         if (seed0) delete seed0;
4534         if (seed1) delete seed1;
4535         continue;
4536       }
4537       //
4538       delete seed0;
4539       delete seed1;            
4540     }
4541     //
4542     if (kink) quality[i] = 160*((0.1+kink->GetDistance())*(2.-kink->GetTPCDensityFactor()))/(sumn+40.);  //the longest -clossest will win
4543   }
4544   TMath::Sort(nkinks,quality,indexes,kFALSE);
4545   //
4546   //remove double find kinks
4547   //
4548   for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
4549     AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
4550     if (!kink0) continue;
4551     //
4552     for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
4553       if (!kink0) continue;
4554       AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
4555       if (!kink1) continue;
4556       // if not close kink continue
4557       if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
4558       if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
4559       if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
4560       //
4561       AliTPCseed &mother0   = mothers[indexes[ikink0]];
4562       AliTPCseed &daughter0 = daughters[indexes[ikink0]];
4563       AliTPCseed &mother1   = mothers[indexes[ikink1]];
4564       AliTPCseed &daughter1 = daughters[indexes[ikink1]];
4565       Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
4566       //
4567       Int_t same  = 0;
4568       Int_t both  = 0;
4569       Int_t samem = 0;
4570       Int_t bothm = 0;
4571       Int_t samed = 0;
4572       Int_t bothd = 0;
4573       //
4574       for (Int_t i=0;i<row0;i++){
4575         if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
4576           both++;
4577           bothm++;
4578           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
4579             same++;
4580             samem++;
4581           }
4582         }
4583       }
4584
4585       for (Int_t i=row0;i<158;i++){
4586         if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){
4587           both++;
4588           bothd++;
4589           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
4590             same++;
4591             samed++;
4592           }
4593         }
4594       }
4595       Float_t ratio = Float_t(same+1)/Float_t(both+1);
4596       Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
4597       Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
4598       if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
4599         Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
4600         Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
4601         if (sum1>sum0){
4602           shared[kink0->GetIndex(0)]= kTRUE;
4603           shared[kink0->GetIndex(1)]= kTRUE;      
4604           delete kinks->RemoveAt(indexes[ikink0]);
4605         }
4606         else{
4607           shared[kink1->GetIndex(0)]= kTRUE;
4608           shared[kink1->GetIndex(1)]= kTRUE;      
4609           delete kinks->RemoveAt(indexes[ikink1]);
4610         }
4611       }
4612     }
4613   }
4614
4615
4616   for (Int_t i=0;i<nkinks;i++){
4617     AliKink * kink = (AliKink*) kinks->At(indexes[i]);
4618     if (!kink) continue;
4619     kink->SetTPCRow0(GetRowNumber(kink->GetR()));
4620     Int_t index0 = kink->GetIndex(0);
4621     Int_t index1 = kink->GetIndex(1);
4622     if (circular[index0]||circular[index1]&&kink->GetDistance()>0.2) continue;
4623     kink->SetMultiple(usage[index0],0);
4624     kink->SetMultiple(usage[index1],1);
4625     if (kink->GetMultiple()[0]+kink->GetMultiple()[1]>2) continue;
4626     if (kink->GetMultiple()[0]+kink->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
4627     if (kink->GetMultiple()[0]+kink->GetMultiple()[1]>0 && kink->GetDistance()>0.2) continue;
4628     if (circular[index0]||circular[index1]&&kink->GetDistance()>0.1) continue;
4629
4630     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
4631     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
4632     if (!ktrack0 || !ktrack1) continue;
4633     Int_t index = esd->AddKink(kink);
4634     //
4635     //
4636     if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) {  //best kink
4637       if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
4638         new (ktrack0) AliTPCseed(mothers[indexes[i]]);
4639         new (ktrack1) AliTPCseed(daughters[indexes[i]]);
4640       }
4641     }
4642     //
4643     ktrack0->SetKinkIndex(usage[index0],-(index+1));
4644     ktrack1->SetKinkIndex(usage[index1], (index+1));
4645     usage[index0]++;
4646     usage[index1]++;
4647   }
4648   //
4649   // Remove tracks corresponding to shared kink's
4650   //
4651   for (Int_t i=0;i<nentries;i++){
4652     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4653     if (!track0) continue;
4654     if (track0->GetKinkIndex(0)!=0) continue;
4655     if (shared[i]) delete array->RemoveAt(i);
4656   }
4657
4658   //
4659   //
4660   RemoveUsed2(array,0.5,0.4,30);
4661   UnsignClusters();
4662   for (Int_t i=0;i<nentries;i++){
4663     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4664     if (!track0) continue;
4665     track0->CookdEdx(0.02,0.6);
4666     track0->CookPID();
4667   }
4668   //
4669   for (Int_t i=0;i<nentries;i++){
4670     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4671     if (!track0) continue;
4672     if (track0->GetPt()<1.4) continue;
4673     //remove double high momenta tracks - overlapped with kink candidates
4674     Int_t shared=0;
4675     Int_t all   =0;
4676     for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
4677       if (track0->GetClusterPointer(icl)!=0){
4678         all++;
4679         if (track0->GetClusterPointer(icl)->IsUsed(10)) shared++;
4680       }
4681     }
4682     if (Float_t(shared+1)/Float_t(nall+1)>0.5) {
4683       delete array->RemoveAt(i);
4684       continue;
4685     }
4686     //
4687     if (track0->GetKinkIndex(0)!=0) continue;
4688     if (track0->GetNumberOfClusters()<80) continue;
4689
4690     AliTPCseed *pmother = new AliTPCseed();
4691     AliTPCseed *pdaughter = new AliTPCseed();
4692     AliKink *pkink = new AliKink;
4693
4694     AliTPCseed & mother = *pmother;
4695     AliTPCseed & daughter = *pdaughter;
4696     AliKink & kink = *pkink;
4697     if (CheckKinkPoint(track0,mother,daughter, kink)){
4698       if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
4699         delete pmother;
4700         delete pdaughter;
4701         delete pkink;
4702         continue;  //too short tracks
4703       }
4704       if (mother.GetPt()<1.4) {
4705         delete pmother;
4706         delete pdaughter;
4707         delete pkink;
4708         continue;
4709       }
4710       Int_t row0= kink.GetTPCRow0();
4711       if (kink.GetDistance()>0.5 || kink.GetR()<110. || kink.GetR()>240.) {
4712         delete pmother;
4713         delete pdaughter;
4714         delete pkink;
4715         continue;
4716       }
4717       //
4718       Int_t index = esd->AddKink(&kink);      
4719       mother.SetKinkIndex(0,-(index+1));
4720       daughter.SetKinkIndex(0,index+1);
4721       if (mother.GetNumberOfClusters()>50) {
4722         delete array->RemoveAt(i);
4723         array->AddAt(new AliTPCseed(mother),i);
4724       }
4725       else{
4726         array->AddLast(new AliTPCseed(mother));
4727       }
4728       array->AddLast(new AliTPCseed(daughter));      
4729       for (Int_t icl=0;icl<row0;icl++) {
4730         if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
4731       }
4732       //
4733       for (Int_t icl=row0;icl<158;icl++) {
4734         if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
4735       }
4736       //
4737     }
4738     delete pmother;
4739     delete pdaughter;
4740     delete pkink;
4741   }
4742
4743   delete [] daughters;
4744   delete [] mothers;
4745   //
4746   //
4747   delete [] dca;
4748   delete []circular;
4749   delete []shared;
4750   delete []quality;
4751   delete []indexes;
4752   //
4753   delete kink;
4754   delete[]fim;
4755   delete[] zm;
4756   delete[] z0;
4757   delete [] usage;
4758   delete[] alpha;
4759   delete[] nclusters;
4760   delete[] sign;
4761   delete[] helixes;
4762   kinks->Delete();
4763   delete kinks;
4764
4765   printf("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall);
4766   timer.Print();
4767 }
4768
4769 void  AliTPCtrackerMI::FindV0s(TObjArray * array, AliESD *esd)
4770 {
4771   //
4772   //  find V0s
4773   //
4774   //
4775   TObjArray *tpcv0s      = new TObjArray(100000);
4776   Int_t     nentries     = array->GetEntriesFast();
4777   AliHelix *helixes      = new AliHelix[nentries];
4778   Int_t    *sign         = new Int_t[nentries];
4779   Float_t  *alpha        = new Float_t[nentries];
4780   Float_t  *z0           = new Float_t[nentries]; 
4781   Float_t  *dca          = new Float_t[nentries];
4782   Float_t  *sdcar        = new Float_t[nentries];
4783   Float_t  *cdcar        = new Float_t[nentries];
4784   Float_t  *pulldcar     = new Float_t[nentries];
4785   Float_t  *pulldcaz     = new Float_t[nentries];
4786   Float_t  *pulldca      = new Float_t[nentries];
4787   Bool_t   *isPrim       = new Bool_t[nentries];  
4788   const AliESDVertex * primvertex = esd->GetVertex();
4789   Double_t             zvertex = primvertex->GetZv(); 
4790   //
4791   //  nentries = array->GetEntriesFast();
4792   //
4793   for (Int_t i=0;i<nentries;i++){
4794     sign[i]=0;
4795     isPrim[i]=0;
4796     AliTPCseed* track = (AliTPCseed*)array->At(i);    
4797     if (!track) continue;
4798     track->GetV0Indexes()[0] = 0;  //rest v0 indexes
4799     track->GetV0Indexes()[1] = 0;  //rest v0 indexes
4800     track->GetV0Indexes()[2] = 0;  //rest v0 indexes
4801     //
4802     alpha[i] = track->GetAlpha();
4803     new (&helixes[i]) AliHelix(*track);
4804     Double_t xyz[3];
4805     helixes[i].Evaluate(0,xyz);
4806     sign[i] = (track->GetC()>0) ? -1:1;
4807     Double_t x,y,z;
4808     x=160;
4809     z0[i]=1000;
4810     if (track->GetProlongation(0,y,z))  z0[i] = z;
4811     dca[i] = track->GetD(0,0);
4812     // 
4813     // dca error parrameterezation + pulls
4814     //
4815     sdcar[i]      = TMath::Sqrt(0.150*0.150+(100*track->GetC())*(100*track->GetC()));
4816     if (TMath::Abs(track->GetTgl())>1) sdcar[i]*=2.5;
4817     cdcar[i]      = TMath::Exp((TMath::Abs(track->GetC())-0.0106)*525.3);
4818     pulldcar[i]   = (dca[i]-cdcar[i])/sdcar[i];
4819     pulldcaz[i]   = (z0[i]-zvertex)/sdcar[i];
4820     pulldca[i]    = TMath::Sqrt(pulldcar[i]*pulldcar[i]+pulldcaz[i]*pulldcaz[i]);
4821     if (track->TPCrPID(1)+track->TPCrPID(2)+track->TPCrPID(3)>0.5) {
4822       if (pulldca[i]<3.) isPrim[i]=kTRUE;  //pion, muon and Kaon  3 sigma cut
4823     }
4824     if (track->TPCrPID(4)>0.5) {
4825       if (pulldca[i]<0.5) isPrim[i]=kTRUE;  //proton 0.5 sigma cut
4826     }
4827     if (track->TPCrPID(0)>0.4) {
4828       isPrim[i]=kFALSE;  //electron no  sigma cut
4829     }
4830   }
4831   //
4832   //
4833   TStopwatch timer;
4834   timer.Start();
4835   Int_t ncandidates =0;
4836   Int_t nall =0;
4837   Int_t ntracks=0; 
4838   Double_t phase[2][2],radius[2];
4839   //
4840   //  Finf V0s loop
4841   // 
4842   //
4843   // //  
4844   TTreeSRedirector &cstream = *fDebugStreamer; 
4845   Float_t fprimvertex[3]={GetX(),GetY(),GetZ()};
4846   AliV0 vertex; 
4847   Double_t cradius0 = 10*10;
4848   Double_t cradius1 = 200*200;
4849   Double_t cdist1=3.;
4850   Double_t cdist2=4.;
4851   Double_t cpointAngle = 0.95;
4852   //
4853   Double_t delta[2]={10000,10000};
4854   for (Int_t i =0;i<nentries;i++){
4855     if (sign[i]==0) continue;
4856     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4857     if (!track0) continue;
4858     if (AliTPCReconstructor::StreamLevel()>0){
4859       cstream<<"Tracks"<<
4860         "Tr0.="<<track0<<
4861         "dca="<<dca[i]<<
4862         "z0="<<z0[i]<<
4863         "zvertex="<<zvertex<<
4864         "sdcar0="<<sdcar[i]<<
4865         "cdcar0="<<cdcar[i]<<
4866         "pulldcar0="<<pulldcar[i]<<
4867         "pulldcaz0="<<pulldcaz[i]<<
4868         "pulldca0="<<pulldca[i]<<
4869         "isPrim="<<isPrim[i]<<
4870         "\n";
4871     }
4872     //
4873     if (track0->Get1Pt()<0) continue;
4874     if (track0->GetKinkIndex(0)>0||isPrim[i]) continue;   //daughter kink
4875     //
4876     if (TMath::Abs(helixes[i].GetHelix(4))<0.000000001) continue;
4877     ntracks++;
4878     // debug output
4879     
4880     
4881     for (Int_t j =0;j<nentries;j++){
4882       AliTPCseed * track1 = (AliTPCseed*)array->At(j);
4883       if (!track1) continue;
4884       if (track1->GetKinkIndex(0)>0 || isPrim[j]) continue; //daughter kink
4885       if (sign[j]*sign[i]>0) continue; 
4886       if (TMath::Abs(helixes[j].GetHelix(4))<0.000001) continue;
4887       if (track0->GetCircular()+track1->GetCircular()>1) continue;    //circling -returning track
4888       nall++;
4889       //
4890       // DCA to prim vertex cut
4891       //
4892       //
4893       delta[0]=10000;
4894       delta[1]=10000;
4895
4896       Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,cdist2);
4897       if (npoints<1) continue;
4898       Int_t iclosest=0;
4899       // cuts on radius      
4900       if (npoints==1){
4901         if (radius[0]<cradius0||radius[0]>cradius1) continue;
4902         helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta[0]);
4903         if (delta[0]>cdist1) continue;
4904       }
4905       else{
4906         if (TMath::Max(radius[0],radius[1])<cradius0|| TMath::Min(radius[0],radius[1])>cradius1) continue;      
4907         helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta[0]);    
4908         helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta[1]);
4909         if (delta[1]<delta[0]) iclosest=1;
4910         if (delta[iclosest]>cdist1) continue;
4911       }
4912       helixes[i].ParabolicDCA(helixes[j],phase[iclosest][0],phase[iclosest][1],radius[iclosest],delta[iclosest]);
4913       if (radius[iclosest]<cradius0 || radius[iclosest]>cradius1 || delta[iclosest]>cdist1) continue;
4914       //
4915       Double_t pointAngle = helixes[i].GetPointAngle(helixes[j],phase[iclosest],fprimvertex);
4916       if (pointAngle<cpointAngle) continue;
4917       //
4918       Bool_t isGamma = kFALSE;
4919       vertex.SetParamP(*track0); //track0 - plus
4920       vertex.SetParamN(*track1); //track1 - minus
4921       vertex.Update(fprimvertex);
4922       if (track0->TPCrPID(0)>0.3&&track1->TPCrPID(0)>0.3&&vertex.GetAnglep()[2]<0.15) isGamma=kTRUE;              // gamma conversion candidate
4923       Double_t pointAngle2 = vertex.GetV0CosineOfPointingAngle();
4924       //continue;
4925       if (vertex.GetV0CosineOfPointingAngle()<cpointAngle && (!isGamma)) continue;// point angle cut
4926       //Bo:      if (vertex.GetDist2()>2&&(!isGamma)) continue;      // point angle cut
4927       if (vertex.GetDcaV0Daughters()>2&&(!isGamma)) continue;//Bo:   // point angle cut
4928       Float_t sigmae     = 0.15*0.15;
4929       if (vertex.GetRr()<80) 
4930         sigmae += (sdcar[i]*sdcar[i]+sdcar[j]*sdcar[j])*(1.-vertex.GetRr()/80.)*(1.-vertex.GetRr()/80.);
4931       sigmae+= TMath::Sqrt(sigmae);
4932       //Bo:      if (vertex.GetDist2()/sigmae>3.&&(!isGamma)) continue; 
4933       if (vertex.GetDcaV0Daughters()/sigmae>3.&&(!isGamma)) continue; 
4934       Float_t densb0=0,densb1=0,densa0=0,densa1=0;
4935       Int_t row0 = GetRowNumber(vertex.GetRr());
4936       if (row0>15){
4937         //Bo:   if (vertex.GetDist2()>0.2) continue;             
4938         if (vertex.GetDcaV0Daughters()>0.2) continue;             
4939         densb0     = track0->Density2(0,row0-5);          
4940         densb1     = track1->Density2(0,row0-5);         
4941         if (densb0>0.3|| densb1>0.3) continue;            //clusters before vertex
4942         densa0     = track0->Density2(row0+5,row0+40);    
4943         densa1     = track1->Density2(row0+5,row0+40);    
4944         if ((densa0<0.4|| densa1<0.4)&&(!isGamma)) continue;            //missing clusters after vertex
4945       }
4946       else{
4947         densa0     = track0->Density2(0,40);  //cluster density
4948         densa1     = track1->Density2(0,40);  //cluster density
4949         if ((vertex.GetRr()<80&&densa0+densa1<1.)&&(!isGamma)) continue;
4950       }
4951 //Bo:        vertex.SetLab(0,track0->GetLabel());
4952 //Bo:        vertex.SetLab(1,track1->GetLabel());
4953       vertex.SetChi2After((densa0+densa1)*0.5);
4954       vertex.SetChi2Before((densb0+densb1)*0.5);
4955       vertex.SetIndex(0,i);
4956       vertex.SetIndex(1,j);
4957 //Bo:      vertex.SetStatus(1); // TPC v0 candidate
4958       vertex.SetOnFlyStatus(2);//Bo: // TPC v0 candidate
4959 //Bo:        vertex.SetRp(track0->TPCrPIDs());
4960 //Bo:        vertex.SetRm(track1->TPCrPIDs());
4961       tpcv0s->AddLast(new AliESDv0(vertex));      
4962       ncandidates++;
4963       {
4964         Int_t eventNr = esd->GetEventNumberInFile(); // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
4965         Double_t radiusm= (delta[0]<delta[1])? TMath::Sqrt(radius[0]):TMath::Sqrt(radius[1]);  
4966         Double_t deltam= (delta[0]<delta[1])? TMath::Sqrt(delta[0]):TMath::Sqrt(delta[1]);  
4967         if (AliTPCReconstructor::StreamLevel()>0) {
4968           Int_t lab0=track0->GetLabel();
4969           Int_t lab1=track1->GetLabel();
4970           Char_t c0=track0->GetCircular();
4971           Char_t c1=track1->GetCircular();
4972           cstream<<"V0"<<
4973           "Event="<<eventNr<<
4974           "vertex.="<<&vertex<<
4975           "Tr0.="<<track0<<
4976           "lab0="<<lab0<<
4977           "Helix0.="<<&helixes[i]<<     
4978           "Tr1.="<<track1<<
4979           "lab1="<<lab1<<
4980           "Helix1.="<<&helixes[j]<<
4981           "pointAngle="<<pointAngle<<
4982           "pointAngle2="<<pointAngle2<<
4983           "dca0="<<dca[i]<<
4984           "dca1="<<dca[j]<<
4985           "z0="<<z0[i]<<
4986           "z1="<<z0[j]<<
4987           "zvertex="<<zvertex<<
4988           "circular0="<<c0<<
4989           "circular1="<<c1<<
4990           "npoints="<<npoints<<
4991           "radius0="<<radius[0]<<
4992           "delta0="<<delta[0]<<
4993           "radius1="<<radius[1]<<
4994           "delta1="<<delta[1]<<
4995           "radiusm="<<radiusm<<
4996           "deltam="<<deltam<<
4997           "sdcar0="<<sdcar[i]<<
4998           "sdcar1="<<sdcar[j]<<
4999           "cdcar0="<<cdcar[i]<<
5000           "cdcar1="<<cdcar[j]<<
5001           "pulldcar0="<<pulldcar[i]<<
5002           "pulldcar1="<<pulldcar[j]<<
5003           "pulldcaz0="<<pulldcaz[i]<<
5004           "pulldcaz1="<<pulldcaz[j]<<
5005           "pulldca0="<<pulldca[i]<<
5006           "pulldca1="<<pulldca[j]<<
5007           "densb0="<<densb0<<
5008           "densb1="<<densb1<<
5009           "densa0="<<densa0<<
5010           "densa1="<<densa1<<
5011           "sigmae="<<sigmae<<
5012             "\n";}
5013       }
5014     }
5015   }    
5016   Float_t *quality = new Float_t[ncandidates];
5017   Int_t *indexes = new Int_t[ncandidates];
5018   Int_t naccepted =0;
5019   for (Int_t i=0;i<ncandidates;i++){
5020     quality[i]     = 0; 
5021     AliESDv0 *v0 = (AliESDv0*)tpcv0s->At(i);
5022     quality[i]     = 1./(1.00001-v0->GetV0CosineOfPointingAngle());   //base point angle
5023     // quality[i]    /= (0.5+v0->GetDist2());  
5024     // quality[i]    *= v0->GetChi2After();               //density factor
5025
5026     Int_t index0 = v0->GetIndex(0);
5027     Int_t index1 = v0->GetIndex(1);
5028     //Bo:    Double_t minpulldca = TMath::Min(2.+pulldca[v0->GetIndex(0)],(2.+pulldca[v0->GetIndex(1)]) );     //pull
5029     Double_t minpulldca = TMath::Min(2.+pulldca[index0],(2.+pulldca[index1]) );//Bo:
5030
5031
5032
5033     AliTPCseed * track0 = (AliTPCseed*)array->At(index0);
5034     AliTPCseed * track1 = (AliTPCseed*)array->At(index1);
5035     if (track0->TPCrPID(0)>0.3&&track1->TPCrPID(0)>0.3&&v0->GetAnglep()[2]<0.15) quality[i]+=1000000;              // gamma conversion candidate
5036     if (track0->TPCrPID(4)>0.9||track1->TPCrPID(4)>0.9&&minpulldca>4) quality[i]*=10;    // lambda candidate candidate
5037   }
5038
5039   TMath::Sort(ncandidates,quality,indexes,kTRUE);
5040   //
5041   //
5042   for (Int_t i=0;i<ncandidates;i++){
5043     AliESDv0 * v0 = (AliESDv0*)tpcv0s->At(indexes[i]);
5044     if (!v0) continue;
5045     Int_t index0 = v0->GetIndex(0);
5046     Int_t index1 = v0->GetIndex(1);
5047     AliTPCseed * track0 = (AliTPCseed*)array->At(index0);
5048     AliTPCseed * track1 = (AliTPCseed*)array->At(index1);
5049     if (!track0||!track1) {
5050       printf("Bug\n");
5051       continue;
5052     }
5053     Bool_t accept =kTRUE;  //default accept
5054     Int_t *v0indexes0 = track0->GetV0Indexes();
5055     Int_t *v0indexes1 = track1->GetV0Indexes();
5056     //
5057     Int_t order0 = (v0indexes0[0]!=0) ? 1:0;
5058     Int_t order1 = (v0indexes1[0]!=0) ? 1:0;    
5059     if (v0indexes0[1]!=0) order0 =2;
5060     if (v0indexes1[1]!=0) order1 =2;      
5061     //
5062     if (v0indexes0[2]!=0) {order0=3; accept=kFALSE;}
5063     if (v0indexes0[2]!=0) {order1=3; accept=kFALSE;}
5064     //
5065     AliESDv0 * v02 = v0;
5066     if (accept){
5067       //Bo:      v0->SetOrder(0,order0);
5068       //Bo:      v0->SetOrder(1,order1);
5069       //Bo:      v0->SetOrder(1,order0+order1);     
5070       v0->SetOnFlyStatus(kTRUE);
5071       Int_t index = esd->AddV0(v0);
5072       v02 = esd->GetV0(index);
5073       v0indexes0[order0]=index;
5074       v0indexes1[order1]=index;
5075       naccepted++;
5076     }
5077     {
5078       Int_t eventNr = esd->GetEventNumberInFile(); // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
5079       if (AliTPCReconstructor::StreamLevel()>0) {
5080         Int_t lab0=track0->GetLabel();
5081         Int_t lab1=track1->GetLabel();
5082         cstream<<"V02"<<
5083         "Event="<<eventNr<<
5084         "vertex.="<<v0<<        
5085         "vertex2.="<<v02<<
5086         "Tr0.="<<track0<<
5087         "lab0="<<lab0<<
5088         "Tr1.="<<track1<<
5089         "lab1="<<lab1<<
5090         "dca0="<<dca[index0]<<
5091         "dca1="<<dca[index1]<<
5092         "order0="<<order0<<
5093         "order1="<<order1<<
5094         "accept="<<accept<<
5095         "quality="<<quality[i]<<
5096         "pulldca0="<<pulldca[index0]<<
5097         "pulldca1="<<pulldca[index1]<<
5098         "index="<<i<<
5099           "\n";}
5100     }
5101   }    
5102
5103
5104   //
5105   //
5106   delete []quality;
5107   delete []indexes;
5108 //
5109   delete [] isPrim;
5110   delete [] pulldca;
5111   delete [] pulldcaz;
5112   delete [] pulldcar;
5113   delete [] cdcar;
5114   delete [] sdcar;
5115   delete [] dca;
5116   //
5117   delete[] z0;
5118   delete[] alpha;
5119   delete[] sign;
5120   delete[] helixes;
5121   printf("TPC V0 finder : naccepted\t%d\tncandidates\t%d\tntracks\t%d\tnall\t%d\n",naccepted,ncandidates,ntracks,nall);
5122   timer.Print();
5123 }
5124
5125 Int_t AliTPCtrackerMI::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, AliESDkink &knk)
5126 {
5127   //
5128   // refit kink towards to the vertex
5129   //
5130   //
5131   AliKink &kink=(AliKink &)knk;
5132
5133   Int_t row0 = GetRowNumber(kink.GetR());
5134   FollowProlongation(mother,0);
5135   mother.Reset(kFALSE);
5136   //
5137   FollowProlongation(daughter,row0);
5138   daughter.Reset(kFALSE);
5139   FollowBackProlongation(daughter,158);
5140   daughter.Reset(kFALSE);
5141   Int_t first = TMath::Max(row0-20,30); 
5142   Int_t last  = TMath::Min(row0+20,140);
5143   //
5144   const Int_t kNdiv =5;
5145   AliTPCseed  param0[kNdiv];  // parameters along the track
5146   AliTPCseed  param1[kNdiv];  // parameters along the track
5147   AliKink     kinks[kNdiv];   // corresponding kink parameters
5148   //
5149   Int_t rows[kNdiv];
5150   for (Int_t irow=0; irow<kNdiv;irow++){
5151     rows[irow] = first +((last-first)*irow)/(kNdiv-1);
5152   }
5153   // store parameters along the track
5154   //
5155   for (Int_t irow=0;irow<kNdiv;irow++){
5156     FollowBackProlongation(mother, rows[irow]);
5157     FollowProlongation(daughter,rows[kNdiv-1-irow]);       
5158     new(&param0[irow])     AliTPCseed(mother);
5159     new(&param1[kNdiv-1-irow])   AliTPCseed(daughter);
5160   }
5161   //
5162   // define kinks 
5163   for (Int_t irow=0; irow<kNdiv-1;irow++){
5164     if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
5165     kinks[irow].SetMother(param0[irow]);
5166     kinks[irow].SetDaughter(param1[irow]);
5167     kinks[irow].Update();
5168   }
5169   //
5170   // choose kink with best "quality"
5171   Int_t index =-1;
5172   Double_t mindist = 10000;
5173   for (Int_t irow=0;irow<kNdiv;irow++){
5174     if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
5175     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
5176     if (TMath::Abs(kinks[irow].GetR())<100.) continue;
5177     //
5178     Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
5179     normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
5180     if (normdist < mindist){
5181       mindist = normdist;
5182       index = irow;
5183     }
5184   }
5185   //
5186   if (index==-1) return 0;
5187   //
5188   //
5189   param0[index].Reset(kTRUE);
5190   FollowProlongation(param0[index],0);
5191   //
5192   new (&mother) AliTPCseed(param0[index]);
5193   new (&daughter) AliTPCseed(param1[index]);  // daughter in vertex
5194   //
5195   kink.SetMother(mother);
5196   kink.SetDaughter(daughter);
5197   kink.Update();
5198   kink.SetTPCRow0(GetRowNumber(kink.GetR()));
5199   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
5200   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
5201   kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
5202   kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
5203   mother.SetLabel(kink.GetLabel(0));
5204   daughter.SetLabel(kink.GetLabel(1));
5205
5206   return 1;
5207 }
5208
5209
5210 void AliTPCtrackerMI::UpdateKinkQualityM(AliTPCseed * seed){
5211   //
5212   // update Kink quality information for mother after back propagation
5213   //
5214   if (seed->GetKinkIndex(0)>=0) return; 
5215   for (Int_t ikink=0;ikink<3;ikink++){
5216     Int_t index = seed->GetKinkIndex(ikink);
5217     if (index>=0) break;
5218     index = TMath::Abs(index)-1;
5219     AliESDkink * kink = fEvent->GetKink(index);
5220     //kink->fTPCdensity2[0][0]=-1;
5221     //kink->fTPCdensity2[0][1]=-1;
5222     kink->SetTPCDensity2(-1,0,0);
5223     kink->SetTPCDensity2(1,0,1);
5224     //
5225     Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5226     if (row0<15) row0=15;
5227     //
5228     Int_t row1 = kink->GetTPCRow0() + 2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5229     if (row1>145) row1=145;
5230     //
5231     Int_t found,foundable,shared;
5232     seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
5233     if (foundable>5)   kink->SetTPCDensity2(Float_t(found)/Float_t(foundable),0,0);
5234     seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
5235     if (foundable>5)   kink->SetTPCDensity2(Float_t(found)/Float_t(foundable),0,1);
5236   }
5237     
5238 }
5239
5240 void AliTPCtrackerMI::UpdateKinkQualityD(AliTPCseed * seed){
5241   //
5242   // update Kink quality information for daughter after refit
5243   //
5244   if (seed->GetKinkIndex(0)<=0) return; 
5245   for (Int_t ikink=0;ikink<3;ikink++){
5246     Int_t index = seed->GetKinkIndex(ikink);
5247     if (index<=0) break;
5248     index = TMath::Abs(index)-1;
5249     AliESDkink * kink = fEvent->GetKink(index);
5250     kink->SetTPCDensity2(-1,1,0);
5251     kink->SetTPCDensity2(-1,1,1);
5252     //
5253     Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5254     if (row0<15) row0=15;
5255     //
5256     Int_t row1 = kink->GetTPCRow0() +2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5257     if (row1>145) row1=145;
5258     //
5259     Int_t found,foundable,shared;
5260     seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
5261     if (foundable>5)   kink->SetTPCDensity2(Float_t(found)/Float_t(foundable),1,0);
5262     seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
5263     if (foundable>5)   kink->SetTPCDensity2(Float_t(found)/Float_t(foundable),1,1);
5264   }
5265     
5266 }
5267
5268
5269 Int_t  AliTPCtrackerMI::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, AliESDkink &knk)
5270 {
5271   //
5272   // check kink point for given track
5273   // if return value=0 kink point not found
5274   // otherwise seed0 correspond to mother particle
5275   //           seed1 correspond to daughter particle
5276   //           kink  parameter of kink point
5277   AliKink &kink=(AliKink &)knk;
5278
5279   Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
5280   Int_t first = seed->GetFirstPoint(); 
5281   Int_t last  = seed->GetLastPoint();
5282   if (last-first<20) return 0;          // shortest length - 2*30 = 60 pad-rows
5283
5284   
5285   AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE);  //middle of chamber
5286   if (!seed1) return 0;
5287   FollowProlongation(*seed1,seed->GetLastPoint()-20);
5288   seed1->Reset(kTRUE);
5289   FollowProlongation(*seed1,158);
5290   seed1->Reset(kTRUE);  
5291   last = seed1->GetLastPoint();
5292   //
5293   AliTPCseed *seed0 = new AliTPCseed(*seed);
5294   seed0->Reset(kFALSE);
5295   seed0->Reset();
5296   //
5297   AliTPCseed  param0[20];  // parameters along the track
5298   AliTPCseed  param1[20];  // parameters along the track
5299   AliKink     kinks[20];   // corresponding kink parameters
5300   Int_t rows[20];
5301   for (Int_t irow=0; irow<20;irow++){
5302     rows[irow] = first +((last-first)*irow)/19;
5303   }
5304   // store parameters along the track
5305   //
5306   for (Int_t irow=0;irow<20;irow++){
5307     FollowBackProlongation(*seed0, rows[irow]);
5308     FollowProlongation(*seed1,rows[19-irow]);       
5309     new(&param0[irow])     AliTPCseed(*seed0);
5310     new(&param1[19-irow])   AliTPCseed(*seed1);
5311   }
5312   //
5313   // define kinks 
5314   for (Int_t irow=0; irow<19;irow++){
5315     kinks[irow].SetMother(param0[irow]);
5316     kinks[irow].SetDaughter(param1[irow]);
5317     kinks[irow].Update();
5318   }
5319   //
5320   // choose kink with biggest change of angle
5321   Int_t index =-1;
5322   Double_t maxchange= 0;
5323   for (Int_t irow=1;irow<19;irow++){
5324     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
5325     if (TMath::Abs(kinks[irow].GetR())<110.) continue;
5326     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
5327     if ( quality > maxchange){
5328       maxchange = quality;
5329       index = irow;
5330       //
5331     }
5332   }
5333   delete seed0;
5334   delete seed1;
5335   if (index<0) return 0;
5336   //
5337   Int_t row0    = GetRowNumber(kinks[index].GetR());   //row 0 estimate
5338   seed0 = new AliTPCseed(param0[index]);
5339   seed1 = new AliTPCseed(param1[index]);
5340   seed0->Reset(kFALSE);
5341   seed1->Reset(kFALSE);
5342   seed0->ResetCovariance(10.);
5343   seed1->ResetCovariance(10.);
5344   FollowProlongation(*seed0,0);
5345   FollowBackProlongation(*seed1,158);
5346   new (&mother) AliTPCseed(*seed0);  // backup mother at position 0
5347   seed0->Reset(kFALSE);  
5348   seed1->Reset(kFALSE);
5349   seed0->ResetCovariance(10.);
5350   seed1->ResetCovariance(10.);
5351   //
5352   first = TMath::Max(row0-20,0);
5353   last  = TMath::Min(row0+20,158);
5354   //
5355   for (Int_t irow=0; irow<20;irow++){
5356     rows[irow] = first +((last-first)*irow)/19;
5357   }
5358   // store parameters along the track
5359   //
5360   for (Int_t irow=0;irow<20;irow++){
5361     FollowBackProlongation(*seed0, rows[irow]);
5362     FollowProlongation(*seed1,rows[19-irow]);       
5363     new(&param0[irow])     AliTPCseed(*seed0);
5364     new(&param1[19-irow])   AliTPCseed(*seed1);
5365   }
5366   //
5367   // define kinks 
5368   for (Int_t irow=0; irow<19;irow++){
5369     kinks[irow].SetMother(param0[irow]);
5370     kinks[irow].SetDaughter(param1[irow]);
5371     //    param0[irow].Dump();
5372     //param1[irow].Dump();
5373     kinks[irow].Update();
5374   }
5375   //
5376   // choose kink with biggest change of angle
5377   index =-1;
5378   maxchange= 0;
5379   for (Int_t irow=0;irow<20;irow++){
5380     if (TMath::Abs(kinks[irow].GetR())>250.) continue;
5381     if (TMath::Abs(kinks[irow].GetR())<90.) continue;
5382     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
5383     if ( quality > maxchange){
5384       maxchange = quality;
5385       index = irow;
5386       //
5387     }
5388   }
5389   //
5390   //
5391   if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
5392     delete seed0;
5393     delete seed1;
5394     return 0;
5395   }
5396   //  Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
5397   
5398   kink.SetMother(param0[index]);
5399   kink.SetDaughter(param1[index]);
5400   kink.Update();
5401   row0    = GetRowNumber(kink.GetR());   
5402   kink.SetTPCRow0(row0);
5403   kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
5404   kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
5405   kink.SetIndex(-10,0);
5406   kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
5407   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
5408   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
5409   //
5410   //
5411   //  new (&mother) AliTPCseed(param0[index]);
5412   new (&daughter) AliTPCseed(param1[index]);
5413   daughter.SetLabel(kink.GetLabel(1));  
5414   param0[index].Reset(kTRUE);
5415   FollowProlongation(param0[index],0);  
5416   new (&mother) AliTPCseed(param0[index]);
5417   mother.SetLabel(kink.GetLabel(0));
5418   delete seed0;
5419   delete seed1;
5420   //
5421   return 1;
5422 }
5423
5424
5425
5426
5427 AliTPCseed*  AliTPCtrackerMI::ReSeed(AliTPCseed *t)
5428 {
5429   //
5430   // reseed - refit -  track
5431   //
5432   Int_t first = 0;
5433   //  Int_t last  = fSectors->GetNRows()-1;
5434   //
5435   if (fSectors == fOuterSec){
5436     first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
5437     //last  = 
5438   }
5439   else
5440     first = t->GetFirstPoint();
5441   //
5442   AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
5443   FollowBackProlongation(*t,fSectors->GetNRows()-1);
5444   t->Reset(kFALSE);
5445   FollowProlongation(*t,first);
5446   return seed;
5447 }
5448
5449
5450
5451
5452
5453
5454
5455 //_____________________________________________________________________________
5456 Int_t AliTPCtrackerMI::ReadSeeds(const TFile *inp) {
5457   //-----------------------------------------------------------------
5458   // This function reades track seeds.
5459   //-----------------------------------------------------------------
5460   TDirectory *savedir=gDirectory; 
5461
5462   TFile *in=(TFile*)inp;
5463   if (!in->IsOpen()) {
5464      cerr<<"AliTPCtrackerMI::ReadSeeds(): input file is not open !\n";
5465      return 1;
5466   }
5467
5468   in->cd();
5469   TTree *seedTree=(TTree*)in->Get("Seeds");
5470   if (!seedTree) {
5471      cerr<<"AliTPCtrackerMI::ReadSeeds(): ";
5472      cerr<<"can't get a tree with track seeds !\n";
5473      return 2;
5474   }
5475   AliTPCtrack *seed=new AliTPCtrack; 
5476   seedTree->SetBranchAddress("tracks",&seed);
5477   
5478   if (fSeeds==0) fSeeds=new TObjArray(15000);
5479
5480   Int_t n=(Int_t)seedTree->GetEntries();
5481   for (Int_t i=0; i<n; i++) {
5482      seedTree->GetEvent(i);
5483      fSeeds->AddLast(new AliTPCseed(*seed/*,seed->GetAlpha()*/));
5484   }
5485   
5486   delete seed;
5487   delete seedTree; 
5488   savedir->cd();
5489   return 0;
5490 }
5491
5492 Int_t AliTPCtrackerMI::Clusters2Tracks (AliESD *esd)
5493 {
5494   //
5495   if (fSeeds) DeleteSeeds();
5496   fEvent = esd;
5497   Clusters2Tracks();
5498   if (!fSeeds) return 1;
5499   FillESD(fSeeds);
5500   return 0;
5501   //
5502 }
5503
5504
5505 //_____________________________________________________________________________
5506 Int_t AliTPCtrackerMI::Clusters2Tracks() {
5507   //-----------------------------------------------------------------
5508   // This is a track finder.
5509   //-----------------------------------------------------------------
5510   TDirectory *savedir=gDirectory; 
5511   TStopwatch timer;
5512
5513   fIteration = 0;
5514   fSeeds = Tracking();
5515
5516   if (fDebug>0){
5517     Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
5518   }
5519   //activate again some tracks
5520   for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
5521     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5522     if (!pt) continue;    
5523     Int_t nc=t.GetNumberOfClusters();
5524     if (nc<20) {
5525       delete fSeeds->RemoveAt(i);
5526       continue;
5527     } 
5528     CookLabel(pt,0.1); 
5529     if (pt->GetRemoval()==10) {
5530       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
5531         pt->Desactivate(10);  // make track again active
5532       else{
5533         pt->Desactivate(20);    
5534         delete fSeeds->RemoveAt(i);
5535       }
5536     } 
5537   }
5538   //
5539   RemoveUsed2(fSeeds,0.85,0.85,0);
5540   if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
5541   RemoveUsed2(fSeeds,0.5,0.4,20);
5542  //  //
5543 //   // refit short tracks
5544 //   //
5545   Int_t nseed=fSeeds->GetEntriesFast();
5546 //   for (Int_t i=0; i<nseed; i++) {
5547 //     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5548 //     if (!pt) continue;    
5549 //     Int_t nc=t.GetNumberOfClusters();
5550 //     if (nc<15) {
5551 //       delete fSeeds->RemoveAt(i);
5552 //       continue;
5553 //     }
5554 //     if (pt->GetKinkIndexes()[0]!=0) continue; // ignore kink candidates
5555 //     if (nc>100) continue;                     // hopefully, enough for ITS
5556 //     AliTPCseed *seed2 = new AliTPCseed(*pt);
5557 //     //seed2->Reset(kFALSE);
5558 //     //pt->ResetCovariance();
5559 //     seed2->Modify(1);
5560 //     FollowBackProlongation(*seed2,158);
5561 //     //seed2->Reset(kFALSE);
5562 //     seed2->Modify(10);
5563 //     FollowProlongation(*seed2,0);
5564 //     TTreeSRedirector &cstream = *fDebugStreamer;
5565 //     cstream<<"Crefit"<<
5566 //       "Tr0.="<<pt<<
5567 //       "Tr1.="<<seed2<<
5568 //       "\n";     
5569 //     if (seed2->fN>pt->fN){
5570 //       delete fSeeds->RemoveAt(i);
5571 //       fSeeds->AddAt(seed2,i);
5572 //     }else{
5573 //       delete seed2;
5574 //     }
5575 //   }
5576 //   RemoveUsed2(fSeeds,0.6,0.6,50);
5577
5578 //  FindV0s(fSeeds,fEvent);  
5579   //RemoveDouble(fSeeds,0.2,0.6,11);
5580
5581   //
5582   Int_t found = 0;
5583   for (Int_t i=0; i<nseed; i++) {
5584     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5585     if (!pt) continue;    
5586     Int_t nc=t.GetNumberOfClusters();
5587     if (nc<15) {
5588       delete fSeeds->RemoveAt(i);
5589       continue;
5590     }
5591     CookLabel(pt,0.1); //For comparison only
5592     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
5593     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
5594       found++;      
5595       if (fDebug>0) cerr<<found<<'\r';      
5596       pt->SetLab2(i);
5597     }
5598     else
5599       delete fSeeds->RemoveAt(i);
5600   }
5601
5602   
5603   //RemoveOverlap(fSeeds,0.99,7,kTRUE);  
5604   SignShared(fSeeds);  
5605   //RemoveUsed(fSeeds,0.9,0.9,6);
5606   // 
5607   nseed=fSeeds->GetEntriesFast();
5608   found = 0;
5609   for (Int_t i=0; i<nseed; i++) {
5610     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5611     if (!pt) continue;    
5612     Int_t nc=t.GetNumberOfClusters();
5613     if (nc<15) {
5614       delete fSeeds->RemoveAt(i);
5615       continue;
5616     }
5617     t.SetUniqueID(i);
5618     t.CookdEdx(0.02,0.6);
5619     //    CheckKinkPoint(&t,0.05);
5620     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
5621     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
5622       found++;
5623       if (fDebug>0){
5624         cerr<<found<<'\r';      
5625       }
5626       pt->SetLab2(i);
5627     }
5628     else
5629       delete fSeeds->RemoveAt(i);
5630     //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
5631     //if (seed1){
5632     //  FollowProlongation(*seed1,0);
5633     //  Int_t n = seed1->GetNumberOfClusters();
5634     //  printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
5635     //  printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
5636     //
5637     //}
5638     //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
5639     
5640   }
5641
5642   SortTracks(fSeeds, 1);
5643   
5644   /*    
5645   fIteration = 1;
5646   PrepareForBackProlongation(fSeeds,5.);
5647   PropagateBack(fSeeds);
5648   printf("Time for back propagation: \t");timer.Print();timer.Start();
5649   
5650   fIteration = 2;
5651   
5652   PrepareForProlongation(fSeeds,5.);
5653   PropagateForward2(fSeeds);
5654    
5655   printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
5656   // RemoveUsed(fSeeds,0.7,0.7,6);
5657   //RemoveOverlap(fSeeds,0.9,7,kTRUE);
5658    
5659   nseed=fSeeds->GetEntriesFast();
5660   found = 0;
5661   for (Int_t i=0; i<nseed; i++) {
5662     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
5663     if (!pt) continue;    
5664     Int_t nc=t.GetNumberOfClusters();
5665     if (nc<15) {
5666       delete fSeeds->RemoveAt(i);
5667       continue;
5668     }
5669     t.CookdEdx(0.02,0.6);
5670     //    CookLabel(pt,0.1); //For comparison only
5671     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
5672     if ((pt->IsActive() || (pt->fRemoval==10) )){
5673       cerr<<found++<<'\r';      
5674     }
5675     else
5676       delete fSeeds->RemoveAt(i);
5677     pt->fLab2 = i;
5678   }
5679   */
5680  
5681   //  fNTracks = found;
5682   if (fDebug>0){
5683     Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
5684   }
5685   //
5686   //  cerr<<"Number of found tracks : "<<"\t"<<found<<endl;  
5687   Info("Clusters2Tracks","Number of found tracks %d",found);  
5688   savedir->cd();
5689   //  UnloadClusters();
5690   //  
5691   return 0;
5692 }
5693
5694 void AliTPCtrackerMI::Tracking(TObjArray * arr)
5695 {
5696   //
5697   // tracking of the seeds
5698   //
5699
5700   fSectors = fOuterSec;
5701   ParallelTracking(arr,150,63);
5702   fSectors = fOuterSec;
5703   ParallelTracking(arr,63,0);
5704 }
5705
5706 TObjArray * AliTPCtrackerMI::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
5707 {
5708   //
5709   //
5710   //tracking routine
5711   TObjArray * arr = new TObjArray;
5712   // 
5713   fSectors = fOuterSec;
5714   TStopwatch timer;
5715   timer.Start();
5716   for (Int_t sec=0;sec<fkNOS;sec++){
5717     if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
5718     if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);    
5719     if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
5720   }
5721   if (fDebug>0){
5722     Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
5723     timer.Print();
5724     timer.Start();
5725   }
5726   Tracking(arr);  
5727   if (fDebug>0){
5728     timer.Print();
5729   }
5730
5731   return arr;
5732 }
5733
5734 TObjArray * AliTPCtrackerMI::Tracking()
5735 {
5736   //
5737   //
5738   if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
5739   TStopwatch timer;
5740   timer.Start();
5741   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
5742
5743   TObjArray * seeds = new TObjArray;
5744   TObjArray * arr=0;
5745   
5746   Int_t gap =20;
5747   Float_t cuts[4];
5748   cuts[0] = 0.002;
5749   cuts[1] = 1.5;
5750   cuts[2] = 3.;
5751   cuts[3] = 3.;
5752   Float_t fnumber  = 3.0;
5753   Float_t fdensity = 3.0;
5754   
5755   //  
5756   //find primaries  
5757   cuts[0]=0.0066;
5758   for (Int_t delta = 0; delta<18; delta+=6){
5759     //
5760     cuts[0]=0.0070;
5761     cuts[1] = 1.5;
5762     arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
5763     SumTracks(seeds,arr);   
5764     SignClusters(seeds,fnumber,fdensity); 
5765     //
5766     for (Int_t i=2;i<6;i+=2){
5767       // seed high pt tracks
5768       cuts[0]=0.0022;
5769       cuts[1]=0.3;
5770       arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
5771       SumTracks(seeds,arr);   
5772       SignClusters(seeds,fnumber,fdensity);        
5773     }
5774   }
5775   fnumber  = 4;
5776   fdensity = 4.;
5777   //  RemoveUsed(seeds,0.9,0.9,1);
5778   //  UnsignClusters();
5779   //  SignClusters(seeds,fnumber,fdensity);    
5780
5781   //find primaries  
5782   cuts[0]=0.0077;
5783   for (Int_t delta = 20; delta<120; delta+=10){
5784     //
5785     // seed high pt tracks
5786     cuts[0]=0.0060;
5787     cuts[1]=0.3;
5788     cuts[2]=6.;
5789     arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
5790     SumTracks(seeds,arr);   
5791     SignClusters(seeds,fnumber,fdensity);            
5792
5793     cuts[0]=0.003;
5794     cuts[1]=0.3;
5795     cuts[2]=6.;
5796     arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
5797     SumTracks(seeds,arr);   
5798     SignClusters(seeds,fnumber,fdensity);            
5799   }
5800
5801   cuts[0] = 0.01;
5802   cuts[1] = 2.0;
5803   cuts[2] = 3.;
5804   cuts[3] = 2.0;
5805   fnumber  = 2.;
5806   fdensity = 2.;
5807   
5808   if (fDebug>0){
5809     Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
5810     timer.Print();
5811     timer.Start();
5812   }
5813   //  RemoveUsed(seeds,0.75,0.75,1);
5814   //UnsignClusters();
5815   //SignClusters(seeds,fnumber,fdensity);
5816   
5817   // find secondaries
5818
5819   cuts[0] = 0.3;
5820   cuts[1] = 1.5;
5821   cuts[2] = 3.;
5822   cuts[3] = 1.5;
5823
5824   arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
5825   SumTracks(seeds,arr);   
5826   SignClusters(seeds,fnumber,fdensity);   
5827   //
5828   arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
5829   SumTracks(seeds,arr);   
5830   SignClusters(seeds,fnumber,fdensity);   
5831   //
5832   arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
5833   SumTracks(seeds,arr);   
5834   SignClusters(seeds,fnumber,fdensity);   
5835   //
5836
5837
5838   for (Int_t delta = 3; delta<30; delta+=5){
5839     //
5840     cuts[0] = 0.3;
5841     cuts[1] = 1.5;
5842     cuts[2] = 3.;
5843     cuts[3] = 1.5;
5844     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
5845     SumTracks(seeds,arr);   
5846     SignClusters(seeds,fnumber,fdensity);   
5847     //
5848     arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
5849     SumTracks(seeds,arr);   
5850     SignClusters(seeds,fnumber,fdensity); 
5851     //
5852   } 
5853   fnumber  = 1;
5854   fdensity = 1;
5855   //
5856   // change cuts
5857   fnumber  = 2.;
5858   fdensity = 2.;
5859   cuts[0]=0.0080;
5860
5861   // find secondaries
5862   for (Int_t delta = 30; delta<90; delta+=10){
5863     //
5864     cuts[0] = 0.3;
5865     cuts[1] = 3.5;
5866     cuts[2] = 3.;
5867     cuts[3] = 3.5;
5868     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
5869     SumTracks(seeds,arr);   
5870     SignClusters(seeds,fnumber,fdensity);   
5871     //
5872     arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
5873     SumTracks(seeds,arr);   
5874     SignClusters(seeds,fnumber,fdensity);   
5875   }
5876  
5877   if (fDebug>0){
5878     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
5879     timer.Print();
5880     timer.Start();
5881   }
5882
5883   return seeds;
5884   //
5885       
5886 }
5887
5888
5889 TObjArray * AliTPCtrackerMI::TrackingSpecial()
5890 {
5891   //
5892   // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
5893   // no primary vertex seeding tried
5894   //
5895   TStopwatch timer;
5896   timer.Start();
5897   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
5898
5899   TObjArray * seeds = new TObjArray;
5900   TObjArray * arr=0;
5901   
5902   Int_t   gap  = 15;
5903   Float_t cuts[4];
5904   Float_t fnumber  = 3.0;
5905   Float_t fdensity = 3.0;
5906   
5907   // find secondaries
5908   cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC();   // max curvature
5909   cuts[1] = 3.5;    // max tan(phi) angle for seeding
5910   cuts[2] = 3.;     // not used (cut on z primary vertex)     
5911   cuts[3] = 3.5;    // max tan(theta) angle for seeding
5912
5913   for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
5914     //
5915     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
5916     SumTracks(seeds,arr);   
5917     SignClusters(seeds,fnumber,fdensity);   
5918   } 
5919  
5920   if (fDebug>0){
5921     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
5922     timer.Print();
5923     timer.Start();
5924   }
5925
5926   return seeds;
5927   //
5928       
5929 }
5930
5931
5932 void AliTPCtrackerMI::SumTracks(TObjArray *arr1,TObjArray *arr2) const
5933 {
5934   //
5935   //sum tracks to common container
5936   //remove suspicious tracks
5937   Int_t nseed = arr2->GetEntriesFast();
5938   for (Int_t i=0;i<nseed;i++){
5939     AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);    
5940     if (pt){
5941       //
5942       // remove tracks with too big curvature
5943       //
5944       if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
5945         delete arr2->RemoveAt(i);
5946         continue;
5947       }
5948        // REMOVE VERY SHORT  TRACKS
5949       if (pt->GetNumberOfClusters()<20){ 
5950         delete arr2->RemoveAt(i);
5951         continue;
5952       }// patch 28 fev06
5953       // NORMAL ACTIVE TRACK
5954       if (pt->IsActive()){
5955         arr1->AddLast(arr2->RemoveAt(i));
5956         continue;
5957       }
5958       //remove not usable tracks
5959       if (pt->GetRemoval()!=10){
5960         delete arr2->RemoveAt(i);
5961         continue;
5962       }
5963      
5964       // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
5965       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
5966         arr1->AddLast(arr2->RemoveAt(i));
5967       else{      
5968         delete arr2->RemoveAt(i);
5969       }
5970     }
5971   }
5972   delete arr2;  
5973 }
5974
5975
5976
5977 void  AliTPCtrackerMI::ParallelTracking(TObjArray * arr, Int_t rfirst, Int_t rlast)
5978 {
5979   //
5980   // try to track in parralel
5981
5982   Int_t nseed=arr->GetEntriesFast();
5983   //prepare seeds for tracking
5984   for (Int_t i=0; i<nseed; i++) {
5985     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt; 
5986     if (!pt) continue;
5987     if (!t.IsActive()) continue;
5988     // follow prolongation to the first layer
5989     if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fParam->GetNRowLow()>rfirst+1) )  
5990       FollowProlongation(t, rfirst+1);
5991   }
5992
5993
5994   //
5995   for (Int_t nr=rfirst; nr>=rlast; nr--){ 
5996     if (nr<fInnerSec->GetNRows()) 
5997       fSectors = fInnerSec;
5998     else
5999       fSectors = fOuterSec;
6000     // make indexes with the cluster tracks for given       
6001
6002     // find nearest cluster
6003     for (Int_t i=0; i<nseed; i++) {
6004       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;       
6005       if (!pt) continue;
6006       if (nr==80) pt->UpdateReference();
6007       if (!pt->IsActive()) continue;
6008       //      if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fParam->GetNRowLow())<nr) continue;
6009       if (pt->GetRelativeSector()>17) {
6010         continue;
6011       }
6012       UpdateClusters(t,nr);
6013     }
6014     // prolonagate to the nearest cluster - if founded
6015     for (Int_t i=0; i<nseed; i++) {
6016       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i); 
6017       if (!pt) continue;
6018       if (!pt->IsActive()) continue; 
6019       // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fParam->GetNRowLow())<nr) continue;
6020       if (pt->GetRelativeSector()>17) {
6021         continue;
6022       }
6023       FollowToNextCluster(*pt,nr);
6024     }
6025   }    
6026 }
6027
6028 void AliTPCtrackerMI::PrepareForBackProlongation(TObjArray * arr,Float_t fac) const
6029 {
6030   //
6031   //
6032   // if we use TPC track itself we have to "update" covariance
6033   //
6034   Int_t nseed= arr->GetEntriesFast();
6035   for (Int_t i=0;i<nseed;i++){
6036     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6037     if (pt) {
6038       pt->Modify(fac);
6039       //
6040       //rotate to current local system at first accepted  point    
6041       Int_t index  = pt->GetClusterIndex2(pt->GetFirstPoint()); 
6042       Int_t sec    = (index&0xff000000)>>24;
6043       sec = sec%18;
6044       Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
6045       if (angle1>TMath::Pi()) 
6046         angle1-=2.*TMath::Pi();
6047       Float_t angle2 = pt->GetAlpha();
6048       
6049       if (TMath::Abs(angle1-angle2)>0.001){
6050         pt->Rotate(angle1-angle2);
6051         //angle2 = pt->GetAlpha();
6052         //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
6053         //if (pt->GetAlpha()<0) 
6054         //  pt->fRelativeSector+=18;
6055         //sec = pt->fRelativeSector;
6056       }
6057         
6058     }
6059     
6060   }
6061
6062
6063 }
6064 void AliTPCtrackerMI::PrepareForProlongation(TObjArray * arr, Float_t fac) const
6065 {
6066   //
6067   //
6068   // if we use TPC track itself we have to "update" covariance
6069   //
6070   Int_t nseed= arr->GetEntriesFast();
6071   for (Int_t i=0;i<nseed;i++){
6072     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6073     if (pt) {
6074       pt->Modify(fac);
6075       pt->SetFirstPoint(pt->GetLastPoint()); 
6076     }
6077     
6078   }
6079
6080
6081 }
6082
6083 Int_t AliTPCtrackerMI::PropagateBack(TObjArray * arr)
6084 {
6085   //
6086   // make back propagation
6087   //
6088   Int_t nseed= arr->GetEntriesFast();
6089   for (Int_t i=0;i<nseed;i++){
6090     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6091     if (pt&& pt->GetKinkIndex(0)<=0) { 
6092       //AliTPCseed *pt2 = new AliTPCseed(*pt);
6093       fSectors = fInnerSec;
6094       //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
6095       //fSectors = fOuterSec;
6096       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);     
6097       //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
6098       //        Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
6099       //        FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
6100       //}
6101     }
6102     if (pt&& pt->GetKinkIndex(0)>0) {
6103       AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
6104       pt->SetFirstPoint(kink->GetTPCRow0());
6105       fSectors = fInnerSec;
6106       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);  
6107     }
6108     
6109   }
6110   return 0;
6111 }
6112
6113
6114 Int_t AliTPCtrackerMI::PropagateForward2(TObjArray * arr)
6115 {
6116   //
6117   // make forward propagation
6118   //
6119   Int_t nseed= arr->GetEntriesFast();
6120   //
6121   for (Int_t i=0;i<nseed;i++){
6122     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6123     if (pt) { 
6124       FollowProlongation(*pt,0);
6125     }
6126   }
6127   return 0;
6128 }
6129
6130
6131 Int_t AliTPCtrackerMI::PropagateForward()
6132 {
6133   //
6134   // propagate track forward
6135   //UnsignClusters();
6136   Int_t nseed = fSeeds->GetEntriesFast();
6137   for (Int_t i=0;i<nseed;i++){
6138     AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
6139     if (pt){
6140       AliTPCseed &t = *pt;
6141       Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
6142       if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
6143       if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
6144       t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
6145     }
6146   }
6147   
6148   fSectors = fOuterSec;
6149   ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
6150   fSectors = fInnerSec;
6151   ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
6152   //WriteTracks();
6153   return 1;
6154 }
6155
6156
6157
6158
6159
6160
6161 Int_t AliTPCtrackerMI::PropagateBack(AliTPCseed * pt, Int_t row0, Int_t row1)
6162 {
6163   //
6164   // make back propagation, in between row0 and row1
6165   //
6166   
6167   if (pt) { 
6168     fSectors = fInnerSec;
6169     Int_t  r1;
6170     //
6171     if (row1<fSectors->GetNRows()) 
6172       r1 = row1;
6173     else 
6174       r1 = fSectors->GetNRows()-1;
6175
6176     if (row0<fSectors->GetNRows()&& r1>0 )
6177       FollowBackProlongation(*pt,r1);
6178     if (row1<=fSectors->GetNRows())
6179       return 0;
6180     //
6181     r1 = row1 - fSectors->GetNRows();
6182     if (r1<=0) return 0;
6183     if (r1>=fOuterSec->GetNRows()) return 0;
6184     fSectors = fOuterSec;
6185     return FollowBackProlongation(*pt,r1);
6186   }        
6187   return 0;
6188 }
6189
6190
6191
6192
6193 void  AliTPCtrackerMI::GetShape(AliTPCseed * seed, Int_t row)
6194 {
6195   //
6196   //
6197   Float_t sd2 = TMath::Abs((fParam->GetZLength()-TMath::Abs(seed->GetZ())))*fParam->GetDiffL()*fParam->GetDiffL();
6198   //  Float_t padlength =  fParam->GetPadPitchLength(seed->fSector);
6199   Float_t padlength =  GetPadPitchLength(row);
6200   //
6201   Float_t sresy = (seed->GetSector() < fParam->GetNSector()/2) ? 0.2 :0.3;
6202   Double_t angulary  = seed->GetSnp();
6203   angulary = angulary*angulary/(1-angulary*angulary);
6204   seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);  
6205   //
6206   Float_t sresz = fParam->GetZSigma();
6207   Float_t angularz  = seed->GetTgl();
6208   seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
6209   /*
6210   Float_t wy = GetSigmaY(seed);
6211   Float_t wz = GetSigmaZ(seed);
6212   wy*=wy;
6213   wz*=wz;
6214   if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
6215     printf("problem\n");
6216   }
6217   */
6218 }
6219
6220
6221 Float_t  AliTPCtrackerMI::GetSigmaY(AliTPCseed * seed)
6222 {
6223   //
6224   //  
6225   Float_t sd2 = TMath::Abs((fParam->GetZLength()-TMath::Abs(seed->GetZ())))*fParam->GetDiffL()*fParam->GetDiffL();
6226   Float_t padlength =  fParam->GetPadPitchLength(seed->GetSector());
6227   Float_t sres = (seed->GetSector() < fParam->GetNSector()/2) ? 0.2 :0.3;
6228   Float_t angular  = seed->GetSnp();
6229   angular = angular*angular/(1-angular*angular);
6230   //  angular*=angular;
6231   //angular  = TMath::Sqrt(angular/(1-angular));
6232   Float_t res = TMath::Sqrt(sd2+padlength*padlength*angular/12.+sres*sres);
6233   return res;
6234 }
6235 Float_t  AliTPCtrackerMI::GetSigmaZ(AliTPCseed * seed)
6236 {
6237   //
6238   //
6239   Float_t sd2 = TMath::Abs((fParam->GetZLength()-TMath::Abs(seed->GetZ())))*fParam->GetDiffL()*fParam->GetDiffL();
6240   Float_t padlength =  fParam->GetPadPitchLength(seed->GetSector());
6241   Float_t sres = fParam->GetZSigma();
6242   Float_t angular  = seed->GetTgl();
6243   Float_t res = TMath::Sqrt(sd2+padlength*padlength*angular*angular/12.+sres*sres);
6244   return res;
6245 }
6246
6247
6248 //__________________________________________________________________________
6249 void AliTPCtrackerMI::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
6250   //--------------------------------------------------------------------
6251   //This function "cooks" a track label. If label<0, this track is fake.
6252   //--------------------------------------------------------------------
6253   AliTPCseed * t = (AliTPCseed*)tk;
6254   Int_t noc=t->GetNumberOfClusters();
6255   if (noc<10){
6256     //printf("\nnot founded prolongation\n\n\n");
6257     //t->Dump();
6258     return ;
6259   }
6260   Int_t lb[160];
6261   Int_t mx[160];
6262   AliTPCclusterMI *clusters[160];
6263   //
6264   for (Int_t i=0;i<160;i++) {
6265     clusters[i]=0;
6266     lb[i]=mx[i]=0;
6267   }
6268
6269   Int_t i;
6270   Int_t current=0;
6271   for (i=0; i<160 && current<noc; i++) {
6272      
6273      Int_t index=t->GetClusterIndex2(i);
6274      if (index<=0) continue; 
6275      if (index&0x8000) continue;
6276      //     
6277      //clusters[current]=GetClusterMI(index);
6278      if (t->GetClusterPointer(i)){
6279        clusters[current]=t->GetClusterPointer(i);     
6280        current++;
6281      }
6282   }
6283   noc = current;
6284
6285   Int_t lab=123456789;
6286   for (i=0; i<noc; i++) {
6287     AliTPCclusterMI *c=clusters[i];
6288     if (!c) continue;
6289     lab=TMath::Abs(c->GetLabel(0));
6290     Int_t j;
6291     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
6292     lb[j]=lab;
6293     (mx[j])++;
6294   }
6295
6296   Int_t max=0;
6297   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
6298     
6299   for (i=0; i<noc; i++) {
6300     AliTPCclusterMI *c=clusters[i]; 
6301     if (!c) continue;
6302     if (TMath::Abs(c->GetLabel(1)) == lab ||
6303         TMath::Abs(c->GetLabel(2)) == lab ) max++;
6304   }
6305
6306   if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
6307
6308   else {
6309      Int_t tail=Int_t(0.10*noc);
6310      max=0;
6311      Int_t ind=0;
6312      for (i=1; i<=160&&ind<tail; i++) {
6313        //       AliTPCclusterMI *c=clusters[noc-i];
6314        AliTPCclusterMI *c=clusters[i];
6315        if (!c) continue;
6316        if (lab == TMath::Abs(c->GetLabel(0)) ||
6317            lab == TMath::Abs(c->GetLabel(1)) ||
6318            lab == TMath::Abs(c->GetLabel(2))) max++;
6319        ind++;
6320      }
6321      if (max < Int_t(0.5*tail)) lab=-lab;
6322   }
6323
6324   t->SetLabel(lab);
6325
6326   //  delete[] lb;
6327   //delete[] mx;
6328   //delete[] clusters;
6329 }
6330
6331
6332 //__________________________________________________________________________
6333 Int_t AliTPCtrackerMI::CookLabel(AliTPCseed *t, Float_t wrong,Int_t first, Int_t last) const {
6334   //--------------------------------------------------------------------
6335   //This function "cooks" a track label. If label<0, this track is fake.
6336   //--------------------------------------------------------------------
6337   Int_t noc=t->GetNumberOfClusters();
6338   if (noc<10){
6339     //printf("\nnot founded prolongation\n\n\n");
6340     //t->Dump();
6341     return -1;
6342   }
6343   Int_t lb[160];
6344   Int_t mx[160];
6345   AliTPCclusterMI *clusters[160];
6346   //
6347   for (Int_t i=0;i<160;i++) {
6348     clusters[i]=0;
6349     lb[i]=mx[i]=0;
6350   }
6351
6352   Int_t i;
6353   Int_t current=0;
6354   for (i=0; i<160 && current<noc; i++) {
6355     if (i<first) continue;
6356     if (i>last)  continue;
6357      Int_t index=t->GetClusterIndex2(i);
6358      if (index<=0) continue; 
6359      if (index&0x8000) continue;
6360      //     
6361      //clusters[current]=GetClusterMI(index);
6362      if (t->GetClusterPointer(i)){
6363        clusters[current]=t->GetClusterPointer(i);     
6364        current++;
6365      }
6366   }
6367   noc = current;
6368   if (noc<5) return -1;
6369   Int_t lab=123456789;
6370   for (i=0; i<noc; i++) {
6371     AliTPCclusterMI *c=clusters[i];
6372     if (!c) continue;
6373     lab=TMath::Abs(c->GetLabel(0));
6374     Int_t j;
6375     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
6376     lb[j]=lab;
6377     (mx[j])++;
6378   }
6379
6380   Int_t max=0;
6381   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
6382     
6383   for (i=0; i<noc; i++) {
6384     AliTPCclusterMI *c=clusters[i]; 
6385     if (!c) continue;
6386     if (TMath::Abs(c->GetLabel(1)) == lab ||
6387         TMath::Abs(c->GetLabel(2)) == lab ) max++;
6388   }
6389
6390   if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
6391
6392   else {
6393      Int_t tail=Int_t(0.10*noc);
6394      max=0;
6395      Int_t ind=0;
6396      for (i=1; i<=160&&ind<tail; i++) {
6397        //       AliTPCclusterMI *c=clusters[noc-i];
6398        AliTPCclusterMI *c=clusters[i];
6399        if (!c) continue;
6400        if (lab == TMath::Abs(c->GetLabel(0)) ||
6401            lab == TMath::Abs(c->GetLabel(1)) ||
6402            lab == TMath::Abs(c->GetLabel(2))) max++;
6403        ind++;
6404      }
6405      if (max < Int_t(0.5*tail)) lab=-lab;
6406   }
6407
6408   //  t->SetLabel(lab);
6409   return lab;
6410   //  delete[] lb;
6411   //delete[] mx;
6412   //delete[] clusters;
6413 }
6414
6415
6416 Int_t  AliTPCtrackerMI::AliTPCSector::GetRowNumber(Double_t x) const 
6417 {
6418   //return pad row number for this x
6419   Double_t r;
6420   if (fN < 64){
6421     r=fRow[fN-1].GetX();
6422     if (x > r) return fN;
6423     r=fRow[0].GetX();
6424     if (x < r) return -1;
6425     return Int_t((x-r)/fPadPitchLength + 0.5);}
6426   else{    
6427     r=fRow[fN-1].GetX();
6428     if (x > r) return fN;
6429     r=fRow[0].GetX();
6430     if (x < r) return -1;
6431     Double_t r1=fRow[64].GetX();
6432     if(x<r1){       
6433       return Int_t((x-r)/f1PadPitchLength + 0.5);}
6434     else{
6435       return (Int_t((x-r1)/f2PadPitchLength + 0.5)+64);} 
6436   }
6437 }
6438
6439 Int_t  AliTPCtrackerMI::GetRowNumber(Double_t x[3]) const 
6440 {
6441   //return pad row number for given x vector
6442   Float_t phi = TMath::ATan2(x[1],x[0]);
6443   if(phi<0) phi=2.*TMath::Pi()+phi;
6444   //  Get the local angle in the sector philoc
6445   const Float_t kRaddeg = 180/3.14159265358979312;
6446   Float_t phiangle   = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
6447   Double_t localx    = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
6448   return GetRowNumber(localx);
6449 }
6450
6451 //_________________________________________________________________________
6452 void AliTPCtrackerMI::AliTPCSector::Setup(const AliTPCParam *par, Int_t f) {
6453   //-----------------------------------------------------------------------
6454   // Setup inner sector
6455   //-----------------------------------------------------------------------
6456   if (f==0) {
6457      fAlpha=par->GetInnerAngle();
6458      fAlphaShift=par->GetInnerAngleShift();
6459      fPadPitchWidth=par->GetInnerPadPitchWidth();
6460      fPadPitchLength=par->GetInnerPadPitchLength();
6461      fN=par->GetNRowLow();
6462      fRow=new AliTPCRow[fN];
6463      for (Int_t i=0; i<fN; i++) {
6464        fRow[i].SetX(par->GetPadRowRadiiLow(i));
6465        fRow[i].SetDeadZone(1.5);  //1.5 cm of dead zone
6466      }
6467   } else {
6468      fAlpha=par->GetOuterAngle();
6469      fAlphaShift=par->GetOuterAngleShift();
6470      fPadPitchWidth  = par->GetOuterPadPitchWidth();
6471      fPadPitchLength = par->GetOuter1PadPitchLength();
6472      f1PadPitchLength = par->GetOuter1PadPitchLength();
6473      f2PadPitchLength = par->GetOuter2PadPitchLength();
6474
6475      fN=par->GetNRowUp();
6476      fRow=new AliTPCRow[fN];
6477      for (Int_t i=0; i<fN; i++) {
6478        fRow[i].SetX(par->GetPadRowRadiiUp(i)); 
6479        fRow[i].SetDeadZone(1.5);  // 1.5 cm of dead zone
6480      }
6481   } 
6482 }
6483
6484 AliTPCtrackerMI::AliTPCRow::AliTPCRow():
6485   fDeadZone(0.),
6486   fClusters1(0),
6487   fN1(0),
6488   fClusters2(0),
6489   fN2(0),
6490   fN(0),
6491   fX(0.)
6492 {
6493   //
6494   // default constructor
6495   //
6496 }
6497
6498 AliTPCtrackerMI::AliTPCRow::~AliTPCRow(){
6499   //
6500
6501 }
6502
6503
6504
6505 //_________________________________________________________________________
6506 void 
6507 AliTPCtrackerMI::AliTPCRow::InsertCluster(const AliTPCclusterMI* c, UInt_t index) {
6508   //-----------------------------------------------------------------------
6509   // Insert a cluster into this pad row in accordence with its y-coordinate
6510   //-----------------------------------------------------------------------
6511   if (fN==kMaxClusterPerRow) {
6512     cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return;
6513   }
6514   if (fN==0) {fIndex[0]=index; fClusters[fN++]=c; return;}
6515   Int_t i=Find(c->GetZ());
6516   memmove(fClusters+i+1 ,fClusters+i,(fN-i)*sizeof(AliTPCclusterMI*));
6517   memmove(fIndex   +i+1 ,fIndex   +i,(fN-i)*sizeof(UInt_t));
6518   fIndex[i]=index; fClusters[i]=c; fN++;
6519 }
6520
6521 void AliTPCtrackerMI::AliTPCRow::ResetClusters() {
6522    //
6523    // reset clusters
6524    fN  = 0; 
6525    fN1 = 0;
6526    fN2 = 0;
6527    //delete[] fClusterArray; 
6528    if (fClusters1) delete []fClusters1; 
6529    if (fClusters2) delete []fClusters2; 
6530    //fClusterArray=0;
6531    fClusters1 = 0;
6532    fClusters2 = 0;
6533 }
6534
6535
6536 //___________________________________________________________________
6537 Int_t AliTPCtrackerMI::AliTPCRow::Find(Double_t z) const {
6538   //-----------------------------------------------------------------------
6539   // Return the index of the nearest cluster 
6540   //-----------------------------------------------------------------------
6541   if (fN==0) return 0;
6542   if (z <= fClusters[0]->GetZ()) return 0;
6543   if (z > fClusters[fN-1]->GetZ()) return fN;
6544   Int_t b=0, e=fN-1, m=(b+e)/2;
6545   for (; b<e; m=(b+e)/2) {
6546     if (z > fClusters[m]->GetZ()) b=m+1;
6547     else e=m; 
6548   }
6549   return m;
6550 }
6551
6552
6553
6554 //___________________________________________________________________
6555 AliTPCclusterMI * AliTPCtrackerMI::AliTPCRow::FindNearest(Double_t y, Double_t z, Double_t roady, Double_t roadz) const {
6556   //-----------------------------------------------------------------------
6557   // Return the index of the nearest cluster in z y 
6558   //-----------------------------------------------------------------------
6559   Float_t maxdistance = roady*roady + roadz*roadz;
6560
6561   AliTPCclusterMI *cl =0;
6562   for (Int_t i=Find(z-roadz); i<fN; i++) {
6563       AliTPCclusterMI *c=(AliTPCclusterMI*)(fClusters[i]);
6564       if (c->GetZ() > z+roadz) break;
6565       if ( (c->GetY()-y) >  roady ) continue;
6566       Float_t distance = (c->GetZ()-z)*(c->GetZ()-z)+(c->GetY()-y)*(c->GetY()-y);
6567       if (maxdistance>distance) {
6568         maxdistance = distance;
6569         cl=c;       
6570       }
6571   }
6572   return cl;      
6573 }
6574
6575 AliTPCclusterMI * AliTPCtrackerMI::AliTPCRow::FindNearest2(Double_t y, Double_t z, Double_t roady, Double_t roadz,UInt_t & index) const 
6576 {
6577   //-----------------------------------------------------------------------
6578   // Return the index of the nearest cluster in z y 
6579   //-----------------------------------------------------------------------
6580   Float_t maxdistance = roady*roady + roadz*roadz;
6581   AliTPCclusterMI *cl =0;
6582
6583   //PH Check boundaries. 510 is the size of fFastCluster
6584   Int_t iz1 = Int_t(z-roadz+254.5);
6585   if (iz1<0 || iz1>=510) return cl;
6586   iz1 = TMath::Max(GetFastCluster(iz1)-1,0);
6587   Int_t iz2 = Int_t(z+roadz+255.5);
6588   if (iz2<0 || iz2>=510) return cl;
6589   iz2 = TMath::Min(GetFastCluster(iz2)+1,fN);
6590
6591   //FindNearest3(y,z,roady,roadz,index);
6592   //  for (Int_t i=Find(z-roadz); i<fN; i++) {
6593   for (Int_t i=iz1; i<iz2; i++) {
6594       AliTPCclusterMI *c=(AliTPCclusterMI*)(fClusters[i]);
6595       if (c->GetZ() > z+roadz) break;
6596       if ( c->GetY()-y >  roady ) continue;
6597       if ( y-c->GetY() >  roady ) continue;
6598       Float_t distance = (c->GetZ()-z)*(c->GetZ()-z)+(c->GetY()-y)*(c->GetY()-y);
6599       if (maxdistance>distance) {
6600         maxdistance = distance;
6601         cl=c;       
6602         index =i;
6603         //roady = TMath::Sqrt(maxdistance);
6604       }
6605   }
6606   return cl;      
6607 }
6608
6609
6610
6611 AliTPCclusterMI * AliTPCtrackerMI::AliTPCRow::FindNearest3(Double_t y, Double_t z, Double_t roady, Double_t roadz,UInt_t & index) const 
6612 {
6613   //-----------------------------------------------------------------------
6614   // Return the index of the nearest cluster in z y 
6615   //-----------------------------------------------------------------------
6616   Float_t maxdistance = roady*roady + roadz*roadz;
6617   //  Int_t iz = Int_t(z+255.);
6618   AliTPCclusterMI *cl =0;
6619   for (Int_t i=Find(z-roadz); i<fN; i++) {
6620     //for (Int_t i=fFastCluster[iz-2]; i<fFastCluster[iz+2]; i++) {
6621       AliTPCclusterMI *c=(AliTPCclusterMI*)(fClusters[i]);
6622       if (c->GetZ() > z+roadz) break;
6623       if ( c->GetY()-y >  roady ) continue;
6624       if ( y-c->GetY() >  roady ) continue;
6625       Float_t distance = (c->GetZ()-z)*(c->GetZ()-z)+(c->GetY()-y)*(c->GetY()-y);
6626       if (maxdistance>distance) {
6627         maxdistance = distance;
6628         cl=c;       
6629         index =i;
6630         //roady = TMath::Sqrt(maxdistance);
6631       }
6632   }
6633   return cl;      
6634 }
6635
6636
6637
6638
6639
6640 // AliTPCTrackerPoint * AliTPCseed::GetTrackPoint(Int_t i)
6641 // {
6642 //   //
6643 //   // 
6644 //   return &fTrackPoints[i];
6645 // }
6646
6647