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