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