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