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