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