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