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