]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/AliTPCtrackerMI.cxx
d09514a8baa919eec0def51debc4263c0d9fd550
[u/mrichter/AliRoot.git] / TPC / AliTPCtrackerMI.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 Kalaman 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); where nis bigger 0
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/cm)
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 - AliTPCtrackerMI::FillESD
88 // 2. Second iteration - 
89 //      2.a ITS->TPC   - AliTPCtrackerMI::ReadSeeds 
90 //      2.b TPC->TRD   - AliTPCtrackerMI::PropagateBack
91 // 3. Third iteration  -
92 //      3.a TRD->TPC   - AliTPCtrackerMI::ReadSeeds
93 //      3.b TPC->ITS   - AliTPCtrackerMI::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 (Log level 9) - dump information about 
99 //         1.a) cluster
100 //         2.a) cluster error estimate
101 //         3.a) cluster shape estimate
102 //
103 //
104 //-------------------------------------------------------
105
106
107 /* $Id$ */
108
109 #include "Riostream.h"
110 #include <TClonesArray.h>
111 #include <TFile.h>
112 #include <TObjArray.h>
113 #include <TTree.h>
114 #include "AliLog.h"
115 #include "AliComplexCluster.h"
116 #include "AliESDEvent.h"
117 #include "AliESDtrack.h"
118 #include "AliESDVertex.h"
119 #include "AliKink.h"
120 #include "AliV0.h"
121 #include "AliHelix.h"
122 #include "AliRunLoader.h"
123 #include "AliTPCClustersRow.h"
124 #include "AliTPCParam.h"
125 #include "AliTPCReconstructor.h"
126 #include "AliTPCpolyTrack.h"
127 #include "AliTPCreco.h"
128 #include "AliTPCseed.h"
129
130 #include "AliTPCtrackerSector.h" 
131 #include "AliTPCtrackerMI.h"
132 #include "TStopwatch.h"
133 #include "AliTPCReconstructor.h"
134 #include "AliPID.h"
135 #include "TTreeStream.h"
136 #include "AliAlignObj.h"
137 #include "AliTrackPointArray.h"
138 #include "TRandom.h"
139 #include "AliTPCcalibDB.h"
140 #include "AliTPCTransform.h"
141 #include "AliTPCClusterParam.h"
142
143 //
144
145 ClassImp(AliTPCtrackerMI)
146
147
148
149 class AliTPCFastMath {
150 public:
151   AliTPCFastMath();  
152   static Double_t FastAsin(Double_t x);   
153  private: 
154   static Double_t fgFastAsin[20000];  //lookup table for fast asin computation
155 };
156
157 Double_t AliTPCFastMath::fgFastAsin[20000];
158 AliTPCFastMath gAliTPCFastMath; // needed to fill the LUT
159
160 AliTPCFastMath::AliTPCFastMath(){
161   //
162   // initialized lookup table;
163   for (Int_t i=0;i<10000;i++){
164     fgFastAsin[2*i] = TMath::ASin(i/10000.);
165     fgFastAsin[2*i+1] = (TMath::ASin((i+1)/10000.)-fgFastAsin[2*i]);
166   }
167 }
168
169 Double_t AliTPCFastMath::FastAsin(Double_t x){
170   //
171   // return asin using lookup table
172   if (x>0){
173     Int_t index = int(x*10000);
174     return fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1];
175   }
176   x*=-1;
177   Int_t index = int(x*10000);
178   return -(fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1]);
179 }
180 //__________________________________________________________________
181 AliTPCtrackerMI::AliTPCtrackerMI()
182                 :AliTracker(),
183                  fkNIS(0),
184                  fInnerSec(0),
185                  fkNOS(0),
186                  fOuterSec(0),
187                  fN(0),
188                  fSectors(0),
189                  fInput(0),
190                  fOutput(0),
191                  fSeedTree(0),
192                  fTreeDebug(0),
193                  fEvent(0),
194                  fDebug(0),
195                  fNewIO(kFALSE),
196                  fNtracks(0),
197                  fSeeds(0),
198                  fIteration(0),
199                  fParam(0),
200                  fDebugStreamer(0)
201 {
202   //
203   // default constructor
204   //
205 }
206 //_____________________________________________________________________
207
208
209
210 Int_t AliTPCtrackerMI::UpdateTrack(AliTPCseed * track, Int_t accept){
211   //
212   //update track information using current cluster - track->fCurrentCluster
213
214
215   AliTPCclusterMI* c =track->GetCurrentCluster();
216   if (accept>0) track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);  //sign not accepted clusters
217
218   UInt_t i = track->GetCurrentClusterIndex1();
219
220   Int_t sec=(i&0xff000000)>>24; 
221   //Int_t row = (i&0x00ff0000)>>16; 
222   track->SetRow((i&0x00ff0000)>>16);
223   track->SetSector(sec);
224   //  Int_t index = i&0xFFFF;
225   if (sec>=fParam->GetNInnerSector()) track->SetRow(track->GetRow()+fParam->GetNRowLow()); 
226   track->SetClusterIndex2(track->GetRow(), i);  
227   //track->fFirstPoint = row;
228   //if ( track->fLastPoint<row) track->fLastPoint =row;
229   //  if (track->fRow<0 || track->fRow>160) {
230   //  printf("problem\n");
231   //}
232   if (track->GetFirstPoint()>track->GetRow()) 
233     track->SetFirstPoint(track->GetRow());
234   if (track->GetLastPoint()<track->GetRow()) 
235     track->SetLastPoint(track->GetRow());
236   
237
238   track->SetClusterPointer(track->GetRow(),c);  
239   //
240
241   Double_t angle2 = track->GetSnp()*track->GetSnp();
242   //
243   //SET NEW Track Point
244   //
245   if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
246   {
247     angle2 = TMath::Sqrt(angle2/(1-angle2)); 
248     AliTPCTrackerPoint   &point =*(track->GetTrackPoint(track->GetRow()));
249     //
250     point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
251     point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
252     point.SetErrY(sqrt(track->GetErrorY2()));
253     point.SetErrZ(sqrt(track->GetErrorZ2()));
254     //
255     point.SetX(track->GetX());
256     point.SetY(track->GetY());
257     point.SetZ(track->GetZ());
258     point.SetAngleY(angle2);
259     point.SetAngleZ(track->GetTgl());
260     if (point.IsShared()){
261       track->SetErrorY2(track->GetErrorY2()*4);
262       track->SetErrorZ2(track->GetErrorZ2()*4);
263     }
264   }  
265
266   Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
267   //
268 //   track->SetErrorY2(track->GetErrorY2()*1.3);
269 //   track->SetErrorY2(track->GetErrorY2()+0.01);    
270 //   track->SetErrorZ2(track->GetErrorZ2()*1.3);   
271 //   track->SetErrorZ2(track->GetErrorZ2()+0.005);      
272     //}
273   if (accept>0) return 0;
274   if (track->GetNumberOfClusters()%20==0){
275     //    if (track->fHelixIn){
276     //  TClonesArray & larr = *(track->fHelixIn);    
277     //  Int_t ihelix = larr.GetEntriesFast();
278     //  new(larr[ihelix]) AliHelix(*track) ;    
279     //}
280   }
281   track->SetNoCluster(0);
282   return track->Update(c,chi2,i);
283 }
284
285
286
287 Int_t AliTPCtrackerMI::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
288 {
289   //
290   // decide according desired precision to accept given 
291   // cluster for tracking
292   Double_t sy2=ErrY2(seed,cluster);
293   Double_t sz2=ErrZ2(seed,cluster);
294   
295   Double_t sdistancey2 = sy2+seed->GetSigmaY2();
296   Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
297   
298   Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-seed->GetY())*
299     (seed->GetCurrentCluster()->GetY()-seed->GetY())/sdistancey2;
300   Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-seed->GetZ())*
301     (seed->GetCurrentCluster()->GetZ()-seed->GetZ())/sdistancez2;
302   
303   Double_t rdistance2  = rdistancey2+rdistancez2;
304   //Int_t  accept =0;
305   
306   if (AliTPCReconstructor::StreamLevel()>5 && seed->GetNumberOfClusters()>20) {
307     Float_t rmsy2 = seed->GetCurrentSigmaY2();
308     Float_t rmsz2 = seed->GetCurrentSigmaZ2();
309     Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
310     Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
311     Float_t rmsy2p30R  = seed->GetCMeanSigmaY2p30R();
312     Float_t rmsz2p30R  = seed->GetCMeanSigmaZ2p30R();
313
314     AliExternalTrackParam param(*seed); 
315     static TVectorD gcl(3),gtr(3);
316     Float_t gclf[3];
317     param.GetXYZ(gcl.GetMatrixArray());
318     cluster->GetGlobalXYZ(gclf);
319     gcl[0]=gclf[0];    gcl[1]=gclf[1];    gcl[2]=gclf[2];
320     (*fDebugStreamer)<<"ErrParam"<<
321       "Cl.="<<cluster<<
322       "T.="<<&param<<
323       "gcl.="<<&gcl<<
324       "gtr.="<<&gtr<<
325       "erry2="<<sy2<<
326       "errz2="<<sz2<<
327       "rmsy2="<<rmsy2<<
328       "rmsz2="<<rmsz2<< 
329       "rmsy2p30="<<rmsy2p30<<
330       "rmsz2p30="<<rmsz2p30<<   
331       "rmsy2p30R="<<rmsy2p30R<<
332       "rmsz2p30R="<<rmsz2p30R<< 
333       "\n";
334   }
335   
336   if (rdistance2>16) return 3;
337   
338   
339   if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)  
340     return 2;  //suspisiouce - will be changed
341   
342   if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)  
343     // strict cut on overlaped cluster
344     return  2;  //suspisiouce - will be changed
345   
346   if ( (rdistancey2>1. || rdistancez2>6.25 ) 
347        && cluster->GetType()<0){
348     seed->SetNFoundable(seed->GetNFoundable()-1);
349     return 2;    
350   }
351   return 0;
352 }
353
354
355
356
357 //_____________________________________________________________________________
358 AliTPCtrackerMI::AliTPCtrackerMI(const AliTPCParam *par): 
359 AliTracker(), 
360                  fkNIS(par->GetNInnerSector()/2),
361                  fInnerSec(0),
362                  fkNOS(par->GetNOuterSector()/2),
363                  fOuterSec(0),
364                  fN(0),
365                  fSectors(0),
366                  fInput(0),
367                  fOutput(0),
368                  fSeedTree(0),
369                  fTreeDebug(0),
370                  fEvent(0),
371                  fDebug(0),
372                  fNewIO(0),
373                  fNtracks(0),
374                  fSeeds(0),
375                  fIteration(0),
376                  fParam(0),
377                  fDebugStreamer(0)
378 {
379   //---------------------------------------------------------------------
380   // The main TPC tracker constructor
381   //---------------------------------------------------------------------
382   fInnerSec=new AliTPCtrackerSector[fkNIS];         
383   fOuterSec=new AliTPCtrackerSector[fkNOS];
384  
385   Int_t i;
386   for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
387   for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
388
389   fParam = par;  
390   Int_t nrowlow = par->GetNRowLow();
391   Int_t nrowup = par->GetNRowUp();
392
393   
394   for (Int_t i=0;i<nrowlow;i++){
395     fXRow[i]     = par->GetPadRowRadiiLow(i);
396     fPadLength[i]= par->GetPadPitchLength(0,i);
397     fYMax[i]     = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
398   }
399
400   
401   for (Int_t i=0;i<nrowup;i++){
402     fXRow[i+nrowlow]      = par->GetPadRowRadiiUp(i);
403     fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
404     fYMax[i+nrowlow]      = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
405   }
406
407   fDebugStreamer = new TTreeSRedirector("TPCdebug.root");
408 }
409 //________________________________________________________________________
410 AliTPCtrackerMI::AliTPCtrackerMI(const AliTPCtrackerMI &t):
411   AliTracker(t),
412                  fkNIS(t.fkNIS),
413                  fInnerSec(0),
414                  fkNOS(t.fkNOS),
415                  fOuterSec(0),
416                  fN(0),
417                  fSectors(0),
418                  fInput(0),
419                  fOutput(0),
420                  fSeedTree(0),
421                  fTreeDebug(0),
422                  fEvent(0),
423                  fDebug(0),
424                  fNewIO(kFALSE),
425                  fNtracks(0),
426                  fSeeds(0),
427                  fIteration(0),
428                  fParam(0),
429                  fDebugStreamer(0)
430 {
431   //------------------------------------
432   // dummy copy constructor
433   //------------------------------------------------------------------
434   fOutput=t.fOutput;
435 }
436 AliTPCtrackerMI & AliTPCtrackerMI::operator=(const AliTPCtrackerMI& /*r*/){
437   //------------------------------
438   // dummy 
439   //--------------------------------------------------------------
440   return *this;
441 }
442 //_____________________________________________________________________________
443 AliTPCtrackerMI::~AliTPCtrackerMI() {
444   //------------------------------------------------------------------
445   // TPC tracker destructor
446   //------------------------------------------------------------------
447   delete[] fInnerSec;
448   delete[] fOuterSec;
449   if (fSeeds) {
450     fSeeds->Delete(); 
451     delete fSeeds;
452   }
453   if (fDebugStreamer) delete fDebugStreamer;
454 }
455
456
457 void AliTPCtrackerMI::FillESD(TObjArray* arr)
458 {
459   //
460   //
461   //fill esds using updated tracks
462   if (fEvent){
463     // write tracks to the event
464     // store index of the track
465     Int_t nseed=arr->GetEntriesFast();
466     //FindKinks(arr,fEvent);
467     for (Int_t i=0; i<nseed; i++) {
468       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
469       if (!pt) continue; 
470       pt->UpdatePoints();
471       AddCovariance(pt);
472       if (AliTPCReconstructor::StreamLevel()>1) {
473         (*fDebugStreamer)<<"Track0"<<
474           "Tr0.="<<pt<<
475           "\n";       
476       }
477       //      pt->PropagateTo(fParam->GetInnerRadiusLow());
478       if (pt->GetKinkIndex(0)<=0){  //don't propagate daughter tracks 
479         pt->PropagateTo(fParam->GetInnerRadiusLow());
480       }
481  
482       if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
483         AliESDtrack iotrack;
484         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
485         iotrack.SetTPCPoints(pt->GetPoints());
486         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
487         iotrack.SetV0Indexes(pt->GetV0Indexes());
488         //      iotrack.SetTPCpid(pt->fTPCr);
489         //iotrack.SetTPCindex(i);
490         fEvent->AddTrack(&iotrack);
491         continue;
492       }
493        
494       if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
495         AliESDtrack iotrack;
496         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
497         iotrack.SetTPCPoints(pt->GetPoints());
498         //iotrack.SetTPCindex(i);
499         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
500         iotrack.SetV0Indexes(pt->GetV0Indexes());
501         //      iotrack.SetTPCpid(pt->fTPCr);
502         fEvent->AddTrack(&iotrack);
503         continue;
504       } 
505       //
506       // short tracks  - maybe decays
507
508       if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
509         Int_t found,foundable,shared;
510         pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
511         if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
512           AliESDtrack iotrack;
513           iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);    
514           //iotrack.SetTPCindex(i);
515           iotrack.SetTPCPoints(pt->GetPoints());
516           iotrack.SetKinkIndexes(pt->GetKinkIndexes());
517           iotrack.SetV0Indexes(pt->GetV0Indexes());
518           //iotrack.SetTPCpid(pt->fTPCr);
519           fEvent->AddTrack(&iotrack);
520           continue;
521         }
522       }       
523       
524       if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
525         Int_t found,foundable,shared;
526         pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
527         if (found<20) continue;
528         if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
529         //
530         AliESDtrack iotrack;
531         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);      
532         iotrack.SetTPCPoints(pt->GetPoints());
533         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
534         iotrack.SetV0Indexes(pt->GetV0Indexes());
535         //iotrack.SetTPCpid(pt->fTPCr);
536         //iotrack.SetTPCindex(i);
537         fEvent->AddTrack(&iotrack);
538         continue;
539       }   
540       // short tracks  - secondaties
541       //
542       if ( (pt->GetNumberOfClusters()>30) ) {
543         Int_t found,foundable,shared;
544         pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
545         if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
546           AliESDtrack iotrack;
547           iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);    
548           iotrack.SetTPCPoints(pt->GetPoints());
549           iotrack.SetKinkIndexes(pt->GetKinkIndexes());
550           iotrack.SetV0Indexes(pt->GetV0Indexes());
551           //iotrack.SetTPCpid(pt->fTPCr);       
552           //iotrack.SetTPCindex(i);
553           fEvent->AddTrack(&iotrack);
554           continue;
555         }
556       }       
557       
558       if ( (pt->GetNumberOfClusters()>15)) {
559         Int_t found,foundable,shared;
560         pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
561         if (found<15) continue;
562         if (foundable<=0) continue;
563         if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
564         if (float(found)/float(foundable)<0.8) continue;
565         //
566         AliESDtrack iotrack;
567         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);      
568         iotrack.SetTPCPoints(pt->GetPoints());
569         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
570         iotrack.SetV0Indexes(pt->GetV0Indexes());
571         //      iotrack.SetTPCpid(pt->fTPCr);
572         //iotrack.SetTPCindex(i);
573         fEvent->AddTrack(&iotrack);
574         continue;
575       }   
576     }
577   }
578   printf("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks());
579 }
580
581
582
583
584
585 Double_t AliTPCtrackerMI::ErrY2(AliTPCseed* seed, AliTPCclusterMI * cl){
586   //
587   //
588   // Use calibrated cluster error from OCDB
589   //
590   AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
591   //
592   Float_t z = TMath::Abs(fParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
593   Int_t ctype = cl->GetType();  
594   Int_t    type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
595   Double_t angle = seed->GetSnp()*seed->GetSnp();
596   angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
597   Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
598   if (ctype<0) {
599     erry2+=0.5;  // edge cluster
600   }
601   erry2*=erry2;
602   seed->SetErrorY2(erry2);
603   //
604   return erry2;
605
606 //calculate look-up table at the beginning
607 //   static Bool_t  ginit = kFALSE;
608 //   static Float_t gnoise1,gnoise2,gnoise3;
609 //   static Float_t ggg1[10000];
610 //   static Float_t ggg2[10000];
611 //   static Float_t ggg3[10000];
612 //   static Float_t glandau1[10000];
613 //   static Float_t glandau2[10000];
614 //   static Float_t glandau3[10000];
615 //   //
616 //   static Float_t gcor01[500];
617 //   static Float_t gcor02[500];
618 //   static Float_t gcorp[500];
619 //   //
620
621 //   //
622 //   if (ginit==kFALSE){
623 //     for (Int_t i=1;i<500;i++){
624 //       Float_t rsigma = float(i)/100.;
625 //       gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
626 //       gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
627 //       gcorp[i]  = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
628 //     }
629
630 //     //
631 //     for (Int_t i=3;i<10000;i++){
632 //       //
633 //       //
634 //       // inner sector
635 //       Float_t amp = float(i);
636 //       Float_t padlength =0.75;
637 //       gnoise1 = 0.0004/padlength;
638 //       Float_t nel     = 0.268*amp;
639 //       Float_t nprim   = 0.155*amp;
640 //       ggg1[i]          = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
641 //       glandau1[i]      = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
642 //       if (glandau1[i]>1) glandau1[i]=1;
643 //       glandau1[i]*=padlength*padlength/12.;      
644 //       //
645 //       // outer short
646 //       padlength =1.;
647 //       gnoise2   = 0.0004/padlength;
648 //       nel       = 0.3*amp;
649 //       nprim     = 0.133*amp;
650 //       ggg2[i]      = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
651 //       glandau2[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
652 //       if (glandau2[i]>1) glandau2[i]=1;
653 //       glandau2[i]*=padlength*padlength/12.;
654 //       //
655 //       //
656 //       // outer long
657 //       padlength =1.5;
658 //       gnoise3   = 0.0004/padlength;
659 //       nel       = 0.3*amp;
660 //       nprim     = 0.133*amp;
661 //       ggg3[i]      = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
662 //       glandau3[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
663 //       if (glandau3[i]>1) glandau3[i]=1;
664 //       glandau3[i]*=padlength*padlength/12.;
665 //       //
666 //     }
667 //     ginit = kTRUE;
668 //   }
669 //   //
670 //   //
671 //   //
672 //   Int_t amp = int(TMath::Abs(cl->GetQ()));  
673 //   if (amp>9999) {
674 //     seed->SetErrorY2(1.);
675 //     return 1.;
676 //   }
677 //   Float_t snoise2;
678 //   Float_t z = TMath::Abs(fParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
679 //   Int_t ctype = cl->GetType();  
680 //   Float_t padlength= GetPadPitchLength(seed->GetRow());
681 //   Double_t angle2 = seed->GetSnp()*seed->GetSnp();
682 //   angle2 = angle2/(1-angle2); 
683 //   //
684 //   //cluster "quality"
685 //   Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
686 //   Float_t res;
687 //   //
688 //   if (fSectors==fInnerSec){
689 //     snoise2 = gnoise1;
690 //     res     = ggg1[amp]*z+glandau1[amp]*angle2;     
691 //     if (ctype==0) res *= gcor01[rsigmay];
692 //     if ((ctype>0)){
693 //       res+=0.002;
694 //       res*= gcorp[rsigmay];
695 //     }
696 //   }
697 //   else {
698 //     if (padlength<1.1){
699 //       snoise2 = gnoise2;
700 //       res     = ggg2[amp]*z+glandau2[amp]*angle2; 
701 //       if (ctype==0) res *= gcor02[rsigmay];      
702 //       if ((ctype>0)){
703 //      res+=0.002;
704 //      res*= gcorp[rsigmay];
705 //       }
706 //     }
707 //     else{
708 //       snoise2 = gnoise3;      
709 //       res     = ggg3[amp]*z+glandau3[amp]*angle2; 
710 //       if (ctype==0) res *= gcor02[rsigmay];
711 //       if ((ctype>0)){
712 //      res+=0.002;
713 //      res*= gcorp[rsigmay];
714 //       }
715 //     }
716 //   }  
717
718 //   if (ctype<0){
719 //     res+=0.005;
720 //     res*=2.4;  // overestimate error 2 times
721 //   }
722 //   res+= snoise2;
723  
724 //   if (res<2*snoise2)
725 //     res = 2*snoise2;
726   
727 //   seed->SetErrorY2(res);
728 //   return res;
729
730
731 }
732
733
734
735 Double_t AliTPCtrackerMI::ErrZ2(AliTPCseed* seed, AliTPCclusterMI * cl){
736   //
737   //
738   // Use calibrated cluster error from OCDB
739   //
740   AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
741   //
742   Float_t z = TMath::Abs(fParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
743   Int_t ctype = cl->GetType();  
744   Int_t    type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
745   //
746   Double_t angle2 = seed->GetSnp()*seed->GetSnp();
747   angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2)); 
748   Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
749   Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
750   if (ctype<0) {
751     errz2+=0.5;  // edge cluster
752   }
753   errz2*=errz2;
754   seed->SetErrorZ2(errz2);
755   //
756   return errz2;
757
758
759
760 //   //seed->SetErrorY2(0.1);
761 //   //return 0.1;
762 //   //calculate look-up table at the beginning
763 //   static Bool_t  ginit = kFALSE;
764 //   static Float_t gnoise1,gnoise2,gnoise3;
765 //   static Float_t ggg1[10000];
766 //   static Float_t ggg2[10000];
767 //   static Float_t ggg3[10000];
768 //   static Float_t glandau1[10000];
769 //   static Float_t glandau2[10000];
770 //   static Float_t glandau3[10000];
771 //   //
772 //   static Float_t gcor01[1000];
773 //   static Float_t gcor02[1000];
774 //   static Float_t gcorp[1000];
775 //   //
776
777 //   //
778 //   if (ginit==kFALSE){
779 //     for (Int_t i=1;i<1000;i++){
780 //       Float_t rsigma = float(i)/100.;
781 //       gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
782 //       gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
783 //       gcorp[i]  = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
784 //     }
785
786 //     //
787 //     for (Int_t i=3;i<10000;i++){
788 //       //
789 //       //
790 //       // inner sector
791 //       Float_t amp = float(i);
792 //       Float_t padlength =0.75;
793 //       gnoise1 = 0.0004/padlength;
794 //       Float_t nel     = 0.268*amp;
795 //       Float_t nprim   = 0.155*amp;
796 //       ggg1[i]          = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
797 //       glandau1[i]      = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
798 //       if (glandau1[i]>1) glandau1[i]=1;
799 //       glandau1[i]*=padlength*padlength/12.;      
800 //       //
801 //       // outer short
802 //       padlength =1.;
803 //       gnoise2   = 0.0004/padlength;
804 //       nel       = 0.3*amp;
805 //       nprim     = 0.133*amp;
806 //       ggg2[i]      = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
807 //       glandau2[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
808 //       if (glandau2[i]>1) glandau2[i]=1;
809 //       glandau2[i]*=padlength*padlength/12.;
810 //       //
811 //       //
812 //       // outer long
813 //       padlength =1.5;
814 //       gnoise3   = 0.0004/padlength;
815 //       nel       = 0.3*amp;
816 //       nprim     = 0.133*amp;
817 //       ggg3[i]      = fParam->GetDiffT()*fParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
818 //       glandau3[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
819 //       if (glandau3[i]>1) glandau3[i]=1;
820 //       glandau3[i]*=padlength*padlength/12.;
821 //       //
822 //     }
823 //     ginit = kTRUE;
824 //   }
825 //   //
826 //   //
827 //   //
828 //   Int_t amp = int(TMath::Abs(cl->GetQ()));  
829 //   if (amp>9999) {
830 //     seed->SetErrorY2(1.);
831 //     return 1.;
832 //   }
833 //   Float_t snoise2;
834 //   Float_t z = TMath::Abs(fParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
835 //   Int_t ctype = cl->GetType();  
836 //   Float_t padlength= GetPadPitchLength(seed->GetRow());
837 //   //
838 //   Double_t angle2 = seed->GetSnp()*seed->GetSnp();
839 //   //  if (angle2<0.6) angle2 = 0.6;
840 //   angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2)); 
841 //   //
842 //   //cluster "quality"
843 //   Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
844 //   Float_t res;
845 //   //
846 //   if (fSectors==fInnerSec){
847 //     snoise2 = gnoise1;
848 //     res     = ggg1[amp]*z+glandau1[amp]*angle2;     
849 //     if (ctype==0) res *= gcor01[rsigmaz];
850 //     if ((ctype>0)){
851 //       res+=0.002;
852 //       res*= gcorp[rsigmaz];
853 //     }
854 //   }
855 //   else {
856 //     if (padlength<1.1){
857 //       snoise2 = gnoise2;
858 //       res     = ggg2[amp]*z+glandau2[amp]*angle2; 
859 //       if (ctype==0) res *= gcor02[rsigmaz];      
860 //       if ((ctype>0)){
861 //      res+=0.002;
862 //      res*= gcorp[rsigmaz];
863 //       }
864 //     }
865 //     else{
866 //       snoise2 = gnoise3;      
867 //       res     = ggg3[amp]*z+glandau3[amp]*angle2; 
868 //       if (ctype==0) res *= gcor02[rsigmaz];
869 //       if ((ctype>0)){
870 //      res+=0.002;
871 //      res*= gcorp[rsigmaz];
872 //       }
873 //     }
874 //   }  
875
876 //   if (ctype<0){
877 //     res+=0.002;
878 //     res*=1.3;
879 //   }
880 //   if ((ctype<0) &&amp<70){
881 //     res+=0.002;
882 //     res*=1.3;  
883 //   }
884 //   res += snoise2;
885 //   if (res<2*snoise2)
886 //      res = 2*snoise2;
887 //   if (res>3) res =3;
888 //   seed->SetErrorZ2(res);
889 //   return res;
890 }
891
892
893
894
895
896 void AliTPCtrackerMI::RotateToLocal(AliTPCseed *seed)
897 {
898   //rotate to track "local coordinata
899   Float_t x = seed->GetX();
900   Float_t y = seed->GetY();
901   Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
902   
903   if (y > ymax) {
904     seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
905     if (!seed->Rotate(fSectors->GetAlpha())) 
906       return;
907   } else if (y <-ymax) {
908     seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
909     if (!seed->Rotate(-fSectors->GetAlpha())) 
910       return;
911   }   
912
913 }
914
915
916
917 //_____________________________________________________________________________
918 Double_t AliTPCtrackerMI::F1old(Double_t x1,Double_t y1,
919                    Double_t x2,Double_t y2,
920                    Double_t x3,Double_t y3) 
921 {
922   //-----------------------------------------------------------------
923   // Initial approximation of the track curvature
924   //-----------------------------------------------------------------
925   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
926   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
927                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
928   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
929                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
930
931   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
932   if ( xr*xr+yr*yr<=0.00000000000001) return 100;
933   return -xr*yr/sqrt(xr*xr+yr*yr); 
934 }
935
936
937
938 //_____________________________________________________________________________
939 Double_t AliTPCtrackerMI::F1(Double_t x1,Double_t y1,
940                    Double_t x2,Double_t y2,
941                    Double_t x3,Double_t y3) 
942 {
943   //-----------------------------------------------------------------
944   // Initial approximation of the track curvature
945   //-----------------------------------------------------------------
946   x3 -=x1;
947   x2 -=x1;
948   y3 -=y1;
949   y2 -=y1;
950   //  
951   Double_t det = x3*y2-x2*y3;
952   if (det==0) {
953     return 100;
954   }
955   //
956   Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
957   Double_t x0 = x3*0.5-y3*u;
958   Double_t y0 = y3*0.5+x3*u;
959   Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
960   if (det<0) c2*=-1;
961   return c2;
962 }
963
964
965 Double_t AliTPCtrackerMI::F2(Double_t x1,Double_t y1,
966                    Double_t x2,Double_t y2,
967                    Double_t x3,Double_t y3) 
968 {
969   //-----------------------------------------------------------------
970   // Initial approximation of the track curvature
971   //-----------------------------------------------------------------
972   x3 -=x1;
973   x2 -=x1;
974   y3 -=y1;
975   y2 -=y1;
976   //  
977   Double_t det = x3*y2-x2*y3;
978   if (det==0) {
979     return 100;
980   }
981   //
982   Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
983   Double_t x0 = x3*0.5-y3*u; 
984   Double_t y0 = y3*0.5+x3*u;
985   Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
986   if (det<0) c2*=-1;
987   x0+=x1;
988   x0*=c2;  
989   return x0;
990 }
991
992
993
994 //_____________________________________________________________________________
995 Double_t AliTPCtrackerMI::F2old(Double_t x1,Double_t y1,
996                    Double_t x2,Double_t y2,
997                    Double_t x3,Double_t y3) 
998 {
999   //-----------------------------------------------------------------
1000   // Initial approximation of the track curvature times center of curvature
1001   //-----------------------------------------------------------------
1002   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1003   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1004                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1005   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1006                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1007
1008   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1009   
1010   return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1011 }
1012
1013 //_____________________________________________________________________________
1014 Double_t AliTPCtrackerMI::F3(Double_t x1,Double_t y1, 
1015                    Double_t x2,Double_t y2,
1016                    Double_t z1,Double_t z2) 
1017 {
1018   //-----------------------------------------------------------------
1019   // Initial approximation of the tangent of the track dip angle
1020   //-----------------------------------------------------------------
1021   return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1022 }
1023
1024
1025 Double_t AliTPCtrackerMI::F3n(Double_t x1,Double_t y1, 
1026                    Double_t x2,Double_t y2,
1027                    Double_t z1,Double_t z2, Double_t c) 
1028 {
1029   //-----------------------------------------------------------------
1030   // Initial approximation of the tangent of the track dip angle
1031   //-----------------------------------------------------------------
1032
1033   //  Double_t angle1;
1034   
1035   //angle1    =  (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1036   //
1037   Double_t d  =  TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1038   if (TMath::Abs(d*c*0.5)>1) return 0;
1039   //  Double_t   angle2    =  TMath::ASin(d*c*0.5);
1040   //  Double_t   angle2    =  AliTPCFastMath::FastAsin(d*c*0.5);
1041   Double_t   angle2    = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1042
1043   angle2  = (z1-z2)*c/(angle2*2.);
1044   return angle2;
1045 }
1046
1047 Bool_t   AliTPCtrackerMI::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z)
1048 {//-----------------------------------------------------------------
1049   // This function find proloncation of a track to a reference plane x=x2.
1050   //-----------------------------------------------------------------
1051   
1052   Double_t dx=x2-x1;
1053
1054   if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {   
1055     return kFALSE;
1056   }
1057
1058   Double_t c1=x[4]*x1 - x[2], r1=sqrt(1.- c1*c1);
1059   Double_t c2=x[4]*x2 - x[2], r2=sqrt(1.- c2*c2);  
1060   y = x[0];
1061   z = x[1];
1062   
1063   Double_t dy = dx*(c1+c2)/(r1+r2);
1064   Double_t dz = 0;
1065   //
1066   Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1067   
1068   if (TMath::Abs(delta)>0.01){
1069     dz = x[3]*TMath::ASin(delta)/x[4];
1070   }else{
1071     dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1072   }
1073   
1074   //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1075
1076   y+=dy;
1077   z+=dz;
1078   
1079   return kTRUE;  
1080 }
1081
1082 Int_t  AliTPCtrackerMI::LoadClusters (TTree *tree)
1083 {
1084   //
1085   //
1086   fInput = tree;
1087   return LoadClusters();
1088 }
1089
1090
1091 Int_t  AliTPCtrackerMI::LoadClusters(TObjArray *arr)
1092 {
1093   //
1094   // load clusters to the memory
1095   AliTPCClustersRow *clrow = 0x0; 
1096   Int_t lower   = arr->LowerBound();
1097   Int_t entries = arr->GetEntriesFast();
1098
1099   for (Int_t i=lower; i<entries; i++) {
1100     clrow = (AliTPCClustersRow*) arr->At(i);
1101         if(!clrow) continue;
1102         if(!clrow->GetArray()) continue;
1103
1104     //  
1105     Int_t sec,row;
1106     fParam->AdjustSectorRow(clrow->GetID(),sec,row);
1107
1108     for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1109       Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1110     }
1111     //
1112     if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1113     AliTPCtrackerRow * tpcrow=0;
1114     Int_t left=0;
1115     if (sec<fkNIS*2){
1116       tpcrow = &(fInnerSec[sec%fkNIS][row]);    
1117       left = sec/fkNIS;
1118     }
1119     else{
1120       tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1121       left = (sec-fkNIS*2)/fkNOS;
1122     }
1123     if (left ==0){
1124       tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1125       tpcrow->SetClusters1(new AliTPCclusterMI[tpcrow->GetN1()]);
1126       for (Int_t i=0;i<tpcrow->GetN1();i++) 
1127         tpcrow->SetCluster1(i, *(AliTPCclusterMI*)(clrow->GetArray()->At(i)));
1128     }
1129     if (left ==1){
1130       tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1131       tpcrow->SetClusters2(new AliTPCclusterMI[tpcrow->GetN2()]);
1132       for (Int_t i=0;i<tpcrow->GetN2();i++) 
1133         tpcrow->SetCluster2(i,*(AliTPCclusterMI*)(clrow->GetArray()->At(i)));
1134     }
1135   }
1136   //
1137   delete clrow;
1138   LoadOuterSectors();
1139   LoadInnerSectors();
1140   return 0;
1141 }
1142
1143
1144 Int_t  AliTPCtrackerMI::LoadClusters()
1145 {
1146   //
1147   // load clusters to the memory
1148   AliTPCClustersRow *clrow= new AliTPCClustersRow;
1149   clrow->SetClass("AliTPCclusterMI");
1150   clrow->SetArray(0);
1151   clrow->GetArray()->ExpandCreateFast(10000);
1152   //
1153   //  TTree * tree = fClustersArray.GetTree();
1154
1155   TTree * tree = fInput;
1156   TBranch * br = tree->GetBranch("Segment");
1157   br->SetAddress(&clrow);
1158   //
1159   Int_t j=Int_t(tree->GetEntries());
1160   for (Int_t i=0; i<j; i++) {
1161     br->GetEntry(i);
1162     //  
1163     Int_t sec,row;
1164     fParam->AdjustSectorRow(clrow->GetID(),sec,row);
1165     for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1166       Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1167     }
1168     //
1169     AliTPCtrackerRow * tpcrow=0;
1170     Int_t left=0;
1171     if (sec<fkNIS*2){
1172       tpcrow = &(fInnerSec[sec%fkNIS][row]);    
1173       left = sec/fkNIS;
1174     }
1175     else{
1176       tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1177       left = (sec-fkNIS*2)/fkNOS;
1178     }
1179     if (left ==0){
1180       tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1181       tpcrow->SetClusters1(new AliTPCclusterMI[tpcrow->GetN1()]);
1182       for (Int_t i=0;i<tpcrow->GetN1();i++) 
1183         tpcrow->SetCluster1(i, *(AliTPCclusterMI*)(clrow->GetArray()->At(i)));
1184     }
1185     if (left ==1){
1186       tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1187       tpcrow->SetClusters2(new AliTPCclusterMI[tpcrow->GetN2()]);
1188       for (Int_t i=0;i<tpcrow->GetN2();i++) 
1189         tpcrow->SetCluster2(i,*(AliTPCclusterMI*)(clrow->GetArray()->At(i)));
1190     }
1191   }
1192   //
1193   delete clrow;
1194   LoadOuterSectors();
1195   LoadInnerSectors();
1196   return 0;
1197 }
1198
1199
1200 void AliTPCtrackerMI::UnloadClusters()
1201 {
1202   //
1203   // unload clusters from the memory
1204   //
1205   Int_t nrows = fOuterSec->GetNRows();
1206   for (Int_t sec = 0;sec<fkNOS;sec++)
1207     for (Int_t row = 0;row<nrows;row++){
1208       AliTPCtrackerRow*  tpcrow = &(fOuterSec[sec%fkNOS][row]);
1209       //      if (tpcrow){
1210       //        if (tpcrow->fClusters1) delete []tpcrow->fClusters1; 
1211       //        if (tpcrow->fClusters2) delete []tpcrow->fClusters2; 
1212       //}
1213       tpcrow->ResetClusters();
1214     }
1215   //
1216   nrows = fInnerSec->GetNRows();
1217   for (Int_t sec = 0;sec<fkNIS;sec++)
1218     for (Int_t row = 0;row<nrows;row++){
1219       AliTPCtrackerRow*  tpcrow = &(fInnerSec[sec%fkNIS][row]);
1220       //if (tpcrow){
1221       //        if (tpcrow->fClusters1) delete []tpcrow->fClusters1; 
1222       //if (tpcrow->fClusters2) delete []tpcrow->fClusters2; 
1223       //}
1224       tpcrow->ResetClusters();
1225     }
1226
1227   return ;
1228 }
1229
1230 void AliTPCtrackerMI::FillClusterArray(TObjArray* array) const{
1231   //
1232   // Filling cluster to the array - For visualization purposes
1233   //
1234   Int_t nrows=0;
1235   nrows = fOuterSec->GetNRows();
1236   for (Int_t sec = 0;sec<fkNOS;sec++)
1237     for (Int_t row = 0;row<nrows;row++){
1238       AliTPCtrackerRow*  tpcrow = &(fOuterSec[sec%fkNOS][row]);
1239       if (!tpcrow) continue;
1240       for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1241         array->AddLast((TObject*)((*tpcrow)[icl]));
1242       }
1243     } 
1244   nrows = fInnerSec->GetNRows();
1245   for (Int_t sec = 0;sec<fkNIS;sec++)
1246     for (Int_t row = 0;row<nrows;row++){
1247       AliTPCtrackerRow*  tpcrow = &(fInnerSec[sec%fkNIS][row]);
1248       if (!tpcrow) continue;
1249       for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1250         array->AddLast((TObject*)(*tpcrow)[icl]);
1251       }
1252     }
1253 }
1254
1255
1256 void   AliTPCtrackerMI::Transform(AliTPCclusterMI * cluster){
1257   //
1258   //
1259   //
1260   AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
1261   if (!transform) {
1262     AliFatal("Tranformations not in calibDB");
1263   }
1264   Double_t x[3]={cluster->GetRow(),cluster->GetPad(),cluster->GetTimeBin()};
1265   Int_t i[1]={cluster->GetDetector()};
1266   transform->Transform(x,i,0,1);  
1267   if (!AliTPCReconstructor::GetRecoParam()->GetBYMirror()){
1268     if (cluster->GetDetector()%36>17){
1269       x[1]*=-1;
1270     }
1271   }
1272
1273   //
1274   // in debug mode  check the transformation
1275   //
1276   if (AliTPCReconstructor::StreamLevel()>1) {
1277     Float_t gx[3];
1278     cluster->GetGlobalXYZ(gx);
1279     Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1280     TTreeSRedirector &cstream = *fDebugStreamer;
1281     cstream<<"Transform"<<
1282       "event="<<event<<
1283       "x0="<<x[0]<<
1284       "x1="<<x[1]<<
1285       "x2="<<x[2]<<
1286       "gx0="<<gx[0]<<
1287       "gx1="<<gx[1]<<
1288       "gx2="<<gx[2]<<
1289       "Cl.="<<cluster<<
1290       "\n"; 
1291   }
1292   cluster->SetX(x[0]);
1293   cluster->SetY(x[1]);
1294   cluster->SetZ(x[2]);
1295   // The old stuff:
1296
1297   //
1298   // 
1299   //
1300   //if (!fParam->IsGeoRead()) fParam->ReadGeoMatrices();
1301   TGeoHMatrix  *mat = fParam->GetClusterMatrix(cluster->GetDetector());
1302   //TGeoHMatrix  mat;
1303   Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1304   Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1305   if (mat) mat->LocalToMaster(pos,posC);
1306   else{
1307     // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1308   }
1309   cluster->SetX(posC[0]);
1310   cluster->SetY(posC[1]);
1311   cluster->SetZ(posC[2]);
1312 }
1313
1314 //_____________________________________________________________________________
1315 Int_t AliTPCtrackerMI::LoadOuterSectors() {
1316   //-----------------------------------------------------------------
1317   // This function fills outer TPC sectors with clusters.
1318   //-----------------------------------------------------------------
1319   Int_t nrows = fOuterSec->GetNRows();
1320   UInt_t index=0;
1321   for (Int_t sec = 0;sec<fkNOS;sec++)
1322     for (Int_t row = 0;row<nrows;row++){
1323       AliTPCtrackerRow*  tpcrow = &(fOuterSec[sec%fkNOS][row]);  
1324       Int_t sec2 = sec+2*fkNIS;
1325       //left
1326       Int_t ncl = tpcrow->GetN1();
1327       while (ncl--) {
1328         AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1329         index=(((sec2<<8)+row)<<16)+ncl;
1330         tpcrow->InsertCluster(c,index);
1331       }
1332       //right
1333       ncl = tpcrow->GetN2();
1334       while (ncl--) {
1335         AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1336         index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
1337         tpcrow->InsertCluster(c,index);
1338       }
1339       //
1340       // write indexes for fast acces
1341       //
1342       for (Int_t i=0;i<510;i++)
1343         tpcrow->SetFastCluster(i,-1);
1344       for (Int_t i=0;i<tpcrow->GetN();i++){
1345         Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1346         tpcrow->SetFastCluster(zi,i);  // write index
1347       }
1348       Int_t last = 0;
1349       for (Int_t i=0;i<510;i++){
1350         if (tpcrow->GetFastCluster(i)<0)
1351           tpcrow->SetFastCluster(i,last);
1352         else
1353           last = tpcrow->GetFastCluster(i);
1354       }
1355     }  
1356   fN=fkNOS;
1357   fSectors=fOuterSec;
1358   return 0;
1359 }
1360
1361
1362 //_____________________________________________________________________________
1363 Int_t  AliTPCtrackerMI::LoadInnerSectors() {
1364   //-----------------------------------------------------------------
1365   // This function fills inner TPC sectors with clusters.
1366   //-----------------------------------------------------------------
1367   Int_t nrows = fInnerSec->GetNRows();
1368   UInt_t index=0;
1369   for (Int_t sec = 0;sec<fkNIS;sec++)
1370     for (Int_t row = 0;row<nrows;row++){
1371       AliTPCtrackerRow*  tpcrow = &(fInnerSec[sec%fkNIS][row]);
1372       //
1373       //left
1374       Int_t ncl = tpcrow->GetN1();
1375       while (ncl--) {
1376         AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1377         index=(((sec<<8)+row)<<16)+ncl;
1378         tpcrow->InsertCluster(c,index);
1379       }
1380       //right
1381       ncl = tpcrow->GetN2();
1382       while (ncl--) {
1383         AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1384         index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
1385         tpcrow->InsertCluster(c,index);
1386       }
1387       //
1388       // write indexes for fast acces
1389       //
1390       for (Int_t i=0;i<510;i++)
1391         tpcrow->SetFastCluster(i,-1);
1392       for (Int_t i=0;i<tpcrow->GetN();i++){
1393         Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1394         tpcrow->SetFastCluster(zi,i);  // write index
1395       }
1396       Int_t last = 0;
1397       for (Int_t i=0;i<510;i++){
1398         if (tpcrow->GetFastCluster(i)<0)
1399           tpcrow->SetFastCluster(i,last);
1400         else
1401           last = tpcrow->GetFastCluster(i);
1402       }
1403
1404     }  
1405    
1406   fN=fkNIS;
1407   fSectors=fInnerSec;
1408   return 0;
1409 }
1410
1411
1412
1413 //_________________________________________________________________________
1414 AliTPCclusterMI *AliTPCtrackerMI::GetClusterMI(Int_t index) const {
1415   //--------------------------------------------------------------------
1416   //       Return pointer to a given cluster
1417   //--------------------------------------------------------------------
1418   if (index<0) return 0; // no cluster
1419   Int_t sec=(index&0xff000000)>>24; 
1420   Int_t row=(index&0x00ff0000)>>16; 
1421   Int_t ncl=(index&0x00007fff)>>00;
1422
1423   const AliTPCtrackerRow * tpcrow=0;
1424   AliTPCclusterMI * clrow =0;
1425
1426   if (sec<0 || sec>=fkNIS*4) {
1427     AliWarning(Form("Wrong sector %d",sec));
1428     return 0x0;
1429   }
1430
1431   if (sec<fkNIS*2){
1432     tpcrow = &(fInnerSec[sec%fkNIS][row]);
1433     if (tpcrow==0) return 0;
1434
1435     if (sec<fkNIS) {
1436       if (tpcrow->GetN1()<=ncl) return 0;
1437       clrow = tpcrow->GetClusters1();
1438     }
1439     else {
1440       if (tpcrow->GetN2()<=ncl) return 0;
1441       clrow = tpcrow->GetClusters2();
1442     }
1443   }
1444   else {
1445     tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1446     if (tpcrow==0) return 0;
1447
1448     if (sec-2*fkNIS<fkNOS) {
1449       if (tpcrow->GetN1()<=ncl) return 0;
1450       clrow = tpcrow->GetClusters1();
1451     }
1452     else {
1453       if (tpcrow->GetN2()<=ncl) return 0;
1454       clrow = tpcrow->GetClusters2();
1455     }
1456   }
1457
1458   return &(clrow[ncl]);      
1459   
1460 }
1461
1462
1463
1464 Int_t AliTPCtrackerMI::FollowToNext(AliTPCseed& t, Int_t nr) {
1465   //-----------------------------------------------------------------
1466   // This function tries to find a track prolongation to next pad row
1467   //-----------------------------------------------------------------
1468   //
1469   Double_t  x= GetXrow(nr), ymax=GetMaxY(nr);
1470   AliTPCclusterMI *cl=0;
1471   Int_t tpcindex= t.GetClusterIndex2(nr);
1472   //
1473   // update current shape info every 5 pad-row
1474   //  if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
1475     GetShape(&t,nr);    
1476     //}
1477   //  
1478   if (fIteration>0 && tpcindex>=-1){  //if we have already clusters 
1479     //        
1480     if (tpcindex==-1) return 0; //track in dead zone
1481     if (tpcindex>0){     //
1482       cl = t.GetClusterPointer(nr);
1483       if ( (cl==0) ) cl = GetClusterMI(tpcindex);
1484       t.SetCurrentClusterIndex1(tpcindex); 
1485     }
1486     if (cl){      
1487       Int_t relativesector = ((tpcindex&0xff000000)>>24)%18;  // if previously accepted cluster in different sector
1488       Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
1489       //
1490       if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
1491       if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
1492       
1493       if (TMath::Abs(angle-t.GetAlpha())>0.001){
1494         Double_t rotation = angle-t.GetAlpha();
1495         t.SetRelativeSector(relativesector);
1496         if (!t.Rotate(rotation)) return 0;      
1497       }
1498       if (!t.PropagateTo(x)) return 0;
1499       //
1500       t.SetCurrentCluster(cl); 
1501       t.SetRow(nr);
1502       Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1503       if ((tpcindex&0x8000)==0) accept =0;
1504       if (accept<3) { 
1505         //if founded cluster is acceptible
1506         if (cl->IsUsed(11)) {  // id cluster is shared inrease uncertainty
1507           t.SetErrorY2(t.GetErrorY2()+0.03);
1508           t.SetErrorZ2(t.GetErrorZ2()+0.03); 
1509           t.SetErrorY2(t.GetErrorY2()*3);
1510           t.SetErrorZ2(t.GetErrorZ2()*3); 
1511         }
1512         t.SetNFoundable(t.GetNFoundable()+1);
1513         UpdateTrack(&t,accept);
1514         return 1;
1515       }    
1516     }
1517   }
1518   if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;  // cut on angle
1519   if (fIteration>1){
1520     // not look for new cluster during refitting    
1521     t.SetNFoundable(t.GetNFoundable()+1);
1522     return 0;
1523   }
1524   //
1525   UInt_t index=0;
1526   //  if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
1527   Double_t  y=t.GetYat(x);
1528   if (TMath::Abs(y)>ymax){
1529     if (y > ymax) {
1530       t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1531       if (!t.Rotate(fSectors->GetAlpha())) 
1532         return 0;
1533     } else if (y <-ymax) {
1534       t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1535       if (!t.Rotate(-fSectors->GetAlpha())) 
1536         return 0;
1537     }
1538     //return 1;
1539   }
1540   //
1541   if (!t.PropagateTo(x)) {
1542     if (fIteration==0) t.SetRemoval(10);
1543     return 0;
1544   }
1545   y=t.GetY(); 
1546   Double_t z=t.GetZ();
1547   //
1548
1549   if (!IsActive(t.GetRelativeSector(),nr)) {
1550     t.SetInDead(kTRUE);
1551     t.SetClusterIndex2(nr,-1); 
1552     return 0;
1553   }
1554   //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1555   Bool_t isActive  = IsActive(t.GetRelativeSector(),nr);
1556   Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
1557   
1558   if (!isActive || !isActive2) return 0;
1559
1560   const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
1561   if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
1562   Double_t  roady  =1.;
1563   Double_t  roadz = 1.;
1564   //
1565   if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1566     t.SetInDead(kTRUE);
1567     t.SetClusterIndex2(nr,-1); 
1568     return 0;
1569   } 
1570   else
1571     {
1572       if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker())) 
1573         t.SetNFoundable(t.GetNFoundable()+1);
1574       else
1575         return 0;
1576     }   
1577   //calculate 
1578   if (krow) {
1579     //    cl = krow.FindNearest2(y+10.,z,roady,roadz,index);    
1580     cl = krow.FindNearest2(y,z,roady,roadz,index);    
1581     if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));       
1582   }  
1583   if (cl) {
1584     t.SetCurrentCluster(cl); 
1585     t.SetRow(nr);
1586     if (fIteration==2&&cl->IsUsed(10)) return 0; 
1587     Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1588     if (fIteration==2&&cl->IsUsed(11)) {
1589       t.SetErrorY2(t.GetErrorY2()+0.03);
1590       t.SetErrorZ2(t.GetErrorZ2()+0.03); 
1591       t.SetErrorY2(t.GetErrorY2()*3);
1592       t.SetErrorZ2(t.GetErrorZ2()*3); 
1593     }
1594     /*    
1595     if (t.fCurrentCluster->IsUsed(10)){
1596       //
1597       //     
1598
1599       t.fNShared++;
1600       if (t.fNShared>0.7*t.GetNumberOfClusters()) {
1601         t.fRemoval =10;
1602         return 0;
1603       }
1604     }
1605     */
1606     if (accept<3) UpdateTrack(&t,accept);
1607
1608   } else {  
1609     if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
1610     
1611   }
1612   return 1;
1613 }
1614
1615 Int_t AliTPCtrackerMI::FollowToNextFast(AliTPCseed& t, Int_t nr) {
1616   //-----------------------------------------------------------------
1617   // This function tries to find a track prolongation to next pad row
1618   //-----------------------------------------------------------------
1619   //
1620   Double_t  x= GetXrow(nr), ymax=GetMaxY(nr);
1621   Double_t y,z; 
1622   if (!t.GetProlongation(x,y,z)) {
1623     t.SetRemoval(10);
1624     return 0;
1625   }
1626   //
1627   //
1628   if (TMath::Abs(y)>ymax){
1629     
1630     if (y > ymax) {
1631       t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1632       if (!t.Rotate(fSectors->GetAlpha())) 
1633         return 0;
1634     } else if (y <-ymax) {
1635       t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1636       if (!t.Rotate(-fSectors->GetAlpha())) 
1637         return 0;
1638     }
1639     if (!t.PropagateTo(x)) {
1640       return 0;
1641     } 
1642     t.GetProlongation(x,y,z);
1643   }
1644   //
1645   // update current shape info every 2 pad-row
1646   if ( (nr%2==0) || t.GetNumberOfClusters()<2 || (t.GetCurrentSigmaY2()<0.0001) ){
1647     //    t.fCurrentSigmaY = GetSigmaY(&t);
1648     //t.fCurrentSigmaZ = GetSigmaZ(&t);
1649     GetShape(&t,nr);
1650   }
1651   //  
1652   AliTPCclusterMI *cl=0;
1653   UInt_t index=0;
1654   
1655   
1656   //Int_t nr2 = nr;
1657   const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
1658   if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
1659   Double_t  roady  =1.;
1660   Double_t  roadz = 1.;
1661   //
1662   Int_t row = nr;
1663   if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1664     t.SetInDead(kTRUE);
1665     t.SetClusterIndex2(row,-1); 
1666     return 0;
1667   } 
1668   else
1669     {
1670       if (TMath::Abs(z)>(AliTPCReconstructor::GetCtgRange()*x+10)) t.SetClusterIndex2(row,-1);
1671     }   
1672   //calculate 
1673   
1674   if ((cl==0)&&(krow)) {
1675     //    cl = krow.FindNearest2(y+10,z,roady,roadz,index);    
1676     cl = krow.FindNearest2(y,z,roady,roadz,index);    
1677
1678     if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));       
1679   }  
1680
1681   if (cl) {
1682     t.SetCurrentCluster(cl); 
1683     //    Int_t accept = AcceptCluster(&t,t.fCurrentCluster);        
1684     //if (accept<3){
1685       t.SetClusterIndex2(row,index);
1686       t.SetClusterPointer(row, cl);
1687       //}
1688   }
1689   return 1;
1690 }
1691
1692
1693
1694 //_________________________________________________________________________
1695 Bool_t AliTPCtrackerMI::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
1696 {
1697   // Get track space point by index
1698   // return false in case the cluster doesn't exist
1699   AliTPCclusterMI *cl = GetClusterMI(index);
1700   if (!cl) return kFALSE;
1701   Int_t sector = (index&0xff000000)>>24;
1702   //  Int_t row = (index&0x00ff0000)>>16;
1703   Float_t xyz[3];
1704   //  xyz[0] = fParam->GetPadRowRadii(sector,row);
1705   xyz[0] = cl->GetX();
1706   xyz[1] = cl->GetY();
1707   xyz[2] = cl->GetZ();
1708   Float_t sin,cos;
1709   fParam->AdjustCosSin(sector,cos,sin);
1710   Float_t x = cos*xyz[0]-sin*xyz[1];
1711   Float_t y = cos*xyz[1]+sin*xyz[0];
1712   Float_t cov[6];
1713   Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
1714   if (sector < fParam->GetNInnerSector()) sigmaY2 *= 2.07;
1715   Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
1716   if (sector < fParam->GetNInnerSector()) sigmaZ2 *= 1.77;
1717   cov[0] = sin*sin*sigmaY2;
1718   cov[1] = -sin*cos*sigmaY2;
1719   cov[2] = 0.;
1720   cov[3] = cos*cos*sigmaY2;
1721   cov[4] = 0.;
1722   cov[5] = sigmaZ2;
1723   p.SetXYZ(x,y,xyz[2],cov);
1724   AliGeomManager::ELayerID iLayer;
1725   Int_t idet;
1726   if (sector < fParam->GetNInnerSector()) {
1727     iLayer = AliGeomManager::kTPC1;
1728     idet = sector;
1729   }
1730   else {
1731     iLayer = AliGeomManager::kTPC2;
1732     idet = sector - fParam->GetNInnerSector();
1733   }
1734   UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
1735   p.SetVolumeID(volid);
1736   return kTRUE;
1737 }
1738
1739
1740
1741 Int_t AliTPCtrackerMI::UpdateClusters(AliTPCseed& t,  Int_t nr) {
1742   //-----------------------------------------------------------------
1743   // This function tries to find a track prolongation to next pad row
1744   //-----------------------------------------------------------------
1745   t.SetCurrentCluster(0);
1746   t.SetCurrentClusterIndex1(0);   
1747    
1748   Double_t xt=t.GetX();
1749   Int_t     row = GetRowNumber(xt)-1; 
1750   Double_t  ymax= GetMaxY(nr);
1751
1752   if (row < nr) return 1; // don't prolongate if not information until now -
1753 //   if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
1754 //     t.fRemoval =10;
1755 //     return 0;  // not prolongate strongly inclined tracks
1756 //   } 
1757 //   if (TMath::Abs(t.GetSnp())>0.95) {
1758 //     t.fRemoval =10;
1759 //     return 0;  // not prolongate strongly inclined tracks
1760 //   }// patch 28 fev 06
1761
1762   Double_t x= GetXrow(nr);
1763   Double_t y,z;
1764   //t.PropagateTo(x+0.02);
1765   //t.PropagateTo(x+0.01);
1766   if (!t.PropagateTo(x)){
1767     return 0;
1768   }
1769   //
1770   y=t.GetY();
1771   z=t.GetZ();
1772
1773   if (TMath::Abs(y)>ymax){
1774     if (y > ymax) {
1775       t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1776       if (!t.Rotate(fSectors->GetAlpha())) 
1777         return 0;
1778     } else if (y <-ymax) {
1779       t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1780       if (!t.Rotate(-fSectors->GetAlpha())) 
1781         return 0;
1782     }
1783     //    if (!t.PropagateTo(x)){
1784     //  return 0;
1785     //}
1786     return 1;
1787     //y = t.GetY();    
1788   }
1789   //
1790   if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
1791
1792   if (!IsActive(t.GetRelativeSector(),nr)) {
1793     t.SetInDead(kTRUE);
1794     t.SetClusterIndex2(nr,-1); 
1795     return 0;
1796   }
1797   //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1798
1799   AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
1800
1801   if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1802     t.SetInDead(kTRUE);
1803     t.SetClusterIndex2(nr,-1); 
1804     return 0;
1805   } 
1806   else
1807     {
1808       if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker())) t.SetNFoundable(t.GetNFoundable()+1);
1809       else
1810         return 0;      
1811     }
1812
1813   // update current
1814   if ( (nr%2==0) || t.GetNumberOfClusters()<2){
1815     //    t.fCurrentSigmaY = GetSigmaY(&t);
1816     //t.fCurrentSigmaZ = GetSigmaZ(&t);
1817     GetShape(&t,nr);
1818   }
1819     
1820   AliTPCclusterMI *cl=0;
1821   Int_t index=0;
1822   //
1823   Double_t roady = 1.;
1824   Double_t roadz = 1.;
1825   //
1826
1827   if (!cl){
1828     index = t.GetClusterIndex2(nr);    
1829     if ( (index>0) && (index&0x8000)==0){
1830       cl = t.GetClusterPointer(nr);
1831       if ( (cl==0) && (index>0)) cl = GetClusterMI(index);
1832       t.SetCurrentClusterIndex1(index);
1833       if (cl) {
1834         t.SetCurrentCluster(cl);
1835         return 1;
1836       }
1837     }
1838   }
1839
1840   //  if (index<0) return 0;
1841   UInt_t uindex = TMath::Abs(index);
1842
1843   if (krow) {    
1844     //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);      
1845     cl = krow.FindNearest2(y,z,roady,roadz,uindex);      
1846   }
1847
1848   if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));   
1849   t.SetCurrentCluster(cl);
1850
1851   return 1;
1852 }
1853
1854
1855 Int_t AliTPCtrackerMI::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
1856   //-----------------------------------------------------------------
1857   // This function tries to find a track prolongation to next pad row
1858   //-----------------------------------------------------------------
1859
1860   //update error according neighborhoud
1861
1862   if (t.GetCurrentCluster()) {
1863     t.SetRow(nr); 
1864     Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1865     
1866     if (t.GetCurrentCluster()->IsUsed(10)){
1867       //
1868       //
1869       //  t.fErrorZ2*=2;
1870       //  t.fErrorY2*=2;
1871       t.SetNShared(t.GetNShared()+1);
1872       if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
1873         t.SetRemoval(10);
1874         return 0;
1875       }
1876     }   
1877     if (fIteration>0) accept = 0;
1878     if (accept<3)  UpdateTrack(&t,accept);  
1879  
1880   } else {
1881     if (fIteration==0){
1882       if ( ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)&& t.GetNumberOfClusters()>18) t.SetRemoval(10);      
1883       if (  t.GetChi2()/t.GetNumberOfClusters()>6 &&t.GetNumberOfClusters()>18) t.SetRemoval(10);      
1884
1885       if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
1886     }
1887   }
1888   return 1;
1889 }
1890
1891
1892
1893 //_____________________________________________________________________________
1894 Int_t AliTPCtrackerMI::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step) {
1895   //-----------------------------------------------------------------
1896   // This function tries to find a track prolongation.
1897   //-----------------------------------------------------------------
1898   Double_t xt=t.GetX();
1899   //
1900   Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
1901   if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
1902   if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
1903   //
1904   t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
1905     
1906   Int_t first = GetRowNumber(xt)-1;
1907   for (Int_t nr= first; nr>=rf; nr-=step) {
1908     // update kink info
1909     if (t.GetKinkIndexes()[0]>0){
1910       for (Int_t i=0;i<3;i++){
1911         Int_t index = t.GetKinkIndexes()[i];
1912         if (index==0) break;
1913         if (index<0) continue;
1914         //
1915         AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
1916         if (!kink){
1917           printf("PROBLEM\n");
1918         }
1919         else{
1920           Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
1921           if (kinkrow==nr){
1922             AliExternalTrackParam paramd(t);
1923             kink->SetDaughter(paramd);
1924             kink->SetStatus(2,5);
1925             kink->Update();
1926           }
1927         }
1928       }
1929     }
1930
1931     if (nr==80) t.UpdateReference();
1932     if (nr<fInnerSec->GetNRows()) 
1933       fSectors = fInnerSec;
1934     else
1935       fSectors = fOuterSec;
1936     if (FollowToNext(t,nr)==0) 
1937       if (!t.IsActive()) 
1938         return 0;
1939     
1940   }   
1941   return 1;
1942 }
1943
1944
1945 //_____________________________________________________________________________
1946 Int_t AliTPCtrackerMI::FollowProlongationFast(AliTPCseed& t, Int_t rf, Int_t step) {
1947   //-----------------------------------------------------------------
1948   // This function tries to find a track prolongation.
1949   //-----------------------------------------------------------------
1950   Double_t xt=t.GetX();
1951   //
1952   Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
1953   if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
1954   if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
1955   t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
1956     
1957   for (Int_t nr=GetRowNumber(xt)-1; nr>=rf; nr-=step) {
1958     
1959     if (FollowToNextFast(t,nr)==0) 
1960       if (!t.IsActive()) return 0;
1961     
1962   }   
1963   return 1;
1964 }
1965
1966
1967
1968
1969
1970 Int_t AliTPCtrackerMI::FollowBackProlongation(AliTPCseed& t, Int_t rf) {
1971   //-----------------------------------------------------------------
1972   // This function tries to find a track prolongation.
1973   //-----------------------------------------------------------------
1974   //
1975   Double_t xt=t.GetX();  
1976   Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
1977   if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
1978   if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
1979   t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
1980     
1981   Int_t first = t.GetFirstPoint();
1982   if (first<GetRowNumber(xt)+1) first = GetRowNumber(xt)+1;
1983   //
1984   if (first<0) first=0;
1985   for (Int_t nr=first; nr<=rf; nr++) {
1986     //    if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
1987     if (t.GetKinkIndexes()[0]<0){
1988       for (Int_t i=0;i<3;i++){
1989         Int_t index = t.GetKinkIndexes()[i];
1990         if (index==0) break;
1991         if (index>0) continue;
1992         index = TMath::Abs(index);
1993         AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
1994         if (!kink){
1995           printf("PROBLEM\n");
1996         }
1997         else{
1998           Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
1999           if (kinkrow==nr){
2000             AliExternalTrackParam paramm(t);
2001             kink->SetMother(paramm);
2002             kink->SetStatus(2,1);
2003             kink->Update();
2004           }
2005         }
2006       }      
2007     }
2008     //
2009     if (nr<fInnerSec->GetNRows()) 
2010       fSectors = fInnerSec;
2011     else
2012       fSectors = fOuterSec;
2013
2014     FollowToNext(t,nr);                                                             
2015   }   
2016   return 1;
2017 }
2018
2019
2020
2021
2022    
2023 Float_t AliTPCtrackerMI::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2024 {
2025   //
2026   //
2027   sum1=0;
2028   sum2=0;
2029   Int_t sum=0;
2030   //
2031   Float_t dz2 =(s1->GetZ() - s2->GetZ());
2032   dz2*=dz2;  
2033
2034   Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2035   dy2*=dy2;
2036   Float_t distance = TMath::Sqrt(dz2+dy2);
2037   if (distance>4.) return 0; // if there are far away  - not overlap - to reduce combinatorics
2038  
2039   //  Int_t offset =0;
2040   Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2041   Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2042   if (lastpoint>160) 
2043     lastpoint =160;
2044   if (firstpoint<0) 
2045     firstpoint = 0;
2046   if (firstpoint>lastpoint) {
2047     firstpoint =lastpoint;
2048     //    lastpoint  =160;
2049   }
2050     
2051   
2052   for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2053     if (s1->GetClusterIndex2(i)>0) sum1++;
2054     if (s2->GetClusterIndex2(i)>0) sum2++;
2055     if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2056       sum++;
2057     }
2058   }
2059   if (sum<5) return 0;
2060
2061   Float_t summin = TMath::Min(sum1+1,sum2+1);
2062   Float_t ratio = (sum+1)/Float_t(summin);
2063   return ratio;
2064 }
2065
2066 void  AliTPCtrackerMI::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2067 {
2068   //
2069   //
2070   Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2071   if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2072   Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2073   Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2074   
2075   //
2076   Int_t sumshared=0;
2077   //
2078   //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2079   //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2080   Int_t firstpoint = 0;
2081   Int_t lastpoint = 160;
2082   //
2083   //  if (firstpoint>=lastpoint-5) return;;
2084
2085   for (Int_t i=firstpoint;i<lastpoint;i++){
2086     //    if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2087     if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2088       sumshared++;
2089       s1->SetSharedMapBit(i, kTRUE);
2090       s2->SetSharedMapBit(i, kTRUE);
2091     }
2092     if (s1->GetClusterIndex2(i)>0)
2093       s1->SetClusterMapBit(i, kTRUE);
2094   }
2095   if (sumshared>cutN0){
2096     // sign clusters
2097     //
2098     for (Int_t i=firstpoint;i<lastpoint;i++){
2099       //      if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2100       if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2101         AliTPCTrackerPoint *p1  = s1->GetTrackPoint(i);
2102         AliTPCTrackerPoint *p2  = s2->GetTrackPoint(i);; 
2103         if (s1->IsActive()&&s2->IsActive()){
2104           p1->SetShared(kTRUE);
2105           p2->SetShared(kTRUE);
2106         }       
2107       }
2108     }
2109   }
2110   //  
2111   if (sumshared>cutN0){
2112     for (Int_t i=0;i<4;i++){
2113       if (s1->GetOverlapLabel(3*i)==0){
2114         s1->SetOverlapLabel(3*i,  s2->GetLabel());
2115         s1->SetOverlapLabel(3*i+1,sumshared);
2116         s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2117         break;
2118       } 
2119     }
2120     for (Int_t i=0;i<4;i++){
2121       if (s2->GetOverlapLabel(3*i)==0){
2122         s2->SetOverlapLabel(3*i,  s1->GetLabel());
2123         s2->SetOverlapLabel(3*i+1,sumshared);
2124         s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2125         break;
2126       } 
2127     }    
2128   }
2129 }
2130
2131 void  AliTPCtrackerMI::SignShared(TObjArray * arr)
2132 {
2133   //
2134   //sort trackss according sectors
2135   //  
2136   for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2137     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2138     if (!pt) continue;
2139     //if (pt) RotateToLocal(pt);
2140     pt->SetSort(0);
2141   }
2142   arr->UnSort();
2143   arr->Sort();  // sorting according relative sectors
2144   arr->Expand(arr->GetEntries());
2145   //
2146   //
2147   Int_t nseed=arr->GetEntriesFast();
2148   for (Int_t i=0; i<nseed; i++) {
2149     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2150     if (!pt) continue;
2151     for (Int_t j=0;j<=12;j++){
2152       pt->SetOverlapLabel(j,0);
2153     }
2154   }
2155   for (Int_t i=0; i<nseed; i++) {
2156     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2157     if (!pt) continue;
2158     if (pt->GetRemoval()>10) continue;
2159     for (Int_t j=i+1; j<nseed; j++){
2160       AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2161       if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
2162       //      if (pt2){
2163       if (pt2->GetRemoval()<=10) {
2164         //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2165         SignShared(pt,pt2);
2166       }
2167     }  
2168   }
2169 }
2170
2171
2172 void AliTPCtrackerMI::SortTracks(TObjArray * arr, Int_t mode) const
2173 {
2174   //
2175   //sort tracks in array according mode criteria
2176   Int_t nseed = arr->GetEntriesFast();    
2177   for (Int_t i=0; i<nseed; i++) {
2178     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2179     if (!pt) {
2180       continue;
2181     }
2182     pt->SetSort(mode);
2183   }
2184   arr->UnSort();
2185   arr->Sort();
2186 }
2187
2188
2189 void AliTPCtrackerMI::RemoveUsed2(TObjArray * arr, Float_t factor1,  Float_t factor2, Int_t minimal)
2190 {
2191   //
2192   // Loop over all tracks and remove overlaped tracks (with lower quality)
2193   // Algorithm:
2194   //    1. Unsign clusters
2195   //    2. Sort tracks according quality
2196   //       Quality is defined by the number of cluster between first and last points 
2197   //       
2198   //    3. Loop over tracks - decreasing quality order
2199   //       a.) remove - If the fraction of shared cluster less than factor (1- n or 2) 
2200   //       b.) remove - If the minimal number of clusters less than minimal and not ITS
2201   //       c.) if track accepted - sign clusters
2202   //
2203   //Called in - AliTPCtrackerMI::Clusters2Tracks()
2204   //          - AliTPCtrackerMI::PropagateBack()
2205   //          - AliTPCtrackerMI::RefitInward()
2206   //
2207
2208  
2209   UnsignClusters();
2210   //
2211   Int_t nseed = arr->GetEntriesFast();  
2212   Float_t * quality = new Float_t[nseed];
2213   Int_t   * indexes = new Int_t[nseed];
2214   Int_t good =0;
2215   //
2216   //
2217   for (Int_t i=0; i<nseed; i++) {
2218     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2219     if (!pt){
2220       quality[i]=-1;
2221       continue;
2222     }
2223     pt->UpdatePoints();    //select first last max dens points
2224     Float_t * points = pt->GetPoints();
2225     if (points[3]<0.8) quality[i] =-1;
2226     quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
2227     //prefer high momenta tracks if overlaps
2228     quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5); 
2229   }
2230   TMath::Sort(nseed,quality,indexes);
2231   //
2232   //
2233   for (Int_t itrack=0; itrack<nseed; itrack++) {
2234     Int_t trackindex = indexes[itrack];
2235     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);   
2236     if (!pt) continue;
2237     //
2238     if (quality[trackindex]<0){
2239       if (pt) {
2240         delete arr->RemoveAt(trackindex);
2241       }
2242       else{
2243         arr->RemoveAt(trackindex);
2244       }
2245       continue;
2246     }
2247     //
2248     //
2249     Int_t first = Int_t(pt->GetPoints()[0]);
2250     Int_t last  = Int_t(pt->GetPoints()[2]);
2251     Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
2252     //
2253     Int_t found,foundable,shared;
2254     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
2255     //    pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
2256     Bool_t itsgold =kFALSE;
2257     if (pt->GetESD()){
2258       Int_t dummy[12];
2259       if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
2260     }
2261     if (!itsgold){
2262       //
2263       if (Float_t(shared+1)/Float_t(found+1)>factor){
2264         if (pt->GetKinkIndexes()[0]!=0) continue;  //don't remove tracks  - part of the kinks
2265         delete arr->RemoveAt(trackindex);
2266         continue;
2267       }      
2268       if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){  //remove short tracks
2269         if (pt->GetKinkIndexes()[0]!=0) continue;  //don't remove tracks  - part of the kinks
2270         delete arr->RemoveAt(trackindex);
2271         continue;
2272       }
2273     }
2274
2275     good++;
2276     //if (sharedfactor>0.4) continue;
2277     if (pt->GetKinkIndexes()[0]>0) continue;
2278     //Remove tracks with undefined properties - seems
2279     if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ? 
2280     //
2281     for (Int_t i=first; i<last; i++) {
2282       Int_t index=pt->GetClusterIndex2(i);
2283       // if (index<0 || index&0x8000 ) continue;
2284       if (index<0 || index&0x8000 ) continue;
2285       AliTPCclusterMI *c= pt->GetClusterPointer(i);        
2286       if (!c) continue;
2287       c->Use(10);  
2288     }    
2289   }
2290   fNtracks = good;
2291   if (fDebug>0){
2292     Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2293   }
2294   delete []quality;
2295   delete []indexes;
2296 }
2297
2298 void AliTPCtrackerMI::UnsignClusters() 
2299 {
2300   //
2301   // loop over all clusters and unsign them
2302   //
2303   
2304   for (Int_t sec=0;sec<fkNIS;sec++){
2305     for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2306       AliTPCclusterMI *cl = fInnerSec[sec][row].GetClusters1();
2307       for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
2308         //      if (cl[icl].IsUsed(10))         
2309         cl[icl].Use(-1);
2310       cl = fInnerSec[sec][row].GetClusters2();
2311       for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
2312         //if (cl[icl].IsUsed(10))       
2313           cl[icl].Use(-1);      
2314     }
2315   }
2316   
2317   for (Int_t sec=0;sec<fkNOS;sec++){
2318     for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2319       AliTPCclusterMI *cl = fOuterSec[sec][row].GetClusters1();
2320       for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
2321         //if (cl[icl].IsUsed(10))       
2322           cl[icl].Use(-1);
2323       cl = fOuterSec[sec][row].GetClusters2();
2324       for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
2325         //if (cl[icl].IsUsed(10))       
2326         cl[icl].Use(-1);      
2327     }
2328   }
2329   
2330 }
2331
2332
2333
2334 void AliTPCtrackerMI::SignClusters(TObjArray * arr, Float_t fnumber, Float_t fdensity)
2335 {
2336   //
2337   //sign clusters to be "used"
2338   //
2339   // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
2340   // loop over "primaries"
2341   
2342   Float_t sumdens=0;
2343   Float_t sumdens2=0;
2344   Float_t sumn   =0;
2345   Float_t sumn2  =0;
2346   Float_t sumchi =0;
2347   Float_t sumchi2 =0;
2348
2349   Float_t sum    =0;
2350
2351   TStopwatch timer;
2352   timer.Start();
2353
2354   Int_t nseed = arr->GetEntriesFast();
2355   for (Int_t i=0; i<nseed; i++) {
2356     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2357     if (!pt) {
2358       continue;
2359     }    
2360     if (!(pt->IsActive())) continue;
2361     Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2362     if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
2363       sumdens += dens;
2364       sumdens2+= dens*dens;
2365       sumn    += pt->GetNumberOfClusters();
2366       sumn2   += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
2367       Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
2368       if (chi2>5) chi2=5;
2369       sumchi  +=chi2;
2370       sumchi2 +=chi2*chi2;
2371       sum++;
2372     }
2373   }
2374
2375   Float_t mdensity = 0.9;
2376   Float_t meann    = 130;
2377   Float_t meanchi  = 1;
2378   Float_t sdensity = 0.1;
2379   Float_t smeann    = 10;
2380   Float_t smeanchi  =0.4;
2381   
2382
2383   if (sum>20){
2384     mdensity = sumdens/sum;
2385     meann    = sumn/sum;
2386     meanchi  = sumchi/sum;
2387     //
2388     sdensity = sumdens2/sum-mdensity*mdensity;
2389     if (sdensity >= 0)
2390        sdensity = TMath::Sqrt(sdensity);
2391     else
2392        sdensity = 0.1;
2393     //
2394     smeann   = sumn2/sum-meann*meann;
2395     if (smeann >= 0)
2396       smeann   = TMath::Sqrt(smeann);
2397     else 
2398       smeann   = 10;
2399     //
2400     smeanchi = sumchi2/sum - meanchi*meanchi;
2401     if (smeanchi >= 0)
2402       smeanchi = TMath::Sqrt(smeanchi);
2403     else
2404       smeanchi = 0.4;
2405   }
2406
2407
2408   //REMOVE  SHORT DELTAS or tracks going out of sensitive volume of TPC
2409   //
2410   for (Int_t i=0; i<nseed; i++) {
2411     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2412     if (!pt) {
2413       continue;
2414     }
2415     if (pt->GetBSigned()) continue;
2416     if (pt->GetBConstrain()) continue;    
2417     //if (!(pt->IsActive())) continue;
2418     /*
2419     Int_t found,foundable,shared;    
2420     pt->GetClusterStatistic(0,160,found, foundable,shared);
2421     if (shared/float(found)>0.3) {
2422       if (shared/float(found)>0.9 ){
2423         //delete arr->RemoveAt(i);
2424       }
2425       continue;
2426     }
2427     */
2428     Bool_t isok =kFALSE;
2429     if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
2430       isok = kTRUE;
2431     if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
2432       isok =kTRUE;
2433     if  (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
2434       isok =kTRUE;
2435     if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
2436       isok =kTRUE;
2437     
2438     if (isok)     
2439       for (Int_t i=0; i<160; i++) {     
2440         Int_t index=pt->GetClusterIndex2(i);
2441         if (index<0) continue;
2442         AliTPCclusterMI *c= pt->GetClusterPointer(i);
2443         if (!c) continue;
2444         //if (!(c->IsUsed(10))) c->Use();  
2445         c->Use(10);  
2446       }
2447   }
2448   
2449   
2450   //
2451   Double_t maxchi  = meanchi+2.*smeanchi;
2452
2453   for (Int_t i=0; i<nseed; i++) {
2454     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2455     if (!pt) {
2456       continue;
2457     }    
2458     //if (!(pt->IsActive())) continue;
2459     if (pt->GetBSigned()) continue;
2460     Double_t chi     = pt->GetChi2()/pt->GetNumberOfClusters();
2461     if (chi>maxchi) continue;
2462
2463     Float_t bfactor=1;
2464     Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2465    
2466     //sign only tracks with enoug big density at the beginning
2467     
2468     if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue; 
2469     
2470     
2471     Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
2472     Double_t minn    = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
2473    
2474     //    if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
2475     if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
2476       minn=0;
2477
2478     if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
2479       //Int_t noc=pt->GetNumberOfClusters();
2480       pt->SetBSigned(kTRUE);
2481       for (Int_t i=0; i<160; i++) {
2482
2483         Int_t index=pt->GetClusterIndex2(i);
2484         if (index<0) continue;
2485         AliTPCclusterMI *c= pt->GetClusterPointer(i);
2486         if (!c) continue;
2487         //      if (!(c->IsUsed(10))) c->Use();  
2488         c->Use(10);  
2489       }
2490     }
2491   }
2492   //  gLastCheck = nseed;
2493   //  arr->Compress();
2494   if (fDebug>0){
2495     timer.Print();
2496   }
2497 }
2498
2499
2500 void  AliTPCtrackerMI::StopNotActive(TObjArray * arr, Int_t row0, Float_t th0, Float_t th1, Float_t th2) const
2501 {
2502   // stop not active tracks
2503   // take th1 as threshold for number of founded to number of foundable on last 10 active rows
2504   // take th2 as threshold for number of founded to number of foundable on last 20 active rows 
2505   Int_t nseed = arr->GetEntriesFast();  
2506   //
2507   for (Int_t i=0; i<nseed; i++) {
2508     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
2509     if (!pt) {
2510       continue;
2511     }
2512     if (!(pt->IsActive())) continue;
2513     StopNotActive(pt,row0,th0, th1,th2);
2514   }
2515 }
2516
2517
2518
2519 void  AliTPCtrackerMI::StopNotActive(AliTPCseed * seed, Int_t row0, Float_t th0, Float_t th1,
2520  Float_t th2) const
2521 {
2522   // stop not active tracks
2523   // take th1 as threshold for number of founded to number of foundable on last 10 active rows
2524   // take th2 as threshold for number of founded to number of foundable on last 20 active rows 
2525   Int_t sumgood1  = 0;
2526   Int_t sumgood2  = 0;
2527   Int_t foundable = 0;
2528   Int_t maxindex = seed->GetLastPoint();  //last foundable row
2529   if (seed->GetNFoundable()*th0 > seed->GetNumberOfClusters()) {
2530     seed->Desactivate(10) ;
2531     return;
2532   }
2533
2534   for (Int_t i=row0; i<maxindex; i++){
2535     Int_t index = seed->GetClusterIndex2(i);
2536     if (index!=-1) foundable++;
2537     //if (!c) continue;
2538     if (foundable<=30) sumgood1++;
2539     if (foundable<=50) {
2540       sumgood2++;
2541     }
2542     else{ 
2543       break;
2544     }        
2545   }
2546   if (foundable>=30.){ 
2547      if (sumgood1<(th1*30.)) seed->Desactivate(10);
2548   }
2549   if (foundable>=50)
2550     if (sumgood2<(th2*50.)) seed->Desactivate(10);
2551 }
2552
2553
2554 Int_t AliTPCtrackerMI::RefitInward(AliESDEvent *event)
2555 {
2556   //
2557   // back propagation of ESD tracks
2558   //
2559   //return 0;
2560   const Int_t kMaxFriendTracks=2000;
2561   fEvent = event;
2562   ReadSeeds(event,2);
2563   fIteration=2;
2564   //PrepareForProlongation(fSeeds,1);
2565   PropagateForward2(fSeeds);
2566   RemoveUsed2(fSeeds,0.4,0.4,20);
2567
2568   TObjArray arraySeed(fSeeds->GetEntries());
2569   for (Int_t i=0;i<fSeeds->GetEntries();i++) {
2570     arraySeed.AddAt(fSeeds->At(i),i);    
2571   }
2572   SignShared(&arraySeed);
2573   //  FindCurling(fSeeds, event,2); // find multi found tracks
2574   FindSplitted(fSeeds, event,2); // find multi found tracks
2575
2576   Int_t ntracks=0;
2577   Int_t nseed = fSeeds->GetEntriesFast();
2578   for (Int_t i=0;i<nseed;i++){
2579     AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
2580     if (!seed) continue;
2581     if (seed->GetKinkIndex(0)>0)  UpdateKinkQualityD(seed);  // update quality informations for kinks
2582
2583     seed->PropagateTo(fParam->GetInnerRadiusLow());
2584     seed->UpdatePoints();
2585     AddCovariance(seed);
2586     MakeBitmaps(seed);
2587     AliESDtrack *esd=event->GetTrack(i);
2588     seed->CookdEdx(0.02,0.6);
2589     CookLabel(seed,0.1); //For comparison only
2590     esd->SetTPCClusterMap(seed->GetClusterMap());
2591     esd->SetTPCSharedMap(seed->GetSharedMap());
2592     //
2593     if (AliTPCReconstructor::StreamLevel()>1 && seed!=0&&esd!=0) {
2594       TTreeSRedirector &cstream = *fDebugStreamer;
2595       cstream<<"Crefit"<<
2596         "Esd.="<<esd<<
2597         "Track.="<<seed<<
2598         "\n"; 
2599     }
2600
2601     if (seed->GetNumberOfClusters()>15){
2602       esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit); 
2603       esd->SetTPCPoints(seed->GetPoints());
2604       esd->SetTPCPointsF(seed->GetNFoundable());
2605       Int_t ndedx   = seed->GetNCDEDX(0)+seed->GetNCDEDX(1)+seed->GetNCDEDX(2)+seed->GetNCDEDX(3);
2606       Float_t sdedx = (seed->GetSDEDX(0)+seed->GetSDEDX(1)+seed->GetSDEDX(2)+seed->GetSDEDX(3))*0.25;
2607       Float_t dedx  = seed->GetdEdx();
2608       esd->SetTPCsignal(dedx, sdedx, ndedx);
2609       //
2610       // add seed to the esd track in Calib level
2611       //
2612       Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
2613       if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
2614         AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE); 
2615         esd->AddCalibObject(seedCopy);
2616       }
2617       ntracks++;
2618     }
2619     else{
2620       //printf("problem\n");
2621     }
2622   }
2623   //FindKinks(fSeeds,event);
2624   Info("RefitInward","Number of refitted tracks %d",ntracks);
2625   return 0;
2626 }
2627
2628
2629 Int_t AliTPCtrackerMI::PropagateBack(AliESDEvent *event)
2630 {
2631   //
2632   // back propagation of ESD tracks
2633   //
2634
2635   fEvent = event;
2636   fIteration = 1;
2637   ReadSeeds(event,1);
2638   PropagateBack(fSeeds); 
2639   RemoveUsed2(fSeeds,0.4,0.4,20);
2640   //FindCurling(fSeeds, fEvent,1);  
2641   FindSplitted(fSeeds, event,1); // find multi found tracks
2642
2643   //
2644   Int_t nseed = fSeeds->GetEntriesFast();
2645   Int_t ntracks=0;
2646   for (Int_t i=0;i<nseed;i++){
2647     AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
2648     if (!seed) continue;
2649     if (seed->GetKinkIndex(0)<0)  UpdateKinkQualityM(seed);  // update quality informations for kinks
2650     seed->UpdatePoints();
2651     AddCovariance(seed);
2652     AliESDtrack *esd=event->GetTrack(i);
2653     seed->CookdEdx(0.02,0.6);
2654     CookLabel(seed,0.1); //For comparison only
2655     if (seed->GetNumberOfClusters()>15){
2656       esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
2657       esd->SetTPCPoints(seed->GetPoints());
2658       esd->SetTPCPointsF(seed->GetNFoundable());
2659       Int_t ndedx   = seed->GetNCDEDX(0)+seed->GetNCDEDX(1)+seed->GetNCDEDX(2)+seed->GetNCDEDX(3);
2660       Float_t sdedx = (seed->GetSDEDX(0)+seed->GetSDEDX(1)+seed->GetSDEDX(2)+seed->GetSDEDX(3))*0.25;
2661       Float_t dedx  = seed->GetdEdx();
2662       esd->SetTPCsignal(dedx, sdedx, ndedx);
2663       ntracks++;
2664       Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
2665       // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number      
2666       if (AliTPCReconstructor::StreamLevel()>1 && esd) {
2667         (*fDebugStreamer)<<"Cback"<<
2668           "Tr0.="<<seed<<
2669           "esd.="<<esd<<
2670           "EventNrInFile="<<eventnumber<<
2671           "\n";       
2672       }
2673     }
2674   }
2675   //FindKinks(fSeeds,event);
2676   Info("PropagateBack","Number of back propagated tracks %d",ntracks);
2677   fEvent =0;
2678   
2679   return 0;
2680 }
2681
2682
2683 void AliTPCtrackerMI::DeleteSeeds()
2684 {
2685   //
2686   //delete Seeds
2687
2688   Int_t nseed = fSeeds->GetEntriesFast();
2689   for (Int_t i=0;i<nseed;i++){
2690     AliTPCseed * seed = (AliTPCseed*)fSeeds->At(i);
2691     if (seed) delete fSeeds->RemoveAt(i);
2692   }
2693   delete fSeeds;
2694
2695   fSeeds =0;
2696 }
2697
2698 void AliTPCtrackerMI::ReadSeeds(AliESDEvent *event, Int_t direction)
2699 {
2700   //
2701   //read seeds from the event
2702   
2703   Int_t nentr=event->GetNumberOfTracks();
2704   if (fDebug>0){
2705     Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
2706   }
2707   if (fSeeds) 
2708     DeleteSeeds();
2709   if (!fSeeds){   
2710     fSeeds = new TObjArray(nentr);
2711   }
2712   UnsignClusters();
2713   //  Int_t ntrk=0;  
2714   for (Int_t i=0; i<nentr; i++) {
2715     AliESDtrack *esd=event->GetTrack(i);
2716     ULong_t status=esd->GetStatus();
2717     if (!(status&AliESDtrack::kTPCin)) continue;
2718     AliTPCtrack t(*esd);
2719     t.SetNumberOfClusters(0);
2720     //    AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
2721     AliTPCseed *seed = new AliTPCseed(t/*,t.GetAlpha()*/);
2722     seed->SetUniqueID(esd->GetID());
2723     AddCovariance(seed);   //add systematic ucertainty
2724     for (Int_t ikink=0;ikink<3;ikink++) {
2725       Int_t index = esd->GetKinkIndex(ikink);
2726       seed->GetKinkIndexes()[ikink] = index;
2727       if (index==0) continue;
2728       index = TMath::Abs(index);
2729       AliESDkink * kink = fEvent->GetKink(index-1);
2730       if (kink&&esd->GetKinkIndex(ikink)<0){
2731         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
2732         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,0);
2733       }
2734       if (kink&&esd->GetKinkIndex(ikink)>0){
2735         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
2736         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,4);
2737       }
2738
2739     }
2740     if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.); 
2741     if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
2742     if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
2743       fSeeds->AddAt(0,i);
2744       delete seed;
2745       continue;    
2746     }
2747     if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) > 0 )  {
2748       Double_t par0[5],par1[5],alpha,x;
2749       esd->GetInnerExternalParameters(alpha,x,par0);
2750       esd->GetExternalParameters(x,par1);
2751       Double_t delta1 = TMath::Abs(par0[4]-par1[4])/(0.000000001+TMath::Abs(par0[4]+par1[4]));
2752       Double_t delta2 = TMath::Abs(par0[3]-par1[3]);
2753       Double_t trdchi2=0;
2754       if (esd->GetTRDncls()>0) trdchi2 = esd->GetTRDchi2()/esd->GetTRDncls();
2755       //reset covariance if suspicious 
2756       if ( (delta1>0.1) || (delta2>0.006) ||trdchi2>7.)
2757         seed->ResetCovariance(10.);
2758     }
2759
2760     //
2761     //
2762     // rotate to the local coordinate system
2763     //   
2764     fSectors=fInnerSec; fN=fkNIS;    
2765     Double_t alpha=seed->GetAlpha() - fSectors->GetAlphaShift();
2766     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2767     if (alpha < 0.            ) alpha += 2.*TMath::Pi();
2768     Int_t ns=Int_t(alpha/fSectors->GetAlpha())%fN;
2769     alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
2770     if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
2771     if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
2772     alpha-=seed->GetAlpha();  
2773     if (!seed->Rotate(alpha)) {
2774       delete seed;
2775       continue;
2776     }
2777     seed->SetESD(esd);
2778     // sign clusters
2779     if (esd->GetKinkIndex(0)<=0){
2780       for (Int_t irow=0;irow<160;irow++){
2781         Int_t index = seed->GetClusterIndex2(irow);    
2782         if (index>0){ 
2783           //
2784           AliTPCclusterMI * cl = GetClusterMI(index);
2785           seed->SetClusterPointer(irow,cl);
2786           if (cl){
2787             if ((index & 0x8000)==0){
2788               cl->Use(10);  // accepted cluster   
2789             }else{
2790               cl->Use(6);   // close cluster not accepted
2791             }   
2792           }else{
2793             Info("ReadSeeds","Not found cluster");
2794           }
2795         }
2796       }
2797     }
2798     fSeeds->AddAt(seed,i);
2799   }
2800 }
2801
2802
2803
2804 //_____________________________________________________________________________
2805 void AliTPCtrackerMI::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
2806                                  Float_t deltay, Int_t ddsec) {
2807   //-----------------------------------------------------------------
2808   // This function creates track seeds.
2809   // SEEDING WITH VERTEX CONSTRAIN 
2810   //-----------------------------------------------------------------
2811   // cuts[0]   - fP4 cut
2812   // cuts[1]   - tan(phi)  cut
2813   // cuts[2]   - zvertex cut
2814   // cuts[3]   - fP3 cut
2815   Int_t nin0  = 0;
2816   Int_t nin1  = 0;
2817   Int_t nin2  = 0;
2818   Int_t nin   = 0;
2819   Int_t nout1 = 0;
2820   Int_t nout2 = 0;
2821
2822   Double_t x[5], c[15];
2823   //  Int_t di = i1-i2;
2824   //
2825   AliTPCseed * seed = new AliTPCseed();
2826   Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
2827   Double_t cs=cos(alpha), sn=sin(alpha);
2828   //
2829   //  Double_t x1 =fOuterSec->GetX(i1);
2830   //Double_t xx2=fOuterSec->GetX(i2);
2831   
2832   Double_t x1 =GetXrow(i1);
2833   Double_t xx2=GetXrow(i2);
2834
2835   Double_t x3=GetX(), y3=GetY(), z3=GetZ();
2836
2837   Int_t imiddle = (i2+i1)/2;    //middle pad row index
2838   Double_t xm = GetXrow(imiddle); // radius of middle pad-row
2839   const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
2840   //
2841   Int_t ns =sec;   
2842
2843   const AliTPCtrackerRow& kr1=GetRow(ns,i1);
2844   Double_t ymax  = GetMaxY(i1)-kr1.GetDeadZone()-1.5;  
2845   Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;  
2846
2847   //
2848   // change cut on curvature if it can't reach this layer
2849   // maximal curvature set to reach it
2850   Double_t dvertexmax  = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
2851   if (dvertexmax*0.5*cuts[0]>0.85){
2852     cuts[0] = 0.85/(dvertexmax*0.5+1.);
2853   }
2854   Double_t r2min = 1/(cuts[0]*cuts[0]);  //minimal square of radius given by cut
2855
2856   //  Int_t ddsec = 1;
2857   if (deltay>0) ddsec = 0; 
2858   // loop over clusters  
2859   for (Int_t is=0; is < kr1; is++) {
2860     //
2861     if (kr1[is]->IsUsed(10)) continue;
2862     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
2863     //if (TMath::Abs(y1)>ymax) continue;
2864
2865     if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge
2866
2867     // find possible directions    
2868     Float_t anglez = (z1-z3)/(x1-x3); 
2869     Float_t extraz = z1 - anglez*(x1-xx2);  // extrapolated z      
2870     //
2871     //
2872     //find   rotation angles relative to line given by vertex and point 1
2873     Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
2874     Double_t dvertex  = TMath::Sqrt(dvertex2);
2875     Double_t angle13  = TMath::ATan((y1-y3)/(x1-x3));
2876     Double_t cs13     = cos(-angle13), sn13 = sin(-angle13);            
2877     
2878     //
2879     // loop over 2 sectors
2880     Int_t dsec1=-ddsec;
2881     Int_t dsec2= ddsec;
2882     if (y1<0)  dsec2= 0;
2883     if (y1>0)  dsec1= 0;
2884     
2885     Double_t dddz1=0;  // direction of delta inclination in z axis
2886     Double_t dddz2=0;
2887     if ( (z1-z3)>0)
2888       dddz1 =1;    
2889     else
2890       dddz2 =1;
2891     //
2892     for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
2893       Int_t sec2 = sec + dsec;
2894       // 
2895       //      AliTPCtrackerRow&  kr2  = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
2896       //AliTPCtrackerRow&  kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
2897       AliTPCtrackerRow&  kr2  = GetRow((sec2+fkNOS)%fkNOS,i2);
2898       AliTPCtrackerRow&  kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
2899       Int_t  index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
2900       Int_t  index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
2901
2902       // rotation angles to p1-p3
2903       Double_t cs13r     = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;            
2904       Double_t x2,   y2,   z2; 
2905       //
2906       //      Double_t dymax = maxangle*TMath::Abs(x1-xx2);
2907
2908       //
2909       Double_t dxx0 =  (xx2-x3)*cs13r;
2910       Double_t dyy0 =  (xx2-x3)*sn13r;
2911       for (Int_t js=index1; js < index2; js++) {
2912         const AliTPCclusterMI *kcl = kr2[js];
2913         if (kcl->IsUsed(10)) continue;  
2914         //
2915         //calcutate parameters
2916         //      
2917         Double_t yy0 =  dyy0 +(kcl->GetY()-y3)*cs13r;
2918         // stright track
2919         if (TMath::Abs(yy0)<0.000001) continue;
2920         Double_t xx0 =  dxx0 -(kcl->GetY()-y3)*sn13r;
2921         Double_t y0  =  0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
2922         Double_t r02 = (0.25+y0*y0)*dvertex2;   
2923         //curvature (radius) cut
2924         if (r02<r2min) continue;                
2925        
2926         nin0++; 
2927         //
2928         Double_t c0  = 1/TMath::Sqrt(r02);
2929         if (yy0>0) c0*=-1.;     
2930                
2931        
2932         //Double_t dfi0   = 2.*TMath::ASin(dvertex*c0*0.5);
2933         //Double_t dfi1   = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
2934         Double_t dfi0   = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
2935         Double_t dfi1   = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);  
2936         //
2937         //
2938         Double_t z0  =  kcl->GetZ();  
2939         Double_t zzzz2    = z1-(z1-z3)*dfi1/dfi0;
2940         if (TMath::Abs(zzzz2-z0)>0.5) continue;       
2941         nin1++;              
2942         //      
2943         Double_t dip    = (z1-z0)*c0/dfi1;        
2944         Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
2945         //
2946         y2 = kcl->GetY(); 
2947         if (dsec==0){
2948           x2 = xx2; 
2949           z2 = kcl->GetZ();       
2950         }
2951         else
2952           {
2953             // rotation 
2954             z2 = kcl->GetZ();  
2955             x2= xx2*cs-y2*sn*dsec;
2956             y2=+xx2*sn*dsec+y2*cs;
2957           }
2958         
2959         x[0] = y1;
2960         x[1] = z1;
2961         x[2] = x0;
2962         x[3] = dip;
2963         x[4] = c0;
2964         //
2965         //
2966         // do we have cluster at the middle ?
2967         Double_t ym,zm;
2968         GetProlongation(x1,xm,x,ym,zm);
2969         UInt_t dummy; 
2970         AliTPCclusterMI * cm=0;
2971         if (TMath::Abs(ym)-ymaxm<0){      
2972           cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
2973           if ((!cm) || (cm->IsUsed(10))) {        
2974             continue;
2975           }
2976         }
2977         else{     
2978           // rotate y1 to system 0
2979           // get state vector in rotated system 
2980           Double_t yr1  = (-0.5*sn13+y0*cs13)*dvertex*c0;
2981           Double_t xr2  =  x0*cs+yr1*sn*dsec;
2982           Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
2983           //
2984           GetProlongation(xx2,xm,xr,ym,zm);
2985           if (TMath::Abs(ym)-ymaxm<0){
2986             cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
2987             if ((!cm) || (cm->IsUsed(10))) {      
2988               continue;
2989             }
2990           }
2991         }
2992        
2993
2994         Double_t dym = 0;
2995         Double_t dzm = 0;
2996         if (cm){
2997           dym = ym - cm->GetY();
2998           dzm = zm - cm->GetZ();
2999         }
3000         nin2++;
3001
3002
3003         //
3004         //
3005         Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3006         Double_t sy2=kcl->GetSigmaY2()*2.,     sz2=kcl->GetSigmaZ2()*2.;
3007         //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3008         Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3009         //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3010
3011         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3012         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3013         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3014         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3015         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3016         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3017         
3018         Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3019         Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3020         Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3021         Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3022         
3023         c[0]=sy1;
3024         c[1]=0.;       c[2]=sz1;
3025         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3026         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3027                        c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3028         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3029         c[13]=f30*sy1*f40+f32*sy2*f42;
3030         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3031         
3032         //      if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3033         
3034         UInt_t index=kr1.GetIndex(is);
3035         seed->~AliTPCseed(); // this does not set the pointer to 0...
3036         AliTPCseed *track=new(seed) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3037         
3038         track->SetIsSeeding(kTRUE);
3039         track->SetSeed1(i1);
3040         track->SetSeed2(i2);
3041         track->SetSeedType(3);
3042
3043        
3044         //if (dsec==0) {
3045           FollowProlongation(*track, (i1+i2)/2,1);
3046           Int_t foundable,found,shared;
3047           track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3048           if ((found<0.55*foundable)  || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3049             seed->Reset();
3050             seed->~AliTPCseed();
3051             continue;
3052           }
3053           //}
3054         
3055         nin++;
3056         FollowProlongation(*track, i2,1);
3057         
3058         
3059         //Int_t rc = 1;
3060         track->SetBConstrain(1);
3061         //      track->fLastPoint = i1+fInnerSec->GetNRows();  // first cluster in track position
3062         track->SetLastPoint(i1);  // first cluster in track position
3063         track->SetFirstPoint(track->GetLastPoint());
3064         
3065         if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
3066             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
3067             track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3068           seed->Reset();
3069           seed->~AliTPCseed();
3070           continue;
3071         }
3072         nout1++;
3073         // Z VERTEX CONDITION
3074         Double_t zv, bz=GetBz();
3075         if ( !track->GetZAt(0.,bz,zv) ) continue;
3076         if (TMath::Abs(zv-z3)>cuts[2]) {
3077           FollowProlongation(*track, TMath::Max(i2-20,0));
3078           if ( !track->GetZAt(0.,bz,zv) ) continue;
3079           if (TMath::Abs(zv-z3)>cuts[2]){
3080             FollowProlongation(*track, TMath::Max(i2-40,0));
3081             if ( !track->GetZAt(0.,bz,zv) ) continue;
3082             if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3083               // make seed without constrain
3084               AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3085               FollowProlongation(*track2, i2,1);
3086               track2->SetBConstrain(kFALSE);
3087               track2->SetSeedType(1);
3088               arr->AddLast(track2); 
3089               seed->Reset();
3090               seed->~AliTPCseed();
3091               continue;         
3092             }
3093             else{
3094               seed->Reset();
3095               seed->~AliTPCseed();
3096               continue;
3097             
3098             }
3099           }
3100         }
3101       
3102         track->SetSeedType(0);
3103         arr->AddLast(track); 
3104         seed = new AliTPCseed;  
3105         nout2++;
3106         // don't consider other combinations
3107         if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3108           break;
3109       }
3110     }
3111   }
3112   if (fDebug>3){
3113     Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3114   }
3115   delete seed;
3116 }
3117
3118
3119 void AliTPCtrackerMI::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
3120                                  Float_t deltay) {
3121   
3122
3123
3124   //-----------------------------------------------------------------
3125   // This function creates track seeds.
3126   //-----------------------------------------------------------------
3127   // cuts[0]   - fP4 cut
3128   // cuts[1]   - tan(phi)  cut
3129   // cuts[2]   - zvertex cut
3130   // cuts[3]   - fP3 cut
3131
3132
3133   Int_t nin0  = 0;
3134   Int_t nin1  = 0;
3135   Int_t nin2  = 0;
3136   Int_t nin   = 0;
3137   Int_t nout1 = 0;
3138   Int_t nout2 = 0;
3139   Int_t nout3 =0;
3140   Double_t x[5], c[15];
3141   //
3142   // make temporary seed
3143   AliTPCseed * seed = new AliTPCseed;
3144   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3145   //  Double_t cs=cos(alpha), sn=sin(alpha);
3146   //
3147   //
3148
3149   // first 3 padrows
3150   Double_t x1 = GetXrow(i1-1);
3151   const    AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
3152   Double_t y1max  = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;  
3153   //
3154   Double_t x1p = GetXrow(i1);
3155   const    AliTPCtrackerRow& kr1p=GetRow(sec,i1);
3156   //
3157   Double_t x1m = GetXrow(i1-2);
3158   const    AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
3159
3160   //
3161   //last 3 padrow for seeding
3162   AliTPCtrackerRow&  kr3  = GetRow((sec+fkNOS)%fkNOS,i1-7);
3163   Double_t    x3   =  GetXrow(i1-7);
3164   //  Double_t    y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;  
3165   //
3166   AliTPCtrackerRow&  kr3p  = GetRow((sec+fkNOS)%fkNOS,i1-6);
3167   Double_t    x3p   = GetXrow(i1-6);
3168   //
3169   AliTPCtrackerRow&  kr3m  = GetRow((sec+fkNOS)%fkNOS,i1-8);
3170   Double_t    x3m   = GetXrow(i1-8);
3171
3172   //
3173   //
3174   // middle padrow
3175   Int_t im = i1-4;                           //middle pad row index
3176   Double_t xm         = GetXrow(im);         // radius of middle pad-row
3177   const AliTPCtrackerRow& krm=GetRow(sec,im);   //middle pad -row
3178   //  Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;  
3179   //
3180   //
3181   Double_t deltax  = x1-x3;
3182   Double_t dymax   = deltax*cuts[1];
3183   Double_t dzmax   = deltax*cuts[3];
3184   //
3185   // loop over clusters  
3186   for (Int_t is=0; is < kr1; is++) {
3187     //
3188     if (kr1[is]->IsUsed(10)) continue;
3189     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
3190     //
3191     if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge    
3192     // 
3193     Int_t  index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3194     Int_t  index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3195     //    
3196     Double_t y3,   z3;
3197     //
3198     //
3199     UInt_t index;
3200     for (Int_t js=index1; js < index2; js++) {
3201       const AliTPCclusterMI *kcl = kr3[js];
3202       if (kcl->IsUsed(10)) continue;
3203       y3 = kcl->GetY(); 
3204       // apply angular cuts
3205       if (TMath::Abs(y1-y3)>dymax) continue;
3206       x3 = x3; 
3207       z3 = kcl->GetZ(); 
3208       if (TMath::Abs(z1-z3)>dzmax) continue;
3209       //
3210       Double_t angley = (y1-y3)/(x1-x3);
3211       Double_t anglez = (z1-z3)/(x1-x3);
3212       //
3213       Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3214       Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3215       //
3216       Double_t yyym = angley*(xm-x1)+y1;
3217       Double_t zzzm = anglez*(xm-x1)+z1;
3218
3219       const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3220       if (!kcm) continue;
3221       if (kcm->IsUsed(10)) continue;
3222       
3223       erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3224       errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3225       //
3226       //
3227       //
3228       Int_t used  =0;
3229       Int_t found =0;
3230       //
3231       // look around first
3232       const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3233                                                       anglez*(x1m-x1)+z1,
3234                                                       erry,errz,index);
3235       //
3236       if (kc1m){
3237         found++;
3238         if (kc1m->IsUsed(10)) used++;
3239       }
3240       const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3241                                                       anglez*(x1p-x1)+z1,
3242                                                       erry,errz,index);
3243       //
3244       if (kc1p){
3245         found++;
3246         if (kc1p->IsUsed(10)) used++;
3247       }
3248       if (used>1)  continue;
3249       if (found<1) continue; 
3250
3251       //
3252       // look around last
3253       const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3254                                                       anglez*(x3m-x3)+z3,
3255                                                       erry,errz,index);
3256       //
3257       if (kc3m){
3258         found++;
3259         if (kc3m->IsUsed(10)) used++;
3260       }
3261       else 
3262         continue;
3263       const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3264                                                       anglez*(x3p-x3)+z3,
3265                                                       erry,errz,index);
3266       //
3267       if (kc3p){
3268         found++;
3269         if (kc3p->IsUsed(10)) used++;
3270       }
3271       else 
3272         continue;
3273       if (used>1)  continue;
3274       if (found<3) continue;       
3275       //
3276       Double_t x2,y2,z2;
3277       x2 = xm;
3278       y2 = kcm->GetY();
3279       z2 = kcm->GetZ();
3280       //
3281                         
3282       x[0]=y1;
3283       x[1]=z1;
3284       x[4]=F1(x1,y1,x2,y2,x3,y3);
3285       //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3286       nin0++;
3287       //
3288       x[2]=F2(x1,y1,x2,y2,x3,y3);
3289       nin1++;
3290       //
3291       x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3292       //if (TMath::Abs(x[3]) > cuts[3]) continue;
3293       nin2++;
3294       //
3295       //
3296       Double_t sy1=0.1,  sz1=0.1;
3297       Double_t sy2=0.1,  sz2=0.1;
3298       Double_t sy3=0.1,  sy=0.1, sz=0.1;
3299       
3300       Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3301       Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3302       Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3303       Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3304       Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3305       Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3306       
3307       Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3308       Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3309       Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3310       Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3311       
3312       c[0]=sy1;
3313       c[1]=0.;       c[2]=sz1; 
3314       c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3315       c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3316       c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3317       c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3318       c[13]=f30*sy1*f40+f32*sy2*f42;
3319       c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3320       
3321       //        if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3322       
3323       UInt_t index=kr1.GetIndex(is);
3324       seed->~AliTPCseed();
3325       AliTPCseed *track=new(seed) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3326       
3327       track->SetIsSeeding(kTRUE);
3328
3329       nin++;      
3330       FollowProlongation(*track, i1-7,1);
3331       if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 || 
3332           track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3333         seed->Reset();
3334         seed->~AliTPCseed();
3335         continue;
3336       }
3337       nout1++;
3338       nout2++;  
3339       //Int_t rc = 1;
3340       FollowProlongation(*track, i2,1);
3341       track->SetBConstrain(0);
3342       track->SetLastPoint(i1+fInnerSec->GetNRows());  // first cluster in track position
3343       track->SetFirstPoint(track->GetLastPoint());
3344       
3345       if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
3346           track->GetNumberOfClusters()<track->GetNFoundable()*0.7 || 
3347           track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3348         seed->Reset();
3349         seed->~AliTPCseed();
3350         continue;
3351       }
3352    
3353       {
3354         FollowProlongation(*track, TMath::Max(i2-10,0),1);
3355         AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3356         FollowProlongation(*track2, i2,1);
3357         track2->SetBConstrain(kFALSE);
3358         track2->SetSeedType(4);
3359         arr->AddLast(track2); 
3360         seed->Reset();
3361         seed->~AliTPCseed();
3362       }
3363       
3364    
3365       //arr->AddLast(track); 
3366       //seed = new AliTPCseed;  
3367       nout3++;
3368     }
3369   }
3370   
3371   if (fDebug>3){
3372     Info("MakeSeeds5","\nSeeding statiistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2,nout3);
3373   }
3374   delete seed;
3375 }
3376
3377
3378 //_____________________________________________________________________________
3379 void AliTPCtrackerMI::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3380                                  Float_t deltay, Bool_t /*bconstrain*/) {
3381   //-----------------------------------------------------------------
3382   // This function creates track seeds - without vertex constraint
3383   //-----------------------------------------------------------------
3384   // cuts[0]   - fP4 cut        - not applied
3385   // cuts[1]   - tan(phi)  cut
3386   // cuts[2]   - zvertex cut    - not applied 
3387   // cuts[3]   - fP3 cut
3388   Int_t nin0=0;
3389   Int_t nin1=0;
3390   Int_t nin2=0;
3391   Int_t nin3=0;
3392   //  Int_t nin4=0;
3393   //Int_t nin5=0;
3394
3395   
3396
3397   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3398   //  Double_t cs=cos(alpha), sn=sin(alpha);
3399   Int_t row0 = (i1+i2)/2;
3400   Int_t drow = (i1-i2)/2;
3401   const AliTPCtrackerRow& kr0=fSectors[sec][row0];
3402   AliTPCtrackerRow * kr=0;
3403
3404   AliTPCpolyTrack polytrack;
3405   Int_t nclusters=fSectors[sec][row0];
3406   AliTPCseed * seed = new AliTPCseed;
3407
3408   Int_t sumused=0;
3409   Int_t cused=0;
3410   Int_t cnused=0;
3411   for (Int_t is=0; is < nclusters; is++) {  //LOOP over clusters
3412     Int_t nfound =0;
3413     Int_t nfoundable =0;
3414     for (Int_t iter =1; iter<2; iter++){   //iterations
3415       const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
3416       const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];      
3417       const AliTPCclusterMI * cl= kr0[is];
3418       
3419       if (cl->IsUsed(10)) {
3420         cused++;
3421       }
3422       else{
3423         cnused++;
3424       }
3425       Double_t x = kr0.GetX();
3426       // Initialization of the polytrack
3427       nfound =0;
3428       nfoundable =0;
3429       polytrack.Reset();
3430       //
3431       Double_t y0= cl->GetY();
3432       Double_t z0= cl->GetZ();
3433       Float_t erry = 0;
3434       Float_t errz = 0;
3435       
3436       Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3437       if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue;  // seed only at the edge
3438       
3439       erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;      
3440       errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;      
3441       polytrack.AddPoint(x,y0,z0,erry, errz);
3442
3443       sumused=0;
3444       if (cl->IsUsed(10)) sumused++;
3445
3446
3447       Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3448       Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3449       //
3450       x = krm.GetX();
3451       AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3452       if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3453         erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;          
3454         errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3455         if (cl1->IsUsed(10))  sumused++;
3456         polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3457       }
3458       //
3459       x = krp.GetX();
3460       AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3461       if (cl2) {
3462         erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;          
3463         errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3464         if (cl2->IsUsed(10)) sumused++;  
3465         polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3466       }
3467       //
3468       if (sumused>0) continue;
3469       nin0++;
3470       polytrack.UpdateParameters();
3471       // follow polytrack
3472       roadz = 1.2;
3473       roady = 1.2;
3474       //
3475       Double_t yn,zn;
3476       nfoundable = polytrack.GetN();
3477       nfound     = nfoundable; 
3478       //
3479       for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
3480         Float_t maxdist = 0.8*(1.+3./(ddrow));
3481         for (Int_t delta = -1;delta<=1;delta+=2){
3482           Int_t row = row0+ddrow*delta;
3483           kr = &(fSectors[sec][row]);
3484           Double_t xn = kr->GetX();
3485           Double_t ymax = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
3486           polytrack.GetFitPoint(xn,yn,zn);
3487           if (TMath::Abs(yn)>ymax) continue;
3488           nfoundable++;
3489           AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
3490           if (cln) {
3491             Float_t dist =  TMath::Sqrt(  (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
3492             if (dist<maxdist){
3493               /*
3494               erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));         
3495               errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3496               if (cln->IsUsed(10)) {
3497                 //      printf("used\n");
3498                 sumused++;
3499                 erry*=2;
3500                 errz*=2;
3501               }
3502               */
3503               erry=0.1;
3504               errz=0.1;
3505               polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
3506               nfound++;
3507             }
3508           }
3509         }
3510         if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable))  break;     
3511         polytrack.UpdateParameters();
3512       }           
3513     }
3514     if ( (sumused>3) || (sumused>0.5*nfound))  {
3515       //printf("sumused   %d\n",sumused);
3516       continue;
3517     }
3518     nin1++;
3519     Double_t dy,dz;
3520     polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
3521     AliTPCpolyTrack track2;
3522     
3523     polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
3524     if (track2.GetN()<0.5*nfoundable) continue;
3525     nin2++;
3526
3527     if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
3528       //
3529       // test seed with and without constrain
3530       for (Int_t constrain=0; constrain<=0;constrain++){
3531         // add polytrack candidate
3532
3533         Double_t x[5], c[15];
3534         Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
3535         track2.GetBoundaries(x3,x1);    
3536         x2 = (x1+x3)/2.;
3537         track2.GetFitPoint(x1,y1,z1);
3538         track2.GetFitPoint(x2,y2,z2);
3539         track2.GetFitPoint(x3,y3,z3);
3540         //
3541         //is track pointing to the vertex ?
3542         Double_t x0,y0,z0;
3543         x0=0;
3544         polytrack.GetFitPoint(x0,y0,z0);
3545
3546         if (constrain) {
3547           x2 = x3;
3548           y2 = y3;
3549           z2 = z3;
3550           
3551           x3 = 0;
3552           y3 = 0;
3553           z3 = 0;
3554         }
3555         x[0]=y1;
3556         x[1]=z1;
3557         x[4]=F1(x1,y1,x2,y2,x3,y3);
3558                 
3559         //      if (TMath::Abs(x[4]) >= cuts[0]) continue;  //
3560         x[2]=F2(x1,y1,x2,y2,x3,y3);
3561         
3562         //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
3563         //x[3]=F3(x1,y1,x2,y2,z1,z2);
3564         x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
3565         //if (TMath::Abs(x[3]) > cuts[3]) continue;
3566
3567         
3568         Double_t sy =0.1, sz =0.1;
3569         Double_t sy1=0.02, sz1=0.02;
3570         Double_t sy2=0.02, sz2=0.02;
3571         Double_t sy3=0.02;
3572
3573         if (constrain){
3574           sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3575         }
3576         
3577         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3578         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3579         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3580         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3581         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3582         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3583
3584         Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
3585         Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
3586         Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
3587         Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
3588
3589         
3590         c[0]=sy1;
3591         c[1]=0.;       c[2]=sz1;
3592         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3593         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3594         c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3595         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3596         c[13]=f30*sy1*f40+f32*sy2*f42;
3597         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3598         
3599         //Int_t row1 = fSectors->GetRowNumber(x1);
3600         Int_t row1 = GetRowNumber(x1);
3601
3602         UInt_t index=0;
3603         //kr0.GetIndex(is);
3604         seed->~AliTPCseed();
3605         AliTPCseed *track=new(seed) AliTPCseed(x1,sec*alpha+shift,x,c,index);
3606         track->SetIsSeeding(kTRUE);
3607         Int_t rc=FollowProlongation(*track, i2);        
3608         if (constrain) track->SetBConstrain(1);
3609         else
3610           track->SetBConstrain(0);
3611         track->SetLastPoint(row1+fInnerSec->GetNRows());  // first cluster in track position
3612         track->SetFirstPoint(track->GetLastPoint());
3613
3614         if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 || 
3615             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
3616             track->GetNShared()>0.4*track->GetNumberOfClusters()) {
3617           //delete track;
3618           seed->Reset();
3619           seed->~AliTPCseed();
3620         }
3621         else {
3622           arr->AddLast(track);
3623           seed = new AliTPCseed;
3624         }
3625         nin3++;
3626       }
3627     }  // if accepted seed
3628   }
3629   if (fDebug>3){
3630     Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
3631   }
3632   delete seed;
3633 }
3634
3635
3636 AliTPCseed *AliTPCtrackerMI::MakeSeed(AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
3637 {
3638   //
3639   //
3640   //reseed using track points
3641   Int_t p0 = int(r0*track->GetNumberOfClusters());     // point 0 
3642   Int_t p1 = int(r1*track->GetNumberOfClusters());
3643   Int_t p2 = int(r2*track->GetNumberOfClusters());   // last point
3644   Int_t pp2=0;
3645   Double_t  x0[3],x1[3],x2[3];
3646   for (Int_t i=0;i<3;i++){
3647     x0[i]=-1;
3648     x1[i]=-1;
3649     x2[i]=-1;
3650   }
3651
3652   // find track position at given ratio of the length
3653   Int_t  sec0=0, sec1=0, sec2=0;
3654   Int_t index=-1;
3655   Int_t clindex;
3656   for (Int_t i=0;i<160;i++){
3657     if (track->GetClusterPointer(i)){
3658       index++;
3659       AliTPCTrackerPoint   *trpoint =track->GetTrackPoint(i);
3660       if ( (index<p0) || x0[0]<0 ){
3661         if (trpoint->GetX()>1){
3662           clindex = track->GetClusterIndex2(i);
3663           if (clindex>0){       
3664             x0[0] = trpoint->GetX();
3665             x0[1] = trpoint->GetY();
3666             x0[2] = trpoint->GetZ();
3667             sec0  = ((clindex&0xff000000)>>24)%18;
3668           }
3669         }
3670       }
3671
3672       if ( (index<p1) &&(trpoint->GetX()>1)){
3673         clindex = track->GetClusterIndex2(i);
3674         if (clindex>0){
3675           x1[0] = trpoint->GetX();
3676           x1[1] = trpoint->GetY();
3677           x1[2] = trpoint->GetZ();
3678           sec1  = ((clindex&0xff000000)>>24)%18;
3679         }
3680       }
3681       if ( (index<p2) &&(trpoint->GetX()>1)){
3682         clindex = track->GetClusterIndex2(i);
3683         if (clindex>0){
3684           x2[0] = trpoint->GetX();
3685           x2[1] = trpoint->GetY();
3686           x2[2] = trpoint->GetZ(); 
3687           sec2  = ((clindex&0xff000000)>>24)%18;
3688           pp2 = i;
3689         }
3690       }
3691     }
3692   }
3693   
3694   Double_t alpha, cs,sn, xx2,yy2;
3695   //
3696   alpha = (sec1-sec2)*fSectors->GetAlpha();
3697   cs = TMath::Cos(alpha);
3698   sn = TMath::Sin(alpha); 
3699   xx2= x1[0]*cs-x1[1]*sn;
3700   yy2= x1[0]*sn+x1[1]*cs;
3701   x1[0] = xx2;
3702   x1[1] = yy2;
3703   //
3704   alpha = (sec0-sec2)*fSectors->GetAlpha();
3705   cs = TMath::Cos(alpha);
3706   sn = TMath::Sin(alpha); 
3707   xx2= x0[0]*cs-x0[1]*sn;
3708   yy2= x0[0]*sn+x0[1]*cs;
3709   x0[0] = xx2;
3710   x0[1] = yy2;
3711   //
3712   //
3713   //
3714   Double_t x[5],c[15];
3715   //
3716   x[0]=x2[1];
3717   x[1]=x2[2];
3718   x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
3719   //  if (x[4]>1) return 0;
3720   x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
3721   x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
3722   //if (TMath::Abs(x[3]) > 2.2)  return 0;
3723   //if (TMath::Abs(x[2]) > 1.99) return 0;
3724   //  
3725   Double_t sy =0.1,  sz =0.1;
3726   //
3727   Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
3728   Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
3729   Double_t sy3=0.01+track->GetSigmaY2();
3730   //
3731   Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
3732   Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
3733   Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
3734   Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
3735   Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
3736   Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
3737   //
3738   Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
3739   Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
3740   Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
3741   Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
3742   
3743   
3744   c[0]=sy1;
3745   c[1]=0.;       c[2]=sz1;
3746   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3747   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3748   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3749   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3750   c[13]=f30*sy1*f40+f32*sy2*f42;
3751   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3752   
3753   //  Int_t row1 = fSectors->GetRowNumber(x2[0]);
3754   AliTPCseed *seed=new  AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
3755   //  Double_t y0,z0,y1,z1, y2,z2;
3756   //seed->GetProlongation(x0[0],y0,z0);
3757   // seed->GetProlongation(x1[0],y1,z1);
3758   //seed->GetProlongation(x2[0],y2,z2);
3759   //  seed =0;
3760   seed->SetLastPoint(pp2);
3761   seed->SetFirstPoint(pp2);
3762   
3763
3764   return seed;
3765 }
3766
3767
3768 AliTPCseed *AliTPCtrackerMI::ReSeed(AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
3769 {
3770   //
3771   //
3772   //reseed using founded clusters 
3773   //
3774   // Find the number of clusters
3775   Int_t nclusters = 0;
3776   for (Int_t irow=0;irow<160;irow++){
3777     if (track->GetClusterIndex(irow)>0) nclusters++;
3778   }
3779   //
3780   Int_t ipos[3];
3781   ipos[0] = TMath::Max(int(r0*nclusters),0);             // point 0 cluster
3782   ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1);   // 
3783   ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1);   // last point
3784   //
3785   //
3786   Double_t  xyz[3][3];
3787   Int_t     row[3],sec[3]={0,0,0};
3788   //
3789   // find track row position at given ratio of the length
3790   Int_t index=-1;
3791   for (Int_t irow=0;irow<160;irow++){    
3792     if (track->GetClusterIndex2(irow)<0) continue;
3793     index++;
3794     for (Int_t ipoint=0;ipoint<3;ipoint++){
3795       if (index<=ipos[ipoint]) row[ipoint] = irow;
3796     }        
3797   }
3798   //
3799   //Get cluster and sector position
3800   for (Int_t ipoint=0;ipoint<3;ipoint++){
3801     Int_t clindex = track->GetClusterIndex2(row[ipoint]);
3802     AliTPCclusterMI * cl = GetClusterMI(clindex);
3803     if (cl==0) {
3804       //Error("Bug\n");
3805       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
3806       return 0;
3807     }
3808     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
3809     xyz[ipoint][0]  = GetXrow(row[ipoint]);
3810     xyz[ipoint][1]  = cl->GetY();
3811     xyz[ipoint][2]  = cl->GetZ();
3812   }
3813   //
3814   //
3815   // Calculate seed state vector and covariance matrix
3816
3817   Double_t alpha, cs,sn, xx2,yy2;
3818   //
3819   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
3820   cs = TMath::Cos(alpha);
3821   sn = TMath::Sin(alpha); 
3822   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
3823   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
3824   xyz[1][0] = xx2;
3825   xyz[1][1] = yy2;
3826   //
3827   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
3828   cs = TMath::Cos(alpha);
3829   sn = TMath::Sin(alpha); 
3830   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
3831   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
3832   xyz[0][0] = xx2;
3833   xyz[0][1] = yy2;
3834   //
3835   //
3836   //
3837   Double_t x[5],c[15];
3838   //
3839   x[0]=xyz[2][1];
3840   x[1]=xyz[2][2];
3841   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
3842   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
3843   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
3844   //  
3845   Double_t sy =0.1,  sz =0.1;
3846   //
3847   Double_t sy1=0.2, sz1=0.2;
3848   Double_t sy2=0.2, sz2=0.2;
3849   Double_t sy3=0.2;
3850   //
3851   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;
3852   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;
3853   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;
3854   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;
3855   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;
3856   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;
3857   //
3858   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;
3859   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;
3860   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;
3861   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;
3862   
3863   
3864   c[0]=sy1;
3865   c[1]=0.;       c[2]=sz1;
3866   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3867   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
3868   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3869   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3870   c[13]=f30*sy1*f40+f32*sy2*f42;
3871   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3872   
3873   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
3874   AliTPCseed *seed=new  AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
3875   seed->SetLastPoint(row[2]);
3876   seed->SetFirstPoint(row[2]);  
3877   return seed;
3878 }
3879
3880
3881 AliTPCseed *AliTPCtrackerMI::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
3882 {
3883   //
3884   //
3885   //reseed using founded clusters 
3886   //
3887   Double_t  xyz[3][3];
3888   Int_t     row[3]={0,0,0};
3889   Int_t     sec[3]={0,0,0};
3890   //
3891   // forward direction
3892   if (forward){
3893     for (Int_t irow=r0;irow<160;irow++){
3894       if (track->GetClusterIndex(irow)>0){
3895         row[0] = irow;
3896         break;
3897       }
3898     }
3899     for (Int_t irow=160;irow>r0;irow--){
3900       if (track->GetClusterIndex(irow)>0){
3901         row[2] = irow;
3902         break;
3903       }
3904     }
3905     for (Int_t irow=row[2]-15;irow>row[0];irow--){
3906       if (track->GetClusterIndex(irow)>0){
3907         row[1] = irow;
3908         break;
3909       }
3910     }
3911     //
3912   }
3913   if (!forward){
3914     for (Int_t irow=0;irow<r0;irow++){
3915       if (track->GetClusterIndex(irow)>0){
3916         row[0] = irow;
3917         break;
3918       }
3919     }
3920     for (Int_t irow=r0;irow>0;irow--){
3921       if (track->GetClusterIndex(irow)>0){
3922         row[2] = irow;
3923         break;
3924       }
3925     }    
3926     for (Int_t irow=row[2]-15;irow>row[0];irow--){
3927       if (track->GetClusterIndex(irow)>0){
3928         row[1] = irow;
3929         break;
3930       }
3931     } 
3932   }
3933   //
3934   if ((row[2]-row[0])<20) return 0;
3935   if (row[1]==0) return 0;
3936   //
3937   //
3938   //Get cluster and sector position
3939   for (Int_t ipoint=0;ipoint<3;ipoint++){
3940     Int_t clindex = track->GetClusterIndex2(row[ipoint]);
3941     AliTPCclusterMI * cl = GetClusterMI(clindex);
3942     if (cl==0) {
3943       //Error("Bug\n");
3944       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
3945       return 0;
3946     }
3947     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
3948     xyz[ipoint][0]  = GetXrow(row[ipoint]);
3949     AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);    
3950     if (point&&ipoint<2){
3951       //
3952        xyz[ipoint][1]  = point->GetY();
3953        xyz[ipoint][2]  = point->GetZ();
3954     }
3955     else{
3956       xyz[ipoint][1]  = cl->GetY();
3957       xyz[ipoint][2]  = cl->GetZ();
3958     }
3959   }
3960   //
3961   //
3962   //
3963   //
3964   // Calculate seed state vector and covariance matrix
3965
3966   Double_t alpha, cs,sn, xx2,yy2;
3967   //
3968   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
3969   cs = TMath::Cos(alpha);
3970   sn = TMath::Sin(alpha); 
3971   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
3972   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
3973   xyz[1][0] = xx2;
3974   xyz[1][1] = yy2;
3975   //
3976   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
3977   cs = TMath::Cos(alpha);
3978   sn = TMath::Sin(alpha); 
3979   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
3980   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
3981   xyz[0][0] = xx2;
3982   xyz[0][1] = yy2;
3983   //
3984   //
3985   //
3986   Double_t x[5],c[15];
3987   //
3988   x[0]=xyz[2][1];
3989   x[1]=xyz[2][2];
3990   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
3991   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
3992   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
3993   //  
3994   Double_t sy =0.1,  sz =0.1;
3995   //
3996   Double_t sy1=0.2, sz1=0.2;
3997   Double_t sy2=0.2, sz2=0.2;
3998   Double_t sy3=0.2;
3999   //
4000   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;
4001   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;
4002   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;
4003   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;
4004   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;
4005   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;
4006   //
4007   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;
4008   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;
4009   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;
4010   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;
4011   
4012   
4013   c[0]=sy1;
4014   c[1]=0.;       c[2]=sz1;
4015   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4016   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
4017   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4018   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4019   c[13]=f30*sy1*f40+f32*sy2*f42;
4020   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4021   
4022   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4023   AliTPCseed *seed=new  AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4024   seed->SetLastPoint(row[2]);
4025   seed->SetFirstPoint(row[2]);  
4026   for (Int_t i=row[0];i<row[2];i++){
4027     seed->SetClusterIndex(i, track->GetClusterIndex(i));
4028   }
4029
4030   return seed;
4031 }
4032
4033
4034
4035 void  AliTPCtrackerMI::FindMultiMC(TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4036 {
4037   //
4038   //  find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
4039   //                      USES MC LABELS
4040   //  Use AliTPCReconstructor::StreamLevel()>2 if you want to tune parameters - cuts
4041   //
4042   //  Two reasons to have multiple find tracks
4043   //  1. Curling tracks can be find more than once
4044   //  2. Splitted tracks 
4045   //     a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)        
4046   //     b.) Edge effect on the sector boundaries
4047   //
4048   //
4049   //  Algorithm done in 2 phases - because of CPU consumption
4050   //  it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated                           
4051   //
4052   //  Algorihm for curling tracks sign:
4053   //    1 phase -makes a very rough fast cuts to minimize combinatorics
4054   //                 a.) opposite sign
4055   //                 b.) one of the tracks - not pointing to the primary vertex - 
4056   //                 c.) delta tan(theta)
4057   //                 d.) delta phi
4058   //    2 phase - calculates DCA between tracks  - time consument
4059
4060   //
4061   //    fast cuts 
4062   //
4063   //    General cuts    - for splitted tracks and for curling tracks
4064   //
4065   const Float_t kMaxdPhi      = 0.2;  // maximal distance in phi
4066   //
4067   //    Curling tracks cuts
4068   //
4069   //
4070   //
4071   //
4072   Int_t nentries = array->GetEntriesFast();  
4073   AliHelix *helixes      = new AliHelix[nentries];
4074   Float_t  *xm           = new Float_t[nentries];
4075   Float_t  *dz0           = new Float_t[nentries];
4076   Float_t  *dz1           = new Float_t[nentries];
4077   //
4078   //
4079   TStopwatch timer;
4080   timer.Start();
4081   //
4082   // Find track COG in x direction - point with best defined parameters
4083   //
4084   for (Int_t i=0;i<nentries;i++){
4085     AliTPCseed* track = (AliTPCseed*)array->At(i);    
4086     if (!track) continue;
4087     track->SetCircular(0);
4088     new (&helixes[i]) AliHelix(*track);
4089     Int_t ncl=0;
4090     xm[i]=0;
4091     Float_t dz[2];
4092     track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
4093     dz0[i]=dz[0];
4094     dz1[i]=dz[1];
4095     for (Int_t icl=0; icl<160; icl++){
4096       AliTPCclusterMI * cl =  track->GetClusterPointer(icl);
4097       if (cl) {
4098         xm[i]+=cl->GetX();
4099         ncl++;
4100       }
4101     }
4102     if (ncl>0) xm[i]/=Float_t(ncl);
4103   }  
4104   TTreeSRedirector &cstream = *fDebugStreamer;
4105   //
4106   for (Int_t i0=0;i0<nentries;i0++){
4107     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4108     if (!track0) continue;    
4109     Float_t xc0 = helixes[i0].GetHelix(6);
4110     Float_t yc0 = helixes[i0].GetHelix(7);
4111     Float_t r0  = helixes[i0].GetHelix(8);
4112     Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4113     Float_t fi0 = TMath::ATan2(yc0,xc0);
4114     
4115     for (Int_t i1=i0+1;i1<nentries;i1++){
4116       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4117       if (!track1) continue;      
4118       Int_t lab0=track0->GetLabel();
4119       Int_t lab1=track1->GetLabel();
4120       if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
4121       //
4122       Float_t xc1 = helixes[i1].GetHelix(6);
4123       Float_t yc1 = helixes[i1].GetHelix(7);
4124       Float_t r1  = helixes[i1].GetHelix(8);
4125       Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4126       Float_t fi1 = TMath::ATan2(yc1,xc1);
4127       //
4128       Float_t dfi = fi0-fi1;
4129       //
4130       //
4131       if (dfi>1.5*TMath::Pi())  dfi-=TMath::Pi();  // take care about edge effect 
4132       if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi();  // 
4133       if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
4134         //
4135         // if short tracks with undefined sign 
4136         fi1 =  -TMath::ATan2(yc1,-xc1);
4137         dfi = fi0-fi1;
4138       }
4139       Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4140       
4141       //
4142       // debug stream to tune "fast cuts" 
4143       //
4144       Double_t dist[3];   // distance at X 
4145       Double_t mdist[3]={0,0,0};  // mean distance X+-40cm
4146       track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
4147       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4148       track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
4149       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4150       track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
4151       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4152       for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
4153       
4154       Float_t sum =0;
4155       Float_t sums=0;
4156       for (Int_t icl=0; icl<160; icl++){
4157         AliTPCclusterMI * cl0 =  track0->GetClusterPointer(icl);
4158         AliTPCclusterMI * cl1 =  track1->GetClusterPointer(icl);
4159         if (cl0&&cl1) {
4160           sum++;
4161           if (cl0==cl1) sums++;
4162         }
4163       }
4164       //
4165       cstream<<"Multi"<<
4166         "iter="<<iter<<
4167         "lab0="<<lab0<<
4168         "lab1="<<lab1<<   
4169         "Tr0.="<<track0<<       // seed0
4170         "Tr1.="<<track1<<       // seed1
4171         "h0.="<<&helixes[i0]<<
4172         "h1.="<<&helixes[i1]<<
4173         //
4174         "sum="<<sum<<           //the sum of rows with cl in both
4175         "sums="<<sums<<         //the sum of shared clusters
4176         "xm0="<<xm[i0]<<        // the center of track
4177         "xm1="<<xm[i1]<<        // the x center of track
4178         // General cut variables                   
4179         "dfi="<<dfi<<           // distance in fi angle
4180         "dtheta="<<dtheta<<     // distance int theta angle
4181         //
4182         "dz00="<<dz0[i0]<<
4183         "dz01="<<dz0[i1]<<
4184         "dz10="<<dz1[i1]<<
4185         "dz11="<<dz1[i1]<<
4186         "dist0="<<dist[0]<<     //distance x
4187         "dist1="<<dist[1]<<     //distance y
4188         "dist2="<<dist[2]<<     //distance z
4189         "mdist0="<<mdist[0]<<   //distance x
4190         "mdist1="<<mdist[1]<<   //distance y
4191         "mdist2="<<mdist[2]<<   //distance z
4192         //
4193         "r0="<<r0<<
4194         "rc0="<<rc0<<
4195         "fi0="<<fi0<<
4196         "fi1="<<fi1<<
4197         "r1="<<r1<<
4198         "rc1="<<rc1<<
4199         "\n";
4200     }
4201   }    
4202   delete [] helixes;
4203   delete [] xm;
4204   if (AliTPCReconstructor::StreamLevel()>1) {
4205     AliInfo("Time for curling tracks removal DEBUGGING MC");
4206     timer.Print();
4207   }
4208 }
4209
4210
4211 void  AliTPCtrackerMI::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4212 {
4213   //
4214   //
4215   //  Two reasons to have multiple find tracks
4216   //  1. Curling tracks can be find more than once
4217   //  2. Splitted tracks 
4218   //     a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)        
4219   //     b.) Edge effect on the sector boundaries
4220   //
4221   //  This function tries to find tracks closed in the parametric space
4222   //
4223   // cut logic if distance is bigger than cut continue - Do Nothing
4224   const Float_t kMaxdTheta    = 0.05;  // maximal distance in theta
4225   const Float_t kMaxdPhi      = 0.05;   // maximal deistance in phi
4226   const Float_t kdelta        = 40.;   //delta r to calculate track distance
4227   //
4228   //  const Float_t kMaxDist0     = 1.;    // maximal distance 0 
4229   //const Float_t kMaxDist1     = 0.3;   // maximal distance 1 - cut if track in separate rows 
4230   //
4231   /*
4232     TCut csec("csec","abs(Tr0.fRelativeSector-Tr1.fRelativeSector)<2");
4233     TCut cdtheta("cdtheta","abs(dtheta)<0.05");
4234   */ 
4235   //
4236   //
4237   //
4238   Int_t nentries = array->GetEntriesFast();  
4239   AliHelix *helixes      = new AliHelix[nentries];
4240   Float_t  *xm           = new Float_t[nentries];
4241   //
4242   //
4243   TStopwatch timer;
4244   timer.Start();
4245   //
4246   //Sort tracks according quality
4247   //
4248   Int_t nseed = array->GetEntriesFast();  
4249   Float_t * quality = new Float_t[nseed];
4250   Int_t   * indexes = new Int_t[nseed];
4251   for (Int_t i=0; i<nseed; i++) {
4252     AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);    
4253     if (!pt){
4254       quality[i]=-1;
4255       continue;
4256     }
4257     pt->UpdatePoints();    //select first last max dens points
4258     Float_t * points = pt->GetPoints();
4259     if (points[3]<0.8) quality[i] =-1;
4260     quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
4261     //prefer high momenta tracks if overlaps
4262     quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5); 
4263   }
4264   TMath::Sort(nseed,quality,indexes);
4265
4266
4267   //
4268   // Find track COG in x direction - point with best defined parameters
4269   //
4270   for (Int_t i=0;i<nentries;i++){
4271     AliTPCseed* track = (AliTPCseed*)array->At(i);    
4272     if (!track) continue;
4273     track->SetCircular(0);
4274     new (&helixes[i]) AliHelix(*track);
4275     Int_t ncl=0;
4276     xm[i]=0;
4277     for (Int_t icl=0; icl<160; icl++){
4278       AliTPCclusterMI * cl =  track->GetClusterPointer(icl);
4279       if (cl) {
4280         xm[i]+=cl->GetX();
4281         ncl++;
4282       }
4283     }
4284     if (ncl>0) xm[i]/=Float_t(ncl);
4285   }  
4286   TTreeSRedirector &cstream = *fDebugStreamer;
4287   //
4288   for (Int_t is0=0;is0<nentries;is0++){
4289     Int_t i0 = indexes[is0];
4290     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4291     if (!track0) continue;     
4292     if (track0->GetKinkIndexes()[0]!=0) continue;
4293     Float_t xc0 = helixes[i0].GetHelix(6);
4294     Float_t yc0 = helixes[i0].GetHelix(7);
4295     Float_t fi0 = TMath::ATan2(yc0,xc0);
4296     
4297     for (Int_t is1=is0+1;is1<nentries;is1++){
4298       Int_t i1 = indexes[is1];
4299       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4300       if (!track1) continue;      
4301       //
4302       if (TMath::Abs(track0->GetRelativeSector()-track1->GetRelativeSector())>1) continue;
4303       if (track1->GetKinkIndexes()[0]>0 &&track0->GetKinkIndexes()[0]<0) continue;
4304       if (track1->GetKinkIndexes()[0]!=0) continue;
4305
4306       Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4307       if (TMath::Abs(dtheta)>kMaxdTheta) continue;      
4308       //
4309       Float_t xc1 = helixes[i1].GetHelix(6);
4310       Float_t yc1 = helixes[i1].GetHelix(7);
4311       Float_t fi1 = TMath::ATan2(yc1,xc1);
4312       //
4313       Float_t dfi = fi0-fi1;
4314       if (dfi>1.5*TMath::Pi())  dfi-=TMath::Pi();  // take care about edge effect 
4315       if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi();  // 
4316       if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
4317         //
4318         // if short tracks with undefined sign 
4319         fi1 =  -TMath::ATan2(yc1,-xc1);
4320         dfi = fi0-fi1;
4321       }
4322       if (TMath::Abs(dfi)>kMaxdPhi) continue;
4323       //
4324       //      
4325       Float_t sum =0;
4326       Float_t sums=0;
4327       Float_t sum0=0;
4328       Float_t sum1=0;
4329       for (Int_t icl=0; icl<160; icl++){
4330         Int_t index0=track0->GetClusterIndex2(icl);
4331         Int_t index1=track1->GetClusterIndex2(icl);       
4332         Bool_t used0 = (index0>0 && !(index0&0x8000));
4333         Bool_t used1 = (index1>0 && !(index1&0x8000));
4334         //
4335         if (used0) sum0++;  // used cluster0
4336         if (used1) sum1++;  // used clusters1
4337         if (used0&&used1) sum++;
4338         if (index0==index1 && used0 && used1) sums++;
4339       } 
4340      
4341       //
4342       if (sums<10) continue;
4343       if (sum<40) continue;
4344       if (sums/Float_t(TMath::Min(sum0,sum1))<0.5) continue;
4345       //
4346       Double_t dist[5][4];   // distance at X 
4347       Double_t mdist[4]={0,0,0,0};  // mean distance on range +-delta
4348      
4349       //
4350       //            
4351       track0->GetDistance(track1,xm[i0],dist[0],AliTracker::GetBz());
4352       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[0][i]);
4353       track0->GetDistance(track1,xm[i1],dist[1],AliTracker::GetBz());
4354       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[1][i]);
4355       //
4356       track0->GetDistance(track1,TMath::Min(xm[i1],xm[i0])-kdelta,dist[2],AliTracker::GetBz());
4357       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[2][i]);
4358       track0->GetDistance(track1,TMath::Max(xm[i1],xm[i0])+kdelta,dist[3],AliTracker::GetBz());
4359       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[3][i]);     
4360       //
4361       track0->GetDistance(track1,(xm[i1]+xm[i0])*0.5,dist[4],AliTracker::GetBz());
4362       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[4][i]);     
4363       for (Int_t i=0;i<3;i++) mdist[i]*=0.2;
4364       //
4365       //
4366       Int_t lab0=track0->GetLabel();
4367       Int_t lab1=track1->GetLabel();
4368       cstream<<"Splitted"<<
4369         "iter="<<iter<<
4370         "lab0="<<lab0<<
4371         "lab1="<<lab1<<   
4372         "Tr0.="<<track0<<       // seed0
4373         "Tr1.="<<track1<<       // seed1
4374         "h0.="<<&helixes[i0]<<
4375         "h1.="<<&helixes[i1]<<
4376         //
4377         "sum="<<sum<<           //the sum of rows with cl in both
4378         "sum0="<<sum0<<           //the sum of rows with cl in 0 track
4379         "sum1="<<sum1<<           //the sum of rows with cl in 1 track
4380         "sums="<<sums<<         //the sum of shared clusters
4381         "xm0="<<xm[i0]<<        // the center of track
4382         "xm1="<<xm[i1]<<        // the x center of track
4383         // General cut variables                   
4384         "dfi="<<dfi<<           // distance in fi angle
4385         "dtheta="<<dtheta<<     // distance int theta angle
4386         //
4387         //
4388         "dist0="<<dist[4][0]<<     //distance x
4389         "dist1="<<dist[4][1]<<     //distance y
4390         "dist2="<<dist[4][2]<<     //distance z
4391         "mdist0="<<mdist[0]<<   //distance x
4392         "mdist1="<<mdist[1]<<   //distance y
4393         "mdist2="<<mdist[2]<<   //distance z
4394
4395         "\n";
4396       delete array->RemoveAt(i1);
4397     }
4398   }    
4399   delete [] helixes;
4400   delete [] xm;
4401   AliInfo("Time for splitted tracks removal");
4402   timer.Print();
4403 }
4404
4405
4406
4407 void  AliTPCtrackerMI::FindCurling(TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4408 {
4409   //
4410   //  find Curling tracks
4411   //  Use AliTPCReconstructor::StreamLevel()>1 if you want to tune parameters - cuts
4412   //
4413   //
4414   //  Algorithm done in 2 phases - because of CPU consumption
4415   //  it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated                           
4416   //  see detal in MC part what can be used to cut
4417   //
4418   //    
4419   //
4420   const Float_t kMaxC         = 400;  // maximal curvature to of the track
4421   const Float_t kMaxdTheta    = 0.15;  // maximal distance in theta
4422   const Float_t kMaxdPhi      = 0.15;  // maximal distance in phi
4423   const Float_t kPtRatio      = 0.3; // ratio between pt
4424   const Float_t kMinDCAR      = 2.;   // distance to the primary vertex in r - see cpipe cut      
4425
4426   //
4427   //    Curling tracks cuts
4428   //
4429   //
4430   const Float_t kMaxDeltaRMax = 40;   // distance in outer radius
4431   const Float_t kMaxDeltaRMin = 5.;   // distance in lower radius - see cpipe cut
4432   const Float_t kMinAngle     = 2.9;  // angle between tracks
4433   const Float_t kMaxDist      = 5;    // biggest distance 
4434   //
4435   // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
4436   /* 
4437      Fast cuts:
4438      TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
4439      TCut cmax("cmax","abs(Tr0.GetC())>1/400");
4440      TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
4441      TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
4442      TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");    
4443      //
4444      TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
4445      TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
4446      //
4447      Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill 
4448      Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
4449      //
4450      Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
4451
4452   */
4453   //  
4454   //
4455   //
4456   Int_t nentries = array->GetEntriesFast();  
4457   AliHelix *helixes      = new AliHelix[nentries];
4458   for (Int_t i=0;i<nentries;i++){
4459     AliTPCseed* track = (AliTPCseed*)array->At(i);    
4460     if (!track) continue;
4461     track->SetCircular(0);
4462     new (&helixes[i]) AliHelix(*track);
4463   }
4464   //
4465   //
4466   TStopwatch timer;
4467   timer.Start();
4468   Double_t phase[2][2],radius[2];
4469   //
4470   // Find tracks
4471   //
4472   TTreeSRedirector &cstream = *fDebugStreamer;
4473   //
4474   for (Int_t i0=0;i0<nentries;i0++){
4475     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4476     if (!track0) continue;    
4477     if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
4478     Float_t xc0 = helixes[i0].GetHelix(6);
4479     Float_t yc0 = helixes[i0].GetHelix(7);
4480     Float_t r0  = helixes[i0].GetHelix(8);
4481     Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4482     Float_t fi0 = TMath::ATan2(yc0,xc0);
4483     
4484     for (Int_t i1=i0+1;i1<nentries;i1++){
4485       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4486       if (!track1) continue;      
4487       if (TMath::Abs(track1->GetC())<1/kMaxC) continue;    
4488       Float_t xc1 = helixes[i1].GetHelix(6);
4489       Float_t yc1 = helixes[i1].GetHelix(7);
4490       Float_t r1  = helixes[i1].GetHelix(8);
4491       Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4492       Float_t fi1 = TMath::ATan2(yc1,xc1);
4493       //
4494       Float_t dfi = fi0-fi1;
4495       //
4496       //
4497       if (dfi>1.5*TMath::Pi())  dfi-=TMath::Pi();  // take care about edge effect 
4498       if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi();  // 
4499       Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4500       //
4501       //
4502       // FIRST fast cuts
4503       if (track0->GetBConstrain()&&track1->GetBConstrain())  continue;  // not constrained
4504       if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0)   continue; // not the same sign
4505       if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
4506       if ( TMath::Abs(dfi)>kMaxdPhi) continue;  //distance in phi
4507       if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
4508       //
4509       Float_t pt0 = track0->GetSignedPt();
4510       Float_t pt1 = track1->GetSignedPt();
4511       if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;      
4512       if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
4513       if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
4514       if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
4515       //
4516       //
4517       // Now find closest approach
4518       //
4519       //
4520       //
4521       Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4522       if (npoints==0) continue;
4523       helixes[i0].GetClosestPhases(helixes[i1], phase);
4524       //
4525       Double_t xyz0[3];
4526       Double_t xyz1[3];
4527       Double_t hangles[3];
4528       helixes[i0].Evaluate(phase[0][0],xyz0);
4529       helixes[i1].Evaluate(phase[0][1],xyz1);
4530
4531       helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4532       Double_t deltah[2],deltabest;
4533       if (TMath::Abs(hangles[2])<kMinAngle) continue;
4534
4535       if (npoints>0){
4536         Int_t ibest=0;
4537         helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
4538         if (npoints==2){
4539           helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
4540           if (deltah[1]<deltah[0]) ibest=1;
4541         }
4542         deltabest  = TMath::Sqrt(deltah[ibest]);
4543         helixes[i0].Evaluate(phase[ibest][0],xyz0);
4544         helixes[i1].Evaluate(phase[ibest][1],xyz1);
4545         helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
4546         Double_t radiusbest = TMath::Sqrt(radius[ibest]);
4547         //
4548         if (deltabest>kMaxDist) continue;
4549         //      if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
4550         Bool_t sign =kFALSE;
4551         if (hangles[2]>kMinAngle) sign =kTRUE;
4552         //
4553         if (sign){
4554           //      circular[i0] = kTRUE;
4555           //      circular[i1] = kTRUE;
4556           if (track0->OneOverPt()<track1->OneOverPt()){
4557             track0->SetCircular(track0->GetCircular()+1);
4558             track1->SetCircular(track1->GetCircular()+2);
4559           }
4560           else{
4561             track1->SetCircular(track1->GetCircular()+1);
4562             track0->SetCircular(track0->GetCircular()+2);
4563           }
4564         }               
4565         if (AliTPCReconstructor::StreamLevel()>1){        
4566           //
4567           //debug stream to tune "fine" cuts      
4568           Int_t lab0=track0->GetLabel();
4569           Int_t lab1=track1->GetLabel();
4570           cstream<<"Curling2"<<
4571             "iter="<<iter<<
4572             "lab0="<<lab0<<
4573             "lab1="<<lab1<<   
4574             "Tr0.="<<track0<<
4575             "Tr1.="<<track1<<
4576             //
4577             "r0="<<r0<<
4578             "rc0="<<rc0<<
4579             "fi0="<<fi0<<
4580             "r1="<<r1<<
4581             "rc1="<<rc1<<
4582             "fi1="<<fi1<<
4583             "dfi="<<dfi<<
4584             "dtheta="<<dtheta<<
4585             //
4586             "npoints="<<npoints<<                      
4587             "hangles0="<<hangles[0]<<
4588             "hangles1="<<hangles[1]<<
4589             "hangles2="<<hangles[2]<<                    
4590             "xyz0="<<xyz0[2]<<
4591             "xyzz1="<<xyz1[2]<<
4592             "radius="<<radiusbest<<
4593             "deltabest="<<deltabest<< 
4594             "phase0="<<phase[ibest][0]<<
4595             "phase1="<<phase[ibest][1]<<
4596             "\n";                 
4597
4598         }
4599       }
4600     }
4601   }
4602   delete [] helixes;
4603   if (AliTPCReconstructor::StreamLevel()>1) {
4604     AliInfo("Time for curling tracks removal");
4605     timer.Print();
4606   }
4607 }
4608
4609
4610
4611
4612
4613 void  AliTPCtrackerMI::FindKinks(TObjArray * array, AliESDEvent *esd)
4614 {
4615   //
4616   //  find kinks
4617   //
4618   //
4619
4620   TObjArray *kinks= new TObjArray(10000);
4621   //  TObjArray *v0s= new TObjArray(10000);
4622   Int_t nentries = array->GetEntriesFast();
4623   AliHelix *helixes      = new AliHelix[nentries];
4624   Int_t    *sign         = new Int_t[nentries];
4625   Int_t    *nclusters    = new Int_t[nentries];
4626   Float_t  *alpha        = new Float_t[nentries];
4627   AliKink  *kink         = new AliKink();
4628   Int_t      * usage     = new Int_t[nentries];
4629   Float_t  *zm           = new Float_t[nentries];
4630   Float_t  *z0           = new Float_t[nentries]; 
4631   Float_t  *fim          = new Float_t[nentries];
4632   Float_t  *shared       = new Float_t[nentries];
4633   Bool_t   *circular     = new Bool_t[nentries];
4634   Float_t *dca          = new Float_t[nentries];
4635   //const AliESDVertex * primvertex = esd->GetVertex();
4636   //
4637   //  nentries = array->GetEntriesFast();
4638   //
4639   
4640   //
4641   //
4642   for (Int_t i=0;i<nentries;i++){
4643     sign[i]=0;
4644     usage[i]=0;
4645     AliTPCseed* track = (AliTPCseed*)array->At(i);    
4646     if (!track) continue;
4647     track->SetCircular(0);
4648     shared[i] = kFALSE;
4649     track->UpdatePoints();
4650     if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
4651     }
4652     nclusters[i]=track->GetNumberOfClusters();
4653     alpha[i] = track->GetAlpha();
4654     new (&helixes[i]) AliHelix(*track);
4655     Double_t xyz[3];
4656     helixes[i].Evaluate(0,xyz);
4657     sign[i] = (track->GetC()>0) ? -1:1;
4658     Double_t x,y,z;
4659     x=160;
4660     if (track->GetProlongation(x,y,z)){
4661       zm[i]  = z;
4662       fim[i] = alpha[i]+TMath::ATan2(y,x);
4663     }
4664     else{
4665       zm[i]  = track->GetZ();
4666       fim[i] = alpha[i];
4667     }   
4668     z0[i]=1000;
4669     circular[i]= kFALSE;
4670     if (track->GetProlongation(0,y,z))  z0[i] = z;
4671     dca[i] = track->GetD(0,0);    
4672   }
4673   //
4674   //
4675   TStopwatch timer;
4676   timer.Start();
4677   Int_t ncandidates =0;
4678   Int_t nall =0;
4679   Int_t ntracks=0; 
4680   Double_t phase[2][2],radius[2];
4681
4682   //
4683   // Find circling track
4684   TTreeSRedirector &cstream = *fDebugStreamer;
4685   //
4686   for (Int_t i0=0;i0<nentries;i0++){
4687     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4688     if (!track0) continue;    
4689     if (track0->GetNumberOfClusters()<40) continue;
4690     if (TMath::Abs(1./track0->GetC())>200) continue;
4691     for (Int_t i1=i0+1;i1<nentries;i1++){
4692       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4693       if (!track1) continue;
4694       if (track1->GetNumberOfClusters()<40)                  continue;
4695       if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
4696       if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
4697       if (TMath::Abs(1./track1->GetC())>200) continue;
4698       if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0)      continue;
4699       if (track1->GetTgl()*track0->GetTgl()>0)      continue;
4700       if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
4701       if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
4702       if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
4703       //
4704       Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
4705       if (mindcar<5)   continue;
4706       Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
4707       if (mindcaz<5) continue;
4708       if (mindcar+mindcaz<20) continue;
4709       //
4710       //
4711       Float_t xc0 = helixes[i0].GetHelix(6);
4712       Float_t yc0 = helixes[i0].GetHelix(7);
4713       Float_t r0  = helixes[i0].GetHelix(8);
4714       Float_t xc1 = helixes[i1].GetHelix(6);
4715       Float_t yc1 = helixes[i1].GetHelix(7);
4716       Float_t r1  = helixes[i1].GetHelix(8);
4717         
4718       Float_t rmean = (r0+r1)*0.5;
4719       Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
4720       //if (delta>30) continue;
4721       if (delta>rmean*0.25) continue;
4722       if (TMath::Abs(r0-r1)/rmean>0.3) continue; 
4723       //
4724       Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4725       if (npoints==0) continue;
4726       helixes[i0].GetClosestPhases(helixes[i1], phase);
4727       //
4728       Double_t xyz0[3];
4729       Double_t xyz1[3];
4730       Double_t hangles[3];
4731       helixes[i0].Evaluate(phase[0][0],xyz0);
4732       helixes[i1].Evaluate(phase[0][1],xyz1);
4733
4734       helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4735       Double_t deltah[2],deltabest;
4736       if (hangles[2]<2.8) continue;
4737       if (npoints>0){
4738         Int_t ibest=0;
4739         helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
4740         if (npoints==2){
4741           helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
4742           if (deltah[1]<deltah[0]) ibest=1;
4743         }
4744         deltabest  = TMath::Sqrt(deltah[ibest]);
4745         helixes[i0].Evaluate(phase[ibest][0],xyz0);
4746         helixes[i1].Evaluate(phase[ibest][1],xyz1);
4747         helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
4748         Double_t radiusbest = TMath::Sqrt(radius[ibest]);
4749         //
4750         if (deltabest>6) continue;
4751         if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
4752         Bool_t sign =kFALSE;
4753         if (hangles[2]>3.06) sign =kTRUE;
4754         //
4755         if (sign){
4756           circular[i0] = kTRUE;
4757           circular[i1] = kTRUE;
4758           if (track0->OneOverPt()<track1->OneOverPt()){
4759             track0->SetCircular(track0->GetCircular()+1);
4760             track1->SetCircular(track1->GetCircular()+2);
4761           }
4762           else{
4763             track1->SetCircular(track1->GetCircular()+1);
4764             track0->SetCircular(track0->GetCircular()+2);
4765           }
4766         }               
4767         if (sign&&AliTPCReconstructor::StreamLevel()>1){          
4768           //debug stream          
4769           Int_t lab0=track0->GetLabel();
4770           Int_t lab1=track1->GetLabel();
4771           cstream<<"Curling"<<
4772             "lab0="<<lab0<<
4773             "lab1="<<lab1<<   
4774             "Tr0.="<<track0<<
4775             "Tr1.="<<track1<<      
4776             "dca0="<<dca[i0]<<
4777             "dca1="<<dca[i1]<<
4778             "mindcar="<<mindcar<<
4779             "mindcaz="<<mindcaz<<
4780             "delta="<<delta<<
4781             "rmean="<<rmean<<
4782             "npoints="<<npoints<<                      
4783             "hangles0="<<hangles[0]<<
4784             "hangles2="<<hangles[2]<<                    
4785             "xyz0="<<xyz0[2]<<
4786             "xyzz1="<<xyz1[2]<<
4787             "z0="<<z0[i0]<<
4788             "z1="<<z0[i1]<<
4789             "radius="<<radiusbest<<
4790             "deltabest="<<deltabest<< 
4791             "phase0="<<phase[ibest][0]<<
4792             "phase1="<<phase[ibest][1]<<
4793             "\n";                 
4794         }
4795       }
4796     }
4797   }
4798   //
4799   //  Finf kinks loop
4800   // 
4801   //
4802   for (Int_t i =0;i<nentries;i++){
4803     if (sign[i]==0) continue;
4804     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
4805     if (track0==0) {
4806       AliInfo("seed==0");
4807       continue;
4808     }
4809     ntracks++;
4810     //
4811     Double_t cradius0 = 40*40;
4812     Double_t cradius1 = 270*270;
4813     Double_t cdist1=8.;
4814     Double_t cdist2=8.;
4815     Double_t cdist3=0.55; 
4816     for (Int_t j =i+1;j<nentries;j++){
4817       nall++;
4818       if (sign[j]*sign[i]<1) continue;
4819       if ( (nclusters[i]+nclusters[j])>200) continue;
4820       if ( (nclusters[i]+nclusters[j])<80) continue;
4821       if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
4822       if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
4823       //AliTPCseed * track1 = (AliTPCseed*)array->At(j);  Double_t phase[2][2],radius[2];    
4824       Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
4825       if (npoints<1) continue;
4826       // cuts on radius      
4827       if (npoints==1){
4828         if (radius[0]<cradius0||radius[0]>cradius1) continue;
4829       }
4830       else{
4831         if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
4832       }
4833       //      
4834       Double_t delta1=10000,delta2=10000;
4835       // cuts on the intersection radius
4836       helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
4837       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
4838       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
4839       if (npoints==2){ 
4840         helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
4841         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
4842         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
4843       }
4844       //
4845       Double_t distance1 = TMath::Min(delta1,delta2);
4846       if (distance1>cdist1) continue;  // cut on DCA linear approximation
4847       //
4848       npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
4849       helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
4850       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
4851       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
4852       //
4853       if (npoints==2){ 
4854         helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);   
4855         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
4856         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex 
4857       }            
4858       distance1 = TMath::Min(delta1,delta2);
4859       Float_t rkink =0;
4860       if (delta1<delta2){
4861         rkink = TMath::Sqrt(radius[0]);
4862       }
4863       else{
4864         rkink = TMath::Sqrt(radius[1]);
4865       }
4866       if (distance1>cdist2) continue;
4867       //
4868       //
4869       AliTPCseed * track1 = (AliTPCseed*)array->At(j);
4870       //
4871       //
4872       Int_t row0 = GetRowNumber(rkink); 
4873       if (row0<10)  continue;
4874       if (row0>150) continue;
4875       //
4876       //
4877       Float_t dens00=-1,dens01=-1;
4878       Float_t dens10=-1,dens11=-1;
4879       //
4880       Int_t found,foundable,shared;
4881       track0->GetClusterStatistic(0,row0-5, found, foundable,shared,kFALSE);
4882       if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
4883       track0->GetClusterStatistic(row0+5,155, found, foundable,shared,kFALSE);
4884       if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
4885       //
4886       track1->GetClusterStatistic(0,row0-5, found, foundable,shared,kFALSE);
4887       if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
4888       track1->GetClusterStatistic(row0+5,155, found, foundable,shared,kFALSE);
4889       if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
4890       //     
4891       if (dens00<dens10 && dens01<dens11) continue;
4892       if (dens00>dens10 && dens01>dens11) continue;
4893       if (TMath::Max(dens00,dens10)<0.1)  continue;
4894       if (TMath::Max(dens01,dens11)<0.3)  continue;
4895       //
4896       if (TMath::Min(dens00,dens10)>0.6)  continue;
4897       if (TMath::Min(dens01,dens11)>0.6)  continue;
4898
4899       //
4900       AliTPCseed * ktrack0, *ktrack1;
4901       if (dens00>dens10){
4902         ktrack0 = track0;
4903         ktrack1 = track1;
4904       }
4905       else{
4906         ktrack0 = track1;
4907         ktrack1 = track0;
4908       }
4909       if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
4910       AliExternalTrackParam paramm(*ktrack0);
4911       AliExternalTrackParam paramd(*ktrack1);
4912       if (row0>60&&ktrack1->GetReference().GetX()>90.)new (&paramd) AliExternalTrackParam(ktrack1->GetReference()); 
4913       //
4914       //
4915       kink->SetMother(paramm);
4916       kink->SetDaughter(paramd);
4917       kink->Update();
4918
4919       Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
4920       Int_t index[4];
4921       fParam->Transform0to1(x,index);
4922       fParam->Transform1to2(x,index);
4923       row0 = GetRowNumber(x[0]); 
4924
4925       if (kink->GetR()<100) continue;
4926       if (kink->GetR()>240) continue;
4927       if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue;  //out of fiducial volume
4928       if (kink->GetDistance()>cdist3) continue;
4929       Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1];  // rough direction estimate
4930       if (dird<0) continue;
4931
4932       Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1];  // rough direction estimate
4933       if (dirm<0) continue;
4934       Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
4935       if (mpt<0.2) continue;
4936
4937       if (mpt<1){
4938         //for high momenta momentum not defined well in first iteration
4939         Double_t qt   =  TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
4940         if (qt>0.35) continue; 
4941       }
4942       
4943       kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
4944       kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
4945       if (dens00>dens10){
4946         kink->SetTPCDensity(dens00,0,0);
4947         kink->SetTPCDensity(dens01,0,1);
4948         kink->SetTPCDensity(dens10,1,0);
4949         kink->SetTPCDensity(dens11,1,1);
4950         kink->SetIndex(i,0);
4951         kink->SetIndex(j,1);
4952       }
4953       else{
4954         kink->SetTPCDensity(dens10,0,0);
4955         kink->SetTPCDensity(dens11,0,1);
4956         kink->SetTPCDensity(dens00,1,0);
4957         kink->SetTPCDensity(dens01,1,1);
4958         kink->SetIndex(j,0);
4959         kink->SetIndex(i,1);
4960       }
4961
4962       if (mpt<1||kink->GetAngle(2)>0.1){
4963         //      angle and densities  not defined yet
4964         if (kink->GetTPCDensityFactor()<0.8) continue;
4965         if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
4966         if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
4967         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
4968         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
4969
4970         Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
4971         criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
4972         criticalangle= 3*TMath::Sqrt(criticalangle);
4973         if (criticalangle>0.02) criticalangle=0.02;
4974         if (kink->GetAngle(2)<criticalangle) continue;
4975       }
4976       //
4977       Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2)));  // overlap region defined
4978       Float_t shapesum =0;
4979       Float_t sum = 0;
4980       for ( Int_t row = row0-drow; row<row0+drow;row++){
4981         if (row<0) continue;
4982         if (row>155) continue;
4983         if (ktrack0->GetClusterPointer(row)){
4984           AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
4985           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
4986           sum++;
4987         }
4988         if (ktrack1->GetClusterPointer(row)){
4989           AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
4990           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
4991           sum++;
4992         }       
4993       }
4994       if (sum<4){
4995         kink->SetShapeFactor(-1.);
4996       }
4997       else{
4998         kink->SetShapeFactor(shapesum/sum);
4999       }      
5000       //      esd->AddKink(kink);
5001       kinks->AddLast(kink);
5002       kink = new AliKink;
5003       ncandidates++;
5004     }
5005   }
5006   //
5007   // sort the kinks according quality - and refit them towards vertex
5008   //
5009   Int_t       nkinks    = kinks->GetEntriesFast();
5010   Float_t    *quality   = new Float_t[nkinks];
5011   Int_t      *indexes   = new Int_t[nkinks];
5012   AliTPCseed *mothers   = new AliTPCseed[nkinks];
5013   AliTPCseed *daughters = new AliTPCseed[nkinks];
5014   //
5015   //
5016   for (Int_t i=0;i<nkinks;i++){
5017     quality[i] =100000;
5018     AliKink *kink = (AliKink*)kinks->At(i);
5019     //
5020     // refit kinks towards vertex
5021     // 
5022     Int_t index0 = kink->GetIndex(0);
5023     Int_t index1 = kink->GetIndex(1);
5024     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5025     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5026     //
5027     Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
5028     //
5029     // Refit Kink under if too small angle
5030     //
5031     if (kink->GetAngle(2)<0.05){
5032       kink->SetTPCRow0(GetRowNumber(kink->GetR()));
5033       Int_t row0 = kink->GetTPCRow0();
5034       Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2)));
5035       //
5036       //
5037       Int_t last  = row0-drow;
5038       if (last<40) last=40;
5039       if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
5040       AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
5041       //
5042       //
5043       Int_t first = row0+drow;
5044       if (first>130) first=130;
5045       if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
5046       AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
5047       //
5048       if (seed0 && seed1){
5049         kink->SetStatus(1,8);
5050         if (RefitKink(*seed0,*seed1,*kink)) kink->SetStatus(1,9);
5051         row0 = GetRowNumber(kink->GetR());
5052         sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
5053         mothers[i] = *seed0;
5054         daughters[i] = *seed1;
5055       }
5056       else{
5057         delete kinks->RemoveAt(i);
5058         if (seed0) delete seed0;
5059         if (seed1) delete seed1;
5060         continue;
5061       }
5062       if (kink->GetDistance()>0.5 || kink->GetR()<110 || kink->GetR()>240) {
5063         delete kinks->RemoveAt(i);
5064         if (seed0) delete seed0;
5065         if (seed1) delete seed1;
5066         continue;
5067       }
5068       //
5069       delete seed0;
5070       delete seed1;            
5071     }
5072     //
5073     if (kink) quality[i] = 160*((0.1+kink->GetDistance())*(2.-kink->GetTPCDensityFactor()))/(sumn+40.);  //the longest -clossest will win
5074   }
5075   TMath::Sort(nkinks,quality,indexes,kFALSE);
5076   //
5077   //remove double find kinks
5078   //
5079   for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
5080     AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5081     if (!kink0) continue;
5082     //
5083     for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
5084       if (!kink0) continue;
5085       AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
5086       if (!kink1) continue;
5087       // if not close kink continue
5088       if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
5089       if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
5090       if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
5091       //
5092       AliTPCseed &mother0   = mothers[indexes[ikink0]];
5093       AliTPCseed &daughter0 = daughters[indexes[ikink0]];
5094       AliTPCseed &mother1   = mothers[indexes[ikink1]];
5095       AliTPCseed &daughter1 = daughters[indexes[ikink1]];
5096       Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
5097       //
5098       Int_t same  = 0;
5099       Int_t both  = 0;
5100       Int_t samem = 0;
5101       Int_t bothm = 0;
5102       Int_t samed = 0;
5103       Int_t bothd = 0;
5104       //
5105       for (Int_t i=0;i<row0;i++){
5106         if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
5107           both++;
5108           bothm++;
5109           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5110             same++;
5111             samem++;
5112           }
5113         }
5114       }
5115
5116       for (Int_t i=row0;i<158;i++){
5117         if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){
5118           both++;
5119           bothd++;
5120           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5121             same++;
5122             samed++;
5123           }
5124         }
5125       }
5126       Float_t ratio = Float_t(same+1)/Float_t(both+1);
5127       Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
5128       Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
5129       if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
5130         Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
5131         Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
5132         if (sum1>sum0){
5133           shared[kink0->GetIndex(0)]= kTRUE;
5134           shared[kink0->GetIndex(1)]= kTRUE;      
5135           delete kinks->RemoveAt(indexes[ikink0]);
5136         }
5137         else{
5138           shared[kink1->GetIndex(0)]= kTRUE;
5139           shared[kink1->GetIndex(1)]= kTRUE;      
5140           delete kinks->RemoveAt(indexes[ikink1]);
5141         }
5142       }
5143     }
5144   }
5145
5146
5147   for (Int_t i=0;i<nkinks;i++){
5148     AliKink * kink = (AliKink*) kinks->At(indexes[i]);
5149     if (!kink) continue;
5150     kink->SetTPCRow0(GetRowNumber(kink->GetR()));
5151     Int_t index0 = kink->GetIndex(0);
5152     Int_t index1 = kink->GetIndex(1);
5153     if (circular[index0]||circular[index1]&&kink->GetDistance()>0.2) continue;
5154     kink->SetMultiple(usage[index0],0);
5155     kink->SetMultiple(usage[index1],1);
5156     if (kink->GetMultiple()[0]+kink->GetMultiple()[1]>2) continue;
5157     if (kink->GetMultiple()[0]+kink->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
5158     if (kink->GetMultiple()[0]+kink->GetMultiple()[1]>0 && kink->GetDistance()>0.2) continue;
5159     if (circular[index0]||circular[index1]&&kink->GetDistance()>0.1) continue;
5160
5161     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5162     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5163     if (!ktrack0 || !ktrack1) continue;
5164     Int_t index = esd->AddKink(kink);
5165     //
5166     //
5167     if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) {  //best kink
5168       if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
5169         *ktrack0 = mothers[indexes[i]];
5170         *ktrack1 = daughters[indexes[i]];
5171       }
5172     }
5173     //
5174     ktrack0->SetKinkIndex(usage[index0],-(index+1));
5175     ktrack1->SetKinkIndex(usage[index1], (index+1));
5176     usage[index0]++;
5177     usage[index1]++;
5178   }
5179   //
5180   // Remove tracks corresponding to shared kink's
5181   //
5182   for (Int_t i=0;i<nentries;i++){
5183     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5184     if (!track0) continue;
5185     if (track0->GetKinkIndex(0)!=0) continue;
5186     if (shared[i]) delete array->RemoveAt(i);
5187   }
5188
5189   //
5190   //
5191   RemoveUsed2(array,0.5,0.4,30);
5192   UnsignClusters();
5193   for (Int_t i=0;i<nentries;i++){
5194     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5195     if (!track0) continue;
5196     track0->CookdEdx(0.02,0.6);
5197     track0->CookPID();
5198   }
5199   //
5200   for (Int_t i=0;i<nentries;i++){
5201     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5202     if (!track0) continue;
5203     if (track0->Pt()<1.4) continue;
5204     //remove double high momenta tracks - overlapped with kink candidates
5205     Int_t shared=0;
5206     Int_t all   =0;
5207     for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
5208       if (track0->GetClusterPointer(icl)!=0){
5209         all++;
5210         if (track0->GetClusterPointer(icl)->IsUsed(10)) shared++;
5211       }
5212     }
5213     if (Float_t(shared+1)/Float_t(all+1)>0.5) {  
5214       delete array->RemoveAt(i);
5215       continue;
5216     }
5217     //
5218     if (track0->GetKinkIndex(0)!=0) continue;
5219     if (track0->GetNumberOfClusters()<80) continue;
5220
5221     AliTPCseed *pmother = new AliTPCseed();
5222     AliTPCseed *pdaughter = new AliTPCseed();
5223     AliKink *pkink = new AliKink;
5224
5225     AliTPCseed & mother = *pmother;
5226     AliTPCseed & daughter = *pdaughter;
5227     AliKink & kink = *pkink;
5228     if (CheckKinkPoint(track0,mother,daughter, kink)){
5229       if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
5230         delete pmother;
5231         delete pdaughter;
5232         delete pkink;
5233         continue;  //too short tracks
5234       }
5235       if (mother.Pt()<1.4) {
5236         delete pmother;
5237         delete pdaughter;
5238         delete pkink;
5239         continue;
5240       }
5241       Int_t row0= kink.GetTPCRow0();
5242       if (kink.GetDistance()>0.5 || kink.GetR()<110. || kink.GetR()>240.) {
5243         delete pmother;
5244         delete pdaughter;
5245         delete pkink;
5246         continue;
5247       }
5248       //
5249       Int_t index = esd->AddKink(&kink);      
5250       mother.SetKinkIndex(0,-(index+1));
5251       daughter.SetKinkIndex(0,index+1);
5252       if (mother.GetNumberOfClusters()>50) {
5253         delete array->RemoveAt(i);
5254         array->AddAt(new AliTPCseed(mother),i);
5255       }
5256       else{
5257         array->AddLast(new AliTPCseed(mother));
5258       }
5259       array->AddLast(new AliTPCseed(daughter));      
5260       for (Int_t icl=0;icl<row0;icl++) {
5261         if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
5262       }
5263       //
5264       for (Int_t icl=row0;icl<158;icl++) {
5265         if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
5266       }
5267       //
5268     }
5269     delete pmother;
5270     delete pdaughter;
5271     delete pkink;
5272   }
5273
5274   delete [] daughters;
5275   delete [] mothers;
5276   //
5277   //
5278   delete [] dca;
5279   delete []circular;
5280   delete []shared;
5281   delete []quality;
5282   delete []indexes;
5283   //
5284   delete kink;
5285   delete[]fim;
5286   delete[] zm;
5287   delete[] z0;
5288   delete [] usage;
5289   delete[] alpha;
5290   delete[] nclusters;
5291   delete[] sign;
5292   delete[] helixes;
5293   kinks->Delete();
5294   delete kinks;
5295
5296   printf("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall);
5297   timer.Print();
5298 }
5299
5300 void  AliTPCtrackerMI::FindV0s(TObjArray * array, AliESDEvent *esd)
5301 {
5302   //
5303   //  find V0s
5304   //
5305   //
5306   TObjArray *tpcv0s      = new TObjArray(100000);
5307   Int_t     nentries     = array->GetEntriesFast();
5308   AliHelix *helixes      = new AliHelix[nentries];
5309   Int_t    *sign         = new Int_t[nentries];
5310   Float_t  *alpha        = new Float_t[nentries];
5311   Float_t  *z0           = new Float_t[nentries]; 
5312   Float_t  *dca          = new Float_t[nentries];
5313   Float_t  *sdcar        = new Float_t[nentries];
5314   Float_t  *cdcar        = new Float_t[nentries];
5315   Float_t  *pulldcar     = new Float_t[nentries];
5316   Float_t  *pulldcaz     = new Float_t[nentries];
5317   Float_t  *pulldca      = new Float_t[nentries];
5318   Bool_t   *isPrim       = new Bool_t[nentries];  
5319   const AliESDVertex * primvertex = esd->GetVertex();
5320   Double_t             zvertex = primvertex->GetZv(); 
5321   //
5322   //  nentries = array->GetEntriesFast();
5323   //
5324   for (Int_t i=0;i<nentries;i++){
5325     sign[i]=0;
5326     isPrim[i]=0;
5327     AliTPCseed* track = (AliTPCseed*)array->At(i);    
5328     if (!track) continue;
5329     track->GetV0Indexes()[0] = 0;  //rest v0 indexes
5330     track->GetV0Indexes()[1] = 0;  //rest v0 indexes
5331     track->GetV0Indexes()[2] = 0;  //rest v0 indexes
5332     //
5333     alpha[i] = track->GetAlpha();
5334     new (&helixes[i]) AliHelix(*track);
5335     Double_t xyz[3];
5336     helixes[i].Evaluate(0,xyz);
5337     sign[i] = (track->GetC()>0) ? -1:1;
5338     Double_t x,y,z;
5339     x=160;
5340     z0[i]=1000;
5341     if (track->GetProlongation(0,y,z))  z0[i] = z;
5342     dca[i] = track->GetD(0,0);
5343     // 
5344     // dca error parrameterezation + pulls
5345     //
5346     sdcar[i]      = TMath::Sqrt(0.150*0.150+(100*track->GetC())*(100*track->GetC()));
5347     if (TMath::Abs(track->GetTgl())>1) sdcar[i]*=2.5;
5348     cdcar[i]      = TMath::Exp((TMath::Abs(track->GetC())-0.0106)*525.3);
5349     pulldcar[i]   = (dca[i]-cdcar[i])/sdcar[i];
5350     pulldcaz[i]   = (z0[i]-zvertex)/sdcar[i];
5351     pulldca[i]    = TMath::Sqrt(pulldcar[i]*pulldcar[i]+pulldcaz[i]*pulldcaz[i]);
5352     if (track->TPCrPID(1)+track->TPCrPID(2)+track->TPCrPID(3)>0.5) {
5353       if (pulldca[i]<3.) isPrim[i]=kTRUE;  //pion, muon and Kaon  3 sigma cut
5354     }
5355     if (track->TPCrPID(4)>0.5) {
5356       if (pulldca[i]<0.5) isPrim[i]=kTRUE;  //proton 0.5 sigma cut
5357     }
5358     if (track->TPCrPID(0)>0.4) {
5359       isPrim[i]=kFALSE;  //electron no  sigma cut
5360     }
5361   }
5362   //
5363   //
5364   TStopwatch timer;
5365   timer.Start();
5366   Int_t ncandidates =0;
5367   Int_t nall =0;
5368   Int_t ntracks=0; 
5369   Double_t phase[2][2],radius[2];
5370   //
5371   //  Finf V0s loop
5372   // 
5373   //
5374   // //  
5375   TTreeSRedirector &cstream = *fDebugStreamer; 
5376   Float_t fprimvertex[3]={GetX(),GetY(),GetZ()};
5377   AliV0 vertex; 
5378   Double_t cradius0 = 10*10;
5379   Double_t cradius1 = 200*200;
5380   Double_t cdist1=3.;
5381   Double_t cdist2=4.;
5382   Double_t cpointAngle = 0.95;
5383   //
5384   Double_t delta[2]={10000,10000};
5385   for (Int_t i =0;i<nentries;i++){
5386     if (sign[i]==0) continue;
5387     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5388     if (!track0) continue;
5389     if (AliTPCReconstructor::StreamLevel()>1){
5390       cstream<<"Tracks"<<
5391         "Tr0.="<<track0<<
5392         "dca="<<dca[i]<<
5393         "z0="<<z0[i]<<
5394         "zvertex="<<zvertex<<
5395         "sdcar0="<<sdcar[i]<<
5396         "cdcar0="<<cdcar[i]<<
5397         "pulldcar0="<<pulldcar[i]<<
5398         "pulldcaz0="<<pulldcaz[i]<<
5399         "pulldca0="<<pulldca[i]<<
5400         "isPrim="<<isPrim[i]<<
5401         "\n";
5402     }
5403     //
5404     if (track0->GetSigned1Pt()<0) continue;
5405     if (track0->GetKinkIndex(0)>0||isPrim[i]) continue;   //daughter kink
5406     //
5407     if (TMath::Abs(helixes[i].GetHelix(4))<0.000000001) continue;
5408     ntracks++;
5409     // debug output
5410     
5411     
5412     for (Int_t j =0;j<nentries;j++){
5413       AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5414       if (!track1) continue;
5415       if (track1->GetKinkIndex(0)>0 || isPrim[j]) continue; //daughter kink
5416       if (sign[j]*sign[i]>0) continue; 
5417       if (TMath::Abs(helixes[j].GetHelix(4))<0.000001) continue;
5418       if (track0->GetCircular()+track1->GetCircular()>1) continue;    //circling -returning track
5419       nall++;
5420       //
5421       // DCA to prim vertex cut
5422       //
5423       //
5424       delta[0]=10000;
5425       delta[1]=10000;
5426
5427       Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,cdist2);
5428       if (npoints<1) continue;
5429       Int_t iclosest=0;
5430       // cuts on radius      
5431       if (npoints==1){
5432         if (radius[0]<cradius0||radius[0]>cradius1) continue;
5433         helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta[0]);
5434         if (delta[0]>cdist1) continue;
5435       }
5436       else{
5437         if (TMath::Max(radius[0],radius[1])<cradius0|| TMath::Min(radius[0],radius[1])>cradius1) continue;      
5438         helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta[0]);    
5439         helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta[1]);
5440         if (delta[1]<delta[0]) iclosest=1;
5441         if (delta[iclosest]>cdist1) continue;
5442       }
5443       helixes[i].ParabolicDCA(helixes[j],phase[iclosest][0],phase[iclosest][1],radius[iclosest],delta[iclosest]);
5444       if (radius[iclosest]<cradius0 || radius[iclosest]>cradius1 || delta[iclosest]>cdist1) continue;
5445       //
5446       Double_t pointAngle = helixes[i].GetPointAngle(helixes[j],phase[iclosest],fprimvertex);
5447       if (pointAngle<cpointAngle) continue;
5448       //
5449       Bool_t isGamma = kFALSE;
5450       vertex.SetParamP(*track0); //track0 - plus
5451       vertex.SetParamN(*track1); //track1 - minus
5452       vertex.Update(fprimvertex);
5453       if (track0->TPCrPID(0)>0.3&&track1->TPCrPID(0)>0.3&&vertex.GetAnglep()[2]<0.15) isGamma=kTRUE;              // gamma conversion candidate
5454       Double_t pointAngle2 = vertex.GetV0CosineOfPointingAngle();
5455       //continue;
5456       if (vertex.GetV0CosineOfPointingAngle()<cpointAngle && (!isGamma)) continue;// point angle cut
5457       //Bo:      if (vertex.GetDist2()>2&&(!isGamma)) continue;      // point angle cut
5458       if (vertex.GetDcaV0Daughters()>2&&(!isGamma)) continue;//Bo:   // point angle cut
5459       Float_t sigmae     = 0.15*0.15;
5460       if (vertex.GetRr()<80) 
5461         sigmae += (sdcar[i]*sdcar[i]+sdcar[j]*sdcar[j])*(1.-vertex.GetRr()/80.)*(1.-vertex.GetRr()/80.);
5462       sigmae+= TMath::Sqrt(sigmae);
5463       //Bo:      if (vertex.GetDist2()/sigmae>3.&&(!isGamma)) continue; 
5464       if (vertex.GetDcaV0Daughters()/sigmae>3.&&(!isGamma)) continue; 
5465       Float_t densb0=0,densb1=0,densa0=0,densa1=0;
5466       Int_t row0 = GetRowNumber(vertex.GetRr());
5467       if (row0>15){
5468         //Bo:   if (vertex.GetDist2()>0.2) continue;             
5469         if (vertex.GetDcaV0Daughters()>0.2) continue;             
5470         densb0     = track0->Density2(0,row0-5);          
5471         densb1     = track1->Density2(0,row0-5);         
5472         if (densb0>0.3|| densb1>0.3) continue;            //clusters before vertex
5473         densa0     = track0->Density2(row0+5,row0+40);    
5474         densa1     = track1->Density2(row0+5,row0+40);    
5475         if ((densa0<0.4|| densa1<0.4)&&(!isGamma)) continue;            //missing clusters after vertex
5476       }
5477       else{
5478         densa0     = track0->Density2(0,40);  //cluster density
5479         densa1     = track1->Density2(0,40);  //cluster density
5480         if ((vertex.GetRr()<80&&densa0+densa1<1.)&&(!isGamma)) continue;
5481       }
5482 //Bo:        vertex.SetLab(0,track0->GetLabel());
5483 //Bo:        vertex.SetLab(1,track1->GetLabel());
5484       vertex.SetChi2After((densa0+densa1)*0.5);
5485       vertex.SetChi2Before((densb0+densb1)*0.5);
5486       vertex.SetIndex(0,i);
5487       vertex.SetIndex(1,j);
5488 //Bo:      vertex.SetStatus(1); // TPC v0 candidate
5489       vertex.SetOnFlyStatus(2);//Bo: // TPC v0 candidate
5490 //Bo:        vertex.SetRp(track0->TPCrPIDs());
5491 //Bo:        vertex.SetRm(track1->TPCrPIDs());
5492       tpcv0s->AddLast(new AliESDv0(vertex));      
5493       ncandidates++;
5494       {
5495         Int_t eventNr = esd->GetEventNumberInFile(); // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
5496         Double_t radiusm= (delta[0]<delta[1])? TMath::Sqrt(radius[0]):TMath::Sqrt(radius[1]);  
5497         Double_t deltam= (delta[0]<delta[1])? TMath::Sqrt(delta[0]):TMath::Sqrt(delta[1]);  
5498         if (AliTPCReconstructor::StreamLevel()>1) {
5499           Int_t lab0=track0->GetLabel();
5500           Int_t lab1=track1->GetLabel();
5501           Char_t c0=track0->GetCircular();
5502           Char_t c1=track1->GetCircular();
5503           cstream<<"V0"<<
5504           "Event="<<eventNr<<
5505           "vertex.="<<&vertex<<
5506           "Tr0.="<<track0<<
5507           "lab0="<<lab0<<
5508           "Helix0.="<<&helixes[i]<<     
5509           "Tr1.="<<track1<<
5510           "lab1="<<lab1<<
5511           "Helix1.="<<&helixes[j]<<
5512           "pointAngle="<<pointAngle<<
5513           "pointAngle2="<<pointAngle2<<
5514           "dca0="<<dca[i]<<
5515           "dca1="<<dca[j]<<
5516           "z0="<<z0[i]<<
5517           "z1="<<z0[j]<<
5518           "zvertex="<<zvertex<<
5519           "circular0="<<c0<<
5520           "circular1="<<c1<<
5521           "npoints="<<npoints<<
5522           "radius0="<<radius[0]<<
5523           "delta0="<<delta[0]<<
5524           "radius1="<<radius[1]<<
5525           "delta1="<<delta[1]<<
5526           "radiusm="<<radiusm<<
5527           "deltam="<<deltam<<
5528           "sdcar0="<<sdcar[i]<<
5529           "sdcar1="<<sdcar[j]<<
5530           "cdcar0="<<cdcar[i]<<
5531           "cdcar1="<<cdcar[j]<<
5532           "pulldcar0="<<pulldcar[i]<<
5533           "pulldcar1="<<pulldcar[j]<<
5534           "pulldcaz0="<<pulldcaz[i]<<
5535           "pulldcaz1="<<pulldcaz[j]<<
5536           "pulldca0="<<pulldca[i]<<
5537           "pulldca1="<<pulldca[j]<<
5538           "densb0="<<densb0<<
5539           "densb1="<<densb1<<
5540           "densa0="<<densa0<<
5541           "densa1="<<densa1<<
5542           "sigmae="<<sigmae<<
5543             "\n";}
5544       }
5545     }
5546   }    
5547   Float_t *quality = new Float_t[ncandidates];
5548   Int_t *indexes = new Int_t[ncandidates];
5549   Int_t naccepted =0;
5550   for (Int_t i=0;i<ncandidates;i++){
5551     quality[i]     = 0; 
5552     AliESDv0 *v0 = (AliESDv0*)tpcv0s->At(i);
5553     quality[i]     = 1./(1.00001-v0->GetV0CosineOfPointingAngle());   //base point angle
5554     // quality[i]    /= (0.5+v0->GetDist2());  
5555     // quality[i]    *= v0->GetChi2After();               //density factor
5556
5557     Int_t index0 = v0->GetIndex(0);
5558     Int_t index1 = v0->GetIndex(1);
5559     //Bo:    Double_t minpulldca = TMath::Min(2.+pulldca[v0->GetIndex(0)],(2.+pulldca[v0->GetIndex(1)]) );     //pull
5560     Double_t minpulldca = TMath::Min(2.+pulldca[index0],(2.+pulldca[index1]) );//Bo:
5561
5562
5563
5564     AliTPCseed * track0 = (AliTPCseed*)array->At(index0);
5565     AliTPCseed * track1 = (AliTPCseed*)array->At(index1);
5566     if (track0->TPCrPID(0)>0.3&&track1->TPCrPID(0)>0.3&&v0->GetAnglep()[2]<0.15) quality[i]+=1000000;              // gamma conversion candidate
5567     if (track0->TPCrPID(4)>0.9||track1->TPCrPID(4)>0.9&&minpulldca>4) quality[i]*=10;    // lambda candidate candidate
5568   }
5569
5570   TMath::Sort(ncandidates,quality,indexes,kTRUE);
5571   //
5572   //
5573   for (Int_t i=0;i<ncandidates;i++){
5574     AliESDv0 * v0 = (AliESDv0*)tpcv0s->At(indexes[i]);
5575     if (!v0) continue;
5576     Int_t index0 = v0->GetIndex(0);
5577     Int_t index1 = v0->GetIndex(1);
5578     AliTPCseed * track0 = (AliTPCseed*)array->At(index0);
5579     AliTPCseed * track1 = (AliTPCseed*)array->At(index1);
5580     if (!track0||!track1) {
5581       printf("Bug\n");
5582       continue;
5583     }
5584     Bool_t accept =kTRUE;  //default accept
5585     Int_t *v0indexes0 = track0->GetV0Indexes();
5586     Int_t *v0indexes1 = track1->GetV0Indexes();
5587     //
5588     Int_t order0 = (v0indexes0[0]!=0) ? 1:0;
5589     Int_t order1 = (v0indexes1[0]!=0) ? 1:0;    
5590     if (v0indexes0[1]!=0) order0 =2;
5591     if (v0indexes1[1]!=0) order1 =2;      
5592     //
5593     if (v0indexes0[2]!=0) {order0=3; accept=kFALSE;}
5594     if (v0indexes0[2]!=0) {order1=3; accept=kFALSE;}
5595     //
5596     AliESDv0 * v02 = v0;
5597     if (accept){
5598       //Bo:      v0->SetOrder(0,order0);
5599       //Bo:      v0->SetOrder(1,order1);
5600       //Bo:      v0->SetOrder(1,order0+order1);     
5601       v0->SetOnFlyStatus(kTRUE);
5602       Int_t index = esd->AddV0(v0);
5603       v02 = esd->GetV0(index);
5604       v0indexes0[order0]=index;
5605       v0indexes1[order1]=index;
5606       naccepted++;
5607     }
5608     {
5609       Int_t eventNr = esd->GetEventNumberInFile(); // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
5610       if (AliTPCReconstructor::StreamLevel()>1) {
5611         Int_t lab0=track0->GetLabel();
5612         Int_t lab1=track1->GetLabel();
5613         cstream<<"V02"<<
5614         "Event="<<eventNr<<
5615         "vertex.="<<v0<<        
5616         "vertex2.="<<v02<<
5617         "Tr0.="<<track0<<
5618         "lab0="<<lab0<<
5619         "Tr1.="<<track1<<
5620         "lab1="<<lab1<<
5621         "dca0="<<dca[index0]<<
5622         "dca1="<<dca[index1]<<
5623         "order0="<<order0<<
5624         "order1="<<order1<<
5625         "accept="<<accept<<
5626         "quality="<<quality[i]<<
5627         "pulldca0="<<pulldca[index0]<<
5628         "pulldca1="<<pulldca[index1]<<
5629         "index="<<i<<
5630           "\n";}
5631     }
5632   }    
5633
5634
5635   //
5636   //
5637   delete []quality;
5638   delete []indexes;
5639 //
5640   delete [] isPrim;
5641   delete [] pulldca;
5642   delete [] pulldcaz;
5643   delete [] pulldcar;
5644   delete [] cdcar;
5645   delete [] sdcar;
5646   delete [] dca;
5647   //
5648   delete[] z0;
5649   delete[] alpha;
5650   delete[] sign;
5651   delete[] helixes;
5652   printf("TPC V0 finder : naccepted\t%d\tncandidates\t%d\tntracks\t%d\tnall\t%d\n",naccepted,ncandidates,ntracks,nall);
5653   timer.Print();
5654 }
5655
5656 Int_t AliTPCtrackerMI::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, AliESDkink &knk)
5657 {
5658   //
5659   // refit kink towards to the vertex
5660   //
5661   //
5662   AliKink &kink=(AliKink &)knk;
5663
5664   Int_t row0 = GetRowNumber(kink.GetR());
5665   FollowProlongation(mother,0);
5666   mother.Reset(kFALSE);
5667   //
5668   FollowProlongation(daughter,row0);
5669   daughter.Reset(kFALSE);
5670   FollowBackProlongation(daughter,158);
5671   daughter.Reset(kFALSE);
5672   Int_t first = TMath::Max(row0-20,30); 
5673   Int_t last  = TMath::Min(row0+20,140);
5674   //
5675   const Int_t kNdiv =5;
5676   AliTPCseed  param0[kNdiv];  // parameters along the track
5677   AliTPCseed  param1[kNdiv];  // parameters along the track
5678   AliKink     kinks[kNdiv];   // corresponding kink parameters
5679   //
5680   Int_t rows[kNdiv];
5681   for (Int_t irow=0; irow<kNdiv;irow++){
5682     rows[irow] = first +((last-first)*irow)/(kNdiv-1);
5683   }
5684   // store parameters along the track
5685   //
5686   for (Int_t irow=0;irow<kNdiv;irow++){
5687     FollowBackProlongation(mother, rows[irow]);
5688     FollowProlongation(daughter,rows[kNdiv-1-irow]);       
5689     param0[irow] = mother;
5690     param1[kNdiv-1-irow] = daughter;
5691   }
5692   //
5693   // define kinks 
5694   for (Int_t irow=0; irow<kNdiv-1;irow++){
5695     if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
5696     kinks[irow].SetMother(param0[irow]);
5697     kinks[irow].SetDaughter(param1[irow]);
5698     kinks[irow].Update();
5699   }
5700   //
5701   // choose kink with best "quality"
5702   Int_t index =-1;
5703   Double_t mindist = 10000;
5704   for (Int_t irow=0;irow<kNdiv;irow++){
5705     if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
5706     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
5707     if (TMath::Abs(kinks[irow].GetR())<100.) continue;
5708     //
5709     Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
5710     normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
5711     if (normdist < mindist){
5712       mindist = normdist;
5713       index = irow;
5714     }
5715   }
5716   //
5717   if (index==-1) return 0;
5718   //
5719   //
5720   param0[index].Reset(kTRUE);
5721   FollowProlongation(param0[index],0);
5722   //
5723   mother = param0[index];
5724   daughter = param1[index];  // daughter in vertex
5725   //
5726   kink.SetMother(mother);
5727   kink.SetDaughter(daughter);
5728   kink.Update();
5729   kink.SetTPCRow0(GetRowNumber(kink.GetR()));
5730   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
5731   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
5732   kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
5733   kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
5734   mother.SetLabel(kink.GetLabel(0));
5735   daughter.SetLabel(kink.GetLabel(1));
5736
5737   return 1;
5738 }
5739
5740
5741 void AliTPCtrackerMI::UpdateKinkQualityM(AliTPCseed * seed){
5742   //
5743   // update Kink quality information for mother after back propagation
5744   //
5745   if (seed->GetKinkIndex(0)>=0) return; 
5746   for (Int_t ikink=0;ikink<3;ikink++){
5747     Int_t index = seed->GetKinkIndex(ikink);
5748     if (index>=0) break;
5749     index = TMath::Abs(index)-1;
5750     AliESDkink * kink = fEvent->GetKink(index);
5751     kink->SetTPCDensity(-1,0,0);
5752     kink->SetTPCDensity(1,0,1);
5753     //
5754     Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5755     if (row0<15) row0=15;
5756     //
5757     Int_t row1 = kink->GetTPCRow0() + 2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5758     if (row1>145) row1=145;
5759     //
5760     Int_t found,foundable,shared;
5761     seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
5762     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
5763     seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
5764     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
5765   }
5766     
5767 }
5768
5769 void AliTPCtrackerMI::UpdateKinkQualityD(AliTPCseed * seed){
5770   //
5771   // update Kink quality information for daughter after refit
5772   //
5773   if (seed->GetKinkIndex(0)<=0) return; 
5774   for (Int_t ikink=0;ikink<3;ikink++){
5775     Int_t index = seed->GetKinkIndex(ikink);
5776     if (index<=0) break;
5777     index = TMath::Abs(index)-1;
5778     AliESDkink * kink = fEvent->GetKink(index);
5779     kink->SetTPCDensity(-1,1,0);
5780     kink->SetTPCDensity(-1,1,1);
5781     //
5782     Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5783     if (row0<15) row0=15;
5784     //
5785     Int_t row1 = kink->GetTPCRow0() +2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
5786     if (row1>145) row1=145;
5787     //
5788     Int_t found,foundable,shared;
5789     seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
5790     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
5791     seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
5792     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
5793   }
5794     
5795 }
5796
5797
5798 Int_t  AliTPCtrackerMI::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, AliESDkink &knk)
5799 {
5800   //
5801   // check kink point for given track
5802   // if return value=0 kink point not found
5803   // otherwise seed0 correspond to mother particle
5804   //           seed1 correspond to daughter particle
5805   //           kink  parameter of kink point
5806   AliKink &kink=(AliKink &)knk;
5807
5808   Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
5809   Int_t first = seed->GetFirstPoint(); 
5810   Int_t last  = seed->GetLastPoint();
5811   if (last-first<20) return 0;          // shortest length - 2*30 = 60 pad-rows
5812
5813   
5814   AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE);  //middle of chamber
5815   if (!seed1) return 0;
5816   FollowProlongation(*seed1,seed->GetLastPoint()-20);
5817   seed1->Reset(kTRUE);
5818   FollowProlongation(*seed1,158);
5819   seed1->Reset(kTRUE);  
5820   last = seed1->GetLastPoint();
5821   //
5822   AliTPCseed *seed0 = new AliTPCseed(*seed);
5823   seed0->Reset(kFALSE);
5824   seed0->Reset();
5825   //
5826   AliTPCseed  param0[20];  // parameters along the track
5827   AliTPCseed  param1[20];  // parameters along the track
5828   AliKink     kinks[20];   // corresponding kink parameters
5829   Int_t rows[20];
5830   for (Int_t irow=0; irow<20;irow++){
5831     rows[irow] = first +((last-first)*irow)/19;
5832   }
5833   // store parameters along the track
5834   //
5835   for (Int_t irow=0;irow<20;irow++){
5836     FollowBackProlongation(*seed0, rows[irow]);
5837     FollowProlongation(*seed1,rows[19-irow]);       
5838     param0[irow] = *seed0;
5839     param1[19-irow] = *seed1;
5840   }
5841   //
5842   // define kinks 
5843   for (Int_t irow=0; irow<19;irow++){
5844     kinks[irow].SetMother(param0[irow]);
5845     kinks[irow].SetDaughter(param1[irow]);
5846     kinks[irow].Update();
5847   }
5848   //
5849   // choose kink with biggest change of angle
5850   Int_t index =-1;
5851   Double_t maxchange= 0;
5852   for (Int_t irow=1;irow<19;irow++){
5853     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
5854     if (TMath::Abs(kinks[irow].GetR())<110.) continue;
5855     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
5856     if ( quality > maxchange){
5857       maxchange = quality;
5858       index = irow;
5859       //
5860     }
5861   }
5862   delete seed0;
5863   delete seed1;
5864   if (index<0) return 0;
5865   //
5866   Int_t row0    = GetRowNumber(kinks[index].GetR());   //row 0 estimate
5867   seed0 = new AliTPCseed(param0[index]);
5868   seed1 = new AliTPCseed(param1[index]);
5869   seed0->Reset(kFALSE);
5870   seed1->Reset(kFALSE);
5871   seed0->ResetCovariance(10.);
5872   seed1->ResetCovariance(10.);
5873   FollowProlongation(*seed0,0);
5874   FollowBackProlongation(*seed1,158);
5875   mother = *seed0; // backup mother at position 0
5876   seed0->Reset(kFALSE);  
5877   seed1->Reset(kFALSE);
5878   seed0->ResetCovariance(10.);
5879   seed1->ResetCovariance(10.);
5880   //
5881   first = TMath::Max(row0-20,0);
5882   last  = TMath::Min(row0+20,158);
5883   //
5884   for (Int_t irow=0; irow<20;irow++){
5885     rows[irow] = first +((last-first)*irow)/19;
5886   }
5887   // store parameters along the track
5888   //
5889   for (Int_t irow=0;irow<20;irow++){
5890     FollowBackProlongation(*seed0, rows[irow]);
5891     FollowProlongation(*seed1,rows[19-irow]);       
5892     param0[irow] = *seed0;
5893     param1[19-irow] = *seed1;
5894   }
5895   //
5896   // define kinks 
5897   for (Int_t irow=0; irow<19;irow++){
5898     kinks[irow].SetMother(param0[irow]);
5899     kinks[irow].SetDaughter(param1[irow]);
5900     //    param0[irow].Dump();
5901     //param1[irow].Dump();
5902     kinks[irow].Update();
5903   }
5904   //
5905   // choose kink with biggest change of angle
5906   index =-1;
5907   maxchange= 0;
5908   for (Int_t irow=0;irow<20;irow++){
5909     if (TMath::Abs(kinks[irow].GetR())>250.) continue;
5910     if (TMath::Abs(kinks[irow].GetR())<90.) continue;
5911     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
5912     if ( quality > maxchange){
5913       maxchange = quality;
5914       index = irow;
5915       //
5916     }
5917   }
5918   //
5919   //
5920   if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
5921     delete seed0;
5922     delete seed1;
5923     return 0;
5924   }
5925   //  Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
5926   
5927   kink.SetMother(param0[index]);
5928   kink.SetDaughter(param1[index]);
5929   kink.Update();
5930   row0    = GetRowNumber(kink.GetR());   
5931   kink.SetTPCRow0(row0);
5932   kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
5933   kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
5934   kink.SetIndex(-10,0);
5935   kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
5936   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
5937   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
5938   //
5939   //
5940   //  new (&mother) AliTPCseed(param0[index]);
5941   daughter = param1[index];
5942   daughter.SetLabel(kink.GetLabel(1));  
5943   param0[index].Reset(kTRUE);
5944   FollowProlongation(param0[index],0);  
5945   mother = param0[index];
5946   mother.SetLabel(kink.GetLabel(0));
5947   delete seed0;
5948   delete seed1;
5949   //
5950   return 1;
5951 }
5952
5953
5954
5955
5956 AliTPCseed*  AliTPCtrackerMI::ReSeed(AliTPCseed *t)
5957 {
5958   //
5959   // reseed - refit -  track
5960   //
5961   Int_t first = 0;
5962   //  Int_t last  = fSectors->GetNRows()-1;
5963   //
5964   if (fSectors == fOuterSec){
5965     first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
5966     //last  = 
5967   }
5968   else
5969     first = t->GetFirstPoint();
5970   //
5971   AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
5972   FollowBackProlongation(*t,fSectors->GetNRows()-1);
5973   t->Reset(kFALSE);
5974   FollowProlongation(*t,first);
5975   return seed;
5976 }
5977
5978
5979
5980
5981
5982
5983
5984 //_____________________________________________________________________________
5985 Int_t AliTPCtrackerMI::ReadSeeds(const TFile *inp) {
5986   //-----------------------------------------------------------------
5987   // This function reades track seeds.
5988   //-----------------------------------------------------------------
5989   TDirectory *savedir=gDirectory; 
5990
5991   TFile *in=(TFile*)inp;
5992   if (!in->IsOpen()) {
5993      cerr<<"AliTPCtrackerMI::ReadSeeds(): input file is not open !\n";
5994      return 1;
5995   }
5996
5997   in->cd();
5998   TTree *seedTree=(TTree*)in->Get("Seeds");
5999   if (!seedTree) {
6000      cerr<<"AliTPCtrackerMI::ReadSeeds(): ";
6001      cerr<<"can't get a tree with track seeds !\n";
6002      return 2;
6003   }
6004   AliTPCtrack *seed=new AliTPCtrack; 
6005   seedTree->SetBranchAddress("tracks",&seed);
6006   
6007   if (fSeeds==0) fSeeds=new TObjArray(15000);
6008
6009   Int_t n=(Int_t)seedTree->GetEntries();
6010   for (Int_t i=0; i<n; i++) {
6011      seedTree->GetEvent(i);
6012      fSeeds->AddLast(new AliTPCseed(*seed/*,seed->GetAlpha()*/));
6013   }
6014   
6015   delete seed;
6016   delete seedTree; 
6017   savedir->cd();
6018   return 0;
6019 }
6020
6021 Int_t AliTPCtrackerMI::Clusters2Tracks (AliESDEvent *esd)
6022 {
6023   //
6024   if (fSeeds) DeleteSeeds();
6025   fEvent = esd;
6026   Clusters2Tracks();
6027   if (!fSeeds) return 1;
6028   FillESD(fSeeds);
6029   return 0;
6030   //
6031 }
6032
6033
6034 //_____________________________________________________________________________
6035 Int_t AliTPCtrackerMI::Clusters2Tracks() {
6036   //-----------------------------------------------------------------
6037   // This is a track finder.
6038   //-----------------------------------------------------------------
6039   TDirectory *savedir=gDirectory; 
6040   TStopwatch timer;
6041
6042   fIteration = 0;
6043   fSeeds = Tracking();
6044
6045   if (fDebug>0){
6046     Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
6047   }
6048   //activate again some tracks
6049   for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
6050     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
6051     if (!pt) continue;    
6052     Int_t nc=t.GetNumberOfClusters();
6053     if (nc<20) {
6054       delete fSeeds->RemoveAt(i);
6055       continue;
6056     } 
6057     CookLabel(pt,0.1); 
6058     if (pt->GetRemoval()==10) {
6059       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
6060         pt->Desactivate(10);  // make track again active
6061       else{
6062         pt->Desactivate(20);    
6063         delete fSeeds->RemoveAt(i);
6064       }
6065     } 
6066   }
6067   //
6068   RemoveUsed2(fSeeds,0.85,0.85,0);
6069   if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
6070   //FindCurling(fSeeds, fEvent,0);  
6071   if (AliTPCReconstructor::StreamLevel()>2)  FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
6072   RemoveUsed2(fSeeds,0.5,0.4,20);
6073   FindSplitted(fSeeds, fEvent,0); // find multi found tracks
6074
6075  //  //
6076 //   // refit short tracks
6077 //   //
6078   Int_t nseed=fSeeds->GetEntriesFast();
6079   //
6080   Int_t found = 0;
6081   for (Int_t i=0; i<nseed; i++) {
6082     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
6083     if (!pt) continue;    
6084     Int_t nc=t.GetNumberOfClusters();
6085     if (nc<15) {
6086       delete fSeeds->RemoveAt(i);
6087       continue;
6088     }
6089     CookLabel(pt,0.1); //For comparison only
6090     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
6091     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
6092       found++;      
6093       if (fDebug>0) cerr<<found<<'\r';      
6094       pt->SetLab2(i);
6095     }
6096     else
6097       delete fSeeds->RemoveAt(i);
6098   }
6099
6100   
6101   //RemoveOverlap(fSeeds,0.99,7,kTRUE);  
6102   SignShared(fSeeds);  
6103   //RemoveUsed(fSeeds,0.9,0.9,6);
6104   // 
6105   nseed=fSeeds->GetEntriesFast();
6106   found = 0;
6107   for (Int_t i=0; i<nseed; i++) {
6108     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
6109     if (!pt) continue;    
6110     Int_t nc=t.GetNumberOfClusters();
6111     if (nc<15) {
6112       delete fSeeds->RemoveAt(i);
6113       continue;
6114     }
6115     t.SetUniqueID(i);
6116     t.CookdEdx(0.02,0.6);
6117     //    CheckKinkPoint(&t,0.05);
6118     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
6119     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
6120       found++;
6121       if (fDebug>0){
6122         cerr<<found<<'\r';      
6123       }
6124       pt->SetLab2(i);
6125     }
6126     else
6127       delete fSeeds->RemoveAt(i);
6128     //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
6129     //if (seed1){
6130     //  FollowProlongation(*seed1,0);
6131     //  Int_t n = seed1->GetNumberOfClusters();
6132     //  printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
6133     //  printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
6134     //
6135     //}
6136     //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
6137     
6138   }
6139
6140   SortTracks(fSeeds, 1);
6141   
6142   /*    
6143   fIteration = 1;
6144   PrepareForBackProlongation(fSeeds,5.);
6145   PropagateBack(fSeeds);
6146   printf("Time for back propagation: \t");timer.Print();timer.Start();
6147   
6148   fIteration = 2;
6149   
6150   PrepareForProlongation(fSeeds,5.);
6151   PropagateForward2(fSeeds);
6152    
6153   printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
6154   // RemoveUsed(fSeeds,0.7,0.7,6);
6155   //RemoveOverlap(fSeeds,0.9,7,kTRUE);
6156    
6157   nseed=fSeeds->GetEntriesFast();
6158   found = 0;
6159   for (Int_t i=0; i<nseed; i++) {
6160     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
6161     if (!pt) continue;    
6162     Int_t nc=t.GetNumberOfClusters();
6163     if (nc<15) {
6164       delete fSeeds->RemoveAt(i);
6165       continue;
6166     }
6167     t.CookdEdx(0.02,0.6);
6168     //    CookLabel(pt,0.1); //For comparison only
6169     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
6170     if ((pt->IsActive() || (pt->fRemoval==10) )){
6171       cerr<<found++<<'\r';      
6172     }
6173     else
6174       delete fSeeds->RemoveAt(i);
6175     pt->fLab2 = i;
6176   }
6177   */
6178  
6179   //  fNTracks = found;
6180   if (fDebug>0){
6181     Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
6182   }
6183   //
6184   //  cerr<<"Number of found tracks : "<<"\t"<<found<<endl;  
6185   Info("Clusters2Tracks","Number of found tracks %d",found);  
6186   savedir->cd();
6187   //  UnloadClusters();
6188   //  
6189   return 0;
6190 }
6191
6192 void AliTPCtrackerMI::Tracking(TObjArray * arr)
6193 {
6194   //
6195   // tracking of the seeds
6196   //
6197
6198   fSectors = fOuterSec;
6199   ParallelTracking(arr,150,63);
6200   fSectors = fOuterSec;
6201   ParallelTracking(arr,63,0);
6202 }
6203
6204 TObjArray * AliTPCtrackerMI::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
6205 {
6206   //
6207   //
6208   //tracking routine
6209   TObjArray * arr = new TObjArray;
6210   // 
6211   fSectors = fOuterSec;
6212   TStopwatch timer;
6213   timer.Start();
6214   for (Int_t sec=0;sec<fkNOS;sec++){
6215     if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
6216     if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);    
6217     if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
6218   }
6219   if (fDebug>0){
6220     Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
6221     timer.Print();
6222     timer.Start();
6223   }
6224   Tracking(arr);  
6225   if (fDebug>0){
6226     timer.Print();
6227   }
6228
6229   return arr;
6230 }
6231
6232 TObjArray * AliTPCtrackerMI::Tracking()
6233 {
6234   //
6235   //
6236   if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
6237   TStopwatch timer;
6238   timer.Start();
6239   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
6240
6241   TObjArray * seeds = new TObjArray;
6242   TObjArray * arr=0;
6243   
6244   Int_t gap =20;
6245   Float_t cuts[4];
6246   cuts[0] = 0.002;
6247   cuts[1] = 1.5;
6248   cuts[2] = 3.;
6249   cuts[3] = 3.;
6250   Float_t fnumber  = 3.0;
6251   Float_t fdensity = 3.0;
6252   
6253   //  
6254   //find primaries  
6255   cuts[0]=0.0066;
6256   for (Int_t delta = 0; delta<18; delta+=6){
6257     //
6258     cuts[0]=0.0070;
6259     cuts[1] = 1.5;
6260     arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
6261     SumTracks(seeds,arr);   
6262     SignClusters(seeds,fnumber,fdensity); 
6263     //
6264     for (Int_t i=2;i<6;i+=2){
6265       // seed high pt tracks
6266       cuts[0]=0.0022;
6267       cuts[1]=0.3;
6268       arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
6269       SumTracks(seeds,arr);   
6270       SignClusters(seeds,fnumber,fdensity);        
6271     }
6272   }
6273   fnumber  = 4;
6274   fdensity = 4.;
6275   //  RemoveUsed(seeds,0.9,0.9,1);
6276   //  UnsignClusters();
6277   //  SignClusters(seeds,fnumber,fdensity);    
6278
6279   //find primaries  
6280   cuts[0]=0.0077;
6281   for (Int_t delta = 20; delta<120; delta+=10){
6282     //
6283     // seed high pt tracks
6284     cuts[0]=0.0060;
6285     cuts[1]=0.3;
6286     cuts[2]=6.;
6287     arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
6288     SumTracks(seeds,arr);   
6289     SignClusters(seeds,fnumber,fdensity);            
6290
6291     cuts[0]=0.003;
6292     cuts[1]=0.3;
6293     cuts[2]=6.;
6294     arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
6295     SumTracks(seeds,arr);   
6296     SignClusters(seeds,fnumber,fdensity);            
6297   }
6298
6299   cuts[0] = 0.01;
6300   cuts[1] = 2.0;
6301   cuts[2] = 3.;
6302   cuts[3] = 2.0;
6303   fnumber  = 2.;
6304   fdensity = 2.;
6305   
6306   if (fDebug>0){
6307     Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
6308     timer.Print();
6309     timer.Start();
6310   }
6311   //  RemoveUsed(seeds,0.75,0.75,1);
6312   //UnsignClusters();
6313   //SignClusters(seeds,fnumber,fdensity);
6314   
6315   // find secondaries
6316
6317   cuts[0] = 0.3;
6318   cuts[1] = 1.5;
6319   cuts[2] = 3.;
6320   cuts[3] = 1.5;
6321
6322   arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
6323   SumTracks(seeds,arr);   
6324   SignClusters(seeds,fnumber,fdensity);   
6325   //
6326   arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
6327   SumTracks(seeds,arr);   
6328   SignClusters(seeds,fnumber,fdensity);   
6329   //
6330   arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
6331   SumTracks(seeds,arr);   
6332   SignClusters(seeds,fnumber,fdensity);   
6333   //
6334
6335
6336   for (Int_t delta = 3; delta<30; delta+=5){
6337     //
6338     cuts[0] = 0.3;
6339     cuts[1] = 1.5;
6340     cuts[2] = 3.;
6341     cuts[3] = 1.5;
6342     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
6343     SumTracks(seeds,arr);   
6344     SignClusters(seeds,fnumber,fdensity);   
6345     //
6346     arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
6347     SumTracks(seeds,arr);   
6348     SignClusters(seeds,fnumber,fdensity); 
6349     //
6350   } 
6351   fnumber  = 1;
6352   fdensity = 1;
6353   //
6354   // change cuts
6355   fnumber  = 2.;
6356   fdensity = 2.;
6357   cuts[0]=0.0080;
6358
6359   Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
6360
6361   // find secondaries
6362   for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=10){
6363     //
6364     cuts[0] = 0.3;
6365     cuts[1] = 3.5;
6366     cuts[2] = 3.;
6367     cuts[3] = 3.5;
6368     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
6369     SumTracks(seeds,arr);   
6370     SignClusters(seeds,fnumber,fdensity);   
6371     //
6372     arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
6373     SumTracks(seeds,arr);   
6374     SignClusters(seeds,fnumber,fdensity);   
6375   }
6376  
6377   if (fDebug>0){
6378     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
6379     timer.Print();
6380     timer.Start();
6381   }
6382
6383   return seeds;
6384   //
6385       
6386 }
6387
6388
6389 TObjArray * AliTPCtrackerMI::TrackingSpecial()
6390 {
6391   //
6392   // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
6393   // no primary vertex seeding tried
6394   //
6395   TStopwatch timer;
6396   timer.Start();
6397   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
6398
6399   TObjArray * seeds = new TObjArray;
6400   TObjArray * arr=0;
6401   
6402   Int_t   gap  = 15;
6403   Float_t cuts[4];
6404   Float_t fnumber  = 3.0;
6405   Float_t fdensity = 3.0;
6406   
6407   // find secondaries
6408   cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC();   // max curvature
6409   cuts[1] = 3.5;    // max tan(phi) angle for seeding
6410   cuts[2] = 3.;     // not used (cut on z primary vertex)     
6411   cuts[3] = 3.5;    // max tan(theta) angle for seeding
6412
6413   for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
6414     //
6415     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
6416     SumTracks(seeds,arr);   
6417     SignClusters(seeds,fnumber,fdensity);   
6418   } 
6419  
6420   if (fDebug>0){
6421     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
6422     timer.Print();
6423     timer.Start();
6424   }
6425
6426   return seeds;
6427   //
6428       
6429 }
6430
6431
6432 void AliTPCtrackerMI::SumTracks(TObjArray *arr1,TObjArray *&arr2) const
6433 {
6434   //
6435   //sum tracks to common container
6436   //remove suspicious tracks
6437   Int_t nseed = arr2->GetEntriesFast();
6438   for (Int_t i=0;i<nseed;i++){
6439     AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);    
6440     if (pt){
6441       //
6442       // remove tracks with too big curvature
6443       //
6444       if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
6445         delete arr2->RemoveAt(i);
6446         continue;
6447       }
6448        // REMOVE VERY SHORT  TRACKS
6449       if (pt->GetNumberOfClusters()<20){ 
6450         delete arr2->RemoveAt(i);
6451         continue;
6452       }// patch 28 fev06
6453       // NORMAL ACTIVE TRACK
6454       if (pt->IsActive()){
6455         arr1->AddLast(arr2->RemoveAt(i));
6456         continue;
6457       }
6458       //remove not usable tracks
6459       if (pt->GetRemoval()!=10){
6460         delete arr2->RemoveAt(i);
6461         continue;
6462       }
6463      
6464       // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
6465       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
6466         arr1->AddLast(arr2->RemoveAt(i));
6467       else{      
6468         delete arr2->RemoveAt(i);
6469       }
6470     }
6471   }
6472   delete arr2;  arr2 = 0;
6473 }
6474
6475
6476
6477 void  AliTPCtrackerMI::ParallelTracking(TObjArray * arr, Int_t rfirst, Int_t rlast)
6478 {
6479   //
6480   // try to track in parralel
6481
6482   Int_t nseed=arr->GetEntriesFast();
6483   //prepare seeds for tracking
6484   for (Int_t i=0; i<nseed; i++) {
6485     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt; 
6486     if (!pt) continue;
6487     if (!t.IsActive()) continue;
6488     // follow prolongation to the first layer
6489     if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fParam->GetNRowLow()>rfirst+1) )  
6490       FollowProlongation(t, rfirst+1);
6491   }
6492
6493
6494   //
6495   for (Int_t nr=rfirst; nr>=rlast; nr--){ 
6496     if (nr<fInnerSec->GetNRows()) 
6497       fSectors = fInnerSec;
6498     else
6499       fSectors = fOuterSec;
6500     // make indexes with the cluster tracks for given       
6501
6502     // find nearest cluster
6503     for (Int_t i=0; i<nseed; i++) {
6504       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;       
6505       if (!pt) continue;
6506       if (nr==80) pt->UpdateReference();
6507       if (!pt->IsActive()) continue;
6508       //      if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fParam->GetNRowLow())<nr) continue;
6509       if (pt->GetRelativeSector()>17) {
6510         continue;
6511       }
6512       UpdateClusters(t,nr);
6513     }
6514     // prolonagate to the nearest cluster - if founded
6515     for (Int_t i=0; i<nseed; i++) {
6516       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i); 
6517       if (!pt) continue;
6518       if (!pt->IsActive()) continue; 
6519       // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fParam->GetNRowLow())<nr) continue;
6520       if (pt->GetRelativeSector()>17) {
6521         continue;
6522       }
6523       FollowToNextCluster(*pt,nr);
6524     }
6525   }    
6526 }
6527
6528 void AliTPCtrackerMI::PrepareForBackProlongation(TObjArray * arr,Float_t fac) const
6529 {
6530   //
6531   //
6532   // if we use TPC track itself we have to "update" covariance
6533   //
6534   Int_t nseed= arr->GetEntriesFast();
6535   for (Int_t i=0;i<nseed;i++){
6536     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6537     if (pt) {
6538       pt->Modify(fac);
6539       //
6540       //rotate to current local system at first accepted  point    
6541       Int_t index  = pt->GetClusterIndex2(pt->GetFirstPoint()); 
6542       Int_t sec    = (index&0xff000000)>>24;
6543       sec = sec%18;
6544       Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
6545       if (angle1>TMath::Pi()) 
6546         angle1-=2.*TMath::Pi();
6547       Float_t angle2 = pt->GetAlpha();
6548       
6549       if (TMath::Abs(angle1-angle2)>0.001){
6550         pt->Rotate(angle1-angle2);
6551         //angle2 = pt->GetAlpha();
6552         //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
6553         //if (pt->GetAlpha()<0) 
6554         //  pt->fRelativeSector+=18;
6555         //sec = pt->fRelativeSector;
6556       }
6557         
6558     }
6559     
6560   }
6561
6562
6563 }
6564 void AliTPCtrackerMI::PrepareForProlongation(TObjArray * arr, Float_t fac) const
6565 {
6566   //
6567   //
6568   // if we use TPC track itself we have to "update" covariance
6569   //
6570   Int_t nseed= arr->GetEntriesFast();
6571   for (Int_t i=0;i<nseed;i++){
6572     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6573     if (pt) {
6574       pt->Modify(fac);
6575       pt->SetFirstPoint(pt->GetLastPoint()); 
6576     }
6577     
6578   }
6579
6580
6581 }
6582
6583 Int_t AliTPCtrackerMI::PropagateBack(TObjArray * arr)
6584 {
6585   //
6586   // make back propagation
6587   //
6588   Int_t nseed= arr->GetEntriesFast();
6589   for (Int_t i=0;i<nseed;i++){
6590     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6591     if (pt&& pt->GetKinkIndex(0)<=0) { 
6592       //AliTPCseed *pt2 = new AliTPCseed(*pt);
6593       fSectors = fInnerSec;
6594       //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
6595       //fSectors = fOuterSec;
6596       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);     
6597       //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
6598       //        Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
6599       //        FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
6600       //}
6601     }
6602     if (pt&& pt->GetKinkIndex(0)>0) {
6603       AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
6604       pt->SetFirstPoint(kink->GetTPCRow0());
6605       fSectors = fInnerSec;
6606       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);  
6607     }
6608     CookLabel(pt,0.3);
6609   }
6610   return 0;
6611 }
6612
6613
6614 Int_t AliTPCtrackerMI::PropagateForward2(TObjArray * arr)
6615 {
6616   //
6617   // make forward propagation
6618   //
6619   Int_t nseed= arr->GetEntriesFast();
6620   //
6621   for (Int_t i=0;i<nseed;i++){
6622     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
6623     if (pt) { 
6624       FollowProlongation(*pt,0);
6625       CookLabel(pt,0.3);
6626     }
6627     
6628   }
6629   return 0;
6630 }
6631
6632
6633 Int_t AliTPCtrackerMI::PropagateForward()
6634 {
6635   //
6636   // propagate track forward
6637   //UnsignClusters();
6638   Int_t nseed = fSeeds->GetEntriesFast();
6639   for (Int_t i=0;i<nseed;i++){
6640     AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
6641     if (pt){
6642       AliTPCseed &t = *pt;
6643       Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
6644       if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
6645       if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
6646       t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
6647     }
6648   }
6649   
6650   fSectors = fOuterSec;
6651   ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
6652   fSectors = fInnerSec;
6653   ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
6654   return 1;
6655 }
6656
6657
6658
6659
6660
6661
6662 Int_t AliTPCtrackerMI::PropagateBack(AliTPCseed * pt, Int_t row0, Int_t row1)
6663 {
6664   //
6665   // make back propagation, in between row0 and row1
6666   //
6667   
6668   if (pt) { 
6669     fSectors = fInnerSec;
6670     Int_t  r1;
6671     //
6672     if (row1<fSectors->GetNRows()) 
6673       r1 = row1;
6674     else 
6675       r1 = fSectors->GetNRows()-1;
6676
6677     if (row0<fSectors->GetNRows()&& r1>0 )
6678       FollowBackProlongation(*pt,r1);
6679     if (row1<=fSectors->GetNRows())
6680       return 0;
6681     //
6682     r1 = row1 - fSectors->GetNRows();
6683     if (r1<=0) return 0;
6684     if (r1>=fOuterSec->GetNRows()) return 0;
6685     fSectors = fOuterSec;
6686     return FollowBackProlongation(*pt,r1);
6687   }        
6688   return 0;
6689 }
6690
6691
6692
6693
6694 void  AliTPCtrackerMI::GetShape(AliTPCseed * seed, Int_t row)
6695 {
6696   //
6697   // 
6698   AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
6699   Float_t zdrift = TMath::Abs((fParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
6700   Int_t type = (seed->GetSector() < fParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
6701   Double_t angulary  = seed->GetSnp();
6702   angulary = angulary*angulary/(1.-angulary*angulary);
6703   Double_t angularz  = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
6704   
6705   Double_t sigmay =  clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
6706   Double_t sigmaz =  clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
6707   seed->SetCurrentSigmaY2(sigmay*sigmay);
6708   seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
6709   // Float_t sd2 = TMath::Abs((fParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fParam->GetDiffL()*fParam->GetDiffL();
6710 //   //  Float_t padlength =  fParam->GetPadPitchLength(seed->fSector);
6711 //   Float_t padlength =  GetPadPitchLength(row);
6712 //   //
6713 //   Float_t sresy = (seed->GetSector() < fParam->GetNSector()/2) ? 0.2 :0.3;
6714 //   seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);  
6715 //   //
6716 //   Float_t sresz = fParam->GetZSigma();
6717 //   seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
6718   /*
6719   Float_t wy = GetSigmaY(seed);
6720   Float_t wz = GetSigmaZ(seed);
6721   wy*=wy;
6722   wz*=wz;
6723   if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
6724     printf("problem\n");
6725   }
6726   */
6727 }
6728
6729
6730
6731 //__________________________________________________________________________
6732 void AliTPCtrackerMI::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
6733   //--------------------------------------------------------------------
6734   //This function "cooks" a track label. If label<0, this track is fake.
6735   //--------------------------------------------------------------------
6736   AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
6737   if(!t){
6738     printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
6739     return;
6740   }
6741
6742   Int_t noc=t->GetNumberOfClusters();
6743   if (noc<10){
6744     //printf("\nnot founded prolongation\n\n\n");
6745     //t->Dump();
6746     return ;
6747   }
6748   Int_t lb[160];
6749   Int_t mx[160];
6750   AliTPCclusterMI *clusters[160];
6751   //
6752   for (Int_t i=0;i<160;i++) {
6753     clusters[i]=0;
6754     lb[i]=mx[i]=0;
6755   }
6756
6757   Int_t i;
6758   Int_t current=0;
6759   for (i=0; i<160 && current<noc; i++) {
6760      
6761      Int_t index=t->GetClusterIndex2(i);
6762      if (index<=0) continue; 
6763      if (index&0x8000) continue;
6764      //     
6765      //clusters[current]=GetClusterMI(index);
6766      if (t->GetClusterPointer(i)){
6767        clusters[current]=t->GetClusterPointer(i);     
6768        current++;
6769      }
6770   }
6771   noc = current;
6772
6773   Int_t lab=123456789;
6774   for (i=0; i<noc; i++) {
6775     AliTPCclusterMI *c=clusters[i];
6776     if (!c) continue;
6777     lab=TMath::Abs(c->GetLabel(0));
6778     Int_t j;
6779     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
6780     lb[j]=lab;
6781     (mx[j])++;
6782   }
6783
6784   Int_t max=0;
6785   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
6786     
6787   for (i=0; i<noc; i++) {
6788     AliTPCclusterMI *c=clusters[i]; 
6789     if (!c) continue;
6790     if (TMath::Abs(c->GetLabel(1)) == lab ||
6791         TMath::Abs(c->GetLabel(2)) == lab ) max++;
6792   }
6793
6794   if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
6795
6796   else {
6797      Int_t tail=Int_t(0.10*noc);
6798      max=0;
6799      Int_t ind=0;
6800      for (i=1; i<=160&&ind<tail; i++) {
6801        //       AliTPCclusterMI *c=clusters[noc-i];
6802        AliTPCclusterMI *c=clusters[i];
6803        if (!c) continue;
6804        if (lab == TMath::Abs(c->GetLabel(0)) ||
6805            lab == TMath::Abs(c->GetLabel(1)) ||
6806            lab == TMath::Abs(c->GetLabel(2))) max++;
6807        ind++;
6808      }
6809      if (max < Int_t(0.5*tail)) lab=-lab;
6810   }
6811
6812   t->SetLabel(lab);
6813
6814   //  delete[] lb;
6815   //delete[] mx;
6816   //delete[] clusters;
6817 }
6818
6819
6820 //__________________________________________________________________________
6821 Int_t AliTPCtrackerMI::CookLabel(AliTPCseed *t, Float_t wrong,Int_t first, Int_t last) const {
6822   //--------------------------------------------------------------------
6823   //This function "cooks" a track label. If label<0, this track is fake.
6824   //--------------------------------------------------------------------
6825   Int_t noc=t->GetNumberOfClusters();
6826   if (noc<10){
6827     //printf("\nnot founded prolongation\n\n\n");
6828     //t->Dump();
6829     return -1;
6830   }
6831   Int_t lb[160];
6832   Int_t mx[160];
6833   AliTPCclusterMI *clusters[160];
6834   //
6835   for (Int_t i=0;i<160;i++) {
6836     clusters[i]=0;
6837     lb[i]=mx[i]=0;
6838   }
6839
6840   Int_t i;
6841   Int_t current=0;
6842   for (i=0; i<160 && current<noc; i++) {
6843     if (i<first) continue;
6844     if (i>last)  continue;
6845      Int_t index=t->GetClusterIndex2(i);
6846      if (index<=0) continue; 
6847      if (index&0x8000) continue;
6848      //     
6849      //clusters[current]=GetClusterMI(index);
6850      if (t->GetClusterPointer(i)){
6851        clusters[current]=t->GetClusterPointer(i);     
6852        current++;
6853      }
6854   }
6855   noc = current;
6856   if (noc<5) return -1;
6857   Int_t lab=123456789;
6858   for (i=0; i<noc; i++) {
6859     AliTPCclusterMI *c=clusters[i];
6860     if (!c) continue;
6861     lab=TMath::Abs(c->GetLabel(0));
6862     Int_t j;
6863     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
6864     lb[j]=lab;
6865     (mx[j])++;
6866   }
6867
6868   Int_t max=0;
6869   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
6870     
6871   for (i=0; i<noc; i++) {
6872     AliTPCclusterMI *c=clusters[i]; 
6873     if (!c) continue;
6874     if (TMath::Abs(c->GetLabel(1)) == lab ||
6875         TMath::Abs(c->GetLabel(2)) == lab ) max++;
6876   }
6877
6878   if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
6879
6880   else {
6881      Int_t tail=Int_t(0.10*noc);
6882      max=0;
6883      Int_t ind=0;
6884      for (i=1; i<=160&&ind<tail; i++) {
6885        //       AliTPCclusterMI *c=clusters[noc-i];
6886        AliTPCclusterMI *c=clusters[i];
6887        if (!c) continue;
6888        if (lab == TMath::Abs(c->GetLabel(0)) ||
6889            lab == TMath::Abs(c->GetLabel(1)) ||
6890            lab == TMath::Abs(c->GetLabel(2))) max++;
6891        ind++;
6892      }
6893      if (max < Int_t(0.5*tail)) lab=-lab;
6894   }
6895
6896   //  t->SetLabel(lab);
6897   return lab;
6898   //  delete[] lb;
6899   //delete[] mx;
6900   //delete[] clusters;
6901 }
6902
6903
6904 Int_t  AliTPCtrackerMI::GetRowNumber(Double_t x[3]) const 
6905 {
6906   //return pad row number for given x vector
6907   Float_t phi = TMath::ATan2(x[1],x[0]);
6908   if(phi<0) phi=2.*TMath::Pi()+phi;
6909   //  Get the local angle in the sector philoc
6910   const Float_t kRaddeg = 180/3.14159265358979312;
6911   Float_t phiangle   = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
6912   Double_t localx    = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
6913   return GetRowNumber(localx);
6914 }
6915
6916
6917
6918 void AliTPCtrackerMI::MakeBitmaps(AliTPCseed *t)
6919 {
6920   //-----------------------------------------------------------------------
6921   // Fill the cluster and sharing bitmaps of the track
6922   //-----------------------------------------------------------------------
6923
6924   Int_t firstpoint = 0;
6925   Int_t lastpoint = 159;
6926   AliTPCTrackerPoint *point;
6927   
6928   for (int iter=firstpoint; iter<lastpoint; iter++) {
6929     point = t->GetTrackPoint(iter);
6930     if (point) {
6931       t->SetClusterMapBit(iter, kTRUE);
6932       if (point->IsShared())
6933         t->SetSharedMapBit(iter,kTRUE);
6934       else
6935         t->SetSharedMapBit(iter, kFALSE);
6936     }
6937     else {
6938       t->SetClusterMapBit(iter, kFALSE);
6939       t->SetSharedMapBit(iter, kFALSE);
6940     }
6941   }
6942 }
6943
6944
6945
6946 void AliTPCtrackerMI::AddCovariance(AliTPCseed * seed){
6947   //
6948   // Adding systematic error
6949   // !!!! the systematic error for element 4 is in 1/cm not in pt 
6950
6951   const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
6952   Double_t covar[15];
6953   for (Int_t i=0;i<15;i++) covar[i]=0;
6954   // 0
6955   // 1    2
6956   // 3    4    5
6957   // 6    7    8    9 
6958   // 10   11   12   13   14
6959   covar[0] = param[0]*param[0];
6960   covar[2] = param[1]*param[1];
6961   covar[5] = param[2]*param[2];
6962   covar[9] = param[3]*param[3];
6963   Double_t facC =  AliTracker::GetBz()*kB2C;
6964   covar[14]= param[4]*param[4]*facC*facC;
6965   seed->AddCovariance(covar);
6966 }