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