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