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