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