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