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