]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/TPCrec/AliTPCtracker.cxx
Store seed in friends regardless on stream-level, since needed for calibration
[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       if (storeFriend){ // RS: seed is needed for calibration, regardless on streamlevel
3576         // RS: this is the only place where the seed is created not in the pool, 
3577         // since it should belong to ESDevent
3578         AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE); 
3579         esd->AddCalibObject(seedCopy);
3580       }
3581       ntracks++;
3582     }
3583     else{
3584       //printf("problem\n");
3585     }
3586   }
3587   //FindKinks(fSeeds,event);
3588   if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0)  DumpClusters(2,fSeeds);  // dump clusters at the end of process (signed with useage flags)
3589   Info("RefitInward","Number of refitted tracks %d",ntracks);
3590
3591   AliCosmicTracker::FindCosmic(event, kTRUE);
3592
3593   FillClusterOccupancyInfo();
3594
3595   return 0;
3596 }
3597
3598
3599 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3600 {
3601   //
3602   // back propagation of ESD tracks
3603   //
3604   if (!event) return 0;
3605   fEvent = event;
3606   fEventHLT = 0;
3607   fIteration = 1;
3608   ReadSeeds(event,1);
3609   PropagateBack(fSeeds); 
3610   RemoveUsed2(fSeeds,0.4,0.4,20);
3611   //FindCurling(fSeeds, fEvent,1);  
3612   FindSplitted(fSeeds, event,1); // find multi found tracks
3613   if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0)  FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3614
3615   //
3616   Int_t nseed = fSeeds->GetEntriesFast();
3617   Int_t ntracks=0;
3618   for (Int_t i=0;i<nseed;i++){
3619     AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3620     if (!seed) continue;
3621     if (seed->GetKinkIndex(0)<0)  UpdateKinkQualityM(seed);  // update quality informations for kinks
3622     seed->UpdatePoints();
3623     AddCovariance(seed);
3624     AliESDtrack *esd=event->GetTrack(i);
3625     if (!esd) continue; //never happen
3626     if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3627       AliExternalTrackParam paramIn;
3628       AliExternalTrackParam paramOut;
3629       Int_t ncl = seed->RefitTrack(seed,&paramIn,&paramOut);
3630       if ((AliTPCReconstructor::StreamLevel()&kStreamRecoverBack)>0) { // flag: stream track information for track  faling PropagateBack function and recovered back (RefitTrack)
3631         (*fDebugStreamer)<<"RecoverBack"<<
3632           "seed.="<<seed<<
3633           "esd.="<<esd<<
3634           "pin.="<<&paramIn<<
3635           "pout.="<<&paramOut<<
3636           "ncl="<<ncl<<
3637           "\n";
3638       }
3639       if (ncl>15) {
3640         seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3641         seed->SetNumberOfClusters(ncl);
3642       }
3643     }
3644     seed->CookdEdx(0.02,0.6);
3645     CookLabel(seed,0.1); //For comparison only
3646     if (seed->GetNumberOfClusters()>15){
3647       esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3648       esd->SetTPCPoints(seed->GetPoints());
3649       esd->SetTPCPointsF(seed->GetNFoundable());
3650       Int_t   ndedx = seed->GetNCDEDX(0);
3651       Float_t sdedx = seed->GetSDEDX(0);
3652       Float_t dedx  = seed->GetdEdx();
3653       esd->SetTPCsignal(dedx, sdedx, ndedx);
3654       ntracks++;
3655       Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3656       // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number      
3657       if (((AliTPCReconstructor::StreamLevel()&kStreamCPropagateBack)>0) && esd) {
3658         (*fDebugStreamer)<<"PropagateBack"<<  // flag: stream track information in PropagateBack function (after tracking Iteration 1)
3659           "Tr0.="<<seed<<
3660           "esd.="<<esd<<
3661           "EventNrInFile="<<eventnumber<<
3662           "\n";       
3663       }
3664     }
3665   }
3666   if (AliTPCReconstructor::StreamLevel()&kStreamClDump)  DumpClusters(1,fSeeds); // flag:stream clusters at the end of process (signed with usage flag)
3667   //FindKinks(fSeeds,event);
3668   Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3669   fEvent =0;
3670   fEventHLT = 0;
3671
3672   return 0;
3673 }
3674
3675
3676 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3677 {
3678   //
3679   // Post process events 
3680   //
3681   if (!event) return 0;
3682
3683   //
3684   // Set TPC event status
3685   // 
3686
3687   // event affected by HV dip
3688   // reset TPC status
3689   if(IsTPCHVDipEvent(event)) { 
3690     event->ResetDetectorStatus(AliDAQ::kTPC);
3691   }
3692  
3693   //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3694
3695   return 0;
3696 }
3697
3698
3699  void AliTPCtracker::DeleteSeeds()
3700 {
3701   //
3702   fSeeds->Clear();
3703   ResetSeedsPool();
3704   delete fSeeds;
3705   fSeeds =0;
3706 }
3707
3708 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3709 {
3710   //
3711   //read seeds from the event
3712   
3713   Int_t nentr=event->GetNumberOfTracks();
3714   if (fDebug>0){
3715     Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3716   }
3717   if (fSeeds) 
3718     DeleteSeeds();
3719   if (!fSeeds){   
3720     fSeeds = new TObjArray(nentr);
3721   }
3722   UnsignClusters();
3723   //  Int_t ntrk=0;  
3724   for (Int_t i=0; i<nentr; i++) {
3725     AliESDtrack *esd=event->GetTrack(i);
3726     ULong_t status=esd->GetStatus();
3727     if (!(status&AliESDtrack::kTPCin)) continue;
3728     AliTPCtrack t(*esd);
3729     t.SetNumberOfClusters(0);
3730     //    AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3731     AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3732     seed->SetPoolID(fLastSeedID);
3733     seed->SetUniqueID(esd->GetID());
3734     AddCovariance(seed);   //add systematic ucertainty
3735     for (Int_t ikink=0;ikink<3;ikink++) {
3736       Int_t index = esd->GetKinkIndex(ikink);
3737       seed->GetKinkIndexes()[ikink] = index;
3738       if (index==0) continue;
3739       index = TMath::Abs(index);
3740       AliESDkink * kink = fEvent->GetKink(index-1);
3741       if (kink&&esd->GetKinkIndex(ikink)<0){
3742         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3743         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,0);
3744       }
3745       if (kink&&esd->GetKinkIndex(ikink)>0){
3746         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3747         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,4);
3748       }
3749
3750     }
3751     if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.); 
3752     //RS    if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3753     if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3754     //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3755     //  fSeeds->AddAt(0,i);
3756     //  MarkSeedFree( seed );
3757     //  continue;    
3758     //}
3759     
3760     //
3761     //
3762     // rotate to the local coordinate system
3763     //   
3764     fSectors=fInnerSec; fN=fkNIS;    
3765     Double_t alpha=seed->GetAlpha();
3766     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3767     if (alpha < 0.            ) alpha += 2.*TMath::Pi();
3768     Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3769     alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3770     alpha-=seed->GetAlpha();  
3771     if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3772     if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3773     if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3774       AliWarning(Form("Rotating track over %f",alpha));
3775       if (!seed->Rotate(alpha)) {
3776         MarkSeedFree( seed );
3777         continue;
3778       }
3779     }
3780     seed->SetESD(esd);
3781     // sign clusters
3782     if (esd->GetKinkIndex(0)<=0){
3783       for (Int_t irow=0;irow<160;irow++){
3784         Int_t index = seed->GetClusterIndex2(irow);    
3785         if (index >= 0){ 
3786           //
3787           AliTPCclusterMI * cl = GetClusterMI(index);
3788           seed->SetClusterPointer(irow,cl);
3789           if (cl){
3790             if ((index & 0x8000)==0){
3791               cl->Use(10);  // accepted cluster   
3792             }else{
3793               cl->Use(6);   // close cluster not accepted
3794             }   
3795           }else{
3796             Info("ReadSeeds","Not found cluster");
3797           }
3798         }
3799       }
3800     }
3801     fSeeds->AddAt(seed,i);
3802   }
3803 }
3804
3805
3806
3807 //_____________________________________________________________________________
3808 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
3809                                  Float_t deltay, Int_t ddsec) {
3810   //-----------------------------------------------------------------
3811   // This function creates track seeds.
3812   // SEEDING WITH VERTEX CONSTRAIN 
3813   //-----------------------------------------------------------------
3814   // cuts[0]   - fP4 cut
3815   // cuts[1]   - tan(phi)  cut
3816   // cuts[2]   - zvertex cut
3817   // cuts[3]   - fP3 cut
3818   Int_t nin0  = 0;
3819   Int_t nin1  = 0;
3820   Int_t nin2  = 0;
3821   Int_t nin   = 0;
3822   Int_t nout1 = 0;
3823   Int_t nout2 = 0;
3824
3825   Double_t x[5], c[15];
3826   //  Int_t di = i1-i2;
3827   //
3828   AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3829   seed->SetPoolID(fLastSeedID);
3830   Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3831   Double_t cs=cos(alpha), sn=sin(alpha);
3832   //
3833   //  Double_t x1 =fOuterSec->GetX(i1);
3834   //Double_t xx2=fOuterSec->GetX(i2);
3835   
3836   Double_t x1 =GetXrow(i1);
3837   Double_t xx2=GetXrow(i2);
3838
3839   Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3840
3841   Int_t imiddle = (i2+i1)/2;    //middle pad row index
3842   Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3843   const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3844   //
3845   Int_t ns =sec;   
3846
3847   const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3848   Double_t ymax  = GetMaxY(i1)-kr1.GetDeadZone()-1.5;  
3849   Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;  
3850
3851   //
3852   // change cut on curvature if it can't reach this layer
3853   // maximal curvature set to reach it
3854   Double_t dvertexmax  = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3855   if (dvertexmax*0.5*cuts[0]>0.85){
3856     cuts[0] = 0.85/(dvertexmax*0.5+1.);
3857   }
3858   Double_t r2min = 1/(cuts[0]*cuts[0]);  //minimal square of radius given by cut
3859
3860   //  Int_t ddsec = 1;
3861   if (deltay>0) ddsec = 0; 
3862   // loop over clusters  
3863   for (Int_t is=0; is < kr1; is++) {
3864     //
3865     if (kr1[is]->IsUsed(10)) continue;
3866     if (kr1[is]->IsDisabled()) {
3867       continue;
3868     }
3869
3870     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
3871     //if (TMath::Abs(y1)>ymax) continue;
3872
3873     if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge
3874
3875     // find possible directions    
3876     Float_t anglez = (z1-z3)/(x1-x3); 
3877     Float_t extraz = z1 - anglez*(x1-xx2);  // extrapolated z      
3878     //
3879     //
3880     //find   rotation angles relative to line given by vertex and point 1
3881     Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3882     Double_t dvertex  = TMath::Sqrt(dvertex2);
3883     Double_t angle13  = TMath::ATan((y1-y3)/(x1-x3));
3884     Double_t cs13     = cos(-angle13), sn13 = sin(-angle13);            
3885     
3886     //
3887     // loop over 2 sectors
3888     Int_t dsec1=-ddsec;
3889     Int_t dsec2= ddsec;
3890     if (y1<0)  dsec2= 0;
3891     if (y1>0)  dsec1= 0;
3892     
3893     Double_t dddz1=0;  // direction of delta inclination in z axis
3894     Double_t dddz2=0;
3895     if ( (z1-z3)>0)
3896       dddz1 =1;    
3897     else
3898       dddz2 =1;
3899     //
3900     for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3901       Int_t sec2 = sec + dsec;
3902       // 
3903       //      AliTPCtrackerRow&  kr2  = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3904       //AliTPCtrackerRow&  kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3905       AliTPCtrackerRow&  kr2  = GetRow((sec2+fkNOS)%fkNOS,i2);
3906       AliTPCtrackerRow&  kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3907       Int_t  index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3908       Int_t  index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3909
3910       // rotation angles to p1-p3
3911       Double_t cs13r     = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;            
3912       Double_t x2,   y2,   z2; 
3913       //
3914       //      Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3915
3916       //
3917       Double_t dxx0 =  (xx2-x3)*cs13r;
3918       Double_t dyy0 =  (xx2-x3)*sn13r;
3919       for (Int_t js=index1; js < index2; js++) {
3920         const AliTPCclusterMI *kcl = kr2[js];
3921         if (kcl->IsUsed(10)) continue;  
3922         if (kcl->IsDisabled()) {
3923           continue;
3924         }
3925         //
3926         //calcutate parameters
3927         //      
3928         Double_t yy0 =  dyy0 +(kcl->GetY()-y3)*cs13r;
3929         // stright track
3930         if (TMath::Abs(yy0)<0.000001) continue;
3931         Double_t xx0 =  dxx0 -(kcl->GetY()-y3)*sn13r;
3932         Double_t y0  =  0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3933         Double_t r02 = (0.25+y0*y0)*dvertex2;   
3934         //curvature (radius) cut
3935         if (r02<r2min) continue;                
3936        
3937         nin0++; 
3938         //
3939         Double_t c0  = 1/TMath::Sqrt(r02);
3940         if (yy0>0) c0*=-1.;     
3941                
3942        
3943         //Double_t dfi0   = 2.*TMath::ASin(dvertex*c0*0.5);
3944         //Double_t dfi1   = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3945         Double_t dfi0   = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3946         Double_t dfi1   = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);  
3947         //
3948         //
3949         Double_t z0  =  kcl->GetZ();  
3950         Double_t zzzz2    = z1-(z1-z3)*dfi1/dfi0;
3951         if (TMath::Abs(zzzz2-z0)>0.5) continue;       
3952         nin1++;              
3953         //      
3954         Double_t dip    = (z1-z0)*c0/dfi1;        
3955         Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3956         //
3957         y2 = kcl->GetY(); 
3958         if (dsec==0){
3959           x2 = xx2; 
3960           z2 = kcl->GetZ();       
3961         }
3962         else
3963           {
3964             // rotation 
3965             z2 = kcl->GetZ();  
3966             x2= xx2*cs-y2*sn*dsec;
3967             y2=+xx2*sn*dsec+y2*cs;
3968           }
3969         
3970         x[0] = y1;
3971         x[1] = z1;
3972         x[2] = x0;
3973         x[3] = dip;
3974         x[4] = c0;
3975         //
3976         //
3977         // do we have cluster at the middle ?
3978         Double_t ym,zm;
3979         GetProlongation(x1,xm,x,ym,zm);
3980         UInt_t dummy; 
3981         AliTPCclusterMI * cm=0;
3982         if (TMath::Abs(ym)-ymaxm<0){      
3983           cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3984           if ((!cm) || (cm->IsUsed(10))) {        
3985             continue;
3986           }
3987         }
3988         else{     
3989           // rotate y1 to system 0
3990           // get state vector in rotated system 
3991           Double_t yr1  = (-0.5*sn13+y0*cs13)*dvertex*c0;
3992           Double_t xr2  =  x0*cs+yr1*sn*dsec;
3993           Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3994           //
3995           GetProlongation(xx2,xm,xr,ym,zm);
3996           if (TMath::Abs(ym)-ymaxm<0){
3997             cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3998             if ((!cm) || (cm->IsUsed(10))) {      
3999               continue;
4000             }
4001           }
4002         }
4003        
4004
4005         // Double_t dym = 0;
4006         // Double_t dzm = 0;
4007         // if (cm){
4008         //   dym = ym - cm->GetY();
4009         //   dzm = zm - cm->GetZ();
4010         // }
4011         nin2++;
4012
4013
4014         //
4015         //
4016         Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
4017         Double_t sy2=kcl->GetSigmaY2()*2.,     sz2=kcl->GetSigmaZ2()*2.;
4018         //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
4019         Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4020         //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
4021
4022         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4023         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4024         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4025         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4026         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4027         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4028         
4029         Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
4030         Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
4031         Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
4032         Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
4033         
4034         c[0]=sy1;
4035         c[1]=0.;       c[2]=sz1;
4036         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4037         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
4038                        c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4039         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4040         c[13]=f30*sy1*f40+f32*sy2*f42;
4041         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4042         
4043         //      if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
4044         
4045         UInt_t index=kr1.GetIndex(is);
4046         if (seed) {MarkSeedFree(seed); seed = 0;}
4047         AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
4048         seed->SetPoolID(fLastSeedID);
4049         track->SetIsSeeding(kTRUE);
4050         track->SetSeed1(i1);
4051         track->SetSeed2(i2);
4052         track->SetSeedType(3);
4053
4054        
4055         //if (dsec==0) {
4056           FollowProlongation(*track, (i1+i2)/2,1);
4057           Int_t foundable,found,shared;
4058           track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
4059           if ((found<0.55*foundable)  || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
4060             MarkSeedFree(seed); seed = 0;
4061             continue;
4062           }
4063           //}
4064         
4065         nin++;
4066         FollowProlongation(*track, i2,1);
4067         
4068         
4069         //Int_t rc = 1;
4070         track->SetBConstrain(1);
4071         //      track->fLastPoint = i1+fInnerSec->GetNRows();  // first cluster in track position
4072         track->SetLastPoint(i1);  // first cluster in track position
4073         track->SetFirstPoint(track->GetLastPoint());
4074         
4075         if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
4076             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
4077             track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
4078           MarkSeedFree(seed); seed = 0;
4079           continue;
4080         }
4081         nout1++;
4082         // Z VERTEX CONDITION
4083         Double_t zv, bz=GetBz();
4084         if ( !track->GetZAt(0.,bz,zv) ) continue;
4085         if (TMath::Abs(zv-z3)>cuts[2]) {
4086           FollowProlongation(*track, TMath::Max(i2-20,0));
4087           if ( !track->GetZAt(0.,bz,zv) ) continue;
4088           if (TMath::Abs(zv-z3)>cuts[2]){
4089             FollowProlongation(*track, TMath::Max(i2-40,0));
4090             if ( !track->GetZAt(0.,bz,zv) ) continue;
4091             if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
4092               // make seed without constrain
4093               AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
4094               FollowProlongation(*track2, i2,1);
4095               track2->SetBConstrain(kFALSE);
4096               track2->SetSeedType(1);
4097               arr->AddLast(track2); 
4098               MarkSeedFree( seed ); seed = 0;
4099               continue;         
4100             }
4101             else{
4102               MarkSeedFree( seed ); seed = 0;
4103               continue;
4104             
4105             }
4106           }
4107         }
4108       
4109         track->SetSeedType(0);
4110         arr->AddLast(track); // note, track is seed, don't free the seed
4111         seed = new( NextFreeSeed() ) AliTPCseed;        
4112         seed->SetPoolID(fLastSeedID);
4113         nout2++;
4114         // don't consider other combinations
4115         if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
4116           break;
4117       }
4118     }
4119   }
4120   if (fDebug>3){
4121     Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
4122   }
4123   if (seed) MarkSeedFree( seed );
4124 }
4125
4126
4127 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
4128                                  Float_t deltay) {
4129   
4130
4131
4132   //-----------------------------------------------------------------
4133   // This function creates track seeds.
4134   //-----------------------------------------------------------------
4135   // cuts[0]   - fP4 cut
4136   // cuts[1]   - tan(phi)  cut
4137   // cuts[2]   - zvertex cut
4138   // cuts[3]   - fP3 cut
4139
4140
4141   Int_t nin0  = 0;
4142   Int_t nin1  = 0;
4143   Int_t nin2  = 0;
4144   Int_t nin   = 0;
4145   Int_t nout1 = 0;
4146   Int_t nout2 = 0;
4147   Int_t nout3 =0;
4148   Double_t x[5], c[15];
4149   //
4150   // make temporary seed
4151   AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
4152   seed->SetPoolID(fLastSeedID);
4153   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
4154   //  Double_t cs=cos(alpha), sn=sin(alpha);
4155   //
4156   //
4157
4158   // first 3 padrows
4159   Double_t x1 = GetXrow(i1-1);
4160   const    AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
4161   Double_t y1max  = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;  
4162   //
4163   Double_t x1p = GetXrow(i1);
4164   const    AliTPCtrackerRow& kr1p=GetRow(sec,i1);
4165   //
4166   Double_t x1m = GetXrow(i1-2);
4167   const    AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
4168
4169   //
4170   //last 3 padrow for seeding
4171   AliTPCtrackerRow&  kr3  = GetRow((sec+fkNOS)%fkNOS,i1-7);
4172   Double_t    x3   =  GetXrow(i1-7);
4173   //  Double_t    y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;  
4174   //
4175   AliTPCtrackerRow&  kr3p  = GetRow((sec+fkNOS)%fkNOS,i1-6);
4176   Double_t    x3p   = GetXrow(i1-6);
4177   //
4178   AliTPCtrackerRow&  kr3m  = GetRow((sec+fkNOS)%fkNOS,i1-8);
4179   Double_t    x3m   = GetXrow(i1-8);
4180
4181   //
4182   //
4183   // middle padrow
4184   Int_t im = i1-4;                           //middle pad row index
4185   Double_t xm         = GetXrow(im);         // radius of middle pad-row
4186   const AliTPCtrackerRow& krm=GetRow(sec,im);   //middle pad -row
4187   //  Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;  
4188   //
4189   //
4190   Double_t deltax  = x1-x3;
4191   Double_t dymax   = deltax*cuts[1];
4192   Double_t dzmax   = deltax*cuts[3];
4193   //
4194   // loop over clusters  
4195   for (Int_t is=0; is < kr1; is++) {
4196     //
4197     if (kr1[is]->IsUsed(10)) continue;  
4198     if (kr1[is]->IsDisabled()) {
4199       continue;
4200     }
4201
4202     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
4203     //
4204     if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge    
4205     // 
4206     Int_t  index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
4207     Int_t  index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
4208     //    
4209     Double_t y3,   z3;
4210     //
4211     //
4212     UInt_t index;
4213     for (Int_t js=index1; js < index2; js++) {
4214       const AliTPCclusterMI *kcl = kr3[js];
4215       if (kcl->IsDisabled()) {
4216         continue;
4217       }
4218
4219       if (kcl->IsUsed(10)) continue;
4220       y3 = kcl->GetY(); 
4221       // apply angular cuts
4222       if (TMath::Abs(y1-y3)>dymax) continue;
4223       //x3 = x3; 
4224       z3 = kcl->GetZ(); 
4225       if (TMath::Abs(z1-z3)>dzmax) continue;
4226       //
4227       Double_t angley = (y1-y3)/(x1-x3);
4228       Double_t anglez = (z1-z3)/(x1-x3);
4229       //
4230       Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
4231       Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
4232       //
4233       Double_t yyym = angley*(xm-x1)+y1;
4234       Double_t zzzm = anglez*(xm-x1)+z1;
4235
4236       const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
4237       if (!kcm) continue;
4238       if (kcm->IsUsed(10)) continue;
4239       if (kcm->IsDisabled()) {
4240         continue;
4241       }
4242
4243       erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
4244       errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
4245       //
4246       //
4247       //
4248       Int_t used  =0;
4249       Int_t found =0;
4250       //
4251       // look around first
4252       const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
4253                                                       anglez*(x1m-x1)+z1,
4254                                                       erry,errz,index);
4255       //
4256       if (kc1m){
4257         found++;
4258         if (kc1m->IsUsed(10)) used++;
4259       }
4260       const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
4261                                                       anglez*(x1p-x1)+z1,
4262                                                       erry,errz,index);
4263       //
4264       if (kc1p){
4265         found++;
4266         if (kc1p->IsUsed(10)) used++;
4267       }
4268       if (used>1)  continue;
4269       if (found<1) continue; 
4270
4271       //
4272       // look around last
4273       const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
4274                                                       anglez*(x3m-x3)+z3,
4275                                                       erry,errz,index);
4276       //
4277       if (kc3m){
4278         found++;
4279         if (kc3m->IsUsed(10)) used++;
4280       }
4281       else 
4282         continue;
4283       const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
4284                                                       anglez*(x3p-x3)+z3,
4285                                                       erry,errz,index);
4286       //
4287       if (kc3p){
4288         found++;
4289         if (kc3p->IsUsed(10)) used++;
4290       }
4291       else 
4292         continue;
4293       if (used>1)  continue;
4294       if (found<3) continue;       
4295       //
4296       Double_t x2,y2,z2;
4297       x2 = xm;
4298       y2 = kcm->GetY();
4299       z2 = kcm->GetZ();
4300       //
4301                         
4302       x[0]=y1;
4303       x[1]=z1;
4304       x[4]=F1(x1,y1,x2,y2,x3,y3);
4305       //if (TMath::Abs(x[4]) >= cuts[0]) continue;
4306       nin0++;
4307       //
4308       x[2]=F2(x1,y1,x2,y2,x3,y3);
4309       nin1++;
4310       //
4311       x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
4312       //if (TMath::Abs(x[3]) > cuts[3]) continue;
4313       nin2++;
4314       //
4315       //
4316       Double_t sy1=0.1,  sz1=0.1;
4317       Double_t sy2=0.1,  sz2=0.1;
4318       Double_t sy3=0.1,  sy=0.1, sz=0.1;
4319       
4320       Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4321       Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4322       Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4323       Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4324       Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4325       Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4326       
4327       Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
4328       Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
4329       Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
4330       Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
4331       
4332       c[0]=sy1;
4333       c[1]=0.;       c[2]=sz1; 
4334       c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4335       c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
4336       c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4337       c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4338       c[13]=f30*sy1*f40+f32*sy2*f42;
4339       c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4340       
4341       //        if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
4342       
4343       index=kr1.GetIndex(is);
4344       if (seed) {MarkSeedFree( seed ); seed = 0;}
4345       AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
4346       seed->SetPoolID(fLastSeedID);
4347       
4348       track->SetIsSeeding(kTRUE);
4349
4350       nin++;      
4351       FollowProlongation(*track, i1-7,1);
4352       if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 || 
4353           track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
4354         MarkSeedFree( seed ); seed = 0;
4355         continue;
4356       }
4357       nout1++;
4358       nout2++;  
4359       //Int_t rc = 1;
4360       FollowProlongation(*track, i2,1);
4361       track->SetBConstrain(0);
4362       track->SetLastPoint(i1+fInnerSec->GetNRows());  // first cluster in track position
4363       track->SetFirstPoint(track->GetLastPoint());
4364       
4365       if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
4366           track->GetNumberOfClusters()<track->GetNFoundable()*0.7 || 
4367           track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
4368         MarkSeedFree( seed ); seed = 0;
4369         continue;
4370       }
4371    
4372       {
4373         FollowProlongation(*track, TMath::Max(i2-10,0),1);
4374         AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
4375         FollowProlongation(*track2, i2,1);
4376         track2->SetBConstrain(kFALSE);
4377         track2->SetSeedType(4);
4378         arr->AddLast(track2);
4379         MarkSeedFree( seed ); seed = 0;
4380       }
4381       
4382    
4383       //arr->AddLast(track); 
4384       //seed = new AliTPCseed;  
4385       nout3++;
4386     }
4387   }
4388   
4389   if (fDebug>3){
4390     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);
4391   }
4392   if (seed) MarkSeedFree(seed);
4393 }
4394
4395
4396 //_____________________________________________________________________________
4397 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
4398                                  Float_t deltay, Bool_t /*bconstrain*/) {
4399   //-----------------------------------------------------------------
4400   // This function creates track seeds - without vertex constraint
4401   //-----------------------------------------------------------------
4402   // cuts[0]   - fP4 cut        - not applied
4403   // cuts[1]   - tan(phi)  cut
4404   // cuts[2]   - zvertex cut    - not applied 
4405   // cuts[3]   - fP3 cut
4406   Int_t nin0=0;
4407   Int_t nin1=0;
4408   Int_t nin2=0;
4409   Int_t nin3=0;
4410   //  Int_t nin4=0;
4411   //Int_t nin5=0;
4412
4413   
4414
4415   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
4416   //  Double_t cs=cos(alpha), sn=sin(alpha);
4417   Int_t row0 = (i1+i2)/2;
4418   Int_t drow = (i1-i2)/2;
4419   const AliTPCtrackerRow& kr0=fSectors[sec][row0];
4420   AliTPCtrackerRow * kr=0;
4421
4422   AliTPCpolyTrack polytrack;
4423   Int_t nclusters=fSectors[sec][row0];
4424   AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
4425   seed->SetPoolID(fLastSeedID);
4426
4427   Int_t sumused=0;
4428   Int_t cused=0;
4429   Int_t cnused=0;
4430   for (Int_t is=0; is < nclusters; is++) {  //LOOP over clusters
4431     Int_t nfound =0;
4432     Int_t nfoundable =0;
4433     for (Int_t iter =1; iter<2; iter++){   //iterations
4434       const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
4435       const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];      
4436       const AliTPCclusterMI * cl= kr0[is];
4437       if (cl->IsDisabled()) {
4438         continue;
4439       }
4440
4441       if (cl->IsUsed(10)) {
4442         cused++;
4443       }
4444       else{
4445         cnused++;
4446       }
4447       Double_t x = kr0.GetX();
4448       // Initialization of the polytrack
4449       nfound =0;
4450       nfoundable =0;
4451       polytrack.Reset();
4452       //
4453       Double_t y0= cl->GetY();
4454       Double_t z0= cl->GetZ();
4455       Float_t erry = 0;
4456       Float_t errz = 0;
4457       
4458       Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
4459       if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue;  // seed only at the edge
4460       
4461       erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;      
4462       errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;      
4463       polytrack.AddPoint(x,y0,z0,erry, errz);
4464
4465       sumused=0;
4466       if (cl->IsUsed(10)) sumused++;
4467
4468
4469       Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
4470       Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
4471       //
4472       x = krm.GetX();
4473       AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
4474       if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
4475         erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;          
4476         errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
4477         if (cl1->IsUsed(10))  sumused++;
4478         polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
4479       }
4480       //
4481       x = krp.GetX();
4482       AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
4483       if (cl2) {
4484         erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;          
4485         errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
4486         if (cl2->IsUsed(10)) sumused++;  
4487         polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
4488       }
4489       //
4490       if (sumused>0) continue;
4491       nin0++;
4492       polytrack.UpdateParameters();
4493       // follow polytrack
4494       roadz = 1.2;
4495       roady = 1.2;
4496       //
4497       Double_t yn,zn;
4498       nfoundable = polytrack.GetN();
4499       nfound     = nfoundable; 
4500       //
4501       for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
4502         Float_t maxdist = 0.8*(1.+3./(ddrow));
4503         for (Int_t delta = -1;delta<=1;delta+=2){
4504           Int_t row = row0+ddrow*delta;
4505           kr = &(fSectors[sec][row]);
4506           Double_t xn = kr->GetX();
4507           Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
4508           polytrack.GetFitPoint(xn,yn,zn);
4509           if (TMath::Abs(yn)>ymax1) continue;
4510           nfoundable++;
4511           AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
4512           if (cln) {
4513             Float_t dist =  TMath::Sqrt(  (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
4514             if (dist<maxdist){
4515               /*
4516               erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));         
4517               errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4518               if (cln->IsUsed(10)) {
4519                 //      printf("used\n");
4520                 sumused++;
4521                 erry*=2;
4522                 errz*=2;
4523               }
4524               */
4525               erry=0.1;
4526               errz=0.1;
4527               polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4528               nfound++;
4529             }
4530           }
4531         }
4532         if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable))  break;     
4533         polytrack.UpdateParameters();
4534       }           
4535     }
4536     if ( (sumused>3) || (sumused>0.5*nfound))  {
4537       //printf("sumused   %d\n",sumused);
4538       continue;
4539     }
4540     nin1++;
4541     Double_t dy,dz;
4542     polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4543     AliTPCpolyTrack track2;
4544     
4545     polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4546     if (track2.GetN()<0.5*nfoundable) continue;
4547     nin2++;
4548
4549     if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4550       //
4551       // test seed with and without constrain
4552       for (Int_t constrain=0; constrain<=0;constrain++){
4553         // add polytrack candidate
4554
4555         Double_t x[5], c[15];
4556         Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4557         track2.GetBoundaries(x3,x1);    
4558         x2 = (x1+x3)/2.;
4559         track2.GetFitPoint(x1,y1,z1);
4560         track2.GetFitPoint(x2,y2,z2);
4561         track2.GetFitPoint(x3,y3,z3);
4562         //
4563         //is track pointing to the vertex ?
4564         Double_t x0,y0,z0;
4565         x0=0;
4566         polytrack.GetFitPoint(x0,y0,z0);
4567
4568         if (constrain) {
4569           x2 = x3;
4570           y2 = y3;
4571           z2 = z3;
4572           
4573           x3 = 0;
4574           y3 = 0;
4575           z3 = 0;
4576         }
4577         x[0]=y1;
4578         x[1]=z1;
4579         x[4]=F1(x1,y1,x2,y2,x3,y3);
4580                 
4581         //      if (TMath::Abs(x[4]) >= cuts[0]) continue;  //
4582         x[2]=F2(x1,y1,x2,y2,x3,y3);
4583         
4584         //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4585         //x[3]=F3(x1,y1,x2,y2,z1,z2);
4586         x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4587         //if (TMath::Abs(x[3]) > cuts[3]) continue;
4588
4589         
4590         Double_t sy =0.1, sz =0.1;
4591         Double_t sy1=0.02, sz1=0.02;
4592         Double_t sy2=0.02, sz2=0.02;
4593         Double_t sy3=0.02;
4594
4595         if (constrain){
4596           sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4597         }
4598         
4599         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4600         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4601         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4602         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4603         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4604         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4605
4606         Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4607         Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4608         Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4609         Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4610
4611         
4612         c[0]=sy1;
4613         c[1]=0.;       c[2]=sz1;
4614         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4615         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
4616         c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4617         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4618         c[13]=f30*sy1*f40+f32*sy2*f42;
4619         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4620         
4621         //Int_t row1 = fSectors->GetRowNumber(x1);
4622         Int_t row1 = GetRowNumber(x1);
4623
4624         UInt_t index=0;
4625         //kr0.GetIndex(is);
4626         if (seed) {MarkSeedFree( seed ); seed = 0;}
4627         AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4628         seed->SetPoolID(fLastSeedID);
4629         track->SetIsSeeding(kTRUE);
4630         Int_t rc=FollowProlongation(*track, i2);        
4631         if (constrain) track->SetBConstrain(1);
4632         else
4633           track->SetBConstrain(0);
4634         track->SetLastPoint(row1+fInnerSec->GetNRows());  // first cluster in track position
4635         track->SetFirstPoint(track->GetLastPoint());
4636
4637         if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 || 
4638             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
4639             track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4640           MarkSeedFree( seed ); seed = 0;
4641         }
4642         else {
4643           arr->AddLast(track); // track IS seed, don't free seed
4644           seed = new( NextFreeSeed() ) AliTPCseed;
4645           seed->SetPoolID(fLastSeedID);
4646         }
4647         nin3++;
4648       }
4649     }  // if accepted seed
4650   }
4651   if (fDebug>3){
4652     Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4653   }
4654   if (seed) MarkSeedFree( seed );
4655 }
4656
4657
4658 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4659 {
4660   //
4661   //
4662   //reseed using track points
4663   Int_t p0 = int(r0*track->GetNumberOfClusters());     // point 0 
4664   Int_t p1 = int(r1*track->GetNumberOfClusters());
4665   Int_t p2 = int(r2*track->GetNumberOfClusters());   // last point
4666   Int_t pp2=0;
4667   Double_t  x0[3],x1[3],x2[3];
4668   for (Int_t i=0;i<3;i++){
4669     x0[i]=-1;
4670     x1[i]=-1;
4671     x2[i]=-1;
4672   }
4673
4674   // find track position at given ratio of the length
4675   Int_t  sec0=0, sec1=0, sec2=0;
4676   Int_t index=-1;
4677   Int_t clindex;
4678   for (Int_t i=0;i<160;i++){
4679     if (track->GetClusterPointer(i)){
4680       index++;
4681       AliTPCTrackerPoint   *trpoint =track->GetTrackPoint(i);
4682       if ( (index<p0) || x0[0]<0 ){
4683         if (trpoint->GetX()>1){
4684           clindex = track->GetClusterIndex2(i);
4685           if (clindex >= 0){    
4686             x0[0] = trpoint->GetX();
4687             x0[1] = trpoint->GetY();
4688             x0[2] = trpoint->GetZ();
4689             sec0  = ((clindex&0xff000000)>>24)%18;
4690           }
4691         }
4692       }
4693
4694       if ( (index<p1) &&(trpoint->GetX()>1)){
4695         clindex = track->GetClusterIndex2(i);
4696         if (clindex >= 0){
4697           x1[0] = trpoint->GetX();
4698           x1[1] = trpoint->GetY();
4699           x1[2] = trpoint->GetZ();
4700           sec1  = ((clindex&0xff000000)>>24)%18;
4701         }
4702       }
4703       if ( (index<p2) &&(trpoint->GetX()>1)){
4704         clindex = track->GetClusterIndex2(i);
4705         if (clindex >= 0){
4706           x2[0] = trpoint->GetX();
4707           x2[1] = trpoint->GetY();
4708           x2[2] = trpoint->GetZ(); 
4709           sec2  = ((clindex&0xff000000)>>24)%18;
4710           pp2 = i;
4711         }
4712       }
4713     }
4714   }
4715   
4716   Double_t alpha, cs,sn, xx2,yy2;
4717   //
4718   alpha = (sec1-sec2)*fSectors->GetAlpha();
4719   cs = TMath::Cos(alpha);
4720   sn = TMath::Sin(alpha); 
4721   xx2= x1[0]*cs-x1[1]*sn;
4722   yy2= x1[0]*sn+x1[1]*cs;
4723   x1[0] = xx2;
4724   x1[1] = yy2;
4725   //
4726   alpha = (sec0-sec2)*fSectors->GetAlpha();
4727   cs = TMath::Cos(alpha);
4728   sn = TMath::Sin(alpha); 
4729   xx2= x0[0]*cs-x0[1]*sn;
4730   yy2= x0[0]*sn+x0[1]*cs;
4731   x0[0] = xx2;
4732   x0[1] = yy2;
4733   //
4734   //
4735   //
4736   Double_t x[5],c[15];
4737   //
4738   x[0]=x2[1];
4739   x[1]=x2[2];
4740   x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4741   //  if (x[4]>1) return 0;
4742   x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4743   x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4744   //if (TMath::Abs(x[3]) > 2.2)  return 0;
4745   //if (TMath::Abs(x[2]) > 1.99) return 0;
4746   //  
4747   Double_t sy =0.1,  sz =0.1;
4748   //
4749   Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4750   Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4751   Double_t sy3=0.01+track->GetSigmaY2();
4752   //
4753   Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4754   Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4755   Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4756   Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4757   Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4758   Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4759   //
4760   Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4761   Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4762   Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4763   Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4764   
4765   
4766   c[0]=sy1;
4767   c[1]=0.;       c[2]=sz1;
4768   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4769   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
4770   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4771   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4772   c[13]=f30*sy1*f40+f32*sy2*f42;
4773   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4774   
4775   //  Int_t row1 = fSectors->GetRowNumber(x2[0]);
4776   AliTPCseed *seed = new( NextFreeSeed() )  AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4777   seed->SetPoolID(fLastSeedID);
4778   //  Double_t y0,z0,y1,z1, y2,z2;
4779   //seed->GetProlongation(x0[0],y0,z0);
4780   // seed->GetProlongation(x1[0],y1,z1);
4781   //seed->GetProlongation(x2[0],y2,z2);
4782   //  seed =0;
4783   seed->SetLastPoint(pp2);
4784   seed->SetFirstPoint(pp2);
4785   
4786
4787   return seed;
4788 }
4789
4790
4791 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4792 {
4793   //
4794   //
4795   //reseed using founded clusters 
4796   //
4797   // Find the number of clusters
4798   Int_t nclusters = 0;
4799   for (Int_t irow=0;irow<160;irow++){
4800     if (track->GetClusterIndex(irow)>0) nclusters++;
4801   }
4802   //
4803   Int_t ipos[3];
4804   ipos[0] = TMath::Max(int(r0*nclusters),0);             // point 0 cluster
4805   ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1);   // 
4806   ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1);   // last point
4807   //
4808   //
4809   Double_t  xyz[3][3]={{0}};
4810   Int_t     row[3]={0},sec[3]={0,0,0};
4811   //
4812   // find track row position at given ratio of the length
4813   Int_t index=-1;
4814   for (Int_t irow=0;irow<160;irow++){    
4815     if (track->GetClusterIndex2(irow)<0) continue;
4816     index++;
4817     for (Int_t ipoint=0;ipoint<3;ipoint++){
4818       if (index<=ipos[ipoint]) row[ipoint] = irow;
4819     }        
4820   }
4821   //
4822   //Get cluster and sector position
4823   for (Int_t ipoint=0;ipoint<3;ipoint++){
4824     Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4825     AliTPCclusterMI * cl = GetClusterMI(clindex);
4826     if (cl==0) {
4827       //Error("Bug\n");
4828       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
4829       return 0;
4830     }
4831     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
4832     xyz[ipoint][0]  = GetXrow(row[ipoint]);
4833     xyz[ipoint][1]  = cl->GetY();
4834     xyz[ipoint][2]  = cl->GetZ();
4835   }
4836   //
4837   //
4838   // Calculate seed state vector and covariance matrix
4839
4840   Double_t alpha, cs,sn, xx2,yy2;
4841   //
4842   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4843   cs = TMath::Cos(alpha);
4844   sn = TMath::Sin(alpha); 
4845   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4846   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4847   xyz[1][0] = xx2;
4848   xyz[1][1] = yy2;
4849   //
4850   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4851   cs = TMath::Cos(alpha);
4852   sn = TMath::Sin(alpha); 
4853   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4854   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4855   xyz[0][0] = xx2;
4856   xyz[0][1] = yy2;
4857   //
4858   //
4859   //
4860   Double_t x[5],c[15];
4861   //
4862   x[0]=xyz[2][1];
4863   x[1]=xyz[2][2];
4864   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4865   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4866   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4867   //  
4868   Double_t sy =0.1,  sz =0.1;
4869   //
4870   Double_t sy1=0.2, sz1=0.2;
4871   Double_t sy2=0.2, sz2=0.2;
4872   Double_t sy3=0.2;
4873   //
4874   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;
4875   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;
4876   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;
4877   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;
4878   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;
4879   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;
4880   //
4881   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;
4882   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;
4883   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;
4884   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;
4885   
4886   
4887   c[0]=sy1;
4888   c[1]=0.;       c[2]=sz1;
4889   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4890   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
4891   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4892   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4893   c[13]=f30*sy1*f40+f32*sy2*f42;
4894   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4895   
4896   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4897   AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4898   seed->SetPoolID(fLastSeedID);
4899   seed->SetLastPoint(row[2]);
4900   seed->SetFirstPoint(row[2]);  
4901   return seed;
4902 }
4903
4904
4905 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4906 {
4907   //
4908   //
4909   //reseed using founded clusters 
4910   //
4911   Double_t  xyz[3][3];
4912   Int_t     row[3]={0,0,0};
4913   Int_t     sec[3]={0,0,0};
4914   //
4915   // forward direction
4916   if (forward){
4917     for (Int_t irow=r0;irow<160;irow++){
4918       if (track->GetClusterIndex(irow)>0){
4919         row[0] = irow;
4920         break;
4921       }
4922     }
4923     for (Int_t irow=160;irow>r0;irow--){
4924       if (track->GetClusterIndex(irow)>0){
4925         row[2] = irow;
4926         break;
4927       }
4928     }
4929     for (Int_t irow=row[2]-15;irow>row[0];irow--){
4930       if (track->GetClusterIndex(irow)>0){
4931         row[1] = irow;
4932         break;
4933       }
4934     }
4935     //
4936   }
4937   if (!forward){
4938     for (Int_t irow=0;irow<r0;irow++){
4939       if (track->GetClusterIndex(irow)>0){
4940         row[0] = irow;
4941         break;
4942       }
4943     }
4944     for (Int_t irow=r0;irow>0;irow--){
4945       if (track->GetClusterIndex(irow)>0){
4946         row[2] = irow;
4947         break;
4948       }
4949     }    
4950     for (Int_t irow=row[2]-15;irow>row[0];irow--){
4951       if (track->GetClusterIndex(irow)>0){
4952         row[1] = irow;
4953         break;
4954       }
4955     } 
4956   }
4957   //
4958   if ((row[2]-row[0])<20) return 0;
4959   if (row[1]==0) return 0;
4960   //
4961   //
4962   //Get cluster and sector position
4963   for (Int_t ipoint=0;ipoint<3;ipoint++){
4964     Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4965     AliTPCclusterMI * cl = GetClusterMI(clindex);
4966     if (cl==0) {
4967       //Error("Bug\n");
4968       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
4969       return 0;
4970     }
4971     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
4972     xyz[ipoint][0]  = GetXrow(row[ipoint]);
4973     AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);    
4974     if (point&&ipoint<2){
4975       //
4976        xyz[ipoint][1]  = point->GetY();
4977        xyz[ipoint][2]  = point->GetZ();
4978     }
4979     else{
4980       xyz[ipoint][1]  = cl->GetY();
4981       xyz[ipoint][2]  = cl->GetZ();
4982     }
4983   }
4984   //
4985   //
4986   //
4987   //
4988   // Calculate seed state vector and covariance matrix
4989
4990   Double_t alpha, cs,sn, xx2,yy2;
4991   //
4992   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4993   cs = TMath::Cos(alpha);
4994   sn = TMath::Sin(alpha); 
4995   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4996   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4997   xyz[1][0] = xx2;
4998   xyz[1][1] = yy2;
4999   //
5000   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
5001   cs = TMath::Cos(alpha);
5002   sn = TMath::Sin(alpha); 
5003   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
5004   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
5005   xyz[0][0] = xx2;
5006   xyz[0][1] = yy2;
5007   //
5008   //
5009   //
5010   Double_t x[5],c[15];
5011   //
5012   x[0]=xyz[2][1];
5013   x[1]=xyz[2][2];
5014   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
5015   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
5016   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
5017   //  
5018   Double_t sy =0.1,  sz =0.1;
5019   //
5020   Double_t sy1=0.2, sz1=0.2;
5021   Double_t sy2=0.2, sz2=0.2;
5022   Double_t sy3=0.2;
5023   //
5024   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;
5025   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;
5026   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;
5027   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;
5028   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;
5029   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;
5030   //
5031   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;
5032   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;
5033   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;
5034   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;
5035   
5036   
5037   c[0]=sy1;
5038   c[1]=0.;       c[2]=sz1;
5039   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
5040   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
5041   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
5042   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
5043   c[13]=f30*sy1*f40+f32*sy2*f42;
5044   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
5045   
5046   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
5047   AliTPCseed *seed=new( NextFreeSeed() )  AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
5048   seed->SetPoolID(fLastSeedID);
5049   seed->SetLastPoint(row[2]);
5050   seed->SetFirstPoint(row[2]);  
5051   for (Int_t i=row[0];i<row[2];i++){
5052     seed->SetClusterIndex(i, track->GetClusterIndex(i));
5053   }
5054
5055   return seed;
5056 }
5057
5058
5059
5060 void  AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
5061 {
5062   //
5063   //  find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
5064   //                      USES MC LABELS
5065   //  Use AliTPCReconstructor::StreamLevel()& kStreamFindMultiMC if you want to tune parameters - cuts
5066   //
5067   //  Two reasons to have multiple find tracks
5068   //  1. Curling tracks can be find more than once
5069   //  2. Splitted tracks 
5070   //     a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)        
5071   //     b.) Edge effect on the sector boundaries
5072   //
5073   //
5074   //  Algorithm done in 2 phases - because of CPU consumption
5075   //  it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated                           
5076   //
5077   //  Algorihm for curling tracks sign:
5078   //    1 phase -makes a very rough fast cuts to minimize combinatorics
5079   //                 a.) opposite sign
5080   //                 b.) one of the tracks - not pointing to the primary vertex - 
5081   //                 c.) delta tan(theta)
5082   //                 d.) delta phi
5083   //    2 phase - calculates DCA between tracks  - time consument
5084
5085   //
5086   //    fast cuts 
5087   //
5088   //    General cuts    - for splitted tracks and for curling tracks
5089   //
5090   const Float_t kMaxdPhi      = 0.2;  // maximal distance in phi
5091   //
5092   //    Curling tracks cuts
5093   //
5094   //
5095   //
5096   //
5097   Int_t nentries = array->GetEntriesFast();  
5098   AliHelix *helixes      = new AliHelix[nentries];
5099   Float_t  *xm           = new Float_t[nentries];
5100   Float_t  *dz0           = new Float_t[nentries];
5101   Float_t  *dz1           = new Float_t[nentries];
5102   //
5103   //
5104   TStopwatch timer;
5105   timer.Start();
5106   //
5107   // Find track COG in x direction - point with best defined parameters
5108   //
5109   for (Int_t i=0;i<nentries;i++){
5110     AliTPCseed* track = (AliTPCseed*)array->At(i);    
5111     if (!track) continue;
5112     track->SetCircular(0);
5113     new (&helixes[i]) AliHelix(*track);
5114     Int_t ncl=0;
5115     xm[i]=0;
5116     Float_t dz[2];
5117     track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
5118     dz0[i]=dz[0];
5119     dz1[i]=dz[1];
5120     for (Int_t icl=0; icl<160; icl++){
5121       AliTPCclusterMI * cl =  track->GetClusterPointer(icl);
5122       if (cl) {
5123         xm[i]+=cl->GetX();
5124         ncl++;
5125       }
5126     }
5127     if (ncl>0) xm[i]/=Float_t(ncl);
5128   }  
5129   //
5130   for (Int_t i0=0;i0<nentries;i0++){
5131     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5132     if (!track0) continue;    
5133     Float_t xc0 = helixes[i0].GetHelix(6);
5134     Float_t yc0 = helixes[i0].GetHelix(7);
5135     Float_t r0  = helixes[i0].GetHelix(8);
5136     Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
5137     Float_t fi0 = TMath::ATan2(yc0,xc0);
5138     
5139     for (Int_t i1=i0+1;i1<nentries;i1++){
5140       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5141       if (!track1) continue;      
5142       Int_t lab0=track0->GetLabel();
5143       Int_t lab1=track1->GetLabel();
5144       if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
5145       //
5146       Float_t xc1 = helixes[i1].GetHelix(6);
5147       Float_t yc1 = helixes[i1].GetHelix(7);
5148       Float_t r1  = helixes[i1].GetHelix(8);
5149       Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
5150       Float_t fi1 = TMath::ATan2(yc1,xc1);
5151       //
5152       Float_t dfi = fi0-fi1;
5153       //
5154       //
5155       if (dfi>1.5*TMath::Pi())  dfi-=TMath::Pi();  // take care about edge effect 
5156       if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi();  // 
5157       if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
5158         //
5159         // if short tracks with undefined sign 
5160         fi1 =  -TMath::ATan2(yc1,-xc1);
5161         dfi = fi0-fi1;
5162       }
5163       Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
5164       
5165       //
5166       // debug stream to tune "fast cuts" 
5167       //
5168       Double_t dist[3];   // distance at X 
5169       Double_t mdist[3]={0,0,0};  // mean distance X+-40cm
5170       track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
5171       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5172       track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
5173       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5174       track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
5175       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5176       for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
5177       
5178       Float_t sum =0;
5179       Float_t sums=0;
5180       for (Int_t icl=0; icl<160; icl++){
5181         AliTPCclusterMI * cl0 =  track0->GetClusterPointer(icl);
5182         AliTPCclusterMI * cl1 =  track1->GetClusterPointer(icl);
5183         if (cl0&&cl1) {
5184           sum++;
5185           if (cl0==cl1) sums++;
5186         }
5187       }
5188       //
5189       if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) {  // flag: stream MC infomation about the multiple find track (ONLY for MC data)
5190       TTreeSRedirector &cstream = *fDebugStreamer;
5191       cstream<<"Multi"<<
5192         "iter="<<iter<<
5193         "lab0="<<lab0<<
5194         "lab1="<<lab1<<   
5195         "Tr0.="<<track0<<       // seed0
5196         "Tr1.="<<track1<<       // seed1
5197         "h0.="<<&helixes[i0]<<
5198         "h1.="<<&helixes[i1]<<
5199         //
5200         "sum="<<sum<<           //the sum of rows with cl in both
5201         "sums="<<sums<<         //the sum of shared clusters
5202         "xm0="<<xm[i0]<<        // the center of track
5203         "xm1="<<xm[i1]<<        // the x center of track
5204         // General cut variables                   
5205         "dfi="<<dfi<<           // distance in fi angle
5206         "dtheta="<<dtheta<<     // distance int theta angle
5207         //
5208         "dz00="<<dz0[i0]<<
5209         "dz01="<<dz0[i1]<<
5210         "dz10="<<dz1[i1]<<
5211         "dz11="<<dz1[i1]<<
5212         "dist0="<<dist[0]<<     //distance x
5213         "dist1="<<dist[1]<<     //distance y
5214         "dist2="<<dist[2]<<     //distance z
5215         "mdist0="<<mdist[0]<<   //distance x
5216         "mdist1="<<mdist[1]<<   //distance y
5217         "mdist2="<<mdist[2]<<   //distance z
5218         //
5219         "r0="<<r0<<
5220         "rc0="<<rc0<<
5221         "fi0="<<fi0<<
5222         "fi1="<<fi1<<
5223         "r1="<<r1<<
5224         "rc1="<<rc1<<
5225         "\n";
5226         }
5227     }
5228   }    
5229   delete [] helixes;
5230   delete [] xm;
5231   delete [] dz0;
5232   delete [] dz1;
5233   if (AliTPCReconstructor::StreamLevel()>0) {
5234     AliInfo("Time for curling tracks removal DEBUGGING MC");
5235     timer.Print();
5236   }
5237 }
5238
5239
5240
5241 void  AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
5242   //
5243   // Find Splitted tracks and remove the one with worst quality  
5244   // Corresponding debug streamer to tune selections - "Splitted2"
5245   // Algorithm:
5246   // 0. Sort tracks according quality
5247   // 1. Propagate the tracks to the reference radius
5248   // 2. Double_t loop to select close tracks (only to speed up process)
5249   // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
5250   // 4. Delete temporary parameters
5251   // 
5252   const Double_t xref=GetXrow(63);  // reference radius -IROC/OROC boundary
5253   //    rough cuts
5254   const Double_t kCutP1=10;       // delta Z cut 10 cm 
5255   const Double_t kCutP2=0.15;     // delta snp(fi) cut 0.15 
5256   const Double_t kCutP3=0.15;     // delta tgl(theta) cut 0.15
5257   const Double_t kCutAlpha=0.15;  // delta alpha cut
5258   Int_t firstpoint = 0;
5259   Int_t lastpoint = 160;
5260   //
5261   Int_t nentries = array->GetEntriesFast();  
5262   AliExternalTrackParam *params      = new AliExternalTrackParam[nentries];
5263   //
5264   //
5265   TStopwatch timer;
5266   timer.Start();
5267   //
5268   //0.  Sort tracks according quality
5269   //1.  Propagate the ext. param to reference radius
5270   Int_t nseed = array->GetEntriesFast();  
5271   if (nseed<=0) return;
5272   Float_t * quality = new Float_t[nseed];
5273   Int_t   * indexes = new Int_t[nseed];
5274   for (Int_t i=0; i<nseed; i++) {
5275     AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);    
5276     if (!pt){
5277       quality[i]=-1;
5278       continue;
5279     }
5280     pt->UpdatePoints();    //select first last max dens points
5281     Float_t * points = pt->GetPoints();
5282     if (points[3]<0.8) quality[i] =-1;
5283     quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
5284     //prefer high momenta tracks if overlaps
5285     quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
5286     params[i]=(*pt);
5287     AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
5288     AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
5289   }
5290   TMath::Sort(nseed,quality,indexes);
5291   //
5292   // 3. Loop over pair of tracks
5293   //
5294   for (Int_t i0=0; i0<nseed; i0++) {
5295     Int_t index0=indexes[i0];
5296     if (!(array->UncheckedAt(index0))) continue;
5297     AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);  
5298     if (!s1->IsActive()) continue;
5299     AliExternalTrackParam &par0=params[index0];
5300     for (Int_t i1=i0+1; i1<nseed; i1++) {
5301       Int_t index1=indexes[i1];
5302       if (!(array->UncheckedAt(index1))) continue;
5303       AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);  
5304       if (!s2->IsActive()) continue;
5305       if (s2->GetKinkIndexes()[0]!=0)
5306         if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
5307       AliExternalTrackParam &par1=params[index1];
5308       if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
5309       if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
5310       if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
5311       Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
5312       if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
5313       if (TMath::Abs(dAlpha)>kCutAlpha) continue;
5314       //
5315       Int_t sumShared=0;
5316       Int_t nall0=0;
5317       Int_t nall1=0;
5318       Int_t firstShared=lastpoint, lastShared=firstpoint;
5319       Int_t firstRow=lastpoint, lastRow=firstpoint;
5320       //
5321       for (Int_t i=firstpoint;i<lastpoint;i++){
5322         if (s1->GetClusterIndex2(i)>0) nall0++;
5323         if (s2->GetClusterIndex2(i)>0) nall1++;
5324         if  (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
5325           if (i<firstRow) firstRow=i;
5326           if (i>lastRow)  lastRow=i;
5327         }
5328         if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
5329           if (i<firstShared) firstShared=i;
5330           if (i>lastShared)  lastShared=i;
5331           sumShared++;
5332         }
5333       }
5334       Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
5335       Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
5336       
5337       if ((AliTPCReconstructor::StreamLevel()&kStreamSplitted2)>0){ // flag:stream information about discarded TPC tracks pair algorithm 
5338         TTreeSRedirector &cstream = *fDebugStreamer;
5339         Int_t n0=s1->GetNumberOfClusters();
5340         Int_t n1=s2->GetNumberOfClusters();
5341         Int_t n0F=s1->GetNFoundable();
5342         Int_t n1F=s2->GetNFoundable();
5343         Int_t lab0=s1->GetLabel();
5344         Int_t lab1=s2->GetLabel();
5345
5346         cstream<<"Splitted2"<<    // flag:stream information about discarded TPC tracks pair algorithm 
5347           "iter="<<fIteration<<
5348           "lab0="<<lab0<<        // MC label if exist
5349           "lab1="<<lab1<<        // MC label if exist
5350           "index0="<<index0<<
5351           "index1="<<index1<<
5352           "ratio0="<<ratio0<<      // shared ratio
5353           "ratio1="<<ratio1<<      // shared ratio
5354           "p0.="<<&par0<<        // track parameters
5355           "p1.="<<&par1<<
5356           "s0.="<<s1<<           // full seed
5357           "s1.="<<s2<<
5358           "n0="<<n0<<     // number of clusters track 0
5359           "n1="<<n1<<     // number of clusters track 1
5360           "nall0="<<nall0<<     // number of clusters track 0
5361           "nall1="<<nall1<<     // number of clusters track 1
5362           "n0F="<<n0F<<   // number of findable
5363           "n1F="<<n1F<<   // number of findable
5364           "shared="<<sumShared<<    // number of shared clusters
5365           "firstS="<<firstShared<<  // first and the last shared row
5366           "lastS="<<lastShared<<
5367           "firstRow="<<firstRow<<   // first and the last row with cluster
5368           "lastRow="<<lastRow<<     //
5369           "\n";
5370       }
5371       //
5372       // remove track with lower quality
5373       //
5374       if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
5375           ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
5376         //
5377         //
5378         //
5379         MarkSeedFree( array->RemoveAt(index1) );
5380       }
5381     }
5382   }
5383   //
5384   // 4. Delete temporary array
5385   //
5386   delete [] params; 
5387   delete [] quality;
5388   delete [] indexes;
5389
5390 }
5391
5392
5393
5394 void  AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
5395 {
5396   //
5397   //  find Curling tracks
5398   //  Use AliTPCReconstructor::StreamLevel()&kStreamFindCurling if you want to tune parameters - cuts
5399   //
5400   //
5401   //  Algorithm done in 2 phases - because of CPU consumption
5402   //  it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated                           
5403   //  see detal in MC part what can be used to cut
5404   //
5405   //    
5406   //
5407   const Float_t kMaxC         = 400;  // maximal curvature to of the track
5408   const Float_t kMaxdTheta    = 0.15;  // maximal distance in theta
5409   const Float_t kMaxdPhi      = 0.15;  // maximal distance in phi
5410   const Float_t kPtRatio      = 0.3; // ratio between pt
5411   const Float_t kMinDCAR      = 2.;   // distance to the primary vertex in r - see cpipe cut      
5412
5413   //
5414   //    Curling tracks cuts
5415   //
5416   //
5417   const Float_t kMaxDeltaRMax = 40;   // distance in outer radius
5418   const Float_t kMaxDeltaRMin = 5.;   // distance in lower radius - see cpipe cut
5419   const Float_t kMinAngle     = 2.9;  // angle between tracks
5420   const Float_t kMaxDist      = 5;    // biggest distance 
5421   //
5422   // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
5423   /* 
5424      Fast cuts:
5425      TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
5426      TCut cmax("cmax","abs(Tr0.GetC())>1/400");
5427      TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
5428      TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
5429      TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");    
5430      //
5431      TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
5432      TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
5433      //
5434      Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill 
5435      Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
5436      //
5437      Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
5438
5439   */
5440   //  
5441   //
5442   //
5443   Int_t nentries = array->GetEntriesFast();  
5444   AliHelix *helixes      = new AliHelix[nentries];
5445   for (Int_t i=0;i<nentries;i++){
5446     AliTPCseed* track = (AliTPCseed*)array->At(i);    
5447     if (!track) continue;
5448     track->SetCircular(0);
5449     new (&helixes[i]) AliHelix(*track);
5450   }
5451   //
5452   //
5453   TStopwatch timer;
5454   timer.Start();
5455   Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5456
5457   //
5458   // Find tracks
5459   //
5460   //
5461   for (Int_t i0=0;i0<nentries;i0++){
5462     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5463     if (!track0) continue;    
5464     if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
5465     Float_t xc0 = helixes[i0].GetHelix(6);
5466     Float_t yc0 = helixes[i0].GetHelix(7);
5467     Float_t r0  = helixes[i0].GetHelix(8);
5468     Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
5469     Float_t fi0 = TMath::ATan2(yc0,xc0);
5470     
5471     for (Int_t i1=i0+1;i1<nentries;i1++){
5472       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5473       if (!track1) continue;      
5474       if (TMath::Abs(track1->GetC())<1/kMaxC) continue;    
5475       Float_t xc1 = helixes[i1].GetHelix(6);
5476       Float_t yc1 = helixes[i1].GetHelix(7);
5477       Float_t r1  = helixes[i1].GetHelix(8);
5478       Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
5479       Float_t fi1 = TMath::ATan2(yc1,xc1);
5480       //
5481       Float_t dfi = fi0-fi1;
5482       //
5483       //
5484       if (dfi>1.5*TMath::Pi())  dfi-=TMath::Pi();  // take care about edge effect 
5485       if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi();  // 
5486       Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
5487       //
5488       //
5489       // FIRST fast cuts
5490       if (track0->GetBConstrain()&&track1->GetBConstrain())  continue;  // not constrained
5491       if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0)   continue; // not the same sign
5492       if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
5493       if ( TMath::Abs(dfi)>kMaxdPhi) continue;  //distance in phi
5494       if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
5495       //
5496       Float_t pt0 = track0->GetSignedPt();
5497       Float_t pt1 = track1->GetSignedPt();
5498       if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;      
5499       if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
5500       if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
5501       if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
5502       //
5503       //
5504       // Now find closest approach
5505       //
5506       //
5507       //
5508       Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5509       if (npoints==0) continue;
5510       helixes[i0].GetClosestPhases(helixes[i1], phase);
5511       //
5512       Double_t xyz0[3];
5513       Double_t xyz1[3];
5514       Double_t hangles[3];
5515       helixes[i0].Evaluate(phase[0][0],xyz0);
5516       helixes[i1].Evaluate(phase[0][1],xyz1);
5517
5518       helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5519       Double_t deltah[2],deltabest;
5520       if (TMath::Abs(hangles[2])<kMinAngle) continue;
5521
5522       if (npoints>0){
5523         Int_t ibest=0;
5524         helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5525         if (npoints==2){
5526           helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5527           if (deltah[1]<deltah[0]) ibest=1;
5528         }
5529         deltabest  = TMath::Sqrt(deltah[ibest]);
5530         helixes[i0].Evaluate(phase[ibest][0],xyz0);
5531         helixes[i1].Evaluate(phase[ibest][1],xyz1);
5532         helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5533         Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5534         //
5535         if (deltabest>kMaxDist) continue;
5536         //      if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5537         Bool_t sign =kFALSE;
5538         if (hangles[2]>kMinAngle) sign =kTRUE;
5539         //
5540         if (sign){
5541           //      circular[i0] = kTRUE;
5542           //      circular[i1] = kTRUE;
5543           if (track0->OneOverPt()<track1->OneOverPt()){
5544             track0->SetCircular(track0->GetCircular()+1);
5545             track1->SetCircular(track1->GetCircular()+2);
5546           }
5547           else{
5548             track1->SetCircular(track1->GetCircular()+1);
5549             track0->SetCircular(track0->GetCircular()+2);
5550           }
5551         }               
5552         if ((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0){  // flag: stream track infroamtion if the FindCurling tracks method       
5553           //
5554           //debug stream to tune "fine" cuts      
5555           Int_t lab0=track0->GetLabel();
5556           Int_t lab1=track1->GetLabel();
5557           TTreeSRedirector &cstream = *fDebugStreamer;
5558           cstream<<"Curling2"<<
5559             "iter="<<iter<<
5560             "lab0="<<lab0<<
5561             "lab1="<<lab1<<   
5562             "Tr0.="<<track0<<
5563             "Tr1.="<<track1<<
5564             //
5565             "r0="<<r0<<
5566             "rc0="<<rc0<<
5567             "fi0="<<fi0<<
5568             "r1="<<r1<<
5569             "rc1="<<rc1<<
5570             "fi1="<<fi1<<
5571             "dfi="<<dfi<<
5572             "dtheta="<<dtheta<<
5573             //
5574             "npoints="<<npoints<<                      
5575             "hangles0="<<hangles[0]<<
5576             "hangles1="<<hangles[1]<<
5577             "hangles2="<<hangles[2]<<                    
5578             "xyz0="<<xyz0[2]<<
5579             "xyzz1="<<xyz1[2]<<
5580             "radius="<<radiusbest<<
5581             "deltabest="<<deltabest<< 
5582             "phase0="<<phase[ibest][0]<<
5583             "phase1="<<phase[ibest][1]<<
5584             "\n";                 
5585
5586         }
5587       }
5588     }
5589   }
5590   delete [] helixes;
5591   if (AliTPCReconstructor::StreamLevel()>1) {
5592     AliInfo("Time for curling tracks removal");
5593     timer.Print();
5594   }
5595 }
5596
5597
5598 void  AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5599 {
5600   //
5601   //  find kinks
5602   //
5603   //
5604   // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5605   // to check later
5606
5607   TObjArray *kinks= new TObjArray(10000);
5608   //  TObjArray *v0s= new TObjArray(10000);
5609   Int_t nentries = array->GetEntriesFast();
5610   AliHelix *helixes      = new AliHelix[nentries];
5611   Int_t    *sign         = new Int_t[nentries];
5612   Int_t    *nclusters    = new Int_t[nentries];
5613   Float_t  *alpha        = new Float_t[nentries];
5614   AliKink  *kink         = new AliKink();
5615   Int_t      * usage     = new Int_t[nentries];
5616   Float_t  *zm           = new Float_t[nentries];
5617   Float_t  *z0           = new Float_t[nentries]; 
5618   Float_t  *fim          = new Float_t[nentries];
5619   Float_t  *shared       = new Float_t[nentries];
5620   Bool_t   *circular     = new Bool_t[nentries];
5621   Float_t *dca          = new Float_t[nentries];
5622   //const AliESDVertex * primvertex = esd->GetVertex();
5623   //
5624   //  nentries = array->GetEntriesFast();
5625   //
5626   
5627   //
5628   //
5629   for (Int_t i=0;i<nentries;i++){
5630     sign[i]=0;
5631     usage[i]=0;
5632     AliTPCseed* track = (AliTPCseed*)array->At(i);    
5633     if (!track) continue;
5634     track->SetCircular(0);
5635     shared[i] = kFALSE;
5636     track->UpdatePoints();
5637     if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5638     }
5639     nclusters[i]=track->GetNumberOfClusters();
5640     alpha[i] = track->GetAlpha();
5641     new (&helixes[i]) AliHelix(*track);
5642     Double_t xyz[3];
5643     helixes[i].Evaluate(0,xyz);
5644     sign[i] = (track->GetC()>0) ? -1:1;
5645     Double_t x,y,z;
5646     x=160;
5647     if (track->GetProlongation(x,y,z)){
5648       zm[i]  = z;
5649       fim[i] = alpha[i]+TMath::ATan2(y,x);
5650     }
5651     else{
5652       zm[i]  = track->GetZ();
5653       fim[i] = alpha[i];
5654     }   
5655     z0[i]=1000;
5656     circular[i]= kFALSE;
5657     if (track->GetProlongation(0,y,z))  z0[i] = z;
5658     dca[i] = track->GetD(0,0);    
5659   }
5660   //
5661   //
5662   TStopwatch timer;
5663   timer.Start();
5664   Int_t ncandidates =0;
5665   Int_t nall =0;
5666   Int_t ntracks=0; 
5667   Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5668
5669   //
5670   // Find circling track
5671   //
5672   for (Int_t i0=0;i0<nentries;i0++){
5673     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5674     if (!track0) continue;    
5675     if (track0->GetNumberOfClusters()<40) continue;
5676     if (TMath::Abs(1./track0->GetC())>200) continue;
5677     for (Int_t i1=i0+1;i1<nentries;i1++){
5678       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5679       if (!track1) continue;
5680       if (track1->GetNumberOfClusters()<40)                  continue;
5681       if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5682       if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5683       if (TMath::Abs(1./track1->GetC())>200) continue;
5684       if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0)      continue;
5685       if (track1->GetTgl()*track0->GetTgl()>0)      continue;
5686       if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5687       if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5688       if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5689       //
5690       Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5691       if (mindcar<5)   continue;
5692       Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5693       if (mindcaz<5) continue;
5694       if (mindcar+mindcaz<20) continue;
5695       //
5696       //
5697       Float_t xc0 = helixes[i0].GetHelix(6);
5698       Float_t yc0 = helixes[i0].GetHelix(7);
5699       Float_t r0  = helixes[i0].GetHelix(8);
5700       Float_t xc1 = helixes[i1].GetHelix(6);
5701       Float_t yc1 = helixes[i1].GetHelix(7);
5702       Float_t r1  = helixes[i1].GetHelix(8);
5703         
5704       Float_t rmean = (r0+r1)*0.5;
5705       Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5706       //if (delta>30) continue;
5707       if (delta>rmean*0.25) continue;
5708       if (TMath::Abs(r0-r1)/rmean>0.3) continue; 
5709       //
5710       Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5711       if (npoints==0) continue;
5712       helixes[i0].GetClosestPhases(helixes[i1], phase);
5713       //
5714       Double_t xyz0[3];
5715       Double_t xyz1[3];
5716       Double_t hangles[3];
5717       helixes[i0].Evaluate(phase[0][0],xyz0);
5718       helixes[i1].Evaluate(phase[0][1],xyz1);
5719
5720       helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5721       Double_t deltah[2],deltabest;
5722       if (hangles[2]<2.8) continue;
5723       if (npoints>0){
5724         Int_t ibest=0;
5725         helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5726         if (npoints==2){
5727           helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5728           if (deltah[1]<deltah[0]) ibest=1;
5729         }
5730         deltabest  = TMath::Sqrt(deltah[ibest]);
5731         helixes[i0].Evaluate(phase[ibest][0],xyz0);
5732         helixes[i1].Evaluate(phase[ibest][1],xyz1);
5733         helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5734         Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5735         //
5736         if (deltabest>6) continue;
5737         if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5738         Bool_t lsign =kFALSE;
5739         if (hangles[2]>3.06) lsign =kTRUE;
5740         //
5741         if (lsign){
5742           circular[i0] = kTRUE;
5743           circular[i1] = kTRUE;
5744           if (track0->OneOverPt()<track1->OneOverPt()){
5745             track0->SetCircular(track0->GetCircular()+1);
5746             track1->SetCircular(track1->GetCircular()+2);
5747           }
5748           else{
5749             track1->SetCircular(track1->GetCircular()+1);
5750             track0->SetCircular(track0->GetCircular()+2);
5751           }
5752         }               
5753         if (lsign&&((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0)){          
5754           //debug stream          
5755           Int_t lab0=track0->GetLabel();
5756           Int_t lab1=track1->GetLabel();
5757           TTreeSRedirector &cstream = *fDebugStreamer;
5758           cstream<<"Curling"<<
5759             "lab0="<<lab0<<
5760             "lab1="<<lab1<<   
5761             "Tr0.="<<track0<<
5762             "Tr1.="<<track1<<      
5763             "dca0="<<dca[i0]<<
5764             "dca1="<<dca[i1]<<
5765             "mindcar="<<mindcar<<
5766             "mindcaz="<<mindcaz<<
5767             "delta="<<delta<<
5768             "rmean="<<rmean<<
5769             "npoints="<<npoints<<                      
5770             "hangles0="<<hangles[0]<<
5771             "hangles2="<<hangles[2]<<                    
5772             "xyz0="<<xyz0[2]<<
5773             "xyzz1="<<xyz1[2]<<
5774             "z0="<<z0[i0]<<
5775             "z1="<<z0[i1]<<
5776             "radius="<<radiusbest<<
5777             "deltabest="<<deltabest<< 
5778             "phase0="<<phase[ibest][0]<<
5779             "phase1="<<phase[ibest][1]<<
5780             "\n";                 
5781         }
5782       }
5783     }
5784   }
5785   //
5786   //  Finf kinks loop
5787   // 
5788   //
5789   for (Int_t i =0;i<nentries;i++){
5790     if (sign[i]==0) continue;
5791     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5792     if (track0==0) {
5793       AliInfo("seed==0");
5794       continue;
5795     }
5796     ntracks++;
5797     //
5798     Double_t cradius0 = 40*40;
5799     Double_t cradius1 = 270*270;
5800     Double_t cdist1=8.;
5801     Double_t cdist2=8.;
5802     Double_t cdist3=0.55; 
5803     for (Int_t j =i+1;j<nentries;j++){
5804       nall++;
5805       if (sign[j]*sign[i]<1) continue;
5806       if ( (nclusters[i]+nclusters[j])>200) continue;
5807       if ( (nclusters[i]+nclusters[j])<80) continue;
5808       if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5809       if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5810       //AliTPCseed * track1 = (AliTPCseed*)array->At(j);  Double_t phase[2][2],radius[2];    
5811       Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5812       if (npoints<1) continue;
5813       // cuts on radius      
5814       if (npoints==1){
5815         if (radius[0]<cradius0||radius[0]>cradius1) continue;
5816       }
5817       else{
5818         if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5819       }
5820       //      
5821       Double_t delta1=10000,delta2=10000;
5822       // cuts on the intersection radius
5823       helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5824       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5825       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5826       if (npoints==2){ 
5827         helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5828         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
5829         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
5830       }
5831       //
5832       Double_t distance1 = TMath::Min(delta1,delta2);
5833       if (distance1>cdist1) continue;  // cut on DCA linear approximation
5834       //
5835       npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5836       helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5837       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5838       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5839       //
5840       if (npoints==2){ 
5841         helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);   
5842         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
5843         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
5844       }            
5845       distance1 = TMath::Min(delta1,delta2);
5846       Float_t rkink =0;
5847       if (delta1<delta2){
5848         rkink = TMath::Sqrt(radius[0]);
5849       }
5850       else{
5851         rkink = TMath::Sqrt(radius[1]);
5852       }
5853       if (distance1>cdist2) continue;
5854       //
5855       //
5856       AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5857       //
5858       //
5859       Int_t row0 = GetRowNumber(rkink); 
5860       if (row0<10)  continue;
5861       if (row0>150) continue;
5862       //
5863       //
5864       Float_t dens00=-1,dens01=-1;
5865       Float_t dens10=-1,dens11=-1;
5866       //
5867       Int_t found,foundable,ishared;
5868       track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5869       if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5870       track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5871       if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5872       //
5873       track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5874       if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5875       track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5876       if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5877       //     
5878       if (dens00<dens10 && dens01<dens11) continue;
5879       if (dens00>dens10 && dens01>dens11) continue;
5880       if (TMath::Max(dens00,dens10)<0.1)  continue;
5881       if (TMath::Max(dens01,dens11)<0.3)  continue;
5882       //
5883       if (TMath::Min(dens00,dens10)>0.6)  continue;
5884       if (TMath::Min(dens01,dens11)>0.6)  continue;
5885
5886       //
5887       AliTPCseed * ktrack0, *ktrack1;
5888       if (dens00>dens10){
5889         ktrack0 = track0;
5890         ktrack1 = track1;
5891       }
5892       else{
5893         ktrack0 = track1;
5894         ktrack1 = track0;
5895       }
5896       if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5897       AliExternalTrackParam paramm(*ktrack0);
5898       AliExternalTrackParam paramd(*ktrack1);
5899       if (row0>60&&ktrack1->GetReference().GetX()>90.)new (&paramd) AliExternalTrackParam(ktrack1->GetReference()); 
5900       //
5901       //
5902       kink->SetMother(paramm);
5903       kink->SetDaughter(paramd);
5904       kink->Update();
5905
5906       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])};
5907       Int_t index[4];
5908       fkParam->Transform0to1(x,index);
5909       fkParam->Transform1to2(x,index);
5910       row0 = GetRowNumber(x[0]); 
5911
5912       if (kink->GetR()<100) continue;
5913       if (kink->GetR()>240) continue;
5914       if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue;  //out of fiducial volume
5915       if (kink->GetDistance()>cdist3) continue;
5916       Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1];  // rough direction estimate
5917       if (dird<0) continue;
5918
5919       Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1];  // rough direction estimate
5920       if (dirm<0) continue;
5921       Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5922       if (mpt<0.2) continue;
5923
5924       if (mpt<1){
5925         //for high momenta momentum not defined well in first iteration
5926         Double_t qt   =  TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5927         if (qt>0.35) continue; 
5928       }
5929       
5930       kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5931       kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5932       if (dens00>dens10){
5933         kink->SetTPCDensity(dens00,0,0);
5934         kink->SetTPCDensity(dens01,0,1);
5935         kink->SetTPCDensity(dens10,1,0);
5936         kink->SetTPCDensity(dens11,1,1);
5937         kink->SetIndex(i,0);
5938         kink->SetIndex(j,1);
5939       }
5940       else{
5941         kink->SetTPCDensity(dens10,0,0);
5942         kink->SetTPCDensity(dens11,0,1);
5943         kink->SetTPCDensity(dens00,1,0);
5944         kink->SetTPCDensity(dens01,1,1);
5945         kink->SetIndex(j,0);
5946         kink->SetIndex(i,1);
5947       }
5948
5949       if (mpt<1||kink->GetAngle(2)>0.1){
5950         //      angle and densities  not defined yet
5951         if (kink->GetTPCDensityFactor()<0.8) continue;
5952         if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5953         if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5954         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5955         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5956
5957         Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5958         criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5959         criticalangle= 3*TMath::Sqrt(criticalangle);
5960         if (criticalangle>0.02) criticalangle=0.02;
5961         if (kink->GetAngle(2)<criticalangle) continue;
5962       }
5963       //
5964       Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2)));  // overlap region defined
5965       Float_t shapesum =0;
5966       Float_t sum = 0;
5967       for ( Int_t row = row0-drow; row<row0+drow;row++){
5968         if (row<0) continue;
5969         if (row>155) continue;
5970         if (ktrack0->GetClusterPointer(row)){
5971           AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5972           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5973           sum++;
5974         }
5975         if (ktrack1->GetClusterPointer(row)){
5976           AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5977           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5978           sum++;
5979         }       
5980       }
5981       if (sum<4){
5982         kink->SetShapeFactor(-1.);
5983       }
5984       else{
5985         kink->SetShapeFactor(shapesum/sum);
5986       }      
5987       //      esd->AddKink(kink);
5988       //
5989       //      kink->SetMother(paramm);
5990       //kink->SetDaughter(paramd);
5991  
5992       Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5993       chi2P2*=chi2P2;
5994       chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5995       Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5996       chi2P3*=chi2P3;
5997       chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5998       //
5999       if ((AliTPCReconstructor::StreamLevel()&kStreamFindKinks)>0) {   // flag: stream track infroamtion in the FindKinks method
6000         (*fDebugStreamer)<<"kinkLpt"<<
6001           "chi2P2="<<chi2P2<<
6002           "chi2P3="<<chi2P3<<
6003           "p0.="<<&paramm<<
6004           "p1.="<<&paramd<<
6005           "k.="<<kink<<
6006           "\n";
6007       }
6008       if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6009         continue;
6010       }
6011       //
6012       kinks->AddLast(kink);
6013       kink = new AliKink;
6014       ncandidates++;
6015     }
6016   }
6017   //
6018   // sort the kinks according quality - and refit them towards vertex
6019   //
6020   Int_t       nkinks    = kinks->GetEntriesFast();
6021   Float_t    *quality   = new Float_t[nkinks];
6022   Int_t      *indexes   = new Int_t[nkinks];
6023   AliTPCseed *mothers   = new AliTPCseed[nkinks];
6024   AliTPCseed *daughters = new AliTPCseed[nkinks];
6025   //
6026   //
6027   for (Int_t i=0;i<nkinks;i++){
6028     quality[i] =100000;
6029     AliKink *kinkl = (AliKink*)kinks->At(i);
6030     //
6031     // refit kinks towards vertex
6032     // 
6033     Int_t index0 = kinkl->GetIndex(0);
6034     Int_t index1 = kinkl->GetIndex(1);
6035     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6036     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6037     //
6038     Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6039     //
6040     // Refit Kink under if too small angle
6041     //
6042     if (kinkl->GetAngle(2)<0.05){
6043       kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6044       Int_t row0 = kinkl->GetTPCRow0();
6045       Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6046       //
6047       //
6048       Int_t last  = row0-drow;
6049       if (last<40) last=40;
6050       if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6051       AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6052       //
6053       //
6054       Int_t first = row0+drow;
6055       if (first>130) first=130;
6056       if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6057       AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6058       //
6059       if (seed0 && seed1){
6060         kinkl->SetStatus(1,8);
6061         if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6062         row0 = GetRowNumber(kinkl->GetR());
6063         sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6064         mothers[i] = *seed0;
6065         daughters[i] = *seed1;
6066       }
6067       else{
6068         delete kinks->RemoveAt(i);
6069         if (seed0) MarkSeedFree( seed0 );
6070         if (seed1) MarkSeedFree( seed1 );
6071         continue;
6072       }
6073       if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6074         delete kinks->RemoveAt(i);
6075         if (seed0) MarkSeedFree( seed0 );
6076         if (seed1) MarkSeedFree( seed1 );
6077         continue;
6078       }
6079       //
6080       MarkSeedFree( seed0 );
6081       MarkSeedFree( seed1 );
6082     }
6083     //
6084     if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.);  //the longest -clossest will win
6085   }
6086   TMath::Sort(nkinks,quality,indexes,kFALSE);
6087   //
6088   //remove double find kinks
6089   //
6090   for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6091     AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6092     if (!kink0) continue;
6093     //
6094     for (Int_t ikink1=0;ikink1<ikink0;ikink1++){ 
6095       kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6096       if (!kink0) continue;
6097       AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6098       if (!kink1) continue;
6099       // if not close kink continue
6100       if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6101       if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6102       if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6103       //
6104       AliTPCseed &mother0   = mothers[indexes[ikink0]];
6105       AliTPCseed &daughter0 = daughters[indexes[ikink0]];
6106       AliTPCseed &mother1   = mothers[indexes[ikink1]];
6107       AliTPCseed &daughter1 = daughters[indexes[ikink1]];
6108       Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6109       //
6110       Int_t same  = 0;
6111       Int_t both  = 0;
6112       Int_t samem = 0;
6113       Int_t bothm = 0;
6114       Int_t samed = 0;
6115       Int_t bothd = 0;
6116       //
6117       for (Int_t i=0;i<row0;i++){
6118         if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6119           both++;
6120           bothm++;
6121           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6122             same++;
6123             samem++;
6124           }
6125         }
6126       }
6127
6128       for (Int_t i=row0;i<158;i++){
6129         //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug? 
6130         if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6131           both++;
6132           bothd++;
6133           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6134             same++;
6135             samed++;
6136           }
6137         }
6138       }
6139       Float_t ratio = Float_t(same+1)/Float_t(both+1);
6140       Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6141       Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6142       if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6143         Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6144         Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6145         if (sum1>sum0){
6146           shared[kink0->GetIndex(0)]= kTRUE;
6147           shared[kink0->GetIndex(1)]= kTRUE;      
6148           delete kinks->RemoveAt(indexes[ikink0]);
6149           break;
6150         }
6151         else{
6152           shared[kink1->GetIndex(0)]= kTRUE;
6153           shared[kink1->GetIndex(1)]= kTRUE;      
6154           delete kinks->RemoveAt(indexes[ikink1]);
6155         }
6156       }
6157     }
6158   }
6159
6160
6161   for (Int_t i=0;i<nkinks;i++){
6162     AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6163     if (!kinkl) continue;
6164     kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6165     Int_t index0 = kinkl->GetIndex(0);
6166     Int_t index1 = kinkl->GetIndex(1);
6167     if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6168     kinkl->SetMultiple(usage[index0],0);
6169     kinkl->SetMultiple(usage[index1],1);
6170     if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6171     if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6172     if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6173     if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6174
6175     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6176     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6177     if (!ktrack0 || !ktrack1) continue;
6178     Int_t index = esd->AddKink(kinkl);
6179     //
6180     //
6181     if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) {  //best kink
6182       if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
6183         *ktrack0 = mothers[indexes[i]];
6184         *ktrack1 = daughters[indexes[i]];
6185       }
6186     }
6187     //
6188     ktrack0->SetKinkIndex(usage[index0],-(index+1));
6189     ktrack1->SetKinkIndex(usage[index1], (index+1));
6190     usage[index0]++;
6191     usage[index1]++;
6192   }
6193   //
6194   // Remove tracks corresponding to shared kink's
6195   //
6196   for (Int_t i=0;i<nentries;i++){
6197     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6198     if (!track0) continue;
6199     if (track0->GetKinkIndex(0)!=0) continue;
6200     if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6201   }
6202
6203   //
6204   //
6205   RemoveUsed2(array,0.5,0.4,30);
6206   UnsignClusters();
6207   for (Int_t i=0;i<nentries;i++){
6208     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6209     if (!track0) continue;
6210     track0->CookdEdx(0.02,0.6);
6211     track0->CookPID();
6212   }
6213   //
6214   for (Int_t i=0;i<nentries;i++){
6215     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6216     if (!track0) continue;
6217     if (track0->Pt()<1.4) continue;
6218     //remove double high momenta tracks - overlapped with kink candidates
6219     Int_t ishared=0;
6220     Int_t all   =0;
6221     for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6222       if (track0->GetClusterPointer(icl)!=0){
6223         all++;
6224         if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6225       }
6226     }
6227     if (Float_t(ishared+1)/Float_t(all+1)>0.5) {  
6228       MarkSeedFree( array->RemoveAt(i) );
6229       continue;
6230     }
6231     //
6232     if (track0->GetKinkIndex(0)!=0) continue;
6233     if (track0->GetNumberOfClusters()<80) continue;
6234
6235     AliTPCseed *pmother = new AliTPCseed();
6236     AliTPCseed *pdaughter = new AliTPCseed();
6237     AliKink *pkink = new AliKink;
6238
6239     AliTPCseed & mother = *pmother;
6240     AliTPCseed & daughter = *pdaughter;
6241     AliKink & kinkl = *pkink;
6242     if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6243       if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6244         delete pmother;
6245         delete pdaughter;
6246         delete pkink;
6247         continue;  //too short tracks
6248       }
6249       if (mother.Pt()<1.4) {
6250         delete pmother;
6251         delete pdaughter;
6252         delete pkink;
6253         continue;
6254       }
6255       Int_t row0= kinkl.GetTPCRow0();
6256       if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6257         delete pmother;
6258         delete pdaughter;
6259         delete pkink;
6260         continue;
6261       }
6262       //
6263       Int_t index = esd->AddKink(&kinkl);      
6264       mother.SetKinkIndex(0,-(index+1));
6265       daughter.SetKinkIndex(0,index+1);
6266       if (mother.GetNumberOfClusters()>50) {
6267         MarkSeedFree( array->RemoveAt(i) );
6268         AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6269         mtc->SetPoolID(fLastSeedID);
6270         array->AddAt(mtc,i);
6271       }
6272       else{
6273         AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6274         mtc->SetPoolID(fLastSeedID);
6275         array->AddLast(mtc);
6276       }
6277       AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6278       dtc->SetPoolID(fLastSeedID);
6279       array->AddLast(dtc);      
6280       for (Int_t icl=0;icl<row0;icl++) {
6281         if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6282       }
6283       //
6284       for (Int_t icl=row0;icl<158;icl++) {
6285         if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6286       }
6287       //
6288     }
6289     delete pmother;
6290     delete pdaughter;
6291     delete pkink;
6292   }
6293
6294   delete [] daughters;
6295   delete [] mothers;
6296   //
6297   //
6298   delete [] dca;
6299   delete []circular;
6300   delete []shared;
6301   delete []quality;
6302   delete []indexes;
6303   //
6304   delete kink;
6305   delete[]fim;
6306   delete[] zm;
6307   delete[] z0;
6308   delete [] usage;
6309   delete[] alpha;
6310   delete[] nclusters;
6311   delete[] sign;
6312   delete[] helixes;
6313   kinks->Delete();
6314   delete kinks;
6315
6316   AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6317   timer.Print();
6318 }
6319
6320
6321 /*
6322 void  AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
6323 {
6324   //
6325   //  find kinks
6326   //
6327   //
6328
6329   TObjArray *kinks= new TObjArray(10000);
6330   //  TObjArray *v0s= new TObjArray(10000);
6331   Int_t nentries = array->GetEntriesFast();
6332   AliHelix *helixes      = new AliHelix[nentries];
6333   Int_t    *sign         = new Int_t[nentries];
6334   Int_t    *nclusters    = new Int_t[nentries];
6335   Float_t  *alpha        = new Float_t[nentries];
6336   AliKink  *kink         = new AliKink();
6337   Int_t      * usage     = new Int_t[nentries];
6338   Float_t  *zm           = new Float_t[nentries];
6339   Float_t  *z0           = new Float_t[nentries]; 
6340   Float_t  *fim          = new Float_t[nentries];
6341   Float_t  *shared       = new Float_t[nentries];
6342   Bool_t   *circular     = new Bool_t[nentries];
6343   Float_t *dca          = new Float_t[nentries];
6344   //const AliESDVertex * primvertex = esd->GetVertex();
6345   //
6346   //  nentries = array->GetEntriesFast();
6347   //
6348   
6349   //
6350   //
6351   for (Int_t i=0;i<nentries;i++){
6352     sign[i]=0;
6353     usage[i]=0;
6354     AliTPCseed* track = (AliTPCseed*)array->At(i);    
6355     if (!track) continue;
6356     track->SetCircular(0);
6357     shared[i] = kFALSE;
6358     track->UpdatePoints();
6359     if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
6360     }
6361     nclusters[i]=track->GetNumberOfClusters();
6362     alpha[i] = track->GetAlpha();
6363     new (&helixes[i]) AliHelix(*track);
6364     Double_t xyz[3];
6365     helixes[i].Evaluate(0,xyz);
6366     sign[i] = (track->GetC()>0) ? -1:1;
6367     Double_t x,y,z;
6368     x=160;
6369     if (track->GetProlongation(x,y,z)){
6370       zm[i]  = z;
6371       fim[i] = alpha[i]+TMath::ATan2(y,x);
6372     }
6373     else{
6374       zm[i]  = track->GetZ();
6375       fim[i] = alpha[i];
6376     }   
6377     z0[i]=1000;
6378     circular[i]= kFALSE;
6379     if (track->GetProlongation(0,y,z))  z0[i] = z;
6380     dca[i] = track->GetD(0,0);    
6381   }
6382   //
6383   //
6384   TStopwatch timer;
6385   timer.Start();
6386   Int_t ncandidates =0;
6387   Int_t nall =0;
6388   Int_t ntracks=0; 
6389   Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
6390
6391   //
6392   // Find circling track
6393   //
6394   for (Int_t i0=0;i0<nentries;i0++){
6395     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
6396     if (!track0) continue;    
6397     if (track0->GetNumberOfClusters()<40) continue;
6398     if (TMath::Abs(1./track0->GetC())>200) continue;
6399     for (Int_t i1=i0+1;i1<nentries;i1++){
6400       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
6401       if (!track1) continue;
6402       if (track1->GetNumberOfClusters()<40)                  continue;
6403       if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
6404       if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
6405       if (TMath::Abs(1./track1->GetC())>200) continue;
6406       if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0)      continue;
6407       if (track1->GetTgl()*track0->GetTgl()>0)      continue;
6408       if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
6409       if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
6410       if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
6411       //
6412       Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
6413       if (mindcar<5)   continue;
6414       Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
6415       if (mindcaz<5) continue;
6416       if (mindcar+mindcaz<20) continue;
6417       //
6418       //
6419       Float_t xc0 = helixes[i0].GetHelix(6);
6420       Float_t yc0 = helixes[i0].GetHelix(7);
6421       Float_t r0  = helixes[i0].GetHelix(8);
6422       Float_t xc1 = helixes[i1].GetHelix(6);
6423       Float_t yc1 = helixes[i1].GetHelix(7);
6424       Float_t r1  = helixes[i1].GetHelix(8);
6425         
6426       Float_t rmean = (r0+r1)*0.5;
6427       Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
6428       //if (delta>30) continue;
6429       if (delta>rmean*0.25) continue;
6430       if (TMath::Abs(r0-r1)/rmean>0.3) continue; 
6431       //
6432       Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
6433       if (npoints==0) continue;
6434       helixes[i0].GetClosestPhases(helixes[i1], phase);
6435       //
6436       Double_t xyz0[3];
6437       Double_t xyz1[3];
6438       Double_t hangles[3];
6439       helixes[i0].Evaluate(phase[0][0],xyz0);
6440       helixes[i1].Evaluate(phase[0][1],xyz1);
6441
6442       helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
6443       Double_t deltah[2],deltabest;
6444       if (hangles[2]<2.8) continue;
6445       if (npoints>0){
6446         Int_t ibest=0;
6447         helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
6448         if (npoints==2){
6449           helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
6450           if (deltah[1]<deltah[0]) ibest=1;
6451         }
6452         deltabest  = TMath::Sqrt(deltah[ibest]);
6453         helixes[i0].Evaluate(phase[ibest][0],xyz0);
6454         helixes[i1].Evaluate(phase[ibest][1],xyz1);
6455         helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
6456         Double_t radiusbest = TMath::Sqrt(radius[ibest]);
6457         //
6458         if (deltabest>6) continue;
6459         if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
6460         Bool_t lsign =kFALSE;
6461         if (hangles[2]>3.06) lsign =kTRUE;
6462         //
6463         if (lsign){
6464           circular[i0] = kTRUE;
6465           circular[i1] = kTRUE;
6466           if (track0->OneOverPt()<track1->OneOverPt()){
6467             track0->SetCircular(track0->GetCircular()+1);
6468             track1->SetCircular(track1->GetCircular()+2);
6469           }
6470           else{
6471             track1->SetCircular(track1->GetCircular()+1);
6472             track0->SetCircular(track0->GetCircular()+2);
6473           }
6474         }               
6475         if (lsign&&((AliTPCReconstructor::StreamLevel()&kStreamFindKinks)>0)){// flag: stream track infroamtion in the FindKinks method   
6476           //debug stream          
6477           Int_t lab0=track0->GetLabel();
6478           Int_t lab1=track1->GetLabel();
6479           TTreeSRedirector &cstream = *fDebugStreamer;
6480           cstream<<"Curling"<<
6481             "lab0="<<lab0<<
6482             "lab1="<<lab1<<   
6483             "Tr0.="<<track0<<
6484             "Tr1.="<<track1<<      
6485             "dca0="<<dca[i0]<<
6486             "dca1="<<dca[i1]<<
6487             "mindcar="<<mindcar<<
6488             "mindcaz="<<mindcaz<<
6489             "delta="<<delta<<
6490             "rmean="<<rmean<<
6491             "npoints="<<npoints<<                      
6492             "hangles0="<<hangles[0]<<
6493             "hangles2="<<hangles[2]<<                    
6494             "xyz0="<<xyz0[2]<<
6495             "xyzz1="<<xyz1[2]<<
6496             "z0="<<z0[i0]<<
6497             "z1="<<z0[i1]<<
6498             "radius="<<radiusbest<<
6499             "deltabest="<<deltabest<< 
6500             "phase0="<<phase[ibest][0]<<
6501             "phase1="<<phase[ibest][1]<<
6502             "\n";                 
6503         }
6504       }
6505     }
6506   }
6507   //
6508   //  Finf kinks loop
6509   // 
6510   //
6511   for (Int_t i =0;i<nentries;i++){
6512     if (sign[i]==0) continue;
6513     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6514     if (track0==0) {
6515       AliInfo("seed==0");
6516       continue;
6517     }
6518     ntracks++;
6519     //
6520     Double_t cradius0 = 40*40;
6521     Double_t cradius1 = 270*270;
6522     Double_t cdist1=8.;
6523     Double_t cdist2=8.;
6524     Double_t cdist3=0.55; 
6525     for (Int_t j =i+1;j<nentries;j++){
6526       nall++;
6527       if (sign[j]*sign[i]<1) continue;
6528       if ( (nclusters[i]+nclusters[j])>200) continue;
6529       if ( (nclusters[i]+nclusters[j])<80) continue;
6530       if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6531       if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6532       //AliTPCseed * track1 = (AliTPCseed*)array->At(j);  Double_t phase[2][2],radius[2];    
6533       Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6534       if (npoints<1) continue;
6535       // cuts on radius      
6536       if (npoints==1){
6537         if (radius[0]<cradius0||radius[0]>cradius1) continue;
6538       }
6539       else{
6540         if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6541       }
6542       //      
6543       Double_t delta1=10000,delta2=10000;
6544       // cuts on the intersection radius
6545       helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6546       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6547       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6548       if (npoints==2){ 
6549         helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6550         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
6551         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
6552       }
6553       //
6554       Double_t distance1 = TMath::Min(delta1,delta2);
6555       if (distance1>cdist1) continue;  // cut on DCA linear approximation
6556       //
6557       npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6558       helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6559       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6560       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6561       //
6562       if (npoints==2){ 
6563         helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);   
6564         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
6565         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
6566       }            
6567       distance1 = TMath::Min(delta1,delta2);
6568       Float_t rkink =0;
6569       if (delta1<delta2){
6570         rkink = TMath::Sqrt(radius[0]);
6571       }
6572       else{
6573         rkink = TMath::Sqrt(radius[1]);
6574       }
6575       if (distance1>cdist2) continue;
6576       //
6577       //
6578       AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6579       //
6580       //
6581       Int_t row0 = GetRowNumber(rkink); 
6582       if (row0<10)  continue;
6583       if (row0>150) continue;
6584       //
6585       //
6586       Float_t dens00=-1,dens01=-1;
6587       Float_t dens10=-1,dens11=-1;
6588       //
6589       Int_t found,foundable,ishared;
6590       track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6591       if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6592       track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6593       if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6594       //
6595       track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6596       if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6597       track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6598       if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6599       //     
6600       if (dens00<dens10 && dens01<dens11) continue;
6601       if (dens00>dens10 && dens01>dens11) continue;
6602       if (TMath::Max(dens00,dens10)<0.1)  continue;
6603       if (TMath::Max(dens01,dens11)<0.3)  continue;
6604       //
6605       if (TMath::Min(dens00,dens10)>0.6)  continue;
6606       if (TMath::Min(dens01,dens11)>0.6)  continue;
6607
6608       //
6609       AliTPCseed * ktrack0, *ktrack1;
6610       if (dens00>dens10){
6611         ktrack0 = track0;
6612         ktrack1 = track1;
6613       }
6614       else{
6615         ktrack0 = track1;
6616         ktrack1 = track0;
6617       }
6618       if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6619       AliExternalTrackParam paramm(*ktrack0);
6620       AliExternalTrackParam paramd(*ktrack1);
6621       if (row0>60&&ktrack1->GetReference().GetX()>90.)new (&paramd) AliExternalTrackParam(ktrack1->GetReference()); 
6622       //
6623       //
6624       kink->SetMother(paramm);
6625       kink->SetDaughter(paramd);
6626       kink->Update();
6627
6628       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])};
6629       Int_t index[4];
6630       fkParam->Transform0to1(x,index);
6631       fkParam->Transform1to2(x,index);
6632       row0 = GetRowNumber(x[0]); 
6633
6634       if (kink->GetR()<100) continue;
6635       if (kink->GetR()>240) continue;
6636       if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue;  //out of fiducial volume
6637       if (kink->GetDistance()>cdist3) continue;
6638       Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1];  // rough direction estimate
6639       if (dird<0) continue;
6640
6641       Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1];  // rough direction estimate
6642       if (dirm<0) continue;
6643       Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6644       if (mpt<0.2) continue;
6645
6646       if (mpt<1){
6647         //for high momenta momentum not defined well in first iteration
6648         Double_t qt   =  TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6649         if (qt>0.35) continue; 
6650       }
6651       
6652       kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6653       kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6654       if (dens00>dens10){
6655         kink->SetTPCDensity(dens00,0,0);
6656         kink->SetTPCDensity(dens01,0,1);
6657         kink->SetTPCDensity(dens10,1,0);
6658         kink->SetTPCDensity(dens11,1,1);
6659         kink->SetIndex(i,0);
6660         kink->SetIndex(j,1);
6661       }
6662       else{
6663         kink->SetTPCDensity(dens10,0,0);
6664         kink->SetTPCDensity(dens11,0,1);
6665         kink->SetTPCDensity(dens00,1,0);
6666         kink->SetTPCDensity(dens01,1,1);
6667         kink->SetIndex(j,0);
6668         kink->SetIndex(i,1);
6669       }
6670
6671       if (mpt<1||kink->GetAngle(2)>0.1){
6672         //      angle and densities  not defined yet
6673         if (kink->GetTPCDensityFactor()<0.8) continue;
6674         if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6675         if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6676         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6677         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6678
6679         Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6680         criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6681         criticalangle= 3*TMath::Sqrt(criticalangle);
6682         if (criticalangle>0.02) criticalangle=0.02;
6683         if (kink->GetAngle(2)<criticalangle) continue;
6684       }
6685       //
6686       Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2)));  // overlap region defined
6687       Float_t shapesum =0;
6688       Float_t sum = 0;
6689       for ( Int_t row = row0-drow; row<row0+drow;row++){
6690         if (row<0) continue;
6691         if (row>155) continue;
6692         if (ktrack0->GetClusterPointer(row)){
6693           AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6694           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6695           sum++;
6696         }
6697         if (ktrack1->GetClusterPointer(row)){
6698           AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6699           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6700           sum++;
6701         }       
6702       }
6703       if (sum<4){
6704         kink->SetShapeFactor(-1.);
6705       }
6706       else{
6707         kink->SetShapeFactor(shapesum/sum);
6708       }      
6709       //      esd->AddKink(kink);
6710       //
6711       //      kink->SetMother(paramm);
6712       //kink->SetDaughter(paramd);
6713  
6714       Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6715       chi2P2*=chi2P2;
6716       chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6717       Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6718       chi2P3*=chi2P3;
6719       chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6720       //
6721       if (AliTPCReconstructor::StreamLevel()&kStreamFindKinks) {// flag: stream track infroamtion in the FindKinks method
6722         (*fDebugStreamer)<<"kinkLpt"<<
6723           "chi2P2="<<chi2P2<<
6724           "chi2P3="<<chi2P3<<
6725           "p0.="<<&paramm<<
6726           "p1.="<<&paramd<<
6727           "k.="<<kink<<
6728           "\n";
6729       }
6730       if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6731         continue;
6732       }
6733       //
6734       kinks->AddLast(kink);
6735       kink = new AliKink;
6736       ncandidates++;
6737     }
6738   }
6739   //
6740   // sort the kinks according quality - and refit them towards vertex
6741   //
6742   Int_t       nkinks    = kinks->GetEntriesFast();
6743   Float_t    *quality   = new Float_t[nkinks];
6744   Int_t      *indexes   = new Int_t[nkinks];
6745   AliTPCseed **mothers   = new AliTPCseed*[nkinks]; memset(mothers,   0, nkinks*sizeof(AliTPCseed*));
6746   AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6747   //
6748   //
6749   for (Int_t i=0;i<nkinks;i++){
6750     quality[i] =100000;
6751     AliKink *kinkl = (AliKink*)kinks->At(i);
6752     //
6753     // refit kinks towards vertex
6754     // 
6755     Int_t index0 = kinkl->GetIndex(0);
6756     Int_t index1 = kinkl->GetIndex(1);
6757     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6758     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6759     //
6760     Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6761     //
6762     // Refit Kink under if too small angle
6763     //
6764     if (kinkl->GetAngle(2)<0.05){
6765       kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6766       Int_t row0 = kinkl->GetTPCRow0();
6767       Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6768       //
6769       //
6770       Int_t last  = row0-drow;
6771       if (last<40) last=40;
6772       if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6773       AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6774       //
6775       //
6776       Int_t first = row0+drow;
6777       if (first>130) first=130;
6778       if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6779       AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6780       //
6781       if (seed0 && seed1){
6782         kinkl->SetStatus(1,8);
6783         if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6784         row0 = GetRowNumber(kinkl->GetR());
6785         sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6786         mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6787         mothers[i]->SetPoolID(fLastSeedID);
6788         daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6789         daughters[i]->SetPoolID(fLastSeedID);
6790       }
6791       else{
6792         delete kinks->RemoveAt(i);
6793         if (seed0) MarkSeedFree( seed0 );
6794         if (seed1) MarkSeedFree( seed1 );
6795         continue;
6796       }
6797       if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6798         delete kinks->RemoveAt(i);
6799         if (seed0) MarkSeedFree( seed0 );
6800         if (seed1) MarkSeedFree( seed1 );
6801         continue;
6802       }
6803       //
6804       MarkSeedFree( seed0 );
6805       MarkSeedFree( seed1 );
6806     }
6807     //
6808     if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.);  //the longest -clossest will win
6809   }
6810   TMath::Sort(nkinks,quality,indexes,kFALSE);
6811   //
6812   //remove double find kinks
6813   //
6814   for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6815     AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6816     if (!kink0) continue;
6817     //
6818     for (Int_t ikink1=0;ikink1<ikink0;ikink1++){ 
6819       kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6820       if (!kink0) continue;
6821       AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6822       if (!kink1) continue;
6823       // if not close kink continue
6824       if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6825       if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6826       if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6827       //
6828       AliTPCseed &mother0   = *mothers[indexes[ikink0]];
6829       AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6830       AliTPCseed &mother1   = *mothers[indexes[ikink1]];
6831       AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6832       Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6833       //
6834       Int_t same  = 0;
6835       Int_t both  = 0;
6836       Int_t samem = 0;
6837       Int_t bothm = 0;
6838       Int_t samed = 0;
6839       Int_t bothd = 0;
6840       //
6841       for (Int_t i=0;i<row0;i++){
6842         if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6843           both++;
6844           bothm++;
6845           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6846             same++;
6847             samem++;
6848           }
6849         }
6850       }
6851
6852       for (Int_t i=row0;i<158;i++){
6853         //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug? 
6854         if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6855           both++;
6856           bothd++;
6857           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6858             same++;
6859             samed++;
6860           }
6861         }
6862       }
6863       Float_t ratio = Float_t(same+1)/Float_t(both+1);
6864       Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6865       Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6866       if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6867         Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6868         Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6869         if (sum1>sum0){
6870           shared[kink0->GetIndex(0)]= kTRUE;
6871           shared[kink0->GetIndex(1)]= kTRUE;      
6872           delete kinks->RemoveAt(indexes[ikink0]);
6873           break;
6874         }
6875         else{
6876           shared[kink1->GetIndex(0)]= kTRUE;
6877           shared[kink1->GetIndex(1)]= kTRUE;      
6878           delete kinks->RemoveAt(indexes[ikink1]);
6879         }
6880       }
6881     }
6882   }
6883
6884
6885   for (Int_t i=0;i<nkinks;i++){
6886     AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6887     if (!kinkl) continue;
6888     kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6889     Int_t index0 = kinkl->GetIndex(0);
6890     Int_t index1 = kinkl->GetIndex(1);
6891     if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6892     kinkl->SetMultiple(usage[index0],0);
6893     kinkl->SetMultiple(usage[index1],1);
6894     if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6895     if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6896     if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6897     if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6898
6899     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6900     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6901     if (!ktrack0 || !ktrack1) continue;
6902     Int_t index = esd->AddKink(kinkl);
6903     //
6904     //
6905     if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) {  //best kink
6906       if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 && 
6907           (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6908         *ktrack0 = *mothers[indexes[i]];
6909         *ktrack1 = *daughters[indexes[i]];
6910       }
6911     }
6912     //
6913     ktrack0->SetKinkIndex(usage[index0],-(index+1));
6914     ktrack1->SetKinkIndex(usage[index1], (index+1));
6915     usage[index0]++;
6916     usage[index1]++;
6917   }
6918   //
6919   // Remove tracks corresponding to shared kink's
6920   //
6921   for (Int_t i=0;i<nentries;i++){
6922     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6923     if (!track0) continue;
6924     if (track0->GetKinkIndex(0)!=0) continue;
6925     if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6926   }
6927
6928   //
6929   //
6930   RemoveUsed2(array,0.5,0.4,30);
6931   UnsignClusters();
6932   for (Int_t i=0;i<nentries;i++){
6933     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6934     if (!track0) continue;
6935     track0->CookdEdx(0.02,0.6);
6936     track0->CookPID();
6937   }
6938   //
6939   for (Int_t i=0;i<nentries;i++){
6940     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6941     if (!track0) continue;
6942     if (track0->Pt()<1.4) continue;
6943     //remove double high momenta tracks - overlapped with kink candidates
6944     Int_t ishared=0;
6945     Int_t all   =0;
6946     for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6947       if (track0->GetClusterPointer(icl)!=0){
6948         all++;
6949         if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6950       }
6951     }
6952     if (Float_t(ishared+1)/Float_t(all+1)>0.5) {  
6953       MarkSeedFree( array->RemoveAt(i) );
6954       continue;
6955     }
6956     //
6957     if (track0->GetKinkIndex(0)!=0) continue;
6958     if (track0->GetNumberOfClusters()<80) continue;
6959
6960     AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6961     pmother->SetPoolID(fLastSeedID);
6962     AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6963     pdaughter->SetPoolID(fLastSeedID);
6964     AliKink *pkink = new AliKink;
6965
6966     AliTPCseed & mother = *pmother;
6967     AliTPCseed & daughter = *pdaughter;
6968     AliKink & kinkl = *pkink;
6969     if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6970       if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6971         MarkSeedFree( pmother );
6972         MarkSeedFree( pdaughter );
6973         delete pkink;
6974         continue;  //too short tracks
6975       }
6976       if (mother.Pt()<1.4) {
6977         MarkSeedFree( pmother );
6978         MarkSeedFree( pdaughter );
6979         delete pkink;
6980         continue;
6981       }
6982       Int_t row0= kinkl.GetTPCRow0();
6983       if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6984         MarkSeedFree( pmother );
6985         MarkSeedFree( pdaughter );
6986         delete pkink;
6987         continue;
6988       }
6989       //
6990       Int_t index = esd->AddKink(&kinkl);      
6991       mother.SetKinkIndex(0,-(index+1));
6992       daughter.SetKinkIndex(0,index+1);
6993       if (mother.GetNumberOfClusters()>50) {
6994         MarkSeedFree( array->RemoveAt(i) );
6995         AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6996         mtc->SetPoolID(fLastSeedID);
6997         array->AddAt(mtc,i);
6998       }
6999       else{
7000         AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
7001         mtc->SetPoolID(fLastSeedID);
7002         array->AddLast(mtc);
7003       }
7004       AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
7005       dtc->SetPoolID(fLastSeedID);
7006       array->AddLast(dtc);
7007       for (Int_t icl=0;icl<row0;icl++) {
7008         if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
7009       }
7010       //
7011       for (Int_t icl=row0;icl<158;icl++) {
7012         if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
7013       }
7014       //
7015     }
7016     MarkSeedFree( pmother );
7017     MarkSeedFree( pdaughter );
7018     delete pkink;
7019   }
7020
7021   delete [] daughters;
7022   delete [] mothers;
7023   //
7024   //
7025   delete [] dca;
7026   delete []circular;
7027   delete []shared;
7028   delete []quality;
7029   delete []indexes;
7030   //
7031   delete kink;
7032   delete[]fim;
7033   delete[] zm;
7034   delete[] z0;
7035   delete [] usage;
7036   delete[] alpha;
7037   delete[] nclusters;
7038   delete[] sign;
7039   delete[] helixes;
7040   kinks->Delete();
7041   delete kinks;
7042
7043   AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
7044   timer.Print();
7045 }
7046 */
7047
7048 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
7049 {
7050   //
7051   // refit kink towards to the vertex
7052   //
7053   //
7054   AliKink &kink=(AliKink &)knk;
7055
7056   Int_t row0 = GetRowNumber(kink.GetR());
7057   FollowProlongation(mother,0);
7058   mother.Reset(kFALSE);
7059   //
7060   FollowProlongation(daughter,row0);
7061   daughter.Reset(kFALSE);
7062   FollowBackProlongation(daughter,158);
7063   daughter.Reset(kFALSE);
7064   Int_t first = TMath::Max(row0-20,30); 
7065   Int_t last  = TMath::Min(row0+20,140);
7066   //
7067   const Int_t kNdiv =5;
7068   AliTPCseed  param0[kNdiv];  // parameters along the track
7069   AliTPCseed  param1[kNdiv];  // parameters along the track
7070   AliKink     kinks[kNdiv];   // corresponding kink parameters
7071   //
7072   Int_t rows[kNdiv];
7073   for (Int_t irow=0; irow<kNdiv;irow++){
7074     rows[irow] = first +((last-first)*irow)/(kNdiv-1);
7075   }
7076   // store parameters along the track
7077   //
7078   for (Int_t irow=0;irow<kNdiv;irow++){
7079     FollowBackProlongation(mother, rows[irow]);
7080     FollowProlongation(daughter,rows[kNdiv-1-irow]);       
7081     param0[irow] = mother;
7082     param1[kNdiv-1-irow] = daughter;
7083   }
7084   //
7085   // define kinks 
7086   for (Int_t irow=0; irow<kNdiv-1;irow++){
7087     if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
7088     kinks[irow].SetMother(param0[irow]);
7089     kinks[irow].SetDaughter(param1[irow]);
7090     kinks[irow].Update();
7091   }
7092   //
7093   // choose kink with best "quality"
7094   Int_t index =-1;
7095   Double_t mindist = 10000;
7096   for (Int_t irow=0;irow<kNdiv;irow++){
7097     if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
7098     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
7099     if (TMath::Abs(kinks[irow].GetR())<100.) continue;
7100     //
7101     Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
7102     normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
7103     if (normdist < mindist){
7104       mindist = normdist;
7105       index = irow;
7106     }
7107   }
7108   //
7109   if (index==-1) return 0;
7110   //
7111   //
7112   param0[index].Reset(kTRUE);
7113   FollowProlongation(param0[index],0);
7114   //
7115   mother = param0[index];
7116   daughter = param1[index];  // daughter in vertex
7117   //
7118   kink.SetMother(mother);
7119   kink.SetDaughter(daughter);
7120   kink.Update();
7121   kink.SetTPCRow0(GetRowNumber(kink.GetR()));
7122   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
7123   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
7124   kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
7125   kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
7126   mother.SetLabel(kink.GetLabel(0));
7127   daughter.SetLabel(kink.GetLabel(1));
7128
7129   return 1;
7130 }
7131
7132
7133 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
7134   //
7135   // update Kink quality information for mother after back propagation
7136   //
7137   if (seed->GetKinkIndex(0)>=0) return; 
7138   for (Int_t ikink=0;ikink<3;ikink++){
7139     Int_t index = seed->GetKinkIndex(ikink);
7140     if (index>=0) break;
7141     index = TMath::Abs(index)-1;
7142     AliESDkink * kink = fEvent->GetKink(index);
7143     kink->SetTPCDensity(-1,0,0);
7144     kink->SetTPCDensity(1,0,1);
7145     //
7146     Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7147     if (row0<15) row0=15;
7148     //
7149     Int_t row1 = kink->GetTPCRow0() + 2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7150     if (row1>145) row1=145;
7151     //
7152     Int_t found,foundable,shared;
7153     seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
7154     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
7155     seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
7156     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
7157   }
7158     
7159 }
7160
7161 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
7162   //
7163   // update Kink quality information for daughter after refit
7164   //
7165   if (seed->GetKinkIndex(0)<=0) return; 
7166   for (Int_t ikink=0;ikink<3;ikink++){
7167     Int_t index = seed->GetKinkIndex(ikink);
7168     if (index<=0) break;
7169     index = TMath::Abs(index)-1;
7170     AliESDkink * kink = fEvent->GetKink(index);
7171     kink->SetTPCDensity(-1,1,0);
7172     kink->SetTPCDensity(-1,1,1);
7173     //
7174     Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7175     if (row0<15) row0=15;
7176     //
7177     Int_t row1 = kink->GetTPCRow0() +2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7178     if (row1>145) row1=145;
7179     //
7180     Int_t found,foundable,shared;
7181     seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
7182     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
7183     seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
7184     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
7185   }
7186     
7187 }
7188
7189
7190 Int_t  AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
7191 {
7192   //
7193   // check kink point for given track
7194   // if return value=0 kink point not found
7195   // otherwise seed0 correspond to mother particle
7196   //           seed1 correspond to daughter particle
7197   //           kink  parameter of kink point
7198   AliKink &kink=(AliKink &)knk;
7199
7200   Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
7201   Int_t first = seed->GetFirstPoint(); 
7202   Int_t last  = seed->GetLastPoint();
7203   if (last-first<20) return 0;          // shortest length - 2*30 = 60 pad-rows
7204
7205   
7206   AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE);  //middle of chamber
7207   if (!seed1) return 0;
7208   FollowProlongation(*seed1,seed->GetLastPoint()-20);
7209   seed1->Reset(kTRUE);
7210   FollowProlongation(*seed1,158);
7211   seed1->Reset(kTRUE);  
7212   last = seed1->GetLastPoint();
7213   //
7214   AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
7215   seed0->SetPoolID(fLastSeedID);
7216   seed0->Reset(kFALSE);
7217   seed0->Reset();
7218   //
7219   AliTPCseed  param0[20];  // parameters along the track
7220   AliTPCseed  param1[20];  // parameters along the track
7221   AliKink     kinks[20];   // corresponding kink parameters
7222   Int_t rows[20];
7223   for (Int_t irow=0; irow<20;irow++){
7224     rows[irow] = first +((last-first)*irow)/19;
7225   }
7226   // store parameters along the track
7227   //
7228   for (Int_t irow=0;irow<20;irow++){
7229     FollowBackProlongation(*seed0, rows[irow]);
7230     FollowProlongation(*seed1,rows[19-irow]);       
7231     param0[irow] = *seed0;
7232     param1[19-irow] = *seed1;
7233   }
7234   //
7235   // define kinks 
7236   for (Int_t irow=0; irow<19;irow++){
7237     kinks[irow].SetMother(param0[irow]);
7238     kinks[irow].SetDaughter(param1[irow]);
7239     kinks[irow].Update();
7240   }
7241   //
7242   // choose kink with biggest change of angle
7243   Int_t index =-1;
7244   Double_t maxchange= 0;
7245   for (Int_t irow=1;irow<19;irow++){
7246     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
7247     if (TMath::Abs(kinks[irow].GetR())<110.) continue;
7248     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
7249     if ( quality > maxchange){
7250       maxchange = quality;
7251       index = irow;
7252       //
7253     }
7254   }
7255   MarkSeedFree( seed0 );
7256   MarkSeedFree( seed1 );
7257   if (index<0) return 0;
7258   //
7259   Int_t row0    = GetRowNumber(kinks[index].GetR());   //row 0 estimate
7260   seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
7261   seed0->SetPoolID(fLastSeedID);
7262   seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
7263   seed1->SetPoolID(fLastSeedID);
7264   seed0->Reset(kFALSE);
7265   seed1->Reset(kFALSE);
7266   seed0->ResetCovariance(10.);
7267   seed1->ResetCovariance(10.);
7268   FollowProlongation(*seed0,0);
7269   FollowBackProlongation(*seed1,158);
7270   mother = *seed0; // backup mother at position 0
7271   seed0->Reset(kFALSE);  
7272   seed1->Reset(kFALSE);
7273   seed0->ResetCovariance(10.);
7274   seed1->ResetCovariance(10.);
7275   //
7276   first = TMath::Max(row0-20,0);
7277   last  = TMath::Min(row0+20,158);
7278   //
7279   for (Int_t irow=0; irow<20;irow++){
7280     rows[irow] = first +((last-first)*irow)/19;
7281   }
7282   // store parameters along the track
7283   //
7284   for (Int_t irow=0;irow<20;irow++){
7285     FollowBackProlongation(*seed0, rows[irow]);
7286     FollowProlongation(*seed1,rows[19-irow]);       
7287     param0[irow] = *seed0;
7288     param1[19-irow] = *seed1;
7289   }
7290   //
7291   // define kinks 
7292   for (Int_t irow=0; irow<19;irow++){
7293     kinks[irow].SetMother(param0[irow]);
7294     kinks[irow].SetDaughter(param1[irow]);
7295     //    param0[irow].Dump();
7296     //param1[irow].Dump();
7297     kinks[irow].Update();
7298   }
7299   //
7300   // choose kink with biggest change of angle
7301   index =-1;
7302   maxchange= 0;
7303   for (Int_t irow=0;irow<20;irow++){
7304     if (TMath::Abs(kinks[irow].GetR())>250.) continue;
7305     if (TMath::Abs(kinks[irow].GetR())<90.) continue;
7306     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
7307     if ( quality > maxchange){
7308       maxchange = quality;
7309       index = irow;
7310       //
7311     }
7312   }
7313   //
7314   //
7315   if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
7316     MarkSeedFree( seed0 );
7317     MarkSeedFree( seed1 );
7318     return 0;
7319   }
7320
7321   //  Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
7322   
7323   kink.SetMother(param0[index]);
7324   kink.SetDaughter(param1[index]);
7325   kink.Update();
7326
7327   Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
7328   chi2P2*=chi2P2;
7329   chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
7330   Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
7331   chi2P3*=chi2P3;
7332   chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
7333   //
7334   if (AliTPCReconstructor::StreamLevel()&kStreamFindKinks) { // flag: stream track infroamtion in the FindKinks method
7335     (*fDebugStreamer)<<"kinkHpt"<<
7336       "chi2P2="<<chi2P2<<
7337       "chi2P3="<<chi2P3<<
7338       "p0.="<<&param0[index]<<
7339       "p1.="<<&param1[index]<<
7340       "k.="<<&kink<<
7341       "\n";
7342   }
7343   if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
7344     MarkSeedFree( seed0 );
7345     MarkSeedFree( seed1 );
7346     return 0; 
7347   }
7348
7349
7350   row0    = GetRowNumber(kink.GetR());   
7351   kink.SetTPCRow0(row0);
7352   kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
7353   kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
7354   kink.SetIndex(-10,0);
7355   kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
7356   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
7357   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
7358   //
7359   //
7360   //  new (&mother) AliTPCseed(param0[index]);
7361   daughter = param1[index];
7362   daughter.SetLabel(kink.GetLabel(1));  
7363   param0[index].Reset(kTRUE);
7364   FollowProlongation(param0[index],0);    
7365   mother = param0[index];
7366   mother.SetLabel(kink.GetLabel(0));
7367   if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
7368     mother=*seed;
7369   }
7370   MarkSeedFree( seed0 );
7371   MarkSeedFree( seed1 );
7372   //
7373   return 1;
7374 }
7375
7376
7377
7378
7379 AliTPCseed*  AliTPCtracker::ReSeed(AliTPCseed *t)
7380 {
7381   //
7382   // reseed - refit -  track
7383   //
7384   Int_t first = 0;
7385   //  Int_t last  = fSectors->GetNRows()-1;
7386   //
7387   if (fSectors == fOuterSec){
7388     first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
7389     //last  = 
7390   }
7391   else
7392     first = t->GetFirstPoint();
7393   //
7394   AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
7395   FollowBackProlongation(*t,fSectors->GetNRows()-1);
7396   t->Reset(kFALSE);
7397   FollowProlongation(*t,first);
7398   return seed;
7399 }
7400
7401
7402
7403
7404
7405
7406
7407 //_____________________________________________________________________________
7408 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
7409   //-----------------------------------------------------------------
7410   // This function reades track seeds.
7411   //-----------------------------------------------------------------
7412   TDirectory *savedir=gDirectory; 
7413
7414   TFile *in=(TFile*)inp;
7415   if (!in->IsOpen()) {
7416      cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
7417      return 1;
7418   }
7419
7420   in->cd();
7421   TTree *seedTree=(TTree*)in->Get("Seeds");
7422   if (!seedTree) {
7423      cerr<<"AliTPCtracker::ReadSeeds(): ";
7424      cerr<<"can't get a tree with track seeds !\n";
7425      return 2;
7426   }
7427   AliTPCtrack *seed=new AliTPCtrack; 
7428   seedTree->SetBranchAddress("tracks",&seed);
7429   
7430   if (fSeeds==0) fSeeds=new TObjArray(15000);
7431
7432   Int_t n=(Int_t)seedTree->GetEntries();
7433   for (Int_t i=0; i<n; i++) {
7434      seedTree->GetEvent(i);
7435      AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
7436      sdc->SetPoolID(fLastSeedID);
7437      fSeeds->AddLast(sdc);
7438   }
7439   
7440   delete seed; // RS: this seed is not from the pool, delete it !!!
7441   delete seedTree; 
7442   savedir->cd();
7443   return 0;
7444 }
7445
7446 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
7447 {
7448   //
7449   // clusters to tracks
7450   if (fSeeds) DeleteSeeds();
7451   else ResetSeedsPool();
7452   fEvent = esd; 
7453   fEventHLT = hltEvent;
7454   if (AliTPCReconstructor::GetRecoParam()->GetUseOulierClusterFilter()) FilterOutlierClusters();  
7455   AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;  
7456   transform->SetCurrentTimeStamp( esd->GetTimeStamp());
7457   transform->SetCurrentRun(esd->GetRunNumber());
7458
7459   
7460   Clusters2Tracks();
7461   fEventHLT = 0;
7462   if (!fSeeds) return 1;
7463   FillESD(fSeeds);
7464   if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0)  DumpClusters(0,fSeeds);
7465   return 0;
7466   //
7467 }
7468
7469 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
7470 {
7471   //
7472   // clusters to tracks
7473   return Clusters2TracksHLT( esd, 0);
7474 }
7475
7476 //_____________________________________________________________________________
7477 Int_t AliTPCtracker::Clusters2Tracks() {
7478   //-----------------------------------------------------------------
7479   // This is a track finder.
7480   //-----------------------------------------------------------------
7481   TDirectory *savedir=gDirectory; 
7482   TStopwatch timer;
7483
7484   fIteration = 0;
7485   fSeeds = Tracking();
7486
7487   if (fDebug>0){
7488     Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
7489   }
7490   //activate again some tracks
7491   for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
7492     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
7493     if (!pt) continue;    
7494     Int_t nc=t.GetNumberOfClusters();
7495     if (nc<20) {
7496       MarkSeedFree( fSeeds->RemoveAt(i) );
7497       continue;
7498     } 
7499     CookLabel(pt,0.1);
7500     if (pt->GetRemoval()==10) {
7501       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7502         pt->Desactivate(10);  // make track again active  // MvL: should be 0 ?
7503       else{
7504         pt->Desactivate(20);    
7505         MarkSeedFree( fSeeds->RemoveAt(i) );
7506       }
7507     } 
7508   }
7509   //
7510   RemoveUsed2(fSeeds,0.85,0.85,0);
7511   if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
7512   //FindCurling(fSeeds, fEvent,0);  
7513   if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)  FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
7514   RemoveUsed2(fSeeds,0.5,0.4,20);
7515   FindSplitted(fSeeds, fEvent,0); // find multi found tracks
7516   if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)  FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
7517
7518  //  //
7519 //   // refit short tracks
7520 //   //
7521   Int_t nseed=fSeeds->GetEntriesFast();
7522   //
7523   Int_t found = 0;
7524   for (Int_t i=0; i<nseed; i++) {
7525     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
7526     if (!pt) continue;    
7527     Int_t nc=t.GetNumberOfClusters();
7528     if (nc<15) {
7529       MarkSeedFree( fSeeds->RemoveAt(i) );
7530       continue;
7531     }
7532     CookLabel(pt,0.1); //For comparison only
7533     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7534     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7535       found++;      
7536       if (fDebug>0) cerr<<found<<'\r';      
7537       pt->SetLab2(i);
7538     }
7539     else
7540       MarkSeedFree( fSeeds->RemoveAt(i) );
7541   }
7542
7543   
7544   //RemoveOverlap(fSeeds,0.99,7,kTRUE);  
7545   SignShared(fSeeds);  
7546   //RemoveUsed(fSeeds,0.9,0.9,6);
7547   // 
7548   nseed=fSeeds->GetEntriesFast();
7549   found = 0;
7550   for (Int_t i=0; i<nseed; i++) {
7551     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
7552     if (!pt) continue;    
7553     Int_t nc=t.GetNumberOfClusters();
7554     if (nc<15) {
7555       MarkSeedFree( fSeeds->RemoveAt(i) );
7556       continue;
7557     }
7558     t.SetUniqueID(i);
7559     t.CookdEdx(0.02,0.6);
7560     //    CheckKinkPoint(&t,0.05);
7561     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7562     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7563       found++;
7564       if (fDebug>0){
7565         cerr<<found<<'\r';      
7566       }
7567       pt->SetLab2(i);
7568     }
7569     else
7570       MarkSeedFree( fSeeds->RemoveAt(i) );
7571     //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7572     //if (seed1){
7573     //  FollowProlongation(*seed1,0);
7574     //  Int_t n = seed1->GetNumberOfClusters();
7575     //  printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7576     //  printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7577     //
7578     //}
7579     //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7580     
7581   }
7582
7583   SortTracks(fSeeds, 1);
7584   
7585   /*    
7586   fIteration = 1;
7587   PrepareForBackProlongation(fSeeds,5.);
7588   PropagateBack(fSeeds);
7589   printf("Time for back propagation: \t");timer.Print();timer.Start();
7590   
7591   fIteration = 2;
7592   
7593   PrepareForProlongation(fSeeds,5.);
7594   PropagateForard2(fSeeds);
7595    
7596   printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7597   // RemoveUsed(fSeeds,0.7,0.7,6);
7598   //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7599    
7600   nseed=fSeeds->GetEntriesFast();
7601   found = 0;
7602   for (Int_t i=0; i<nseed; i++) {
7603     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
7604     if (!pt) continue;    
7605     Int_t nc=t.GetNumberOfClusters();
7606     if (nc<15) {
7607       MarkSeedFree( fSeeds->RemoveAt(i) );
7608       continue;
7609     }
7610     t.CookdEdx(0.02,0.6);
7611     //    CookLabel(pt,0.1); //For comparison only
7612     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7613     if ((pt->IsActive() || (pt->fRemoval==10) )){
7614       cerr<<found++<<'\r';      
7615     }
7616     else
7617       MarkSeedFree( fSeeds->RemoveAt(i) );
7618     pt->fLab2 = i;
7619   }
7620   */
7621  
7622   //  fNTracks = found;
7623   if (fDebug>0){
7624     Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7625   }
7626   //
7627   //  cerr<<"Number of found tracks : "<<"\t"<<found<<endl;  
7628   Info("Clusters2Tracks","Number of found tracks %d",found);  
7629   savedir->cd();
7630   //  UnloadClusters();
7631   //  
7632   return 0;
7633 }
7634
7635 void AliTPCtracker::Tracking(TObjArray * arr)
7636 {
7637   //
7638   // tracking of the seeds
7639   //
7640
7641   fSectors = fOuterSec;
7642   ParallelTracking(arr,150,63);
7643   fSectors = fOuterSec;
7644   ParallelTracking(arr,63,0);
7645 }
7646
7647 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7648 {
7649   //
7650   //
7651   //tracking routine
7652   static TObjArray arrTracks;
7653   TObjArray * arr = &arrTracks;
7654   // 
7655   fSectors = fOuterSec;
7656   TStopwatch timer;
7657   timer.Start();
7658   for (Int_t sec=0;sec<fkNOS;sec++){
7659     if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7660     if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);    
7661     if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7662   }
7663   if (fDebug>0){
7664     Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7665     timer.Print();
7666     timer.Start();
7667   }
7668   Tracking(arr);  
7669   if (fDebug>0){
7670     timer.Print();
7671   }
7672
7673   return arr;
7674 }
7675
7676 TObjArray * AliTPCtracker::Tracking()
7677 {
7678   // tracking
7679   //
7680   if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7681   TStopwatch timer;
7682   timer.Start();
7683   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7684
7685   TObjArray * seeds = new TObjArray;
7686   TObjArray * arr=0;
7687   Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7688   Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7689   Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7690   
7691   Int_t gap =20;
7692   Float_t cuts[4];
7693   cuts[0] = 0.002;
7694   cuts[1] = 1.5;
7695   cuts[2] = 3.;
7696   cuts[3] = 3.;
7697   Float_t fnumber  = 3.0;
7698   Float_t fdensity = 3.0;
7699
7700   // make HLT seeds
7701   if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7702     arr = MakeSeedsHLT( fEventHLT );
7703     if( arr ){
7704       SumTracks(seeds,arr);     
7705       delete arr;
7706       arr=0;
7707       //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7708       //SignClusters(seeds,fnumber,fdensity);    
7709     }
7710   }
7711   
7712   //  
7713   //find primaries  
7714   cuts[0]=0.0066;
7715   for (Int_t delta = 0; delta<18; delta+=gapPrim){
7716     //
7717     cuts[0]=0.0070;
7718     cuts[1] = 1.5;
7719     arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7720     SumTracks(seeds,arr);   
7721     SignClusters(seeds,fnumber,fdensity); 
7722     //
7723     for (Int_t i=2;i<6;i+=2){
7724       // seed high pt tracks
7725       cuts[0]=0.0022;
7726       cuts[1]=0.3;
7727       arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7728       SumTracks(seeds,arr);   
7729       SignClusters(seeds,fnumber,fdensity);        
7730     }
7731   }
7732   fnumber  = 4;
7733   fdensity = 4.;
7734   //  RemoveUsed(seeds,0.9,0.9,1);
7735   //  UnsignClusters();
7736   //  SignClusters(seeds,fnumber,fdensity);    
7737
7738   //find primaries  
7739   cuts[0]=0.0077;
7740   for (Int_t delta = 20; delta<120; delta+=gapPrim){
7741     //
7742     // seed high pt tracks
7743     cuts[0]=0.0060;
7744     cuts[1]=0.3;
7745     cuts[2]=6.;
7746     arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7747     SumTracks(seeds,arr);   
7748     SignClusters(seeds,fnumber,fdensity);            
7749
7750     cuts[0]=0.003;
7751     cuts[1]=0.3;
7752     cuts[2]=6.;
7753     arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7754     SumTracks(seeds,arr);   
7755     SignClusters(seeds,fnumber,fdensity);            
7756   }
7757
7758   cuts[0] = 0.01;
7759   cuts[1] = 2.0;
7760   cuts[2] = 3.;
7761   cuts[3] = 2.0;
7762   fnumber  = 2.;
7763   fdensity = 2.;
7764   
7765   if (fDebug>0){
7766     Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7767     timer.Print();
7768     timer.Start();
7769   }
7770   //  RemoveUsed(seeds,0.75,0.75,1);
7771   //UnsignClusters();
7772   //SignClusters(seeds,fnumber,fdensity);
7773   
7774   // find secondaries
7775
7776   cuts[0] = 0.3;
7777   cuts[1] = 1.5;
7778   cuts[2] = 3.;
7779   cuts[3] = 1.5;
7780
7781   arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7782   SumTracks(seeds,arr);   
7783   SignClusters(seeds,fnumber,fdensity);   
7784   //
7785   arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7786   SumTracks(seeds,arr);   
7787   SignClusters(seeds,fnumber,fdensity);   
7788   //
7789   arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7790   SumTracks(seeds,arr);   
7791   SignClusters(seeds,fnumber,fdensity);   
7792   //
7793   arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7794   SumTracks(seeds,arr);   
7795   SignClusters(seeds,fnumber,fdensity);   
7796   //
7797   arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7798   SumTracks(seeds,arr);   
7799   SignClusters(seeds,fnumber,fdensity);   
7800   //
7801   //
7802   arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7803   SumTracks(seeds,arr);   
7804   SignClusters(seeds,fnumber,fdensity);   
7805   //
7806
7807
7808   for (Int_t delta = 9; delta<30; delta+=gapSec){
7809     //
7810     cuts[0] = 0.3;
7811     cuts[1] = 1.5;
7812     cuts[2] = 3.;
7813     cuts[3] = 1.5;
7814     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7815     SumTracks(seeds,arr);   
7816     SignClusters(seeds,fnumber,fdensity);   
7817     //
7818     arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7819     SumTracks(seeds,arr);   
7820     SignClusters(seeds,fnumber,fdensity); 
7821     //
7822   } 
7823   fnumber  = 1;
7824   fdensity = 1;
7825   //
7826   // change cuts
7827   fnumber  = 2.;
7828   fdensity = 2.;
7829   cuts[0]=0.0080;
7830
7831
7832   // find secondaries
7833   for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7834     //
7835     cuts[0] = 0.3;
7836     cuts[1] = 3.5;
7837     cuts[2] = 3.;
7838     cuts[3] = 3.5;
7839     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7840     SumTracks(seeds,arr);   
7841     SignClusters(seeds,fnumber,fdensity);   
7842     //
7843     arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7844     SumTracks(seeds,arr);   
7845     SignClusters(seeds,fnumber,fdensity);   
7846   }
7847  
7848   if (fDebug>0){
7849     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7850     timer.Print();
7851     timer.Start();
7852   }
7853
7854   return seeds;
7855   //
7856       
7857 }
7858
7859
7860 TObjArray * AliTPCtracker::TrackingSpecial()
7861 {
7862   //
7863   // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7864   // no primary vertex seeding tried
7865   //
7866   TStopwatch timer;
7867   timer.Start();
7868   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7869
7870   TObjArray * seeds = new TObjArray;
7871   TObjArray * arr=0;
7872   
7873   Int_t   gap  = 15;
7874   Float_t cuts[4];
7875   Float_t fnumber  = 3.0;
7876   Float_t fdensity = 3.0;
7877   
7878   // find secondaries
7879   cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC();   // max curvature
7880   cuts[1] = 3.5;    // max tan(phi) angle for seeding
7881   cuts[2] = 3.;     // not used (cut on z primary vertex)     
7882   cuts[3] = 3.5;    // max tan(theta) angle for seeding
7883
7884   for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7885     //
7886     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7887     SumTracks(seeds,arr);   
7888     SignClusters(seeds,fnumber,fdensity);   
7889   } 
7890  
7891   if (fDebug>0){
7892     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7893     timer.Print();
7894     timer.Start();
7895   }
7896
7897   return seeds;
7898   //
7899       
7900 }
7901
7902
7903 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7904 {
7905   //
7906   //sum tracks to common container
7907   //remove suspicious tracks
7908   // RS: Attention: supplied tracks come in the static array, don't delete them
7909   Int_t nseed = arr2->GetEntriesFast();
7910   for (Int_t i=0;i<nseed;i++){
7911     AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);    
7912     if (pt){
7913       //
7914       // remove tracks with too big curvature
7915       //
7916       if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7917         MarkSeedFree( arr2->RemoveAt(i) );
7918         continue;
7919       }
7920        // REMOVE VERY SHORT  TRACKS
7921       if (pt->GetNumberOfClusters()<20){ 
7922         MarkSeedFree( arr2->RemoveAt(i) );
7923         continue;
7924       }// patch 28 fev06
7925       // NORMAL ACTIVE TRACK
7926       if (pt->IsActive()){
7927         arr1->AddLast(arr2->RemoveAt(i));
7928         continue;
7929       }
7930       //remove not usable tracks
7931       if (pt->GetRemoval()!=10){
7932         MarkSeedFree( arr2->RemoveAt(i) );
7933         continue;
7934       }
7935      
7936       // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7937       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7938         arr1->AddLast(arr2->RemoveAt(i));
7939       else{      
7940         MarkSeedFree( arr2->RemoveAt(i) );
7941       }
7942     }
7943   }
7944   // delete arr2;  arr2 = 0; // RS: this is static array, don't delete it
7945 }
7946
7947
7948
7949 void  AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7950 {
7951   //
7952   // try to track in parralel
7953
7954   Int_t nseed=arr->GetEntriesFast();
7955   //prepare seeds for tracking
7956   for (Int_t i=0; i<nseed; i++) {
7957     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt; 
7958     if (!pt) continue;
7959     if (!t.IsActive()) continue;
7960     // follow prolongation to the first layer
7961     if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )  
7962       FollowProlongation(t, rfirst+1);
7963   }
7964
7965
7966   //
7967   for (Int_t nr=rfirst; nr>=rlast; nr--){ 
7968     if (nr<fInnerSec->GetNRows()) 
7969       fSectors = fInnerSec;
7970     else
7971       fSectors = fOuterSec;
7972     // make indexes with the cluster tracks for given       
7973
7974     // find nearest cluster
7975     for (Int_t i=0; i<nseed; i++) {
7976       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;       
7977       if (!pt) continue;
7978       if (nr==80) pt->UpdateReference();
7979       if (!pt->IsActive()) continue;
7980       //      if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7981       if (pt->GetRelativeSector()>17) {
7982         continue;
7983       }
7984       UpdateClusters(t,nr);
7985     }
7986     // prolonagate to the nearest cluster - if founded
7987     for (Int_t i=0; i<nseed; i++) {
7988       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i); 
7989       if (!pt) continue;
7990       if (!pt->IsActive()) continue; 
7991       // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7992       if (pt->GetRelativeSector()>17) {
7993         continue;
7994       }
7995       FollowToNextCluster(*pt,nr);
7996     }
7997   }    
7998 }
7999
8000 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
8001 {
8002   //
8003   //
8004   // if we use TPC track itself we have to "update" covariance
8005   //
8006   Int_t nseed= arr->GetEntriesFast();
8007   for (Int_t i=0;i<nseed;i++){
8008     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8009     if (pt) {
8010       pt->Modify(fac);
8011       //
8012       //rotate to current local system at first accepted  point    
8013       Int_t index  = pt->GetClusterIndex2(pt->GetFirstPoint()); 
8014       Int_t sec    = (index&0xff000000)>>24;
8015       sec = sec%18;
8016       Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
8017       if (angle1>TMath::Pi()) 
8018         angle1-=2.*TMath::Pi();
8019       Float_t angle2 = pt->GetAlpha();
8020       
8021       if (TMath::Abs(angle1-angle2)>0.001){
8022         if (!pt->Rotate(angle1-angle2)) return;
8023         //angle2 = pt->GetAlpha();
8024         //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
8025         //if (pt->GetAlpha()<0) 
8026         //  pt->fRelativeSector+=18;
8027         //sec = pt->fRelativeSector;
8028       }
8029         
8030     }
8031     
8032   }
8033
8034
8035 }
8036 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
8037 {
8038   //
8039   //
8040   // if we use TPC track itself we have to "update" covariance
8041   //
8042   Int_t nseed= arr->GetEntriesFast();
8043   for (Int_t i=0;i<nseed;i++){
8044     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8045     if (pt) {
8046       pt->Modify(fac);
8047       pt->SetFirstPoint(pt->GetLastPoint()); 
8048     }
8049     
8050   }
8051
8052
8053 }
8054
8055 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
8056 {
8057   //
8058   // make back propagation
8059   //
8060   Int_t nseed= arr->GetEntriesFast();
8061   for (Int_t i=0;i<nseed;i++){
8062     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8063     if (pt&& pt->GetKinkIndex(0)<=0) { 
8064       //AliTPCseed *pt2 = new AliTPCseed(*pt);
8065       fSectors = fInnerSec;
8066       //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
8067       //fSectors = fOuterSec;
8068       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);     
8069       //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
8070       //        Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
8071       //        FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
8072       //}
8073     }
8074     if (pt&& pt->GetKinkIndex(0)>0) {
8075       AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
8076       pt->SetFirstPoint(kink->GetTPCRow0());
8077       fSectors = fInnerSec;
8078       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);  
8079     }
8080     CookLabel(pt,0.3);
8081   }
8082   return 0;
8083 }
8084
8085
8086 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
8087 {
8088   //
8089   // make forward propagation
8090   //
8091   Int_t nseed= arr->GetEntriesFast();
8092   //
8093   for (Int_t i=0;i<nseed;i++){
8094     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8095     if (pt) { 
8096       FollowProlongation(*pt,0,1,1);
8097       CookLabel(pt,0.3);
8098     }
8099     
8100   }
8101  return 0;
8102 }
8103
8104
8105 Int_t AliTPCtracker::PropagateForward()
8106 {
8107   //
8108   // propagate track forward
8109   //UnsignClusters();
8110   Int_t nseed = fSeeds->GetEntriesFast();
8111   for (Int_t i=0;i<nseed;i++){
8112     AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
8113     if (pt){
8114       AliTPCseed &t = *pt;
8115       Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
8116       if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
8117       if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
8118       t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8119     }
8120   }
8121   
8122   fSectors = fOuterSec;
8123   ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
8124   fSectors = fInnerSec;
8125   ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
8126   return 1;
8127 }
8128
8129
8130
8131
8132
8133
8134 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
8135 {
8136   //
8137   // make back propagation, in between row0 and row1
8138   //
8139   
8140   if (pt) { 
8141     fSectors = fInnerSec;
8142     Int_t  r1;
8143     //
8144     if (row1<fSectors->GetNRows()) 
8145       r1 = row1;
8146     else 
8147       r1 = fSectors->GetNRows()-1;
8148
8149     if (row0<fSectors->GetNRows()&& r1>0 )
8150       FollowBackProlongation(*pt,r1);
8151     if (row1<=fSectors->GetNRows())
8152       return 0;
8153     //
8154     r1 = row1 - fSectors->GetNRows();
8155     if (r1<=0) return 0;
8156     if (r1>=fOuterSec->GetNRows()) return 0;
8157     fSectors = fOuterSec;
8158     return FollowBackProlongation(*pt,r1);
8159   }        
8160   return 0;
8161 }
8162
8163
8164
8165
8166 void  AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
8167 {
8168   // gets cluster shape
8169   // 
8170   AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
8171   Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
8172   Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
8173   Double_t angulary  = seed->GetSnp();
8174
8175   if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
8176     angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
8177   }
8178
8179   angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
8180   Double_t angularz  = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
8181   
8182   Double_t sigmay =  clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
8183   Double_t sigmaz =  clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
8184   seed->SetCurrentSigmaY2(sigmay*sigmay);
8185   seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
8186   // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
8187 //   //  Float_t padlength =  fkParam->GetPadPitchLength(seed->fSector);
8188 //   Float_t padlength =  GetPadPitchLength(row);
8189 //   //
8190 //   Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
8191 //   seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);  
8192 //   //
8193 //   Float_t sresz = fkParam->GetZSigma();
8194 //   seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
8195   /*
8196   Float_t wy = GetSigmaY(seed);
8197   Float_t wz = GetSigmaZ(seed);
8198   wy*=wy;
8199   wz*=wz;
8200   if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
8201     printf("problem\n");
8202   }
8203   */
8204 }
8205
8206
8207
8208 //__________________________________________________________________________
8209 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
8210   //--------------------------------------------------------------------
8211   //This function "cooks" a track label. If label<0, this track is fake.
8212   //--------------------------------------------------------------------
8213   AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
8214   if(!t){
8215     printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
8216     return;
8217   }
8218
8219   Int_t noc=t->GetNumberOfClusters();
8220   if (noc<10){
8221     //printf("\nnot founded prolongation\n\n\n");
8222     //t->Dump();
8223     return ;
8224   }
8225   Int_t lb[160];
8226   Int_t mx[160];
8227   AliTPCclusterMI *clusters[160];
8228   //
8229   for (Int_t i=0;i<160;i++) {
8230     clusters[i]=0;
8231     lb[i]=mx[i]=0;
8232   }
8233
8234   Int_t i;
8235   Int_t current=0;
8236   for (i=0; i<160 && current<noc; i++) {
8237      
8238      Int_t index=t->GetClusterIndex2(i);
8239      if (index<=0) continue; 
8240      if (index&0x8000) continue;
8241      //     
8242      //clusters[current]=GetClusterMI(index);
8243      if (t->GetClusterPointer(i)){
8244        clusters[current]=t->GetClusterPointer(i);     
8245        current++;
8246      }
8247   }
8248   noc = current;
8249
8250   Int_t lab=123456789;
8251   for (i=0; i<noc; i++) {
8252     AliTPCclusterMI *c=clusters[i];
8253     if (!c) continue;
8254     lab=TMath::Abs(c->GetLabel(0));
8255     Int_t j;
8256     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
8257     lb[j]=lab;
8258     (mx[j])++;
8259   }
8260
8261   Int_t max=0;
8262   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
8263     
8264   for (i=0; i<noc; i++) {
8265     AliTPCclusterMI *c=clusters[i]; 
8266     if (!c) continue;
8267     if (TMath::Abs(c->GetLabel(1)) == lab ||
8268         TMath::Abs(c->GetLabel(2)) == lab ) max++;
8269   }
8270   if (noc<=0) { lab=-1; return;}
8271   if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
8272
8273   else {
8274      Int_t tail=Int_t(0.10*noc);
8275      max=0;
8276      Int_t ind=0;
8277      for (i=1; i<160&&ind<tail; i++) {
8278        //       AliTPCclusterMI *c=clusters[noc-i];
8279        AliTPCclusterMI *c=clusters[i];
8280        if (!c) continue;
8281        if (lab == TMath::Abs(c->GetLabel(0)) ||
8282            lab == TMath::Abs(c->GetLabel(1)) ||
8283            lab == TMath::Abs(c->GetLabel(2))) max++;
8284        ind++;
8285      }
8286      if (max < Int_t(0.5*tail)) lab=-lab;
8287   }
8288
8289   t->SetLabel(lab);
8290
8291   //  delete[] lb;
8292   //delete[] mx;
8293   //delete[] clusters;
8294 }
8295
8296
8297 //__________________________________________________________________________
8298 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
8299   //--------------------------------------------------------------------
8300   //This function "cooks" a track label. If label<0, this track is fake.
8301   //--------------------------------------------------------------------
8302   Int_t noc=t->GetNumberOfClusters();
8303   if (noc<10){
8304     //printf("\nnot founded prolongation\n\n\n");
8305     //t->Dump();
8306     return -1;
8307   }
8308   Int_t lb[160];
8309   Int_t mx[160];
8310   AliTPCclusterMI *clusters[160];
8311   //
8312   for (Int_t i=0;i<160;i++) {
8313     clusters[i]=0;
8314     lb[i]=mx[i]=0;
8315   }
8316
8317   Int_t i;
8318   Int_t current=0;
8319   for (i=0; i<160 && current<noc; i++) {
8320     if (i<first) continue;
8321     if (i>last)  continue;
8322      Int_t index=t->GetClusterIndex2(i);
8323      if (index<=0) continue; 
8324      if (index&0x8000) continue;
8325      //     
8326      //clusters[current]=GetClusterMI(index);
8327      if (t->GetClusterPointer(i)){
8328        clusters[current]=t->GetClusterPointer(i);     
8329        current++;
8330      }
8331   }
8332   noc = current;
8333   //if (noc<5) return -1;
8334   Int_t lab=123456789;
8335   for (i=0; i<noc; i++) {
8336     AliTPCclusterMI *c=clusters[i];
8337     if (!c) continue;
8338     lab=TMath::Abs(c->GetLabel(0));
8339     Int_t j;
8340     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
8341     lb[j]=lab;
8342     (mx[j])++;
8343   }
8344
8345   Int_t max=0;
8346   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
8347     
8348   for (i=0; i<noc; i++) {
8349     AliTPCclusterMI *c=clusters[i]; 
8350     if (!c) continue;
8351     if (TMath::Abs(c->GetLabel(1)) == lab ||
8352         TMath::Abs(c->GetLabel(2)) == lab ) max++;
8353   }
8354   if (noc<=0) { lab=-1; return -1;}
8355   if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
8356
8357   else {
8358      Int_t tail=Int_t(0.10*noc);
8359      max=0;
8360      Int_t ind=0;
8361      for (i=1; i<160&&ind<tail; i++) {
8362        //       AliTPCclusterMI *c=clusters[noc-i];
8363        AliTPCclusterMI *c=clusters[i];
8364        if (!c) continue;
8365        if (lab == TMath::Abs(c->GetLabel(0)) ||
8366            lab == TMath::Abs(c->GetLabel(1)) ||
8367            lab == TMath::Abs(c->GetLabel(2))) max++;
8368        ind++;
8369      }
8370      if (max < Int_t(0.5*tail)) lab=-lab;
8371   }
8372
8373   //  t->SetLabel(lab);
8374   return lab;
8375   //  delete[] lb;
8376   //delete[] mx;
8377   //delete[] clusters;
8378 }
8379
8380
8381 Int_t  AliTPCtracker::GetRowNumber(Double_t x[3]) const 
8382 {
8383   //return pad row number for given x vector
8384   Float_t phi = TMath::ATan2(x[1],x[0]);
8385   if(phi<0) phi=2.*TMath::Pi()+phi;
8386   //  Get the local angle in the sector philoc
8387   const Float_t kRaddeg = 180/3.14159265358979312;
8388   Float_t phiangle   = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
8389   Double_t localx    = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
8390   return GetRowNumber(localx);
8391 }
8392
8393
8394
8395 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
8396 {
8397   //-----------------------------------------------------------------------
8398   // Fill the cluster and sharing bitmaps of the track
8399   //-----------------------------------------------------------------------
8400
8401   Int_t firstpoint = 0;
8402   Int_t lastpoint = 159;
8403   AliTPCTrackerPoint *point;
8404   AliTPCclusterMI    *cluster;
8405   
8406   Int_t nclsf = 0;
8407   TBits clusterMap(159);
8408   TBits sharedMap(159);
8409   TBits fitMap(159);
8410   for (int iter=firstpoint; iter<lastpoint; iter++) {
8411     // Change to cluster pointers to see if we have a cluster at given padrow
8412
8413     cluster = t->GetClusterPointer(iter);
8414     if (cluster) {
8415       clusterMap.SetBitNumber(iter, kTRUE);
8416       point = t->GetTrackPoint(iter);
8417       if (point->IsShared())
8418         sharedMap.SetBitNumber(iter,kTRUE);
8419     }
8420     if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
8421       fitMap.SetBitNumber(iter, kTRUE);
8422       nclsf++;
8423     }
8424   }
8425   esd->SetTPCClusterMap(clusterMap);
8426   esd->SetTPCSharedMap(sharedMap);
8427   esd->SetTPCFitMap(fitMap);
8428   if (nclsf != t->GetNumberOfClusters())
8429     AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
8430 }
8431
8432 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
8433   //
8434   // return flag if there is findable cluster at given position
8435   //
8436   Float_t kDeltaZ=10;
8437   Float_t z = track.GetZ();
8438   
8439   if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) && 
8440       TMath::Abs(z)<fkParam->GetZLength(0) && 
8441       (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
8442     return kTRUE;
8443   return kFALSE;      
8444 }
8445
8446
8447 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
8448   //
8449   // Adding systematic error estimate to the covariance matrix
8450   //                !!!! the systematic error for element 4 is in 1/GeV 
8451   // 03.03.2012     MI changed in respect to the previous versions
8452   const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
8453   //
8454   // use only the diagonal part if not specified otherwise
8455   if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
8456   //
8457   Double_t *covarS= (Double_t*)seed->GetCovariance();
8458   Double_t factor[5]={1,1,1,1,1};
8459   factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
8460   factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
8461   factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
8462   factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
8463   factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
8464   //
8465   factor[0]=factor[2];
8466   factor[4]=factor[2];
8467   // 0
8468   // 1    2
8469   // 3    4    5
8470   // 6    7    8    9 
8471   // 10   11   12   13   14
8472   for (Int_t i=0; i<5; i++){
8473     for (Int_t j=i; j<5; j++){
8474       Int_t index=seed->GetIndex(i,j);
8475       covarS[index]*=factor[i]*factor[j];
8476     }
8477   }
8478 }
8479
8480
8481 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
8482   //
8483   // Adding systematic error - as additive factor without correlation
8484   //
8485   //                !!!! the systematic error for element 4 is in 1/GeV 
8486   // 03.03.2012     MI changed in respect to the previous versions
8487
8488   const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
8489   Double_t *covarIn= (Double_t*)seed->GetCovariance();
8490   Double_t covar[15];
8491   for (Int_t i=0;i<15;i++) covar[i]=0;
8492   // 0
8493   // 1    2
8494   // 3    4    5
8495   // 6    7    8    9 
8496   // 10   11   12   13   14
8497   covar[0] = param[0]*param[0];
8498   covar[2] = param[1]*param[1];
8499   covar[5] = param[2]*param[2];
8500   covar[9] = param[3]*param[3];
8501   covar[14]= param[4]*param[4];
8502   //
8503   covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
8504   //
8505   covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
8506   covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
8507   //
8508   covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
8509   covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
8510   covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
8511   //
8512   covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
8513   covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
8514   covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
8515   covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
8516   //
8517   seed->AddCovariance(covar);
8518 }
8519
8520 //_____________________________________________________________________________
8521 Bool_t  AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
8522 {
8523   //
8524   // check events affected by TPC HV dip
8525   //
8526   if(!esdEvent) return kFALSE;
8527
8528   // Init TPC OCDB
8529   AliTPCcalibDB *db=AliTPCcalibDB::Instance();
8530   if(!db) return kFALSE;
8531   db->SetRun(esdEvent->GetRunNumber());
8532
8533   // maximum allowed voltage before an event is identified as a dip event
8534   // and scanning period
8535   const Double_t kTPCHVdip          = db->GetParameters()->GetMaxDipVoltage(); 
8536   const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8537   const Double_t tevSec             = esdEvent->GetTimeStamp();
8538   
8539   for(Int_t sector=0; sector<72; sector++)
8540   {
8541     // don't use excluded chambers, since the state is not defined at all
8542     if (!db->GetChamberHVStatus(sector)) continue;
8543     
8544     // get hv sensor of the chamber
8545     AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8546     if (!sensor) continue;
8547     TGraph *grSensor=sensor->GetGraph();
8548     if (!grSensor) continue;
8549     if (grSensor->GetN()<1) continue;
8550     
8551     // get median
8552     const Double_t median = db->GetChamberHighVoltageMedian(sector);
8553     if(median < 1.) continue;
8554     
8555     for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8556       Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8557       if (tevSec-dipEventScanPeriod>nextTime) continue;
8558       const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8559       if (deltaV>kTPCHVdip) {
8560         AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8561         return kTRUE;
8562       }
8563       if (nextTime>tevSec+dipEventScanPeriod) break;
8564     }
8565   }
8566   
8567   return kFALSE;
8568 }
8569
8570 //________________________________________
8571 void AliTPCtracker::MarkSeedFree(TObject *sd) 
8572 {
8573   // account that this seed is "deleted" 
8574   AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8575   if (!seed) {
8576     AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd)); 
8577     return;
8578   }
8579   int id = seed->GetPoolID();
8580   if (id<0) {
8581     AliError(Form("Freeing of seed %p NOT from the pool is requested",sd)); 
8582     return;
8583   }
8584   //  AliInfo(Form("%d %p",id, seed));
8585   fSeedsPool->RemoveAt(id);
8586   if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8587   fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8588 }
8589
8590 //________________________________________
8591 TObject *&AliTPCtracker::NextFreeSeed()
8592 {
8593   // return next free slot where the seed can be created
8594   fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8595   //  AliInfo(Form("%d",fLastSeedID));
8596   return (*fSeedsPool)[ fLastSeedID ];
8597   //
8598 }
8599
8600 //________________________________________
8601 void AliTPCtracker::ResetSeedsPool()
8602 {
8603   // mark all seeds in the pool as unused
8604   AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8605   fNFreeSeeds = 0;
8606   fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8607 }
8608
8609 Int_t  AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8610 {
8611   AliTPCseed &t=*pt;
8612   Double_t x= GetXrow(nrow);
8613   Double_t  ymax= GetMaxY(nrow);
8614   Int_t rotate = 0;
8615   Int_t nRotations=0;
8616   int ret = 1;
8617   do{
8618     rotate = 0;
8619     if (!t.PropagateTo(x) ){
8620       //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl; 
8621       //t.Print();
8622       ret = 0;
8623       break;
8624     }
8625     t.SetRow(nrow);
8626     Double_t y = t.GetY();
8627     if( y > ymax ) {    
8628       if( rotate!=-1 ) rotate=1;
8629     } else if (y <-ymax) {
8630       if( rotate!=1 ) rotate = -1;
8631     }
8632     if( rotate==0 ) break;
8633     //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8634     if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8635       //cout<<"can't rotate "<<endl; 
8636       ret=0;
8637       break;
8638     }
8639     nRotations+= rotate;
8640   }while(rotate!=0);
8641   if( nRotations!=0 ){
8642     int newSec= t.GetRelativeSector()+nRotations;
8643     if( newSec>=fN ) newSec-=fN;
8644     else if( newSec<0 ) newSec +=fN; 
8645     //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8646     //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8647     t.SetRelativeSector(newSec);
8648   }
8649   return ret;
8650 }
8651
8652 void  AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8653 {
8654   //
8655   // try to track in parralel
8656
8657   Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8658   fSectors=fInnerSec;
8659
8660   Int_t nseed=arr->GetEntriesFast();
8661   //cout<<"Parallel tracking My.."<<endl;
8662   double shapeY2[160], shapeZ2[160];
8663   Int_t clusterIndex[160];
8664  
8665   for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8666     //if( iSeed!=1 ) continue;
8667     AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8668     if (!pt) continue;
8669     AliTPCseed &t=*pt;    
8670     
8671     //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8672     
8673     // t.Print();
8674     
8675     for( int iter=0; iter<3; iter++ ){
8676             
8677       t.Reset();
8678       t.SetLastPoint(0);  // first cluster in track position
8679       t.SetFirstPoint(nRows-1);
8680       t.ResetCovariance(.1);
8681       t.SetNumberOfClusters(0);
8682       for( int i=0; i<nRows; i++ ){
8683         shapeY2[i]=1.;
8684         shapeZ2[i]=1.;
8685         clusterIndex[i]=-1;
8686         t.SetClusterIndex2(i,-1); 
8687         t.SetClusterIndex(i,-1); 
8688       }
8689
8690      // pick up the clusters
8691       
8692       Double_t roady = 20.;
8693       Double_t roadz = 20.;
8694       double roadr = 5;
8695
8696       AliTPCseed t0(t);
8697       t0.Reset();
8698       int nClusters = 0;      
8699       {
8700         t0.SetRelativeSector(t.GetRelativeSector());
8701         t0.SetLastPoint(0);  // first cluster in track position
8702         t0.SetFirstPoint(159);
8703         for (Int_t nr=0; nr<nRows; nr++){ 
8704           if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8705           else fSectors=fOuterSec;
8706
8707           if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8708           if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8709             //cout<<"Snp is too big: "<<t0.GetSnp()<<endl; 
8710             continue;
8711           }
8712           if (!IsActive(t0.GetRelativeSector(),nr)) {
8713             continue;
8714           }
8715           
8716           if( iter==0 ){
8717             GetShape(&t0,nr); 
8718             shapeY2[nr]=t0.GetCurrentSigmaY2();
8719             shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8720           }
8721
8722           AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8723           if( !krow ) continue; 
8724
8725           t.SetClusterIndex2(nr,-3); // foundable
8726           t.SetClusterIndex(nr,-3); 
8727
8728           AliTPCclusterMI *cl=0;
8729           UInt_t uindex = 0;
8730           cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex); 
8731           if (!cl ) continue;
8732           double dy = cl->GetY()-t0.GetY();
8733           double dz = cl->GetZ()-t0.GetZ();
8734           double dr = sqrt(dy*dy+dz*dz);
8735           if( dr>roadr ){ 
8736             //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8737             continue;
8738           }
8739           //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8740
8741           t0.SetClusterPointer(nr, cl);   
8742           clusterIndex[nr] = krow.GetIndex(uindex);       
8743           if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8744           t0.SetLastPoint(nr);
8745           nClusters++;
8746         }
8747       }
8748
8749       if( nClusters <3 ){
8750         //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8751         break;
8752       }
8753       Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8754
8755       // find midpoint
8756       {
8757         Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8758         int dist=200;
8759         for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8760           if( !t0.GetClusterPointer(nr) ) continue;       
8761           int d = TMath::Abs(nr-midRow);
8762           if( d < dist ){
8763             dist = d;
8764             basePoints[1] = nr;
8765           }
8766         }
8767       }
8768
8769       // first fit 3 base points
8770       if( 1||iter<2 ){
8771         //cout<<"Fit3: "<<endl;
8772         for( int icl=0; icl<3; icl++){
8773           int nr = basePoints[icl];
8774           int lr=nr;
8775           if( nr>=fInnerSec->GetNRows()){ 
8776             lr = nr - fInnerSec->GetNRows();
8777             fSectors=fOuterSec;
8778           } else fSectors=fInnerSec;
8779
8780           AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8781           if(!cl){
8782             //cout<<"WRONG!!!!"<<endl; 
8783             continue;
8784           }
8785           int iSec = cl->GetDetector() %fkNIS;
8786           int rotate = iSec - t.GetRelativeSector();    
8787           if( rotate!=0 ){
8788             //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8789             if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8790               //cout<<"can't rotate "<<endl; 
8791               break;
8792             }
8793             t.SetRelativeSector(iSec);
8794           }
8795           Double_t x= cl->GetX();
8796           if (!t.PropagateTo(x)){
8797             //cout<<"can't propagate to x="<<x<<endl; 
8798             break;
8799           }    
8800
8801           if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8802             //cout<<"Snp is too big: "<<t.GetSnp()<<endl; 
8803             break;
8804           }
8805           //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8806           
8807           t.SetCurrentClusterIndex1(clusterIndex[nr]);
8808           t.SetCurrentCluster(cl);
8809           t.SetRow(lr); 
8810           
8811           t.SetErrorY2(shapeY2[nr]);
8812           t.SetErrorZ2(shapeZ2[nr]);
8813           if( icl==0 ){
8814             double cov[15];
8815             for( int j=0; j<15; j++ ) cov[j]=0;
8816             cov[0]=10;
8817             cov[2]=10;
8818             cov[5]=.5;
8819             cov[9]=.5;
8820             cov[14]=1.;
8821             t.AliExternalTrackParam::AddCovariance(cov);
8822           }
8823           if( !UpdateTrack(&t,0) ){
8824             //cout<<"Can not update"<<endl;
8825             //t.Print();
8826             t.SetClusterIndex2(nr,-1); 
8827             t.SetClusterIndex(nr,-1); 
8828             t.SetClusterPointer(nr,0); 
8829             break;
8830           }             
8831           //t.SetClusterPointer(nr, cl);
8832         }
8833         
8834         //t.SetLastPoint(t0.GetLastPoint());
8835         //t.SetFirstPoint(t0.GetFirstPoint());
8836
8837         //cout<<"Fit: "<<endl;
8838         for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8839           int lr=nr;
8840           if( nr>=fInnerSec->GetNRows()){ 
8841             lr = nr - fInnerSec->GetNRows();
8842             fSectors=fOuterSec;
8843           } else fSectors=fInnerSec;
8844           
8845           if(1|| iter<2 ){
8846             if( nr == basePoints[0] ) continue;
8847             if( nr == basePoints[1] ) continue;
8848             if( nr == basePoints[2] ) continue;
8849           }
8850           AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8851           if(!cl) continue;
8852           
8853           int iSec = cl->GetDetector() %fkNIS;
8854           int rotate = iSec - t.GetRelativeSector();    
8855           if( rotate!=0 ){
8856             //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8857             if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8858               //cout<<"can't rotate "<<endl; 
8859               break;
8860             }
8861             t.SetRelativeSector(iSec);
8862           }
8863           Double_t x= cl->GetX();
8864           if (!t.PropagateTo(x)){
8865             //cout<<"can't propagate to x="<<x<<endl; 
8866             break;
8867           }    
8868           if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8869             //cout<<"Snp is too big: "<<t.GetSnp()<<endl; 
8870             break;
8871           }     
8872           
8873           //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8874
8875           t.SetCurrentClusterIndex1(clusterIndex[nr]);
8876           t.SetCurrentCluster(cl);
8877           t.SetRow(lr); 
8878           t.SetErrorY2(shapeY2[nr]);
8879           t.SetErrorZ2(shapeZ2[nr]);
8880           
8881           if( !UpdateTrack(&t,0) ){
8882             //cout<<"Can not update"<<endl;
8883             //t.Print();
8884             t.SetClusterIndex2(nr,-1); 
8885             t.SetClusterIndex(nr,-1); 
8886             break;
8887           }             
8888           //t.SetClusterPointer(nr, cl);
8889         }
8890       }
8891       //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8892     }
8893
8894     //cout<<"fitted track"<<iSeed<<endl;
8895     //t.Print();
8896     //cout<<"Statistics: "<<endl;    
8897     Int_t foundable,found,shared;
8898     t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8899     t.SetNFoundable(foundable);
8900     //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8901     
8902   }
8903 }
8904
8905
8906 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8907 {
8908   // tracking
8909   //  
8910
8911   if( !hltEvent ) return 0;  
8912  
8913
8914   Int_t nentr=hltEvent->GetNumberOfTracks();
8915  
8916   AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8917  
8918   TObjArray * seeds = new TObjArray(nentr);
8919
8920   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8921   Int_t index = 0;
8922   
8923   Int_t nTr=hltEvent->GetNumberOfTracks();      
8924     
8925   for( int itr=0; itr<nTr; itr++ ){
8926     //if( itr!=97 ) continue;
8927     const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8928     if( !param ) continue;
8929     //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8930     //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8931     AliTPCtrack tr;    
8932     tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8933     tr.SetNumberOfClusters(0);
8934     AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8935
8936     Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8937     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8938     if (alpha < 0.            ) alpha += 2.*TMath::Pi();
8939     //
8940     seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8941     Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8942  
8943     if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8944     if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8945
8946     seed->Rotate(alphaSec - alpha);
8947     
8948     seed->SetPoolID(fLastSeedID);
8949     seed->SetIsSeeding(kTRUE);
8950     seed->SetSeed1(nup-1);
8951     seed->SetSeed2(nup-2);
8952     seed->SetSeedType(0);
8953     seed->SetFirstPoint(-1);
8954     seed->SetLastPoint(-1);
8955     seeds->AddLast(seed); // note, track is seed, don't free the seed
8956     index++;
8957     //if( index>3 ) break;
8958   }
8959  
8960
8961   fSectors = fOuterSec;
8962   
8963   TrackFollowingHLT(seeds );
8964
8965   nTr = seeds->GetEntriesFast();
8966   for( int itr=0; itr<nTr; itr++ ){
8967     AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8968     if( !seed ) continue;
8969     //FollowBackProlongation(*seed,0);
8970     // cout<<seed->GetNumberOfClusters()<<endl;
8971     Int_t foundable,found,shared;
8972     seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8973     seed->SetNFoundable(foundable);
8974     //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8975     //if ((found<0.55*foundable)  || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8976     //MarkSeedFree(seeds->RemoveAt(itr)); 
8977     //continue;
8978     //}
8979     if (seed->GetNumberOfClusters()<30 || 
8980         seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 || 
8981         seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8982       MarkSeedFree(seeds->RemoveAt(itr)); 
8983       continue;
8984     }      
8985
8986     for( int ir=0; ir<nup; ir++){
8987       AliTPCclusterMI *c = seed->GetClusterPointer(ir);      
8988       if( c ) c->Use(10);
8989     }
8990   }
8991   std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
8992   return seeds;    
8993 }
8994
8995 void AliTPCtracker::FillClusterOccupancyInfo()
8996 {
8997   //fill the cluster occupancy info into the ESD friend
8998   AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
8999   if (!esdFriend) return;
9000
9001   for (Int_t isector=0; isector<18; isector++){
9002     AliTPCtrackerSector &iroc = fInnerSec[isector];
9003     AliTPCtrackerSector &oroc = fOuterSec[isector];
9004     //all clusters
9005     esdFriend->SetNclustersTPC(isector,   iroc.GetNClInSector(0));
9006     esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
9007     esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
9008     esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
9009     //clusters used in tracking
9010     esdFriend->SetNclustersTPCused(isector,    iroc.GetNClUsedInSector(0));
9011     esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
9012     esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
9013     esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));
9014   }
9015 }