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