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