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