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