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