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