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