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