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