LCOV - code coverage report
Current view: top level - TPC/TPCrec - AliTPCtracker.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2644 5462 48.4 %
Date: 2016-06-14 17:26:59 Functions: 71 119 59.7 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       7             :  * Permission to use, copy, modify and distribute this software and its   *
       8             :  * documentation strictly for non-commercial purposes is hereby granted   *
       9             :  * without fee, provided that the above copyright notice appears in all   *
      10             :  * copies and that both the copyright notice and this permission notice   *
      11             :  * appear in the supporting documentation. The authors make no claims     *
      12             :  * about the suitability of this software for any purpose. It is          *
      13             :  * provided "as is" without express or implied warranty.                  *
      14             :  **************************************************************************/
      15             : 
      16             : 
      17             : //-------------------------------------------------------
      18             : //          Implementation of the TPC tracker
      19             : //
      20             : //   Origin: Marian Ivanov   Marian.Ivanov@cern.ch
      21             : // 
      22             : //  AliTPC parallel tracker
      23             : //
      24             : //  The track fitting is based on Kalman filtering approach
      25             : //  The track finding steps:
      26             : //      1. Seeding - with and without vertex constraint
      27             : //                 - seeding with vertex constain done at first n^2 proble
      28             : //                 - seeding without vertex constraint n^3 problem
      29             : //      2. Tracking - follow prolongation road - find cluster - update kalman track
      30             : //  The seeding and tracking is repeated several times, in different seeding region.
      31             : //  This approach enables to find the track which cannot be seeded in some region of TPC
      32             : //  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) ...
      33             : 
      34             : //  With this approach we reach almost 100 % efficiency also for high occupancy events.
      35             : //  (If the seeding efficiency in a region is about 90 % than with logical or of several 
      36             : //  regions we will reach 100% (in theory - supposing independence) 
      37             : 
      38             : //  Repeating several seeding - tracking procedures some of the tracks can be find 
      39             : //  several times. 
      40             : 
      41             : //  The procedures to remove multi find tacks are impremented:
      42             : //  RemoveUsed2 - fast procedure n problem - 
      43             : //                 Algorithm - Sorting tracks according quality
      44             : //                             remove tracks with some shared fraction 
      45             : //                             Sharing in respect to all tacks 
      46             : //                             Signing clusters in gold region
      47             : //  FindSplitted - slower algorithm n^2
      48             : //                 Sort the tracks according quality
      49             : //                 Loop over pair of tracks
      50             : //                 If overlap with other track bigger than threshold - remove track
      51             : //  
      52             : //  FindCurling  - Finds the pair of tracks which are curling
      53             : //               - About 10% of tracks can be find with this procedure
      54             : //                 The combinatorial background is too big to be used in High 
      55             : //                  multiplicity environment 
      56             : //               - n^2 problem - Slow procedure - currently it is disabled because of 
      57             : //                  low efficiency
      58             : //                 
      59             : //  The number of splitted tracks can be reduced disabling the sharing of the cluster.
      60             : //  tpcRecoParam-> SetClusterSharing(kFALSE);
      61             : //  IT IS HIGHLY non recomended to use it in high flux enviroonment
      62             : //  Even using this switch some tracks can be found more than once 
      63             : //  (because of multiple seeding and low quality tracks which will not cross full chamber)
      64             : //                          
      65             : //
      66             : // The tracker itself can be debugged  - the information about tracks can be stored in several // phases of the reconstruction
      67             : // To enable storage of the TPC tracks in the ESD friend track
      68             : // use AliTPCReconstructor::SetStreamLevel(n); 
      69             : //
      70             : // The debug level -  different procedure produce tree for numerical debugging of code and data (see comments foEStreamFlags in AliTPCtracker.h  )
      71             : //
      72             : 
      73             : //
      74             : // Adding systematic errors to the covariance:
      75             : // 
      76             : // The systematic errors due to the misalignment and miscalibration are added to the covariance matrix
      77             : // of the tracks (not to the clusters as they are dependent):
      78             : // The parameters form AliTPCRecoParam are used AliTPCRecoParam::GetSystematicError
      79             : // The systematic errors are expressed there in RMS - position (cm), angle (rad), curvature (1/GeV)
      80             : // The default values are 0. 
      81             : //
      82             : // The systematic errors are added to the covariance matrix in following places:
      83             : //
      84             : // 1. During fisrt itteration - AliTPCtracker::FillESD
      85             : // 2. Second iteration - 
      86             : //      2.a ITS->TPC   - AliTPCtracker::ReadSeeds 
      87             : //      2.b TPC->TRD   - AliTPCtracker::PropagateBack
      88             : // 3. Third iteration  -
      89             : //      3.a TRD->TPC   - AliTPCtracker::ReadSeeds
      90             : //      3.b TPC->ITS   - AliTPCtracker::RefitInward
      91             : //
      92             : 
      93             : /* $Id$ */
      94             : 
      95             : #include "Riostream.h"
      96             : #include <TClonesArray.h>
      97             : #include <TFile.h>
      98             : #include <TObjArray.h>
      99             : #include <TTree.h>
     100             : #include <TMatrixD.h>
     101             : #include <TGraphErrors.h>
     102             : #include <TTimeStamp.h>
     103             : #include "AliLog.h"
     104             : #include "AliComplexCluster.h"
     105             : #include "AliESDEvent.h"
     106             : #include "AliESDtrack.h"
     107             : #include "AliESDVertex.h"
     108             : #include "AliKink.h"
     109             : #include "AliV0.h"
     110             : #include "AliHelix.h"
     111             : #include "AliRunLoader.h"
     112             : #include "AliTPCClustersRow.h"
     113             : #include "AliTPCParam.h"
     114             : #include "AliTPCReconstructor.h"
     115             : #include "AliTPCpolyTrack.h"
     116             : #include "AliTPCreco.h"
     117             : //#include "AliTPCseed.h"
     118             : 
     119             : #include "AliTPCtrackerSector.h" 
     120             : #include "AliTPCtracker.h"
     121             : #include "TStopwatch.h"
     122             : #include "AliTPCReconstructor.h"
     123             : #include "AliAlignObj.h"
     124             : #include "AliTrackPointArray.h"
     125             : #include "TRandom.h"
     126             : #include "AliTPCcalibDB.h"
     127             : #include "AliTPCcalibDButil.h"
     128             : #include "AliTPCTransform.h"
     129             : #include "AliTPCClusterParam.h"
     130             : #include "AliTPCdEdxInfo.h"
     131             : #include "AliDCSSensorArray.h"
     132             : #include "AliDCSSensor.h"
     133             : #include "AliDAQ.h"
     134             : #include "AliCosmicTracker.h"
     135             : #include "AliTPCROC.h"
     136             : #include "AliMathBase.h"
     137             : #include <math.h>
     138             : //
     139             : #include "AliESDfriendTrack.h"
     140             : 
     141             : using std::cout;
     142             : using std::cerr;
     143             : using std::endl;
     144          16 : ClassImp(AliTPCtracker)
     145             : 
     146             : //__________________________________________________________________
     147             : AliTPCtracker::AliTPCtracker()
     148           0 :   :AliTracker(),
     149           0 :   fkNIS(0),
     150           0 :   fInnerSec(0),
     151           0 :   fkNOS(0),
     152           0 :   fOuterSec(0),
     153           0 :   fN(0),
     154           0 :   fSectors(0),
     155           0 :   fInput(0),
     156           0 :   fOutput(0),
     157           0 :   fSeedTree(0),
     158           0 :   fTreeDebug(0),
     159           0 :   fEvent(0),
     160           0 :   fEventHLT(0),
     161           0 :   fDebug(0),
     162           0 :   fNewIO(kFALSE),
     163           0 :   fNtracks(0),
     164           0 :   fSeeds(0),
     165           0 :   fIteration(0),
     166           0 :   fkParam(0),
     167           0 :   fDebugStreamer(0),
     168           0 :   fUseHLTClusters(4),
     169           0 :   fClExtraRoadY(0.),
     170           0 :   fClExtraRoadZ(0.), 
     171           0 :   fExtraClErrYZ2(0), 
     172           0 :   fExtraClErrY2(0),
     173           0 :   fExtraClErrZ2(0),
     174           0 :   fPrimaryDCAZCut(-1),
     175           0 :   fPrimaryDCAYCut(-1),
     176           0 :   fDisableSecondaries(kFALSE),
     177           0 :   fCrossTalkSignalArray(0),
     178           0 :   fClPointersPool(0),
     179           0 :   fClPointersPoolPtr(0),
     180           0 :   fClPointersPoolSize(0),
     181           0 :   fSeedsPool(0),
     182           0 :   fHelixPool(0),
     183           0 :   fETPPool(0),
     184           0 :   fFreeSeedsID(500),
     185           0 :   fNFreeSeeds(0),
     186           0 :   fLastSeedID(-1),
     187           0 :   fAccountDistortions(0)
     188           0 : {
     189             :   //
     190             :   // default constructor
     191             :   //
     192           0 :   for (Int_t irow=0; irow<200; irow++){
     193           0 :     fXRow[irow]=0;
     194           0 :     fYMax[irow]=0;
     195           0 :     fPadLength[irow]=0;
     196             :   }
     197           0 : }
     198             : //_____________________________________________________________________
     199             : 
     200             : 
     201             : 
     202             : Int_t AliTPCtracker::UpdateTrack(AliTPCseed * track, Int_t accept){
     203             :   //
     204             :   //update track information using current cluster - track->fCurrentCluster
     205             : 
     206             : 
     207      206720 :   AliTPCclusterMI* c =track->GetCurrentCluster();
     208      206720 :   if (accept > 0) //sign not accepted clusters
     209      107472 :     track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);  
     210             :   else // unsign accpeted clusters
     211       99248 :     track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() & 0xffff7fff);  
     212      103360 :   UInt_t i = track->GetCurrentClusterIndex1();
     213             : 
     214      103360 :   Int_t sec=(i&0xff000000)>>24; 
     215      103360 :   Int_t row = (i&0x00ff0000)>>16; 
     216      167432 :   if (sec>=fkParam->GetNInnerSector()) row += fkParam->GetNRowLow(); 
     217      103360 :   track->SetRow(row);
     218      103360 :   track->SetSector(sec);
     219      103360 :   track->SetClusterIndex2(row, i);  
     220             :   //track->fFirstPoint = row;
     221             :   //if ( track->fLastPoint<row) track->fLastPoint =row;
     222             :   //  if (track->fRow<0 || track->fRow>=kMaxRow) {
     223             :   //  printf("problem\n");
     224             :   //}
     225      103360 :   if (track->GetFirstPoint()>row) 
     226       38460 :     track->SetFirstPoint(row);
     227      103360 :   if (track->GetLastPoint()<row) 
     228       17776 :     track->SetLastPoint(row);
     229             :   
     230      103360 :   Double_t angle2 = track->GetSnp()*track->GetSnp();
     231             :   //
     232             :   //SET NEW Track Point
     233             :   //
     234      103360 :   if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
     235             :   {
     236      103360 :     angle2 = TMath::Sqrt(angle2/(1-angle2));
     237      103360 :     AliTPCTrackerPoints::Point   &point =*((AliTPCTrackerPoints::Point*)track->GetTrackPoint(row));
     238             :     //
     239      103360 :     point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
     240      103360 :     point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
     241      103360 :     point.SetErrY(sqrt(track->GetErrorY2()));
     242      103360 :     point.SetErrZ(sqrt(track->GetErrorZ2()));
     243             :     //
     244      103360 :     point.SetX(track->GetX());
     245      103360 :     point.SetY(track->GetY());
     246      103360 :     point.SetZ(track->GetZ());
     247      103360 :     point.SetAngleY(angle2);
     248      103360 :     point.SetAngleZ(track->GetTgl());
     249      103360 :     if (track->IsShared(row)){
     250           0 :       track->SetErrorY2(track->GetErrorY2()*4);
     251           0 :       track->SetErrorZ2(track->GetErrorZ2()*4);
     252           0 :     }
     253      103360 :   }  
     254             : 
     255      107472 :   if (accept>0) return 0;
     256       99248 :   Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
     257             :   //
     258             : //   track->SetErrorY2(track->GetErrorY2()*1.3);
     259             : //   track->SetErrorY2(track->GetErrorY2()+0.01);    
     260             : //   track->SetErrorZ2(track->GetErrorZ2()*1.3);   
     261             : //   track->SetErrorZ2(track->GetErrorZ2()+0.005);      
     262             :     //}
     263       99248 :   if (track->GetNumberOfClusters()%20==0){
     264             :     //    if (track->fHelixIn){
     265             :     //  TClonesArray & larr = *(track->fHelixIn);    
     266             :     //  Int_t ihelix = larr.GetEntriesFast();
     267             :     //  new(larr[ihelix]) AliHelix(*track) ;    
     268             :     //}
     269             :   }
     270       99248 :   if (AliTPCReconstructor::StreamLevel()&kStreamUpdateTrack) {
     271           0 :     Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
     272           0 :     AliExternalTrackParam param(*track);
     273           0 :     TTreeSRedirector &cstream = *fDebugStreamer;
     274           0 :     cstream<<"UpdateTrack"<<
     275           0 :       "cl.="<<c<<
     276           0 :       "event="<<event<<
     277           0 :       "track.="<<&param<<
     278             :       "\n";
     279           0 :   }
     280       99248 :   track->SetNoCluster(0);
     281       99248 :   return track->Update(c,chi2,i);
     282      103360 : }
     283             : 
     284             : 
     285             : 
     286             : Int_t AliTPCtracker::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
     287             : {
     288             :   //
     289             :   // decide according desired precision to accept given 
     290             :   // cluster for tracking
     291      209276 :   Double_t  yt = seed->GetY(),zt = seed->GetZ();
     292             :   // RS: use propagation only if the seed in far from the cluster
     293             :   const double kTolerance = 10e-4; // assume track is at cluster X if X-distance below this
     294      175082 :   if (TMath::Abs(seed->GetX()-cluster->GetX())>kTolerance) seed->GetProlongation(cluster->GetX(),yt,zt); 
     295      104638 :   Double_t sy2=0;//ErrY2(seed,cluster);
     296      104638 :   Double_t sz2=0;//ErrZ2(seed,cluster);
     297      104638 :   ErrY2Z2(seed,cluster,sy2,sz2);
     298             :   
     299      104638 :   Double_t sdistancey2 = sy2+seed->GetSigmaY2();
     300      104638 :   Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
     301      104638 :   Double_t dy=seed->GetCurrentCluster()->GetY()-yt;
     302      104638 :   Double_t dz=seed->GetCurrentCluster()->GetZ()-zt;
     303      104638 :   Double_t rdistancey2 = dy*dy/sdistancey2;
     304      104638 :   Double_t rdistancez2 = dz*dz/sdistancez2;
     305             :   
     306      104638 :   Double_t rdistance2  = rdistancey2+rdistancez2;
     307             :   //Int_t  accept =0;
     308             :   
     309      104638 :   if (AliTPCReconstructor::StreamLevel()>2 && ( (fIteration>0)|| (seed->GetNumberOfClusters()>20))) {
     310             :     //  if (AliTPCReconstructor::StreamLevel()>2 && seed->GetNumberOfClusters()>20) {
     311           0 :     Float_t rmsy2 = seed->GetCurrentSigmaY2();
     312           0 :     Float_t rmsz2 = seed->GetCurrentSigmaZ2();
     313           0 :     Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
     314           0 :     Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
     315           0 :     Float_t rmsy2p30R  = seed->GetCMeanSigmaY2p30R();
     316           0 :     Float_t rmsz2p30R  = seed->GetCMeanSigmaZ2p30R();
     317           0 :     AliExternalTrackParam param(*seed);
     318           0 :     static TVectorD gcl(3),gtr(3);
     319           0 :     Float_t gclf[3];
     320           0 :     param.GetXYZ(gcl.GetMatrixArray());
     321           0 :     cluster->GetGlobalXYZ(gclf);
     322           0 :     gcl[0]=gclf[0];    gcl[1]=gclf[1];    gcl[2]=gclf[2];
     323           0 :     Int_t nclSeed=seed->GetNumberOfClusters();
     324           0 :     int seedType = seed->GetSeedType();
     325           0 :     if (AliTPCReconstructor::StreamLevel()&kStreamErrParam) { // flag:stream in debug mode cluster and track extrapolation at given row together with error nad shape estimate
     326           0 :       Int_t eventNr = fEvent->GetEventNumberInFile();
     327             :         
     328           0 :     (*fDebugStreamer)<<"ErrParam"<<
     329           0 :       "iter="<<fIteration<<
     330           0 :       "eventNr="<<eventNr<<
     331           0 :       "Cl.="<<cluster<<
     332           0 :       "nclSeed="<<nclSeed<<
     333           0 :       "seedType="<<seedType<<
     334           0 :       "T.="<<&param<<
     335           0 :       "dy="<<dy<<
     336           0 :       "dz="<<dz<<
     337           0 :       "yt="<<yt<<
     338           0 :       "zt="<<zt<<
     339           0 :       "gcl.="<<&gcl<<
     340           0 :       "gtr.="<<&gtr<<
     341           0 :       "erry2="<<sy2<<
     342           0 :       "errz2="<<sz2<<
     343           0 :       "rmsy2="<<rmsy2<<
     344           0 :       "rmsz2="<<rmsz2<<   
     345           0 :       "rmsy2p30="<<rmsy2p30<<
     346           0 :       "rmsz2p30="<<rmsz2p30<<     
     347           0 :       "rmsy2p30R="<<rmsy2p30R<<
     348           0 :       "rmsz2p30R="<<rmsz2p30R<<   
     349             :       // normalize distance - 
     350           0 :       "rdisty="<<rdistancey2<<
     351           0 :       "rdistz="<<rdistancez2<<
     352           0 :       "rdist="<<rdistance2<< //       
     353             :       "\n";
     354           0 :     }
     355           0 :   }
     356             :   //return 0;  // temporary
     357      105918 :   if (rdistance2>32) return 3;
     358             :   
     359             :   
     360      107702 :   if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)  
     361        3832 :     return 2;  //suspisiouce - will be changed
     362             :   
     363      103838 :   if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)  
     364             :     // strict cut on overlaped cluster
     365         662 :     return  2;  //suspisiouce - will be changed
     366             :   
     367      130849 :   if ( (rdistancey2>1. || rdistancez2>6.25 ) 
     368       31985 :        && cluster->GetType()<0){
     369          54 :     seed->SetNFoundable(seed->GetNFoundable()-1);
     370          54 :     return 2;    
     371             :   }
     372             : 
     373      197620 :   if (fUseHLTClusters == 3 || fUseHLTClusters == 4) {
     374           0 :     if (fIteration==2){
     375           0 :       if(!AliTPCReconstructor::GetRecoParam()->GetUseHLTOnePadCluster()) {
     376           0 :         if (TMath::Abs(cluster->GetSigmaY2()) < kAlmost0)
     377           0 :           return 2;
     378             :       }
     379             :     }
     380             :   }
     381             : 
     382       98810 :   return 0;
     383      104638 : }
     384             : 
     385             : 
     386             : 
     387             : 
     388             : 
     389             : //_____________________________________________________________________________
     390             : AliTPCtracker::AliTPCtracker(const AliTPCParam *par): 
     391           2 :   AliTracker(), 
     392           2 :   fkNIS(par->GetNInnerSector()/2),
     393           2 :   fInnerSec(0),
     394           2 :   fkNOS(par->GetNOuterSector()/2),
     395           2 :   fOuterSec(0),
     396           2 :   fN(0),
     397           2 :   fSectors(0),
     398           2 :   fInput(0),
     399           2 :   fOutput(0),
     400           2 :   fSeedTree(0),
     401           2 :   fTreeDebug(0),
     402           2 :   fEvent(0),
     403           2 :   fEventHLT(0),
     404           2 :   fDebug(0),
     405           2 :   fNewIO(0),
     406           2 :   fNtracks(0),
     407           2 :   fSeeds(0),
     408           2 :   fIteration(0),
     409           2 :   fkParam(0), 
     410           2 :   fDebugStreamer(0),
     411           2 :   fUseHLTClusters(4),
     412           2 :   fClExtraRoadY(0.),
     413           2 :   fClExtraRoadZ(0.), 
     414           2 :   fExtraClErrYZ2(0), 
     415           2 :   fExtraClErrY2(0),
     416           2 :   fExtraClErrZ2(0),
     417           2 :   fPrimaryDCAZCut(-1),
     418           2 :   fPrimaryDCAYCut(-1),
     419           2 :   fDisableSecondaries(kFALSE),
     420           2 :   fCrossTalkSignalArray(0),
     421           2 :   fClPointersPool(0),
     422           2 :   fClPointersPoolPtr(0),
     423           2 :   fClPointersPoolSize(0),
     424           2 :   fSeedsPool(0),
     425           2 :   fHelixPool(0),
     426           2 :   fETPPool(0),
     427           2 :   fFreeSeedsID(500),
     428           2 :   fNFreeSeeds(0),
     429           2 :   fLastSeedID(-1),
     430           2 :   fAccountDistortions(0)
     431          10 : {
     432             :   //---------------------------------------------------------------------
     433             :   // The main TPC tracker constructor
     434             :   //---------------------------------------------------------------------
     435          80 :   fInnerSec=new AliTPCtrackerSector[fkNIS];         
     436          80 :   fOuterSec=new AliTPCtrackerSector[fkNOS];
     437             :  
     438             :   Int_t i;
     439         112 :   for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
     440         112 :   for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
     441             : 
     442           2 :   fkParam = par;  
     443           2 :   Int_t nrowlow = par->GetNRowLow();
     444           2 :   Int_t nrowup = par->GetNRowUp();
     445             : 
     446             :   
     447         256 :   for (i=0;i<nrowlow;i++){
     448         252 :     fXRow[i]     = par->GetPadRowRadiiLow(i);
     449         126 :     fPadLength[i]= par->GetPadPitchLength(0,i);
     450         252 :     fYMax[i]     = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
     451             :   }
     452             : 
     453             :   
     454         388 :   for (i=0;i<nrowup;i++){
     455         384 :     fXRow[i+nrowlow]      = par->GetPadRowRadiiUp(i);
     456         192 :     fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
     457         384 :     fYMax[i+nrowlow]      = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
     458             :   }
     459             : 
     460           2 :   if (AliTPCReconstructor::StreamLevel()>0) {
     461           0 :     fDebugStreamer = new TTreeSRedirector("TPCdebug.root","recreate");
     462           0 :     AliTPCReconstructor::SetDebugStreamer(fDebugStreamer);
     463           0 :   }
     464             :   //
     465           6 :   fSeedsPool = new TClonesArray("AliTPCseed",1000);
     466           4 :   fClPointersPool = new AliTPCclusterMI*[kMaxFriendTracks*kMaxRow];
     467           2 :   memset(fClPointersPool,0,kMaxFriendTracks*kMaxRow*sizeof(AliTPCclusterMI*));
     468           2 :   fClPointersPoolPtr = fClPointersPool;
     469           2 :   fClPointersPoolSize = kMaxFriendTracks;
     470             :   //
     471             :   // crosstalk array and matrix initialization
     472             :   Int_t nROCs   = 72;
     473           4 :   Int_t nTimeBinsAll  = AliTPCcalibDB::Instance()->GetMaxTimeBinAllPads() ;
     474             :   Int_t nWireSegments = 11;
     475           6 :   fCrossTalkSignalArray = new TObjArray(nROCs*4);  //  
     476           2 :   fCrossTalkSignalArray->SetOwner(kTRUE);
     477        1156 :   for (Int_t isector=0; isector<4*nROCs; isector++){
     478        1152 :     TMatrixD * crossTalkSignal = new TMatrixD(nWireSegments,nTimeBinsAll);
     479       13824 :     for (Int_t imatrix = 0; imatrix<11; imatrix++)
     480    12177792 :       for (Int_t jmatrix = 0; jmatrix<nTimeBinsAll; jmatrix++){
     481    18247680 :         (*crossTalkSignal)[imatrix][jmatrix]=0.;
     482             :       }
     483         576 :     fCrossTalkSignalArray->AddAt(crossTalkSignal,isector);
     484             :   }
     485             : 
     486           4 : }
     487             : //________________________________________________________________________
     488             : AliTPCtracker::AliTPCtracker(const AliTPCtracker &t):
     489           0 :   AliTracker(t),
     490           0 :   fkNIS(t.fkNIS),
     491           0 :   fInnerSec(0),
     492           0 :   fkNOS(t.fkNOS),
     493           0 :   fOuterSec(0),
     494           0 :   fN(0),
     495           0 :   fSectors(0),
     496           0 :   fInput(0),
     497           0 :   fOutput(0),
     498           0 :   fSeedTree(0),
     499           0 :   fTreeDebug(0),
     500           0 :   fEvent(0),
     501           0 :   fEventHLT(0),
     502           0 :   fDebug(0),
     503           0 :   fNewIO(kFALSE),
     504           0 :   fNtracks(0),
     505           0 :   fSeeds(0),
     506           0 :   fIteration(0),
     507           0 :   fkParam(0),
     508           0 :   fDebugStreamer(0),
     509           0 :   fUseHLTClusters(4),
     510           0 :   fClExtraRoadY(0.),
     511           0 :   fClExtraRoadZ(0.), 
     512           0 :   fExtraClErrYZ2(0), 
     513           0 :   fExtraClErrY2(0),
     514           0 :   fExtraClErrZ2(0),
     515           0 :   fPrimaryDCAZCut(-1),
     516           0 :   fPrimaryDCAYCut(-1),
     517           0 :   fDisableSecondaries(kFALSE),
     518           0 :   fCrossTalkSignalArray(0),
     519           0 :   fClPointersPool(0),
     520           0 :   fClPointersPoolPtr(0),
     521           0 :   fClPointersPoolSize(0),
     522           0 :   fSeedsPool(0),
     523           0 :   fHelixPool(0),
     524           0 :   fETPPool(0),
     525           0 :   fFreeSeedsID(500),
     526           0 :   fNFreeSeeds(0),
     527           0 :   fLastSeedID(-1),
     528           0 :   fAccountDistortions(0)
     529           0 : {
     530             :   //------------------------------------
     531             :   // dummy copy constructor
     532             :   //------------------------------------------------------------------
     533           0 :   fOutput=t.fOutput;
     534           0 :   for (Int_t irow=0; irow<200; irow++){
     535           0 :     fXRow[irow]=0;
     536           0 :     fYMax[irow]=0;
     537           0 :     fPadLength[irow]=0;
     538             :   }
     539             : 
     540           0 : }
     541             : AliTPCtracker & AliTPCtracker::operator=(const AliTPCtracker& /*r*/)
     542             : {
     543             :   //------------------------------
     544             :   // dummy 
     545             :   //--------------------------------------------------------------
     546           0 :   return *this;
     547             : }
     548             : //_____________________________________________________________________________
     549          12 : AliTPCtracker::~AliTPCtracker() {
     550             :   //------------------------------------------------------------------
     551             :   // TPC tracker destructor
     552             :   //------------------------------------------------------------------
     553          42 :   delete[] fInnerSec;
     554          42 :   delete[] fOuterSec;
     555           2 :   if (fSeeds) {
     556           2 :     fSeeds->Clear(); 
     557           4 :     delete fSeeds;
     558             :   }
     559           4 :   delete[] fClPointersPool;
     560           6 :   if (fCrossTalkSignalArray) delete fCrossTalkSignalArray;
     561           2 :   if (fDebugStreamer) delete fDebugStreamer;
     562           2 :   if (fSeedsPool) {
     563          62 :     for (int isd=fSeedsPool->GetEntriesFast();isd--;) {
     564          56 :       AliTPCseed* seed = (AliTPCseed*)fSeedsPool->At(isd);
     565          28 :       if (seed) {
     566          28 :         seed->SetClusterOwner(kFALSE);
     567          28 :         seed->SetClustersArrayTMP(0);
     568          28 :       }
     569             :     }
     570           4 :     delete fSeedsPool;
     571             :   }
     572           4 :   if (fHelixPool) fHelixPool->Delete();
     573           4 :   delete fHelixPool;
     574           4 :   if (fETPPool) fETPPool->Delete();
     575           4 :   delete fETPPool;
     576           6 : }
     577             : 
     578             : 
     579             : void AliTPCtracker::FillESD(const TObjArray* arr)
     580             : {
     581             :   //
     582             :   //
     583             :   //fill esds using updated tracks
     584             : 
     585          16 :   if (!fEvent) return;
     586             : 
     587           8 :   AliESDtrack iotrack;
     588             :   
     589             :     // write tracks to the event
     590             :     // store index of the track
     591           8 :     Int_t nseed=arr->GetEntriesFast();
     592             :     //FindKinks(arr,fEvent);
     593         288 :     for (Int_t i=0; i<nseed; i++) {
     594         136 :       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
     595         136 :       if (!pt) continue; 
     596         136 :       pt->UpdatePoints();
     597         136 :       AddCovariance(pt);
     598         136 :       if (AliTPCReconstructor::StreamLevel()&kStreamFillESD) {
     599           0 :         (*fDebugStreamer)<<"FillESD"<<  // flag: stream track information in FillESD function (after track Iteration 0)
     600           0 :           "Tr0.="<<pt<<
     601             :           "\n";       
     602             :       }
     603             :       //      pt->PropagateTo(fkParam->GetInnerRadiusLow());
     604         272 :       if (pt->GetKinkIndex(0)<=0){  //don't propagate daughter tracks 
     605         132 :         pt->PropagateTo(fkParam->GetInnerRadiusLow());
     606         132 :         pt->SetRow(0); // RS: memorise row
     607         132 :       }
     608             :  
     609         272 :       if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
     610         136 :         iotrack.~AliESDtrack();
     611         272 :         new(&iotrack) AliESDtrack;
     612         136 :         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
     613         136 :         iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0)); 
     614         136 :         iotrack.SetTPCPoints(pt->GetPoints());
     615         136 :         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
     616         136 :         iotrack.SetV0Indexes(pt->GetV0Indexes());
     617             :         //      iotrack.SetTPCpid(pt->fTPCr);
     618             :         //iotrack.SetTPCindex(i); 
     619         136 :         MakeESDBitmaps(pt, &iotrack);
     620         136 :         fEvent->AddTrack(&iotrack);
     621         136 :         continue;
     622             :       }
     623             :        
     624           0 :       if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
     625           0 :         iotrack.~AliESDtrack();
     626           0 :         new(&iotrack) AliESDtrack;
     627           0 :         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
     628           0 :         iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0)); 
     629           0 :         iotrack.SetTPCPoints(pt->GetPoints());
     630             :         //iotrack.SetTPCindex(i);
     631           0 :         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
     632           0 :         iotrack.SetV0Indexes(pt->GetV0Indexes());
     633           0 :         MakeESDBitmaps(pt, &iotrack);
     634             :         //      iotrack.SetTPCpid(pt->fTPCr);
     635           0 :         fEvent->AddTrack(&iotrack);
     636           0 :         continue;
     637             :       } 
     638             :       //
     639             :       // short tracks  - maybe decays
     640             : 
     641             :       //RS Seed don't keep their cluster pointers, cache cluster usage stat. for fast evaluation
     642             :       // FillSeedClusterStatCache(pt); // RS use this slow method only if info on shared statistics is needed
     643             : 
     644           0 :       if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
     645           0 :         Int_t found,foundable; //,shared;
     646             :         //GetCachedSeedClusterStatistic(0,60,found, foundable,shared,kFALSE); // RS make sure FillSeedClusterStatCache is called
     647             :         //pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE); //RS: avoid this method: seed does not keep clusters
     648           0 :         pt->GetClusterStatistic(0,60,found, foundable);
     649           0 :         if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
     650           0 :           iotrack.~AliESDtrack();
     651           0 :           new(&iotrack) AliESDtrack;
     652           0 :           iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);    
     653           0 :           iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0)); 
     654             :           //iotrack.SetTPCindex(i);
     655           0 :           iotrack.SetTPCPoints(pt->GetPoints());
     656           0 :           iotrack.SetKinkIndexes(pt->GetKinkIndexes());
     657           0 :           iotrack.SetV0Indexes(pt->GetV0Indexes());
     658           0 :           MakeESDBitmaps(pt, &iotrack);
     659             :           //iotrack.SetTPCpid(pt->fTPCr);
     660           0 :           fEvent->AddTrack(&iotrack);
     661           0 :           continue;
     662             :         }
     663           0 :       }       
     664             :       
     665           0 :       if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
     666           0 :         Int_t found,foundable;//,shared;
     667             :         //RS GetCachedSeedClusterStatistic(0,60,found, foundable,shared,kFALSE); // RS make sure FillSeedClusterStatCache is called
     668             :         //pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE); //RS: avoid this method: seed does not keep clusters
     669           0 :         pt->GetClusterStatistic(0,60,found,foundable);
     670           0 :         if (found<20) continue;
     671           0 :         if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
     672             :         //
     673           0 :         iotrack.~AliESDtrack();
     674           0 :         new(&iotrack) AliESDtrack;
     675           0 :         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);      
     676           0 :         iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0)); 
     677           0 :         iotrack.SetTPCPoints(pt->GetPoints());
     678           0 :         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
     679           0 :         iotrack.SetV0Indexes(pt->GetV0Indexes());
     680           0 :         MakeESDBitmaps(pt, &iotrack);
     681             :         //iotrack.SetTPCpid(pt->fTPCr);
     682             :         //iotrack.SetTPCindex(i);
     683           0 :         fEvent->AddTrack(&iotrack);
     684           0 :         continue;
     685           0 :       }   
     686             :       // short tracks  - secondaties
     687             :       //
     688           0 :       if ( (pt->GetNumberOfClusters()>30) ) {
     689           0 :         Int_t found,foundable;//,shared;
     690             :         //GetCachedSeedClusterStatistic(128,158,found, foundable,shared,kFALSE); // RS make sure FillSeedClusterStatCache is called
     691             :         //pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);  //RS: avoid this method: seed does not keep clusters
     692           0 :         pt->GetClusterStatistic(128,158,found, foundable);
     693           0 :         if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
     694           0 :           iotrack.~AliESDtrack();
     695           0 :           new(&iotrack) AliESDtrack;
     696           0 :           iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);    
     697           0 :           iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0)); 
     698           0 :           iotrack.SetTPCPoints(pt->GetPoints());
     699           0 :           iotrack.SetKinkIndexes(pt->GetKinkIndexes());
     700           0 :           iotrack.SetV0Indexes(pt->GetV0Indexes());
     701           0 :           MakeESDBitmaps(pt, &iotrack);
     702             :           //iotrack.SetTPCpid(pt->fTPCr);    
     703             :           //iotrack.SetTPCindex(i);
     704           0 :           fEvent->AddTrack(&iotrack);
     705           0 :           continue;
     706             :         }
     707           0 :       }       
     708             :       
     709           0 :       if ( (pt->GetNumberOfClusters()>15)) {
     710           0 :         Int_t found,foundable,shared;
     711             :         //GetCachedSeedClusterStatistic(138,158,found, foundable,shared,kFALSE); // RS make sure FillSeedClusterStatCache is called
     712             :         //RS pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);  //RS: avoid this method: seed does not keep clusters
     713           0 :         pt->GetClusterStatistic(138,158,found, foundable);
     714           0 :         if (found<15) continue;
     715           0 :         if (foundable<=0) continue;
     716           0 :         if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
     717           0 :         if (float(found)/float(foundable)<0.8) continue;
     718             :         //
     719           0 :         iotrack.~AliESDtrack();
     720           0 :         new(&iotrack) AliESDtrack;
     721           0 :         iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);      
     722           0 :         iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0)); 
     723           0 :         iotrack.SetTPCPoints(pt->GetPoints());
     724           0 :         iotrack.SetKinkIndexes(pt->GetKinkIndexes());
     725           0 :         iotrack.SetV0Indexes(pt->GetV0Indexes());
     726           0 :         MakeESDBitmaps(pt, &iotrack);
     727             :         //      iotrack.SetTPCpid(pt->fTPCr);
     728             :         //iotrack.SetTPCindex(i);
     729           0 :         fEvent->AddTrack(&iotrack);
     730           0 :         continue;
     731           0 :       }   
     732           0 :     }
     733             :     // >> account for suppressed tracks in the kink indices (RS)
     734           8 :     int nESDtracks = fEvent->GetNumberOfTracks();
     735         152 :     for (int it=nESDtracks;it--;) {
     736         136 :       AliESDtrack* esdTr = fEvent->GetTrack(it);
     737         536 :       if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
     738          32 :       for (int ik=0;ik<3;ik++) {
     739             :         int knkId=0;
     740          40 :         if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
     741           8 :         AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
     742           8 :         if (!kink) {
     743           0 :           AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
     744           0 :           continue;
     745             :         }
     746           8 :         kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
     747           8 :       }
     748           8 :     }
     749             : 
     750             :     // << account for suppressed tracks in the kink indices (RS)  
     751          32 :     AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
     752             :   
     753          16 : }
     754             : 
     755             : //_____________________________________________________________________________________
     756             : void AliTPCtracker::ErrY2Z2(AliTPCseed* seed, const AliTPCclusterMI * cl, double &erry2, double &errz2)
     757             : {
     758             :   //
     759             :   //
     760             :   // Use calibrated cluster error from OCDB
     761             :   //
     762      209276 :   const AliTPCRecoParam* rp = AliTPCReconstructor::GetRecoParam();
     763      104638 :   AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
     764             :   //
     765      104638 :   Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
     766      104638 :   Int_t ctype = cl->GetType();  
     767      231950 :   Int_t    type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
     768      104638 :   double   snp2 = seed->GetSnp()*seed->GetSnp();
     769      104638 :   if (snp2>1.-1e-6) snp2 = 1.-1e-6;
     770      104638 :   double   tgp2 = snp2/(1.f-snp2);
     771      104638 :   double   tgp  = TMath::Sqrt(tgp2);
     772      104638 :   double   tgl2m = seed->GetTgl()*seed->GetTgl()*(1+tgp2); 
     773      104638 :   Double_t tglm = TMath::Sqrt(tgl2m);
     774      104638 :   erry2 = clparam->GetError0Par(0,type, z,tgp);
     775      104638 :   errz2 = clparam->GetError0Par(1,type, z,tglm);
     776      104638 :   if (ctype<0) { // edge cluster
     777        2622 :     erry2+=0.5;  
     778        2622 :     errz2+=0.5; 
     779        2622 :   }
     780      104638 :   erry2 *= erry2;
     781      104638 :   errz2 *= errz2;
     782             :   // additional systematic error on the cluster
     783      104638 :   double serry2=0,serrz2=0;
     784      104638 :   AliTPCcalibDB::Instance()->GetTransform()->ErrY2Z2Syst(cl, tgp, seed->GetTgl(), serry2,serrz2);
     785      104638 :   erry2 += serry2;
     786      104638 :   errz2 += serrz2;
     787      104638 :   seed->SetErrorY2(erry2);
     788      104638 :   seed->SetErrorZ2(errz2);
     789             :   //
     790      104638 : }
     791             : 
     792             : 
     793             : 
     794             : //_____________________________________________________________________________________
     795             : Double_t AliTPCtracker::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
     796             :   //
     797             :   //
     798             :   // Use calibrated cluster error from OCDB
     799             :   //
     800           0 :   const AliTPCRecoParam* rp = AliTPCReconstructor::GetRecoParam();
     801           0 :   AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
     802             :   //
     803           0 :   Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
     804           0 :   Int_t ctype = cl->GetType();  
     805           0 :   Int_t    type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
     806           0 :   double   angle2 = seed->GetSnp()*seed->GetSnp();
     807           0 :   double   angle = TMath::Sqrt(TMath::Abs(angle2/(1.f-angle2)));
     808           0 :   Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
     809           0 :   if (ctype<0) {
     810           0 :     erry2+=0.5;  // edge cluster
     811           0 :   }
     812           0 :   erry2 *= erry2;
     813             :   // additional systematic error on the cluster
     814           0 :   erry2 += AliTPCcalibDB::Instance()->GetTransform()->ErrY2Syst(cl, angle);
     815           0 :   seed->SetErrorY2(erry2);
     816             :   //
     817           0 :   return erry2;
     818             : 
     819             : //calculate look-up table at the beginning
     820             : //   static Bool_t  ginit = kFALSE;
     821             : //   static Float_t gnoise1,gnoise2,gnoise3;
     822             : //   static Float_t ggg1[10000];
     823             : //   static Float_t ggg2[10000];
     824             : //   static Float_t ggg3[10000];
     825             : //   static Float_t glandau1[10000];
     826             : //   static Float_t glandau2[10000];
     827             : //   static Float_t glandau3[10000];
     828             : //   //
     829             : //   static Float_t gcor01[500];
     830             : //   static Float_t gcor02[500];
     831             : //   static Float_t gcorp[500];
     832             : //   //
     833             : 
     834             : //   //
     835             : //   if (ginit==kFALSE){
     836             : //     for (Int_t i=1;i<500;i++){
     837             : //       Float_t rsigma = float(i)/100.;
     838             : //       gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
     839             : //       gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
     840             : //       gcorp[i]  = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
     841             : //     }
     842             : 
     843             : //     //
     844             : //     for (Int_t i=3;i<10000;i++){
     845             : //       //
     846             : //       //
     847             : //       // inner sector
     848             : //       Float_t amp = float(i);
     849             : //       Float_t padlength =0.75;
     850             : //       gnoise1 = 0.0004/padlength;
     851             : //       Float_t nel     = 0.268*amp;
     852             : //       Float_t nprim   = 0.155*amp;
     853             : //       ggg1[i]          = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
     854             : //       glandau1[i]      = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
     855             : //       if (glandau1[i]>1) glandau1[i]=1;
     856             : //       glandau1[i]*=padlength*padlength/12.;      
     857             : //       //
     858             : //       // outer short
     859             : //       padlength =1.;
     860             : //       gnoise2   = 0.0004/padlength;
     861             : //       nel       = 0.3*amp;
     862             : //       nprim     = 0.133*amp;
     863             : //       ggg2[i]      = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
     864             : //       glandau2[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
     865             : //       if (glandau2[i]>1) glandau2[i]=1;
     866             : //       glandau2[i]*=padlength*padlength/12.;
     867             : //       //
     868             : //       //
     869             : //       // outer long
     870             : //       padlength =1.5;
     871             : //       gnoise3   = 0.0004/padlength;
     872             : //       nel       = 0.3*amp;
     873             : //       nprim     = 0.133*amp;
     874             : //       ggg3[i]      = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
     875             : //       glandau3[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
     876             : //       if (glandau3[i]>1) glandau3[i]=1;
     877             : //       glandau3[i]*=padlength*padlength/12.;
     878             : //       //
     879             : //     }
     880             : //     ginit = kTRUE;
     881             : //   }
     882             : //   //
     883             : //   //
     884             : //   //
     885             : //   Int_t amp = int(TMath::Abs(cl->GetQ()));  
     886             : //   if (amp>9999) {
     887             : //     seed->SetErrorY2(1.);
     888             : //     return 1.;
     889             : //   }
     890             : //   Float_t snoise2;
     891             : //   Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
     892             : //   Int_t ctype = cl->GetType();  
     893             : //   Float_t padlength= GetPadPitchLength(seed->GetRow());
     894             : //   Double_t angle2 = seed->GetSnp()*seed->GetSnp();
     895             : //   angle2 = angle2/(1-angle2); 
     896             : //   //
     897             : //   //cluster "quality"
     898             : //   Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
     899             : //   Float_t res;
     900             : //   //
     901             : //   if (fSectors==fInnerSec){
     902             : //     snoise2 = gnoise1;
     903             : //     res     = ggg1[amp]*z+glandau1[amp]*angle2;     
     904             : //     if (ctype==0) res *= gcor01[rsigmay];
     905             : //     if ((ctype>0)){
     906             : //       res+=0.002;
     907             : //       res*= gcorp[rsigmay];
     908             : //     }
     909             : //   }
     910             : //   else {
     911             : //     if (padlength<1.1){
     912             : //       snoise2 = gnoise2;
     913             : //       res     = ggg2[amp]*z+glandau2[amp]*angle2; 
     914             : //       if (ctype==0) res *= gcor02[rsigmay];      
     915             : //       if ((ctype>0)){
     916             : //      res+=0.002;
     917             : //      res*= gcorp[rsigmay];
     918             : //       }
     919             : //     }
     920             : //     else{
     921             : //       snoise2 = gnoise3;      
     922             : //       res     = ggg3[amp]*z+glandau3[amp]*angle2; 
     923             : //       if (ctype==0) res *= gcor02[rsigmay];
     924             : //       if ((ctype>0)){
     925             : //      res+=0.002;
     926             : //      res*= gcorp[rsigmay];
     927             : //       }
     928             : //     }
     929             : //   }  
     930             : 
     931             : //   if (ctype<0){
     932             : //     res+=0.005;
     933             : //     res*=2.4;  // overestimate error 2 times
     934             : //   }
     935             : //   res+= snoise2;
     936             :  
     937             : //   if (res<2*snoise2)
     938             : //     res = 2*snoise2;
     939             :   
     940             : //   seed->SetErrorY2(res);
     941             : //   return res;
     942             : 
     943             : 
     944             : }
     945             : 
     946             : 
     947             : //__________________________________________________________________________________
     948             : Double_t AliTPCtracker::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
     949             :   //
     950             :   //
     951             :   // Use calibrated cluster error from OCDB
     952             :   //
     953           0 :   const AliTPCRecoParam* rp = AliTPCReconstructor::GetRecoParam();
     954           0 :   AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
     955             :   //
     956           0 :   Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
     957           0 :   Int_t ctype = cl->GetType();  
     958           0 :   Int_t    type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
     959             :   //
     960           0 :   double angle2 = seed->GetSnp()*seed->GetSnp();
     961           0 :   angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2)); 
     962           0 :   Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
     963           0 :   Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
     964           0 :   if (ctype<0) {
     965           0 :     errz2+=0.5;  // edge cluster
     966           0 :   }
     967           0 :   errz2*=errz2;
     968             :   // additional systematic error on the cluster
     969           0 :   errz2 += AliTPCcalibDB::Instance()->GetTransform()->ErrZ2Syst(cl, seed->GetTgl());
     970           0 :   seed->SetErrorZ2(errz2);
     971             :   //
     972           0 :   return errz2;
     973             : 
     974             : 
     975             : 
     976             : //   //seed->SetErrorY2(0.1);
     977             : //   //return 0.1;
     978             : //   //calculate look-up table at the beginning
     979             : //   static Bool_t  ginit = kFALSE;
     980             : //   static Float_t gnoise1,gnoise2,gnoise3;
     981             : //   static Float_t ggg1[10000];
     982             : //   static Float_t ggg2[10000];
     983             : //   static Float_t ggg3[10000];
     984             : //   static Float_t glandau1[10000];
     985             : //   static Float_t glandau2[10000];
     986             : //   static Float_t glandau3[10000];
     987             : //   //
     988             : //   static Float_t gcor01[1000];
     989             : //   static Float_t gcor02[1000];
     990             : //   static Float_t gcorp[1000];
     991             : //   //
     992             : 
     993             : //   //
     994             : //   if (ginit==kFALSE){
     995             : //     for (Int_t i=1;i<1000;i++){
     996             : //       Float_t rsigma = float(i)/100.;
     997             : //       gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
     998             : //       gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
     999             : //       gcorp[i]  = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
    1000             : //     }
    1001             : 
    1002             : //     //
    1003             : //     for (Int_t i=3;i<10000;i++){
    1004             : //       //
    1005             : //       //
    1006             : //       // inner sector
    1007             : //       Float_t amp = float(i);
    1008             : //       Float_t padlength =0.75;
    1009             : //       gnoise1 = 0.0004/padlength;
    1010             : //       Float_t nel     = 0.268*amp;
    1011             : //       Float_t nprim   = 0.155*amp;
    1012             : //       ggg1[i]          = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
    1013             : //       glandau1[i]      = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
    1014             : //       if (glandau1[i]>1) glandau1[i]=1;
    1015             : //       glandau1[i]*=padlength*padlength/12.;      
    1016             : //       //
    1017             : //       // outer short
    1018             : //       padlength =1.;
    1019             : //       gnoise2   = 0.0004/padlength;
    1020             : //       nel       = 0.3*amp;
    1021             : //       nprim     = 0.133*amp;
    1022             : //       ggg2[i]      = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
    1023             : //       glandau2[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
    1024             : //       if (glandau2[i]>1) glandau2[i]=1;
    1025             : //       glandau2[i]*=padlength*padlength/12.;
    1026             : //       //
    1027             : //       //
    1028             : //       // outer long
    1029             : //       padlength =1.5;
    1030             : //       gnoise3   = 0.0004/padlength;
    1031             : //       nel       = 0.3*amp;
    1032             : //       nprim     = 0.133*amp;
    1033             : //       ggg3[i]      = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
    1034             : //       glandau3[i]  = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
    1035             : //       if (glandau3[i]>1) glandau3[i]=1;
    1036             : //       glandau3[i]*=padlength*padlength/12.;
    1037             : //       //
    1038             : //     }
    1039             : //     ginit = kTRUE;
    1040             : //   }
    1041             : //   //
    1042             : //   //
    1043             : //   //
    1044             : //   Int_t amp = int(TMath::Abs(cl->GetQ()));  
    1045             : //   if (amp>9999) {
    1046             : //     seed->SetErrorY2(1.);
    1047             : //     return 1.;
    1048             : //   }
    1049             : //   Float_t snoise2;
    1050             : //   Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
    1051             : //   Int_t ctype = cl->GetType();  
    1052             : //   Float_t padlength= GetPadPitchLength(seed->GetRow());
    1053             : //   //
    1054             : //   Double_t angle2 = seed->GetSnp()*seed->GetSnp();
    1055             : //   //  if (angle2<0.6) angle2 = 0.6;
    1056             : //   angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2)); 
    1057             : //   //
    1058             : //   //cluster "quality"
    1059             : //   Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
    1060             : //   Float_t res;
    1061             : //   //
    1062             : //   if (fSectors==fInnerSec){
    1063             : //     snoise2 = gnoise1;
    1064             : //     res     = ggg1[amp]*z+glandau1[amp]*angle2;     
    1065             : //     if (ctype==0) res *= gcor01[rsigmaz];
    1066             : //     if ((ctype>0)){
    1067             : //       res+=0.002;
    1068             : //       res*= gcorp[rsigmaz];
    1069             : //     }
    1070             : //   }
    1071             : //   else {
    1072             : //     if (padlength<1.1){
    1073             : //       snoise2 = gnoise2;
    1074             : //       res     = ggg2[amp]*z+glandau2[amp]*angle2; 
    1075             : //       if (ctype==0) res *= gcor02[rsigmaz];      
    1076             : //       if ((ctype>0)){
    1077             : //      res+=0.002;
    1078             : //      res*= gcorp[rsigmaz];
    1079             : //       }
    1080             : //     }
    1081             : //     else{
    1082             : //       snoise2 = gnoise3;      
    1083             : //       res     = ggg3[amp]*z+glandau3[amp]*angle2; 
    1084             : //       if (ctype==0) res *= gcor02[rsigmaz];
    1085             : //       if ((ctype>0)){
    1086             : //      res+=0.002;
    1087             : //      res*= gcorp[rsigmaz];
    1088             : //       }
    1089             : //     }
    1090             : //   }  
    1091             : 
    1092             : //   if (ctype<0){
    1093             : //     res+=0.002;
    1094             : //     res*=1.3;
    1095             : //   }
    1096             : //   if ((ctype<0) &&amp<70){
    1097             : //     res+=0.002;
    1098             : //     res*=1.3;  
    1099             : //   }
    1100             : //   res += snoise2;
    1101             : //   if (res<2*snoise2)
    1102             : //      res = 2*snoise2;
    1103             : //   if (res>3) res =3;
    1104             : //   seed->SetErrorZ2(res);
    1105             : //   return res;
    1106             : }
    1107             : 
    1108             : 
    1109             : 
    1110             : 
    1111             : 
    1112             : void AliTPCtracker::RotateToLocal(AliTPCseed *seed)
    1113             : {
    1114             :   //rotate to track "local coordinata
    1115           0 :   Float_t x = seed->GetX();
    1116           0 :   Float_t y = seed->GetY();
    1117           0 :   Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
    1118             :   
    1119           0 :   if (y > ymax) {
    1120           0 :     seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
    1121           0 :     if (!seed->Rotate(fSectors->GetAlpha())) 
    1122           0 :       return;
    1123           0 :   } else if (y <-ymax) {
    1124           0 :     seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
    1125           0 :     if (!seed->Rotate(-fSectors->GetAlpha())) 
    1126           0 :       return;
    1127             :   }   
    1128             : 
    1129           0 : }
    1130             : 
    1131             : 
    1132             : 
    1133             : //_____________________________________________________________________________
    1134             : Double_t AliTPCtracker::F1old(Double_t x1,Double_t y1,
    1135             :                    Double_t x2,Double_t y2,
    1136             :                    Double_t x3,Double_t y3) const
    1137             : {
    1138             :   //-----------------------------------------------------------------
    1139             :   // Initial approximation of the track curvature
    1140             :   //-----------------------------------------------------------------
    1141           0 :   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
    1142           0 :   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
    1143           0 :                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
    1144           0 :   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
    1145           0 :                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
    1146             : 
    1147           0 :   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
    1148           0 :   if ( xr*xr+yr*yr<=0.00000000000001) return 100;
    1149           0 :   return -xr*yr/sqrt(xr*xr+yr*yr); 
    1150           0 : }
    1151             : 
    1152             : 
    1153             : 
    1154             : //_____________________________________________________________________________
    1155             : Double_t AliTPCtracker::F1(Double_t x1,Double_t y1,
    1156             :                    Double_t x2,Double_t y2,
    1157             :                    Double_t x3,Double_t y3) const
    1158             : {
    1159             :   //-----------------------------------------------------------------
    1160             :   // Initial approximation of the track curvature
    1161             :   //-----------------------------------------------------------------
    1162        5144 :   x3 -=x1;
    1163        2572 :   x2 -=x1;
    1164        2572 :   y3 -=y1;
    1165        2572 :   y2 -=y1;
    1166             :   //  
    1167        2572 :   Double_t det = x3*y2-x2*y3;
    1168        2572 :   if (TMath::Abs(det)<1e-10){
    1169           0 :     return 100;
    1170             :   }
    1171             :   //
    1172        2572 :   Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
    1173        2572 :   Double_t x0 = x3*0.5-y3*u;
    1174        2572 :   Double_t y0 = y3*0.5+x3*u;
    1175        2572 :   Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
    1176        3854 :   if (det<0) c2*=-1;
    1177             :   return c2;
    1178        2572 : }
    1179             : 
    1180             : 
    1181             : Double_t AliTPCtracker::F2(Double_t x1,Double_t y1,
    1182             :                    Double_t x2,Double_t y2,
    1183             :                    Double_t x3,Double_t y3) const 
    1184             : {
    1185             :   //-----------------------------------------------------------------
    1186             :   // Initial approximation of the track curvature
    1187             :   //-----------------------------------------------------------------
    1188        5144 :   x3 -=x1;
    1189        2572 :   x2 -=x1;
    1190        2572 :   y3 -=y1;
    1191        2572 :   y2 -=y1;
    1192             :   //  
    1193        2572 :   Double_t det = x3*y2-x2*y3;
    1194        2572 :   if (TMath::Abs(det)<1e-10) {
    1195           0 :     return 100;
    1196             :   }
    1197             :   //
    1198        2572 :   Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
    1199        2572 :   Double_t x0 = x3*0.5-y3*u; 
    1200        2572 :   Double_t y0 = y3*0.5+x3*u;
    1201        2572 :   Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
    1202        3854 :   if (det<0) c2*=-1;
    1203        2572 :   x0+=x1;
    1204        2572 :   x0*=c2;  
    1205             :   return x0;
    1206        2572 : }
    1207             : 
    1208             : 
    1209             : 
    1210             : //_____________________________________________________________________________
    1211             : Double_t AliTPCtracker::F2old(Double_t x1,Double_t y1,
    1212             :                    Double_t x2,Double_t y2,
    1213             :                    Double_t x3,Double_t y3) const
    1214             : {
    1215             :   //-----------------------------------------------------------------
    1216             :   // Initial approximation of the track curvature times center of curvature
    1217             :   //-----------------------------------------------------------------
    1218           0 :   Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
    1219           0 :   Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
    1220           0 :                   (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
    1221           0 :   Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
    1222           0 :                   (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
    1223             : 
    1224           0 :   Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
    1225             :   
    1226           0 :   return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
    1227             : }
    1228             : 
    1229             : //_____________________________________________________________________________
    1230             : Double_t AliTPCtracker::F3(Double_t x1,Double_t y1, 
    1231             :                    Double_t x2,Double_t y2,
    1232             :                    Double_t z1,Double_t z2) const
    1233             : {
    1234             :   //-----------------------------------------------------------------
    1235             :   // Initial approximation of the tangent of the track dip angle
    1236             :   //-----------------------------------------------------------------
    1237        5600 :   return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    1238             : }
    1239             : 
    1240             : 
    1241             : Double_t AliTPCtracker::F3n(Double_t x1,Double_t y1, 
    1242             :                    Double_t x2,Double_t y2,
    1243             :                    Double_t z1,Double_t z2, Double_t c) const
    1244             : {
    1245             :   //-----------------------------------------------------------------
    1246             :   // Initial approximation of the tangent of the track dip angle
    1247             :   //-----------------------------------------------------------------
    1248             : 
    1249             :   //  Double_t angle1;
    1250             :   
    1251             :   //angle1    =  (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
    1252             :   //
    1253         944 :   Double_t d  =  TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    1254         472 :   if (TMath::Abs(d*c*0.5)>1) return 0;
    1255         472 :   Double_t   angle2    = asinf(d*c*0.5);
    1256             : 
    1257         472 :   angle2  = (z1-z2)*c/(angle2*2.);
    1258             :   return angle2;
    1259         472 : }
    1260             : 
    1261             : Bool_t   AliTPCtracker::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
    1262             : {//-----------------------------------------------------------------
    1263             :   // This function find proloncation of a track to a reference plane x=x2.
    1264             :   //-----------------------------------------------------------------
    1265             :   
    1266         668 :   Double_t dx=x2-x1;
    1267         334 :   Double_t c1=x[4]*x1 - x[2];
    1268         334 :   if (TMath::Abs(c1) >= 0.999) return kFALSE;
    1269         334 :   Double_t c2=x[4]*x2 - x[2];
    1270         334 :   if (TMath::Abs(c2) >= 0.999) return kFALSE;
    1271         334 :   Double_t r1=TMath::Sqrt((1.-c1)*(1.+c1)),r2=TMath::Sqrt((1.-c2)*(1.+c2));  
    1272         334 :   y = x[0];
    1273         334 :   z = x[1];
    1274             :   
    1275         334 :   Double_t dy = dx*(c1+c2)/(r1+r2);
    1276             :   //
    1277         334 :   Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
    1278         334 :   Double_t dz = x[3]*asinf(delta)/x[4];
    1279             :   
    1280         334 :   y+=dy;
    1281         334 :   z+=dz;
    1282             :   
    1283             :   return kTRUE;  
    1284         334 : }
    1285             : 
    1286             : Bool_t   AliTPCtracker::GetProlongationLine(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
    1287             : {//-----------------------------------------------------------------
    1288             :   // This function find straight line prolongation of a track to a reference plane x=x2.
    1289             :   //-----------------------------------------------------------------
    1290             :   
    1291           0 :   if (TMath::Abs(x[2]) >= 0.999) return kFALSE;
    1292           0 :   Double_t c1=- x[2], dx2r = (x2-x1)/TMath::Sqrt((1.-c1)*(1.+c1));
    1293           0 :   y = x[0] + dx2r*c1;
    1294           0 :   z = x[1] + dx2r*x[3];
    1295             :   return kTRUE;  
    1296           0 : }
    1297             : 
    1298             : 
    1299             : Int_t  AliTPCtracker::LoadClusters (TTree *const tree)
    1300             : {
    1301             :   // load clusters
    1302             :   //
    1303          16 :   fInput = tree;
    1304           8 :   return LoadClusters();
    1305             : }
    1306             : 
    1307             : 
    1308             : Int_t  AliTPCtracker::LoadClusters(const TObjArray *arr)
    1309             : {
    1310             :   //
    1311             :   // load clusters to the memory
    1312             :   AliTPCClustersRow *clrow = 0; //RS: why this new? new AliTPCClustersRow("AliTPCclusterMI");
    1313           0 :   Int_t lower   = arr->LowerBound();
    1314           0 :   Int_t entries = arr->GetEntriesFast();
    1315             : 
    1316           0 :   AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
    1317           0 :   AliTPCTransform *transform = calibDB->GetTransform() ;
    1318           0 :   transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
    1319           0 :   transform->SetCurrentTimeStamp( GetTimeStamp());
    1320           0 :   transform->SetCurrentRun( GetRunNumber() );
    1321             : 
    1322           0 :   AliWarning("Sector Change ins not checked in LoadClusters(const TObjArray *arr)");
    1323             : 
    1324           0 :   for (Int_t i=lower; i<entries; i++) {
    1325           0 :     clrow = (AliTPCClustersRow*) arr->At(i);
    1326           0 :     if(!clrow) continue;
    1327           0 :     TClonesArray* arr = clrow->GetArray();
    1328           0 :     if(!arr) continue;
    1329           0 :     int ncl = arr->GetEntriesFast();
    1330           0 :     if (ncl<1) continue;
    1331             :     //  
    1332           0 :     Int_t sec,row;
    1333           0 :     fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
    1334             :     
    1335           0 :     for (Int_t icl=ncl; icl--;) {
    1336           0 :       Transform((AliTPCclusterMI*)(arr->At(icl)));
    1337             :     }
    1338             :     //
    1339             :     // RS: Check for possible sector change due to the distortions: TODO
    1340             :     //
    1341             :     AliTPCtrackerRow * tpcrow=0;
    1342             :     Int_t left=0;
    1343           0 :     if (sec<fkNIS*2){
    1344           0 :       tpcrow = &(fInnerSec[sec%fkNIS][row]);    
    1345           0 :       left = sec/fkNIS;
    1346           0 :     }
    1347             :     else{
    1348           0 :       tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
    1349           0 :       left = (sec-fkNIS*2)/fkNOS;
    1350             :     }
    1351           0 :     if (left ==0){
    1352           0 :       tpcrow->SetN1(ncl);
    1353           0 :       for (Int_t j=0;j<ncl;++j) 
    1354           0 :         tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(arr->At(j)));
    1355           0 :     }
    1356           0 :     if (left ==1){
    1357           0 :       tpcrow->SetN2(ncl);
    1358           0 :       for (Int_t j=0;j<ncl;++j) 
    1359           0 :         tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(arr->At(j)));
    1360           0 :     }
    1361           0 :     clrow->GetArray()->Clear(); // RS AliTPCclusterMI does not allocate memory
    1362           0 :   }
    1363             :   //
    1364             :   //  delete clrow;
    1365           0 :   LoadOuterSectors();
    1366           0 :   LoadInnerSectors();
    1367           0 :   return 0;
    1368             : }
    1369             : 
    1370             : Int_t  AliTPCtracker::LoadClusters(const TClonesArray *arr)
    1371             : {
    1372             :   //
    1373             :   // load clusters to the memory from one 
    1374             :   // TClonesArray
    1375             :   //
    1376             :   // RS: Check for possible sector change due to the distortions: TODO
    1377           0 :   AliWarning("Sector Change ins not checked in LoadClusters(const TClonesArray *arr)");
    1378             :   //
    1379             : 
    1380           0 :   AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
    1381           0 :   AliTPCTransform *transform = calibDB->GetTransform() ;
    1382           0 :   transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
    1383           0 :   transform->SetCurrentTimeStamp( GetTimeStamp());
    1384           0 :   transform->SetCurrentRun( GetRunNumber() );
    1385             :   //
    1386             :   AliTPCclusterMI *clust=0;
    1387           0 :   Int_t count[72][96] = { {0} , {0} }; 
    1388             : 
    1389             :   // loop over clusters
    1390           0 :   for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
    1391           0 :     clust = (AliTPCclusterMI*)arr->At(icl);
    1392           0 :     if(!clust) continue;
    1393             :     //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
    1394             : 
    1395             :     // transform clusters
    1396           0 :     Transform(clust);
    1397             : 
    1398             :     // count clusters per pad row
    1399           0 :     count[clust->GetDetector()][clust->GetRow()]++;
    1400           0 :   }
    1401             : 
    1402             :   // insert clusters to sectors
    1403           0 :   for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
    1404           0 :     clust = (AliTPCclusterMI*)arr->At(icl);
    1405           0 :     if(!clust) continue;
    1406             : 
    1407           0 :     Int_t sec = clust->GetDetector();
    1408           0 :     Int_t row = clust->GetRow();
    1409             : 
    1410             :     // filter overlapping pad rows needed by HLT
    1411           0 :     if(sec<fkNIS*2) { //IROCs
    1412           0 :      if(row == 30) continue;
    1413             :     }
    1414             :     else { // OROCs
    1415           0 :       if(row == 27 || row == 76) continue;
    1416             :     }
    1417             : 
    1418             :     //    Int_t left=0;
    1419           0 :     if (sec<fkNIS*2){
    1420             :       //      left = sec/fkNIS;
    1421           0 :       fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);    
    1422           0 :     }
    1423             :     else{
    1424             :       //      left = (sec-fkNIS*2)/fkNOS;
    1425           0 :       fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
    1426             :     }
    1427           0 :   }
    1428             : 
    1429             :   // Load functions must be called behind LoadCluster(TClonesArray*)
    1430             :   // needed by HLT
    1431             :   //LoadOuterSectors();
    1432             :   //LoadInnerSectors();
    1433             : 
    1434           0 :   return 0;
    1435           0 : }
    1436             : 
    1437             : Int_t  AliTPCtracker::LoadClusters()
    1438             : {
    1439             :  //
    1440             :   // load clusters to the memory
    1441          24 :   static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
    1442             :   //
    1443             : 
    1444           8 :   AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
    1445           8 :   AliTPCTransform *transform = calibDB->GetTransform() ;
    1446           8 :   transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
    1447           8 :   transform->SetCurrentTimeStamp( GetTimeStamp());
    1448           8 :   transform->SetCurrentRun( GetRunNumber() );
    1449             : 
    1450             :   //  TTree * tree = fClustersArray.GetTree();
    1451           8 :   AliInfo("LoadClusters()\n");
    1452             : 
    1453           8 :   fNClusters = 0;
    1454             : 
    1455           8 :   TTree * tree = fInput;
    1456           8 :   TBranch * br = tree->GetBranch("Segment");
    1457           8 :   br->SetAddress(&clrow);
    1458             : 
    1459             :   // Conversion of pad, row coordinates in local tracking coords.
    1460             :   // Could be skipped here; is already done in clusterfinder
    1461             : 
    1462           8 :   double cutZ2X = AliTPCReconstructor::GetPrimaryZ2XCut();
    1463           8 :   double cutZOutSector = AliTPCReconstructor::GetZOutSectorCut();
    1464           8 :   if (cutZOutSector>0 && AliTPCReconstructor::GetExtendedRoads()) 
    1465           0 :     cutZOutSector += AliTPCReconstructor::GetExtendedRoads()[1];
    1466             :   //
    1467           8 :   if (cutZ2X>0 || cutZOutSector>0) {
    1468           0 :     AliInfoF("Cut on cluster |Z/X| : %s, on cluster Z on wrong CE side: %s",
    1469             :              cutZ2X>0        ? Form("%.3f",cutZ2X) : "N/A",
    1470             :              cutZOutSector>0 ? Form("%.3f",cutZOutSector) : "N/A");
    1471           0 :   }
    1472           8 :   Int_t j=Int_t(tree->GetEntries());
    1473       91474 :   for (Int_t i=0; i<j; i++) {
    1474       45729 :     br->GetEntry(i);
    1475             :     //
    1476       45729 :     TClonesArray* clArr = clrow->GetArray();
    1477       45729 :     int nClus = clArr->GetEntriesFast();
    1478       45729 :     Int_t sec,row;
    1479       45729 :     fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
    1480      221354 :     for (Int_t icl=nClus; icl--;) Transform((AliTPCclusterMI*)(clArr->At(icl)));
    1481             :     //
    1482             :     AliTPCtrackerRow * tpcrow=0;
    1483             :     Int_t left=0;
    1484       45729 :     if (sec<fkNIS*2){
    1485       18081 :       tpcrow = &(fInnerSec[sec%fkNIS][row]);    
    1486       18081 :       left = sec/fkNIS;
    1487       18081 :     }
    1488             :     else{
    1489       27648 :       tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
    1490       27648 :       left = (sec-fkNIS*2)/fkNOS;
    1491             :     }
    1492             :     int nClusAdd = 0;
    1493       45729 :     if (left ==0){  // A side     
    1494      113132 :       for (int k=0;k<nClus;k++) {
    1495       33670 :         const AliTPCclusterMI& cl = *((AliTPCclusterMI*)clArr->At(k));
    1496       33670 :         if (cutZOutSector>0 && cl.GetZ()<-cutZOutSector) continue;
    1497       33670 :         if (cutZ2X>0 && cl.GetZ()/cl.GetX() > cutZ2X) continue;
    1498       33670 :         tpcrow->SetCluster1(nClusAdd++, cl);
    1499       33670 :       }
    1500       22896 :       tpcrow->SetN1(nClusAdd);
    1501       22896 :     }
    1502       45729 :     if (left ==1){ // C side
    1503      108222 :       for (int k=0;k<nClus;k++) {
    1504       31278 :         const AliTPCclusterMI& cl = *((AliTPCclusterMI*)clArr->At(k));
    1505       31278 :         if (cutZOutSector>0 && cl.GetZ()>cutZOutSector) continue;
    1506       31278 :         if (cutZ2X>0 && cl.GetZ()/cl.GetX() < -cutZ2X) continue;
    1507       31278 :         tpcrow->SetCluster2(nClusAdd++, cl);
    1508       31278 :       }
    1509       22833 :       tpcrow->SetN2(nClusAdd);
    1510       22833 :     }
    1511       45729 :     fNClusters += nClusAdd;
    1512       45729 :   }
    1513             :   //
    1514             :   //clrow->Clear("C");
    1515           8 :   clrow->Clear(); // RS AliTPCclusterMI does not allocate memory
    1516           8 :   LoadOuterSectors();
    1517           8 :   LoadInnerSectors();
    1518             : 
    1519           8 :   cout << " =================================================================================================================================== " << endl;
    1520           8 :   cout << " AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection() =  " << AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection() << endl;
    1521           8 :   cout << " AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection()  =  " << AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection()  << endl;
    1522           8 :   cout << " =================================================================================================================================== " << endl;
    1523             : 
    1524           8 :   if (AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection()) ApplyTailCancellation();
    1525           8 :   if (AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection()!=0.) CalculateXtalkCorrection();
    1526           8 :   if (AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection()!=0.) ApplyXtalkCorrection();
    1527             :   //if (AliTPCReconstructor::GetRecoParam()->GetUseOulierClusterFilter()) FilterOutlierClusters();  
    1528             : 
    1529             :   /*
    1530             :   static int maxClus[18][2][kMaxRow]={0};
    1531             :   int maxAcc=0,nclEv=0, capacity=0;
    1532             :   for (int isec=0;isec<18;isec++) {
    1533             :     for (int irow=0;irow<kMaxRow;irow++) {
    1534             :       AliTPCtrackerRow * tpcrow = irow>62 ?  &(fOuterSec[isec][irow-63]) : &(fInnerSec[isec][irow]);
    1535             :       maxClus[isec][0][irow] = TMath::Max(maxClus[isec][0][irow], tpcrow->GetN1());
    1536             :       maxClus[isec][1][irow] = TMath::Max(maxClus[isec][1][irow], tpcrow->GetN2());
    1537             :       maxAcc += maxClus[isec][0][irow]+maxClus[isec][1][irow];
    1538             :       nclEv += tpcrow->GetN();
    1539             :       capacity += tpcrow->GetClusters1()->Capacity();
    1540             :       capacity += tpcrow->GetClusters2()->Capacity();
    1541             :     }
    1542             :   }
    1543             :   printf("RS:AccumulatedSpace: %d for %d | pointers: %d\n",maxAcc,nclEv,capacity);
    1544             :   */
    1545           8 :   return 0;
    1546           0 : }
    1547             : 
    1548             : void  AliTPCtracker::CalculateXtalkCorrection(){
    1549             :   //
    1550             :   // Calculate crosstalk estimate
    1551             :   //
    1552           0 :   TStopwatch sw;
    1553           0 :   sw.Start();
    1554             :   const Int_t nROCs   = 72;
    1555             :   const Int_t   nIterations=3;  // 
    1556             :   // 0.) reset crosstalk matrix 
    1557             :   //
    1558           0 :   for (Int_t isector=0; isector<nROCs*4; isector++){  //set all ellemts of crosstalk matrix to 0 
    1559           0 :     TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
    1560           0 :     if (crossTalkMatrix)(*crossTalkMatrix)*=0;
    1561             :   }
    1562             :   
    1563             :   //
    1564             :   // 1.) Filling part -- loop over clusters
    1565             :   //
    1566           0 :   Double_t missingChargeFactor= AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrectionMissingCharge();
    1567           0 :   for (Int_t iter=0; iter<nIterations;iter++){
    1568           0 :     for (Int_t isector=0; isector<36; isector++){      // loop over sectors
    1569           0 :       for (Int_t iside=0; iside<2; iside++){           // loop over sides A/C
    1570           0 :         AliTPCtrackerSector &sector= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
    1571           0 :         Int_t nrows = sector.GetNRows();
    1572             :         Int_t sec=0;
    1573           0 :         if (isector<18) sec=isector+18*iside;
    1574           0 :         if (isector>=18) sec=18+isector+18*iside;
    1575           0 :         for (Int_t row = 0;row<nrows;row++){           // loop over rows       
    1576             :           //
    1577             :           //
    1578           0 :           Int_t wireSegmentID     = fkParam->GetWireSegment(sec,row);
    1579           0 :           Float_t nPadsPerSegment = (Float_t)(fkParam->GetNPadsPerSegment(wireSegmentID));
    1580           0 :           TMatrixD &crossTalkSignal =  *((TMatrixD*)fCrossTalkSignalArray->At(sec));
    1581           0 :           TMatrixD &crossTalkSignalCache =  *((TMatrixD*)fCrossTalkSignalArray->At(sec+nROCs*2));   // this is the cache value of the crosstalk from previous iteration
    1582           0 :           TMatrixD &crossTalkSignalBelow =  *((TMatrixD*)fCrossTalkSignalArray->At(sec+nROCs));
    1583           0 :           Int_t nCols=crossTalkSignal.GetNcols();
    1584             :           //
    1585           0 :           AliTPCtrackerRow&  tpcrow = sector[row];       
    1586           0 :           Int_t ncl = tpcrow.GetN1();                  // number of clusters in the row
    1587           0 :           if (iside>0) ncl=tpcrow.GetN2();
    1588           0 :           for (Int_t i=0;i<ncl;i++) {  // loop over clusters
    1589           0 :             AliTPCclusterMI *clXtalk= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
    1590             :             
    1591           0 :             Int_t timeBinXtalk = clXtalk->GetTimeBin();      
    1592           0 :             Double_t rmsPadMin2=0.5*0.5+(fkParam->GetDiffT()*fkParam->GetDiffT())*(TMath::Abs((clXtalk->GetZ()-fkParam->GetZLength())))/(fkParam->GetPadPitchWidth(sec)*fkParam->GetPadPitchWidth(sec)); // minimal PRF width - 0.5 is the PRF in the pad units - we should et it from fkparam getters 
    1593           0 :             Double_t rmsTimeMin2=1+(fkParam->GetDiffL()*fkParam->GetDiffL())*(TMath::Abs((clXtalk->GetZ()-fkParam->GetZLength())))/(fkParam->GetZWidth()*fkParam->GetZWidth()); // minimal PRF width - 1 is the TRF in the time bin units - we should et it from fkParam getters
    1594           0 :             Double_t rmsTime2   = clXtalk->GetSigmaZ2()/(fkParam->GetZWidth()*fkParam->GetZWidth()); 
    1595           0 :             Double_t rmsPad2    = clXtalk->GetSigmaY2()/(fkParam->GetPadPitchWidth(sec)*fkParam->GetPadPitchWidth(sec)); 
    1596           0 :             if (rmsPadMin2>rmsPad2){
    1597             :               rmsPad2=rmsPadMin2;
    1598           0 :             }
    1599           0 :             if (rmsTimeMin2>rmsTime2){
    1600             :               rmsTime2=rmsTimeMin2;
    1601           0 :             }
    1602             :             
    1603           0 :             Double_t norm= 2.*TMath::Exp(-1.0/(2.*rmsTime2))+2.*TMath::Exp(-4.0/(2.*rmsTime2))+1.;
    1604             :             Double_t qTotXtalk = 0.;   
    1605             :             Double_t qTotXtalkMissing = 0.;   
    1606           0 :             for (Int_t itb=timeBinXtalk-2, idelta=-2; itb<=timeBinXtalk+2; itb++,idelta++) {        
    1607           0 :               if (itb<0 || itb>=nCols) continue;
    1608             :               Double_t missingCharge=0;
    1609           0 :               Double_t trf= TMath::Exp(-idelta*idelta/(2.*rmsTime2));
    1610           0 :               if (missingChargeFactor>0) {
    1611           0 :                 for (Int_t dpad=-2; dpad<=2; dpad++){
    1612           0 :                   Double_t qPad =   clXtalk->GetMax()*TMath::Exp(-dpad*dpad/(2.*rmsPad2))*trf;
    1613           0 :                   if (TMath::Nint(qPad-crossTalkSignalCache[wireSegmentID][itb])<=fkParam->GetZeroSup()){
    1614           0 :                     missingCharge+=qPad+crossTalkSignalCache[wireSegmentID][itb];
    1615           0 :                   }else{
    1616           0 :                     missingCharge+=crossTalkSignalCache[wireSegmentID][itb];
    1617             :                   }
    1618             :                 }
    1619           0 :               }
    1620           0 :               qTotXtalk = clXtalk->GetQ()*trf/norm+missingCharge*missingChargeFactor;
    1621             :               qTotXtalkMissing = missingCharge;
    1622           0 :               crossTalkSignal[wireSegmentID][itb]+= qTotXtalk/nPadsPerSegment; 
    1623           0 :               crossTalkSignalBelow[wireSegmentID][itb]+= qTotXtalkMissing/nPadsPerSegment; 
    1624           0 :             } // end of time bin loop
    1625             :           } // end of cluster loop      
    1626             :         } // end of rows loop
    1627             :       }  // end of side loop
    1628             :     }    // end of sector loop
    1629             :     //
    1630             :     // copy crosstalk matrix to cached used for next itteration
    1631             :     //
    1632             :     //
    1633             :     // 2.) dump the crosstalk matrices to tree for further investigation
    1634             :     //     a.) to estimate fluctuation of pedestal in indiviula wire segments
    1635             :     //     b.) to check correlation between regions
    1636             :     //     c.) to check relative conribution of signal below threshold to crosstalk
    1637             :     
    1638           0 :     if (AliTPCReconstructor::StreamLevel()&kStreamCrosstalkMatrix) {
    1639           0 :       for (Int_t isector=0; isector<nROCs; isector++){  //set all ellemts of crosstalk matrix to 0
    1640           0 :         TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
    1641           0 :         TMatrixD * crossTalkMatrixBelow = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs);
    1642           0 :         TMatrixD * crossTalkMatrixCache = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs*2);
    1643           0 :         TVectorD vecAll(crossTalkMatrix->GetNrows());
    1644           0 :         TVectorD vecBelow(crossTalkMatrix->GetNrows());
    1645           0 :         TVectorD vecCache(crossTalkMatrixCache->GetNrows());
    1646             :         //
    1647           0 :         for (Int_t itime=0; itime<crossTalkMatrix->GetNcols(); itime++){
    1648           0 :           for (Int_t iwire=0; iwire<crossTalkMatrix->GetNrows(); iwire++){
    1649           0 :             vecAll[iwire]=(*crossTalkMatrix)(iwire,itime);
    1650           0 :             vecBelow[iwire]=(*crossTalkMatrixBelow)(iwire,itime);
    1651           0 :             vecCache[iwire]=(*crossTalkMatrixCache)(iwire,itime);
    1652             :           }
    1653           0 :           (*fDebugStreamer)<<"crosstalkMatrix"<<
    1654           0 :             "iter="<<iter<<                      //iteration
    1655           0 :             "sector="<<isector<<                 // sector
    1656           0 :             "itime="<<itime<<                    // time bin index
    1657           0 :             "vecAll.="<<&vecAll<<                // crosstalk charge + charge below threshold
    1658           0 :             "vecCache.="<<&vecCache<<                // crosstalk charge + charge below threshold       
    1659           0 :             "vecBelow.="<<&vecBelow<<            // crosstalk contribution from signal below threshold
    1660             :             "\n";
    1661             :         }
    1662           0 :       }
    1663           0 :     }
    1664           0 :     if (iter<nIterations-1) for (Int_t isector=0; isector<nROCs*2; isector++){  //set all ellemts of crosstalk matrix to 0 
    1665           0 :       TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
    1666           0 :       TMatrixD * crossTalkMatrixCache = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs*2);
    1667           0 :       if (crossTalkMatrix){
    1668           0 :         (*crossTalkMatrixCache)*=0;
    1669           0 :         (*crossTalkMatrixCache)+=(*crossTalkMatrix);
    1670           0 :         (*crossTalkMatrix)*=0;
    1671             :       }
    1672           0 :     }      
    1673             :   }
    1674             : 
    1675           0 :   sw.Stop();
    1676           0 :   AliInfoF("timing: %e/%e real/cpu",sw.RealTime(),sw.CpuTime());
    1677             :   //
    1678           0 : }
    1679             : 
    1680             : 
    1681             : 
    1682             : 
    1683             : void    AliTPCtracker::FilterOutlierClusters(){
    1684             :   //
    1685             :   // filter outlier clusters  
    1686             :   //
    1687             :   /*
    1688             :     1.)..... booking part
    1689             :     nSectors=72;
    1690             :     nTimeBins=fParam->Get....
    1691             :     TH2F hisTime("","", sector,0,sector, nTimeBins,0,nTimeBins);
    1692             :     TH2F hisPadRow("","", sector,0,sector, nPadRows,0,nPadRows);
    1693             :     2.) .... filling part
    1694             :     .... cluster loop { hisTime.Fill(cluster->GetDetector(),cluster->GetTimeBin()); }
    1695             :     
    1696             :     3.) ...filtering part 
    1697             :     sector loop { calculate median,mean80 and rms80 of the nclusters per time bin; calculate median,mean80 and rms80 of the nclusters per par row; .... export values to the debug streamers - to decide which threshold to be used... }
    1698             :     
    1699             :     sector loop
    1700             :     { disable clusters in time bins > mean+ n rms80+ offsetTime disable clusters in padRow > mean+ n rms80+ offsetPadRow // how to dislable clusters? - new bit to introduce } 
    1701             :     //
    1702             :     4. Disabling clusters
    1703             :     
    1704             :   */
    1705             :   
    1706             :   //
    1707             :   // 1.) booking part 
    1708             :   // 
    1709             :   //  AliTPCcalibDB *db=AliTPCcalibDB::Instance();
    1710           0 :   Int_t nSectors=AliTPCROC::Instance()->GetNSectors(); 
    1711             :   Int_t nTimeBins= 1100; // *Bug here - we should get NTimeBins from ALTRO - Parameters not relyable
    1712           0 :   Int_t nPadRows=(AliTPCROC::Instance()->GetNRows(0) + AliTPCROC::Instance()->GetNRows(36));
    1713             :   // parameters for filtering
    1714             :   const Double_t nSigmaCut=9.;           // should be in recoParam ?
    1715             :   const Double_t offsetTime=100;         // should be in RecoParam ?  -
    1716             :   const Double_t offsetPadRow=300;       // should be in RecoParam ?
    1717             :   const Double_t offsetTimeAccept=8;     // should be in RecoParam ?  - obtained as mean +1 rms in high IR pp
    1718           0 :   TH2F hisTime("hisSectorTime","hisSectorTime", nSectors,0,nSectors, nTimeBins,0,nTimeBins);
    1719           0 :   TH2F hisPadRow("hisSectorRow","hisSectorRow", nSectors,0,nSectors, nPadRows,0,nPadRows);
    1720             :   //
    1721             :   // 2.) Filling part -- loop over clusters
    1722             :   //
    1723           0 :   for (Int_t isector=0; isector<36; isector++){      // loop over sectors
    1724           0 :     for (Int_t iside=0; iside<2; iside++){           // loop over sides A/C
    1725           0 :       AliTPCtrackerSector &sector= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
    1726           0 :       Int_t nrows = sector.GetNRows();
    1727           0 :       for (Int_t row = 0;row<nrows;row++){           // loop over rows       
    1728           0 :         AliTPCtrackerRow&  tpcrow = sector[row];       
    1729           0 :         Int_t ncl = tpcrow.GetN1();                  // number of clusters in the row
    1730           0 :         if (iside>0) ncl=tpcrow.GetN2();
    1731           0 :         for (Int_t i=0;i<ncl;i++) {  // loop over clusters
    1732           0 :           AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
    1733           0 :           hisTime.Fill(cluster->GetDetector(),cluster->GetTimeBin()); 
    1734           0 :           hisPadRow.Fill(cluster->GetDetector(),cluster->GetRow()); 
    1735             :         }
    1736             :       } 
    1737             :     } 
    1738             :   } 
    1739             : 
    1740             :   //
    1741             :   // 3. Filtering part
    1742             :   //
    1743           0 :   TVectorD vecTime(nTimeBins);
    1744           0 :   TVectorD vecPadRow(nPadRows);
    1745           0 :   TVectorD vecMedianSectorTime(nSectors);
    1746           0 :   TVectorD vecRMSSectorTime(nSectors);
    1747           0 :   TVectorD vecMedianSectorTimeOut6(nSectors);
    1748           0 :   TVectorD vecMedianSectorTimeOut9(nSectors);//
    1749           0 :   TVectorD vecMedianSectorTimeOut(nSectors);//
    1750           0 :   TVectorD vecMedianSectorPadRow(nSectors);
    1751           0 :   TVectorD vecRMSSectorPadRow(nSectors);
    1752           0 :   TVectorD vecMedianSectorPadRowOut6(nSectors);
    1753           0 :   TVectorD vecMedianSectorPadRowOut9(nSectors);
    1754           0 :   TVectorD vecMedianSectorPadRowOut(nSectors);
    1755           0 :   TVectorD vecSectorOut6(nSectors);
    1756           0 :   TVectorD vecSectorOut9(nSectors);
    1757           0 :   TMatrixD matSectorCluster(nSectors,2);
    1758             :   //
    1759             :   // 3.a)  median, rms calculations for hisTime 
    1760             :   //
    1761           0 :   for (Int_t isec=0; isec<nSectors; isec++){
    1762           0 :     vecMedianSectorTimeOut6[isec]=0;
    1763           0 :     vecMedianSectorTimeOut9[isec]=0;
    1764           0 :     for (Int_t itime=0; itime<nTimeBins; itime++){
    1765           0 :       vecTime[itime]=hisTime.GetBinContent(isec+1, itime+1);      
    1766             :     }
    1767           0 :     Double_t median= TMath::Mean(nTimeBins,vecTime.GetMatrixArray());
    1768           0 :     Double_t rms= TMath::RMS(nTimeBins,vecTime.GetMatrixArray()); 
    1769           0 :     vecMedianSectorTime[isec]=median;
    1770           0 :     vecRMSSectorTime[isec]=rms;
    1771           0 :     if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector TimeStat: %d\t%8.0f\t%8.0f",isec,median,rms).Data());
    1772             :     //
    1773             :     // declare outliers
    1774           0 :     for (Int_t itime=0; itime<nTimeBins; itime++){
    1775           0 :       Double_t entries= hisTime.GetBinContent(isec+1, itime+1); 
    1776           0 :       if (entries>median+6.*rms+offsetTime) {
    1777           0 :         vecMedianSectorTimeOut6[isec]+=1;
    1778           0 :       }
    1779           0 :       if (entries>median+9.*rms+offsetTime) {
    1780           0 :         vecMedianSectorTimeOut9[isec]+=1;
    1781           0 :       }
    1782             :     }
    1783             :   }    
    1784             :   //
    1785             :   // 3.b) median, rms calculations for hisPadRow
    1786             :   // 
    1787           0 :   for (Int_t isec=0; isec<nSectors; isec++){
    1788           0 :     vecMedianSectorPadRowOut6[isec]=0;
    1789           0 :     vecMedianSectorPadRowOut9[isec]=0;
    1790           0 :     for (Int_t ipadrow=0; ipadrow<nPadRows; ipadrow++){
    1791           0 :       vecPadRow[ipadrow]=hisPadRow.GetBinContent(isec+1, ipadrow+1);      
    1792             :     }
    1793           0 :     Int_t nPadRowsSector= AliTPCROC::Instance()->GetNRows(isec);
    1794           0 :     Double_t median= TMath::Mean(nPadRowsSector,vecPadRow.GetMatrixArray());
    1795           0 :     Double_t rms= TMath::RMS(nPadRowsSector,vecPadRow.GetMatrixArray());
    1796           0 :     vecMedianSectorPadRow[isec]=median;
    1797           0 :     vecRMSSectorPadRow[isec]=rms;
    1798           0 :     if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector PadRowStat: %d\t%8.0f\t%8.0f",isec,median,rms).Data());
    1799             :     //
    1800             :     // declare outliers
    1801           0 :     for (Int_t ipadrow=0; ipadrow<nPadRows; ipadrow++){
    1802           0 :       Double_t entries= hisPadRow.GetBinContent(isec+1, ipadrow+1);
    1803           0 :       if (entries>median+6.*rms+offsetPadRow) {
    1804           0 :         vecMedianSectorPadRowOut6[isec]+=1;
    1805           0 :       }
    1806           0 :       if (entries>median+9.*rms+offsetPadRow) {
    1807           0 :         vecMedianSectorPadRowOut9[isec]+=1;
    1808           0 :       }
    1809             :     }
    1810             :   }
    1811             :   //
    1812             :   // 3.c) filter outlier sectors
    1813             :   //
    1814           0 :   Double_t medianSectorTime = TMath::Median(nSectors, vecTime.GetMatrixArray());
    1815           0 :   Double_t mean69SectorTime, rms69SectorTime=0;
    1816           0 :   AliMathBase::EvaluateUni(nSectors,  vecTime.GetMatrixArray(), mean69SectorTime,rms69SectorTime,69);
    1817           0 :   for (Int_t isec=0; isec<nSectors; isec++){
    1818           0 :     vecSectorOut6[isec]=0;
    1819           0 :     vecSectorOut9[isec]=0;
    1820           0 :     matSectorCluster(isec,0)=0;
    1821           0 :     matSectorCluster(isec,1)=0;
    1822           0 :     if (TMath::Abs(vecMedianSectorTime[isec])>(mean69SectorTime+6.*(rms69SectorTime+ offsetTimeAccept))) {
    1823           0 :       vecSectorOut6[isec]=1;
    1824           0 :     }
    1825           0 :     if (TMath::Abs(vecMedianSectorTime[isec])>(mean69SectorTime+9.*(rms69SectorTime+ offsetTimeAccept))){
    1826           0 :       vecSectorOut9[isec]=1;
    1827           0 :     }
    1828             :   }
    1829             :   // light version of export variable
    1830           0 :   Int_t filteredSector= vecSectorOut9.Sum();                  // light version of export variable
    1831           0 :   Int_t filteredSectorTime= vecMedianSectorTimeOut9.Sum();
    1832           0 :   Int_t filteredSectorPadRow= vecMedianSectorPadRowOut9.Sum();
    1833           0 :   if (fEvent) if (fEvent->GetHeader()){
    1834           0 :     fEvent->GetHeader()->SetTPCNoiseFilterCounter(0,TMath::Min(filteredSector,255));
    1835           0 :     fEvent->GetHeader()->SetTPCNoiseFilterCounter(1,TMath::Min(filteredSectorTime,255));
    1836           0 :     fEvent->GetHeader()->SetTPCNoiseFilterCounter(2,TMath::Min(filteredSectorPadRow,255));
    1837           0 :   }
    1838             :  
    1839             :   //
    1840             :   // 4. Disabling clusters in outlier layers
    1841             :   //
    1842           0 :   Int_t counterAll=0;
    1843           0 :   Int_t counterOut=0;
    1844           0 :   for (Int_t isector=0; isector<36; isector++){      // loop over sectors
    1845           0 :     for (Int_t iside=0; iside<2; iside++){           // loop over sides A/C
    1846           0 :       AliTPCtrackerSector &sector= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
    1847           0 :       Int_t nrows = sector.GetNRows();
    1848           0 :       for (Int_t row = 0;row<nrows;row++){           // loop over rows       
    1849           0 :         AliTPCtrackerRow&  tpcrow = sector[row];       
    1850           0 :         Int_t ncl = tpcrow.GetN1();                  // number of clusters in the row
    1851           0 :         if (iside>0) ncl=tpcrow.GetN2();
    1852           0 :         for (Int_t i=0;i<ncl;i++) {  // loop over clusters
    1853           0 :           AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
    1854           0 :           Double_t medianTime=vecMedianSectorTime[cluster->GetDetector()];
    1855           0 :           Double_t medianPadRow=vecMedianSectorPadRow[cluster->GetDetector()];
    1856           0 :           Double_t rmsTime=vecRMSSectorTime[cluster->GetDetector()];
    1857           0 :           Double_t rmsPadRow=vecRMSSectorPadRow[cluster->GetDetector()];
    1858           0 :           Int_t entriesPadRow=hisPadRow.GetBinContent(cluster->GetDetector()+1, cluster->GetRow()+1);
    1859           0 :           Int_t entriesTime=hisTime.GetBinContent(cluster->GetDetector()+1, cluster->GetTimeBin()+1);
    1860             :           Bool_t isOut=kFALSE;
    1861           0 :           if (vecSectorOut9[cluster->GetDetector()]>0.5) {
    1862             :             isOut=kTRUE;
    1863           0 :           }
    1864             :           
    1865           0 :           if (entriesTime>medianTime+nSigmaCut*rmsTime+offsetTime) {
    1866             :             isOut=kTRUE;
    1867           0 :             vecMedianSectorTimeOut[cluster->GetDetector()]++;
    1868           0 :           }
    1869           0 :           if (entriesPadRow>medianPadRow+nSigmaCut*rmsPadRow+offsetPadRow) {
    1870             :             isOut=kTRUE;
    1871           0 :             vecMedianSectorPadRowOut[cluster->GetDetector()]++;
    1872           0 :           }
    1873           0 :           counterAll++;
    1874           0 :           matSectorCluster(cluster->GetDetector(),0)+=1;
    1875           0 :           if (isOut){
    1876           0 :             cluster->Disable();
    1877           0 :             counterOut++;
    1878           0 :             matSectorCluster(cluster->GetDetector(),1)+=1;
    1879           0 :           }
    1880             :         }
    1881             :       }
    1882             :     }
    1883             :   }
    1884           0 :   for (Int_t isec=0; isec<nSectors; isec++){
    1885           0 :     if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector Stat: %d\t%8.0f\t%8.0f",isec,matSectorCluster(isec,1),matSectorCluster(isec,0)).Data());
    1886             :   }
    1887             :   //
    1888             :   // dump info to streamer - for later tuning of cuts
    1889             :   //
    1890           0 :   if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) {  // stream TPC data ouliers filtering infomation
    1891           0 :     AliLog::Flush();
    1892           0 :     AliInfo(TString::Format("Cluster counter: (%d/%d) (Filtered/All)",counterOut,counterAll).Data());
    1893           0 :     for (Int_t iSec=0; iSec<nSectors; iSec++){
    1894           0 :       if (vecSectorOut9[iSec]>0 ||  matSectorCluster(iSec,1)>0) {
    1895           0 :         AliInfo(TString::Format("Filtered sector\t%d",iSec).Data());
    1896           0 :         Double_t vecMedTime =TMath::Median(72,vecMedianSectorTime.GetMatrixArray());
    1897           0 :         Double_t vecMedPadRow =TMath::Median(72,vecMedianSectorPadRow.GetMatrixArray());
    1898           0 :         Double_t vecMedCluster=(counterAll-counterOut)/72;
    1899           0 :         AliInfo(TString::Format("VecMedianSectorTime\t(%4.4f/%4.4f/%4.4f)",       vecMedianSectorTimeOut[iSec],vecMedianSectorTime[iSec],vecMedTime).Data());
    1900           0 :         AliInfo(TString::Format("VecMedianSectorPadRow\t(%4.4f/%4.4f/%4.4f)",     vecMedianSectorPadRowOut[iSec],vecMedianSectorPadRow[iSec],vecMedPadRow).Data());
    1901           0 :         AliInfo(TString::Format("MatSectorCluster\t(%4.4f/%4.4f/%4.4f)\n",          matSectorCluster(iSec,1), matSectorCluster(iSec,0),  vecMedCluster).Data());
    1902           0 :         AliLog::Flush();
    1903           0 :       }
    1904             :     }
    1905           0 :     AliLog::Flush();
    1906           0 :     Int_t eventNr = fEvent->GetEventNumberInFile();
    1907           0 :     (*fDebugStreamer)<<"filterClusterInfo"<<
    1908             :       // minimal set variables for the ESDevent
    1909           0 :       "eventNr="<<eventNr<<
    1910           0 :       "counterAll="<<counterAll<<
    1911           0 :       "counterOut="<<counterOut<<
    1912           0 :       "matSectotCluster.="<<&matSectorCluster<<                   // 
    1913             :       //
    1914           0 :       "filteredSector="<<filteredSector<<                        //  counter filtered sectors                   
    1915           0 :       "filteredSectorTime="<<filteredSectorTime<<                //  counter filtered time bins
    1916           0 :       "filteredSectorPadRow="<<filteredSectorPadRow<<            //  counter filtered pad-rows
    1917             :       // per sector outlier information
    1918           0 :       "medianSectorTime="<<medianSectorTime<<                    // median number of clusters per sector/timebin
    1919           0 :       "mean69SectorTime="<<mean69SectorTime<<                    // LTM statistic  mean of clusters per sector/timebin
    1920           0 :       "rms69SectorTime="<<rms69SectorTime<<                      // LTM statistic  RMS of clusters per sector/timebin
    1921           0 :       "vecSectorOut6.="<<&vecSectorOut6<<                        // flag array sector  - 6 sigma +accept margin outlier
    1922           0 :       "vecSectorOut9.="<<&vecSectorOut9<<                        // flag array sector  - 9 sigma + accept margin outlier
    1923             :       // per sector/timebin outlier detection
    1924           0 :       "vecMedianSectorTime.="<<&vecMedianSectorTime<<
    1925           0 :       "vecRMSSectorTime.="<<&vecRMSSectorTime<<
    1926           0 :       "vecMedianSectorTimeOut6.="<<&vecMedianSectorTimeOut6<<
    1927           0 :       "vecMedianSectorTimeOut9.="<<&vecMedianSectorTimeOut9<<
    1928           0 :       "vecMedianSectorTimeOut0.="<<&vecMedianSectorTimeOut<<
    1929             :       // per sector/pad-row outlier detection
    1930           0 :       "vecMedianSectorPadRow.="<<&vecMedianSectorPadRow<<
    1931           0 :       "vecRMSSectorPadRow.="<<&vecRMSSectorPadRow<<
    1932           0 :       "vecMedianSectorPadRowOut6.="<<&vecMedianSectorPadRowOut6<<
    1933           0 :       "vecMedianSectorPadRowOut9.="<<&vecMedianSectorPadRowOut9<<
    1934           0 :       "vecMedianSectorPadRowOut9.="<<&vecMedianSectorPadRowOut<<
    1935             :       "\n";
    1936           0 :     ((*fDebugStreamer)<<"filterClusterInfo").GetTree()->Write();
    1937           0 :     fDebugStreamer->GetFile()->Flush();
    1938           0 :   }
    1939           0 : }
    1940             : 
    1941             : void AliTPCtracker::UnloadClusters()
    1942             : {
    1943             :   //
    1944             :   // unload clusters from the memory
    1945             :   //
    1946          16 :   Int_t nrows = fOuterSec->GetNRows();
    1947         304 :   for (Int_t sec = 0;sec<fkNOS;sec++)
    1948       27936 :     for (Int_t row = 0;row<nrows;row++){
    1949       13824 :       AliTPCtrackerRow*  tpcrow = &(fOuterSec[sec%fkNOS][row]);
    1950             :       //      if (tpcrow){
    1951             :       //        if (tpcrow->fClusters1) delete []tpcrow->fClusters1; 
    1952             :       //        if (tpcrow->fClusters2) delete []tpcrow->fClusters2; 
    1953             :       //}
    1954       13824 :       tpcrow->ResetClusters();
    1955             :     }
    1956             :   //
    1957           8 :   nrows = fInnerSec->GetNRows();
    1958         304 :   for (Int_t sec = 0;sec<fkNIS;sec++)
    1959       18432 :     for (Int_t row = 0;row<nrows;row++){
    1960        9072 :       AliTPCtrackerRow*  tpcrow = &(fInnerSec[sec%fkNIS][row]);
    1961             :       //if (tpcrow){
    1962             :       //        if (tpcrow->fClusters1) delete []tpcrow->fClusters1; 
    1963             :       //if (tpcrow->fClusters2) delete []tpcrow->fClusters2; 
    1964             :       //}
    1965        9072 :       tpcrow->ResetClusters();
    1966             :     }
    1967             : 
    1968           8 :   fNClusters = 0;
    1969             :   return ;
    1970           8 : }
    1971             : 
    1972             : void AliTPCtracker::FillClusterArray(TObjArray* array) const{
    1973             :   //
    1974             :   // Filling cluster to the array - For visualization purposes
    1975             :   //
    1976             :   Int_t nrows=0;
    1977           0 :   nrows = fOuterSec->GetNRows();
    1978           0 :   for (Int_t sec = 0;sec<fkNOS;sec++)
    1979           0 :     for (Int_t row = 0;row<nrows;row++){
    1980           0 :       AliTPCtrackerRow*  tpcrow = &(fOuterSec[sec%fkNOS][row]);
    1981           0 :       if (!tpcrow) continue;
    1982           0 :       for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
    1983           0 :         array->AddLast((TObject*)((*tpcrow)[icl]));
    1984             :       }
    1985           0 :     } 
    1986           0 :   nrows = fInnerSec->GetNRows();
    1987           0 :   for (Int_t sec = 0;sec<fkNIS;sec++)
    1988           0 :     for (Int_t row = 0;row<nrows;row++){
    1989           0 :       AliTPCtrackerRow*  tpcrow = &(fInnerSec[sec%fkNIS][row]);
    1990           0 :       if (!tpcrow) continue;
    1991           0 :       for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
    1992           0 :         array->AddLast((TObject*)(*tpcrow)[icl]);
    1993             :       }
    1994           0 :     }
    1995           0 : }
    1996             : 
    1997             : 
    1998             : void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
    1999             :   //
    2000             :   // transformation
    2001             :   //
    2002      129896 :   const double kMaxY2X = AliTPCTransform::GetMaxY2X();  // tg of sector angular span
    2003       64948 :   const double kSinSect = TMath::Sin(TMath::Pi()/9), kCosSect = TMath::Cos(TMath::Pi()/9);
    2004             :   //
    2005       64948 :   AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
    2006       64948 :   AliTPCTransform *transform = calibDB->GetTransform() ;
    2007       64948 :   if (!transform) {
    2008           0 :     AliFatal("Tranformations not in calibDB");
    2009           0 :     return;
    2010             :   }
    2011             :   //  if (!transform->GetCurrentRecoParam()) transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
    2012       64948 :   Double_t x[3]={static_cast<Double_t>(cluster->GetRow()),static_cast<Double_t>(cluster->GetPad()),static_cast<Double_t>(cluster->GetTimeBin())};
    2013       64948 :   Int_t idROC = cluster->GetDetector();
    2014       64948 :   transform->Transform(x,&idROC,0,1);
    2015       64948 :   const float* clCorr = transform->GetLastMapCorrection();
    2016       64948 :   const float* clCorrRef = transform->GetLastMapCorrectionRef();
    2017             :   //
    2018      129896 :   cluster->SetDistortions(clCorr[0]-clCorrRef[0],
    2019       64948 :                           clCorr[1]-clCorrRef[1],
    2020       64948 :                           clCorr[2]-clCorrRef[2]); // memorize distortions (difference to reference one)
    2021             :   // store the dispersion difference
    2022       64948 :   cluster->SetDistortionDispersion(clCorr[3]); // ref error is already subtracted
    2023             :   //
    2024       64948 :   cluster->SetX(x[0]);
    2025       64948 :   cluster->SetY(x[1]);
    2026       64948 :   cluster->SetZ(x[2]);
    2027             :   // in debug mode  check the transformation
    2028             :   //
    2029       64948 :   if ((AliTPCReconstructor::StreamLevel()&kStreamTransform)>0) { 
    2030           0 :     Float_t gx[3];
    2031           0 :     cluster->GetGlobalXYZ(gx);
    2032           0 :     Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
    2033           0 :     TTreeSRedirector &cstream = *fDebugStreamer;
    2034           0 :     Int_t timeStamp=transform->GetCurrentTimeStamp();
    2035           0 :     float* nCclCorr = (float*)transform->GetLastMapCorrection();  
    2036           0 :     float* nCclCorrRef = (float*)transform->GetLastMapCorrectionRef();
    2037           0 :     transform->SetDebugStreamer(fDebugStreamer);
    2038             : 
    2039           0 :     cstream<<"Transform"<<  // needed for debugging of the cluster transformation, resp. used for later visualization 
    2040           0 :       "event="<<event<<
    2041           0 :       "timeStamp="<<timeStamp<<
    2042           0 :       "x0="<<x[0]<<
    2043           0 :       "x1="<<x[1]<<
    2044           0 :       "x2="<<x[2]<<
    2045           0 :       "gx0="<<gx[0]<<
    2046           0 :       "gx1="<<gx[1]<<
    2047           0 :       "gx2="<<gx[2]<<
    2048           0 :       "dx="<<nCclCorr[0]<<
    2049           0 :       "dy="<<nCclCorr[1]<<
    2050           0 :       "dz="<<nCclCorr[2]<<
    2051           0 :       "dxRef="<<nCclCorrRef[0]<<
    2052           0 :       "dyRef="<<nCclCorrRef[1]<<
    2053           0 :       "dzRef="<<nCclCorrRef[2]<<
    2054           0 :       "Cl.="<<cluster<<
    2055             :       "\n"; 
    2056           0 :   }
    2057             :   // The old stuff:
    2058             :   //
    2059             :   // 
    2060             :   //
    2061             :   //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
    2062      129896 :   if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
    2063       64948 :     TGeoHMatrix  *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
    2064             :     //TGeoHMatrix  mat;
    2065       64948 :     Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
    2066       64948 :     Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
    2067      129896 :     if (mat) mat->LocalToMaster(pos,posC);
    2068             :     else{
    2069             :       // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
    2070             :     }
    2071       64948 :     cluster->SetX(posC[0]);
    2072       64948 :     cluster->SetY(posC[1]);
    2073       64948 :     cluster->SetZ(posC[2]);
    2074       64948 :   }
    2075      129896 : }
    2076             : 
    2077             : void  AliTPCtracker::ApplyXtalkCorrection(){
    2078             :   //
    2079             :   // ApplyXtalk correction 
    2080             :   // Loop over all clusters
    2081             :   //      add to each cluster signal corresponding to common Xtalk mode for given time bin at given wire segment
    2082             :   // cluster loop
    2083           0 :   TStopwatch sw;
    2084           0 :   sw.Start();
    2085           0 :   for (Int_t isector=0; isector<36; isector++){  //loop tracking sectors
    2086           0 :     for (Int_t iside=0; iside<2; iside++){       // loop over sides A/C
    2087           0 :       AliTPCtrackerSector &sector= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
    2088           0 :       Int_t nrows     = sector.GetNRows();       
    2089           0 :       for (Int_t row = 0;row<nrows;row++){           // loop over rows       
    2090           0 :         AliTPCtrackerRow&  tpcrow = sector[row];     // row object   
    2091           0 :         Int_t ncl = tpcrow.GetN1();                  // number of clusters in the row
    2092           0 :         if (iside>0) ncl=tpcrow.GetN2();
    2093           0 :         Int_t xSector=0;    // sector number in the TPC convention 0-72
    2094           0 :         if (isector<18){  //if IROC
    2095           0 :           xSector=isector+(iside>0)*18;
    2096           0 :         }else{
    2097           0 :           xSector=isector+18;  // isector -18 +36   
    2098           0 :           if (iside>0) xSector+=18;
    2099             :         }       
    2100           0 :         TMatrixD &crossTalkMatrix= *((TMatrixD*)fCrossTalkSignalArray->At(xSector));
    2101           0 :         Int_t wireSegmentID     = fkParam->GetWireSegment(xSector,row);
    2102           0 :         for (Int_t i=0;i<ncl;i++) {
    2103           0 :           AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
    2104           0 :           Int_t iTimeBin=TMath::Nint(cluster->GetTimeBin());
    2105           0 :           Double_t xTalk= crossTalkMatrix[wireSegmentID][iTimeBin];
    2106           0 :           cluster->SetMax(cluster->GetMax()+xTalk);
    2107             :           const Double_t kDummy=4;
    2108           0 :           Double_t sumxTalk=xTalk*kDummy; // should be calculated via time response function
    2109           0 :           cluster->SetQ(cluster->GetQ()+sumxTalk);
    2110             : 
    2111             : 
    2112           0 :           if ((AliTPCReconstructor::StreamLevel()&kStreamXtalk)>0) {  // flag: stream crosstalk correctio as applied to cluster
    2113           0 :             TTreeSRedirector &cstream = *fDebugStreamer;
    2114           0 :             if (gRandom->Rndm() > 0.){
    2115           0 :               cstream<<"Xtalk"<<
    2116           0 :                 "isector=" << isector <<               // sector [0,36]
    2117           0 :                 "iside=" << iside <<                   // side A or C
    2118           0 :                 "row=" << row <<                       // padrow
    2119           0 :                 "i=" << i <<                           // index of the cluster 
    2120           0 :                 "xSector=" << xSector <<               // sector [0,72] 
    2121           0 :                 "wireSegmentID=" << wireSegmentID <<   // anode wire segment id [0,10] 
    2122           0 :                 "iTimeBin=" << iTimeBin <<             // timebin of the corrected cluster 
    2123           0 :                 "xTalk=" << xTalk <<                   // Xtalk contribution added to Qmax
    2124           0 :                 "sumxTalk=" << sumxTalk <<             // Xtalk contribution added to Qtot (roughly 3*Xtalk) 
    2125           0 :                 "cluster.=" << cluster <<              // corrected cluster object 
    2126             :                 "\n";
    2127             :             }
    2128           0 :           }// dump the results to the debug streamer if in debug mode
    2129           0 :         }
    2130           0 :       }
    2131             :     }
    2132             :   }
    2133           0 :   sw.Stop();
    2134           0 :   AliInfoF("timing: %e/%e real/cpu",sw.RealTime(),sw.CpuTime());
    2135             :   //
    2136           0 : }
    2137             : 
    2138             : void  AliTPCtracker::ApplyTailCancellation(){
    2139             :   //
    2140             :   // Correct the cluster charge for the ion tail effect 
    2141             :   // The TimeResponse function accessed via  AliTPCcalibDB (TPC/Calib/IonTail)
    2142             :   //
    2143           0 :   TStopwatch sw;
    2144           0 :   sw.Start();
    2145             :   // Retrieve
    2146           0 :   TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
    2147           0 :   if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
    2148           0 :   TObject *rocFactorIROC  = ionTailArr->FindObject("factorIROC");
    2149           0 :   TObject *rocFactorOROC  = ionTailArr->FindObject("factorOROC");   
    2150           0 :   Float_t factorIROC      = (atof(rocFactorIROC->GetTitle()));
    2151           0 :   Float_t factorOROC      = (atof(rocFactorOROC->GetTitle()));
    2152             : 
    2153             :   // find the number of clusters for the whole TPC (nclALL)
    2154           0 :   Int_t nclALL=0;
    2155           0 :   for (Int_t isector=0; isector<36; isector++){
    2156           0 :     AliTPCtrackerSector &sector= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
    2157           0 :     nclALL += sector.GetNClInSector(0);
    2158           0 :     nclALL += sector.GetNClInSector(1);
    2159             :   }
    2160             : 
    2161             :   //RS changed from heap allocation in the loop to stack allocation
    2162           0 :   TGraphErrors * graphRes[20]; 
    2163           0 :   Float_t        indexAmpGraphs[20];      
    2164             :   //  AliTPCclusterMI* rowClusterArray[kMaxClusterPerRow]; // caches clusters for each row  // RS avoid trashing the heap
    2165             : 
    2166             :   // start looping over all clusters 
    2167           0 :   for (Int_t iside=0; iside<2; iside++){    // loop over sides
    2168             :     //
    2169             :     //
    2170           0 :     for (Int_t secType=0; secType<2; secType++){  //loop over inner or outer sector
    2171             :       // cache experimantal tuning factor for the different chamber type 
    2172           0 :       const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
    2173             : //       std::cout << " ampfactor = " << ampfactor << std::endl;
    2174             :       //
    2175           0 :       for (Int_t sec = 0;sec<fkNOS;sec++){        //loop overs sectors
    2176             :         //
    2177             :         //
    2178             :         // Cache time response functions and their positons to COG of the cluster       
    2179             :         // TGraphErrors ** graphRes   = new TGraphErrors *[20]; // RS avoid heap allocations if stack can be used
    2180             :         // Float_t * indexAmpGraphs   = new Float_t[20];        // RS Moved outside of the loop
    2181           0 :         memset(graphRes,0,20*sizeof(TGraphErrors*));
    2182           0 :         memset(indexAmpGraphs,0,20*sizeof(float));
    2183             :         //for (Int_t icache=0; icache<20; icache++)  //RS
    2184             :         //{
    2185             :         //  graphRes[icache]       = NULL;
    2186             :         //  indexAmpGraphs[icache] = 0;
    2187             :         // }
    2188             :         /////////////////////////////  --> position fo sie loop
    2189           0 :         if (!AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs))
    2190             :         {
    2191             :           continue;
    2192             :         }
    2193             : 
    2194             :         // set time range from graph
    2195           0 :         const Int_t timeRangeMax=graphRes[0]?graphRes[0]->GetN():600;
    2196             : //         std::cout << " timeRangeMax = " << timeRangeMax << std::endl;
    2197             : 
    2198           0 :         AliTPCtrackerSector &sector= (secType==0)?fInnerSec[sec]:fOuterSec[sec];  
    2199           0 :         Int_t nrows     = sector.GetNRows();                                       // number of rows
    2200           0 :         Int_t nclSector = sector.GetNClInSector(iside);                            // ncl per sector to be used for debugging
    2201             : 
    2202           0 :         for (Int_t row = 0;row<nrows;row++){           // loop over rows
    2203             : 
    2204           0 :           AliTPCtrackerRow&  tpcrow = sector[row];     // row object   
    2205           0 :           Int_t ncl = tpcrow.GetN1();                  // number of clusters in the row
    2206           0 :           if (iside>0) ncl=tpcrow.GetN2();
    2207             : 
    2208             :           // Order clusters in time for the proper correction of ion tail
    2209           0 :           Float_t qTotArray[ncl];          // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion  
    2210           0 :           Float_t qMaxArray[ncl];
    2211           0 :           Int_t sortedClusterIndex[ncl];
    2212           0 :           Float_t sortedClusterTimeBin[ncl];
    2213             :           //TObjArray *rowClusterArray = new TObjArray(ncl);  // cache clusters for each row  // RS avoid trashing the heap
    2214           0 :           AliTPCclusterMI* rowClusterArray[ncl]; // caches clusters for each row  // RS avoid trashing the heap 
    2215             :           //  memset(rowClusterArray,0,sizeof(AliTPCclusterMI*)*ncl);  //.Clear();
    2216             :           //if (rowClusterArray.GetSize()<ncl) rowClusterArray.Expand(ncl);
    2217           0 :           for (Int_t i=0;i<ncl;i++) 
    2218             :           {
    2219           0 :             qTotArray[i]=0;
    2220           0 :             qMaxArray[i]=0;
    2221           0 :             sortedClusterIndex[i]=i;
    2222           0 :             AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
    2223           0 :             rowClusterArray[i] = rowcl;
    2224             :             //if (rowcl) {
    2225             :             //  rowClusterArray.AddAt(rowcl,i);
    2226             :             //} else {
    2227             :             //  rowClusterArray.RemoveAt(i);
    2228             :             //}
    2229             :             // Fill the timebin info to the array in order to sort wrt tb
    2230           0 :             if (!rowcl) {
    2231           0 :               sortedClusterTimeBin[i]=0.0;
    2232           0 :             } else {
    2233           0 :               sortedClusterTimeBin[i] = rowcl->GetTimeBin();
    2234             :             }
    2235             : 
    2236             :           } 
    2237           0 :           TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE);       // sort clusters in time
    2238             :      
    2239             :           // Main cluster correction loops over clusters
    2240           0 :           for (Int_t icl0=0; icl0<ncl;icl0++){    // first loop over clusters
    2241             : 
    2242           0 :             AliTPCclusterMI *cl0= rowClusterArray[sortedClusterIndex[icl0]]; //RS static_cast<AliTPCclusterMI*>(rowClusterArray.At(sortedClusterIndex[icl0]));
    2243             :             
    2244           0 :             if (!cl0) continue;
    2245           0 :             Int_t nclPad=0;
    2246             :             //for (Int_t icl1=0; icl1<ncl;icl1++){  // second loop over clusters        
    2247             :             // RS: time increases with index since sorted -> cl0->GetTimeBin()>cl1->GetTimeBin() means that icl0>icl1
    2248           0 :             for (Int_t icl1=0; icl1<icl0;icl1++){  // second loop over clusters
    2249           0 :               AliTPCclusterMI *cl1= rowClusterArray[sortedClusterIndex[icl1]];//RS static_cast<AliTPCclusterMI*>(rowClusterArray.At(sortedClusterIndex[icl1]));
    2250           0 :               if (!cl1) continue;
    2251             :               // RS no needed with proper loop organization
    2252             :               //if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue;               // no contibution to the tail if later
    2253             : 
    2254           0 :               int dpad = TMath::Abs(cl0->GetPad()-cl1->GetPad());
    2255           0 :               if (dpad>4) continue;           // no contribution if far away in pad direction
    2256             : 
    2257             :               // RS no point in iterating further with sorted clusters once large distance reached
    2258           0 :               if (cl0->GetTimeBin()-cl1->GetTimeBin()>=timeRangeMax) continue; // out of the range of response function
    2259             : 
    2260             :               // RS: what about dpad=4?
    2261           0 :               if (dpad<4) nclPad++;           // count ncl for every pad for debugging
    2262             :             
    2263             :               // Get the correction values for Qmax and Qtot and find total correction for a given cluster
    2264           0 :               Double_t ionTailMax=0.;  
    2265           0 :               Double_t ionTailTotal=0.;  
    2266           0 :               GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
    2267           0 :               ionTailMax=TMath::Abs(ionTailMax);
    2268           0 :               ionTailTotal=TMath::Abs(ionTailTotal);
    2269           0 :               qTotArray[icl0]+=ionTailTotal;
    2270           0 :               qMaxArray[icl0]+=ionTailMax;
    2271             : 
    2272             :               // Dump some info for debugging while clusters are being corrected
    2273           0 :               if ((AliTPCReconstructor::StreamLevel()&kStreamIonTail)>0) {  // flag: stream ion tail correction  as applied to cluster
    2274           0 :                 TTreeSRedirector &cstream = *fDebugStreamer;
    2275           0 :                 if (gRandom->Rndm() > 0.999){
    2276           0 :                   cstream<<"IonTail"<<
    2277           0 :                       "cl0.="         <<cl0          <<   // cluster 0 (to be corrected)
    2278           0 :                       "cl1.="         <<cl1          <<   // cluster 1 (previous cluster)
    2279           0 :                       "ionTailTotal=" <<ionTailTotal <<   // ion Tail from cluster 1 contribution to cluster0
    2280           0 :                       "ionTailMax="   <<ionTailMax   <<   // ion Tail from cluster 1 contribution to cluster0 
    2281             :                       "\n";
    2282             :                 }
    2283           0 :               }// dump the results to the debug streamer if in debug mode
    2284             :             
    2285           0 :             }//end of second loop over clusters
    2286             :             
    2287             :             // Set corrected values of the corrected cluster          
    2288           0 :             cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
    2289           0 :             cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
    2290             :           
    2291             :             // Dump some info for debugging after clusters are corrected 
    2292           0 :             if ((AliTPCReconstructor::StreamLevel()&kStreamIonTail)>0) {
    2293           0 :               TTreeSRedirector &cstream = *fDebugStreamer;
    2294           0 :               if (gRandom->Rndm() > 0.999){
    2295           0 :               cstream<<"IonTailCorrected"<<
    2296           0 :                   "cl0.="                     << cl0              <<   // cluster 0 with huge Qmax
    2297           0 :                   "ionTailTotalPerCluster="   << qTotArray[icl0]  <<
    2298           0 :                   "ionTailMaxPerCluster="     << qMaxArray[icl0]  <<
    2299           0 :                   "nclALL="                   << nclALL           <<
    2300           0 :                   "nclSector="                << nclSector        <<
    2301           0 :                   "nclRow="                   << ncl              <<
    2302           0 :                   "nclPad="                   << nclPad           <<
    2303           0 :                   "row="                      << row              <<
    2304           0 :                   "sector="                   << sec              <<
    2305           0 :                   "icl0="                     << icl0             <<
    2306             :                   "\n";
    2307             :               }
    2308           0 :             }// dump the results to the debug streamer if in debug mode
    2309             :           
    2310           0 :           }//end of first loop over cluster
    2311             :           // delete rowClusterArray; // RS was moved to stack allocation
    2312           0 :         }//end of loop over rows
    2313           0 :         for (int i=0; i<20; i++) delete graphRes[i];
    2314             :         //        delete [] graphRes; //RS was changed to stack allocation
    2315             :         //        delete [] indexAmpGraphs;
    2316             :       
    2317           0 :       }//end of loop over sectors
    2318             :     }//end of loop over IROC/OROC
    2319             :   }// end of side loop
    2320           0 :   sw.Stop();
    2321           0 :   AliInfoF("timing: %e/%e real/cpu",sw.RealTime(),sw.CpuTime());
    2322             :   //
    2323           0 : }
    2324             : //_____________________________________________________________________________
    2325             : void AliTPCtracker::GetTailValue(Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
    2326             : 
    2327             :   //
    2328             :   // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
    2329             :   // Parameters:
    2330             :   // cl0 -  cluster to be modified
    2331             :   // cl1 -  source cluster ion tail of this cluster will be added to the cl0 (accroding time and pad response function)
    2332             :   // 
    2333             :   const float kMinPRF       = 0.5f;                          // minimal PRF width
    2334           0 :   ionTailTotal              = 0.;                            // correction value to be added to Qtot of cl0
    2335           0 :   ionTailMax                = 0.;                            // correction value to be added to Qmax of cl0
    2336             : 
    2337           0 :   Float_t qTot0             =  cl0->GetQ();                  // cl0 Qtot info
    2338           0 :   Float_t qTot1             =  cl1->GetQ();                  // cl1 Qtot info
    2339           0 :   Int_t sectorPad           =  cl1->GetDetector();           // sector number
    2340           0 :   Int_t padcl0              =  TMath::Nint(cl0->GetPad());   // pad0
    2341           0 :   Int_t padcl1              =  TMath::Nint(cl1->GetPad());   // pad1
    2342           0 :   Float_t padWidth          = (sectorPad < 36)?0.4:0.6;      // pad width in cm
    2343           0 :   const Int_t deltaTimebin  =  TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12;  //distance between pads of cl1 and cl0 increased by 12 bins
    2344           0 :   float rmsPad1I            = (cl1->GetSigmaY2()==0)?0.5f/kMinPRF:(0.5f*padWidth/sqrtf(cl1->GetSigmaY2()));
    2345           0 :   float rmsPad0I            = (cl0->GetSigmaY2()==0)?0.5f/kMinPRF:(0.5f*padWidth/sqrtf(cl0->GetSigmaY2()));
    2346             :   
    2347             :   // RS avoid useless calculations
    2348             :   //Double_t sumAmp1=0.;
    2349             :   //for (Int_t idelta =-2; idelta<=2;idelta++){
    2350             :   //  sumAmp1+=TMath::Exp(-idelta*idelta*rmsPad1I);
    2351             :   //}
    2352             :   // Double_t sumAmp0=0.;
    2353             :   //for (Int_t idelta =-2; idelta<=2;idelta++){
    2354             :   //  sumAmp0+=TMath::Exp(-idelta*idelta*rmsPad0I));
    2355             :   //}
    2356             : 
    2357           0 :   float tmp = expf(-rmsPad1I);
    2358           0 :   float sumAmp1 = 1.f/(1.f+2.f*tmp*(1.f+tmp*tmp*tmp));
    2359           0 :   tmp = expf(-rmsPad0I);
    2360           0 :   float sumAmp0 = 1.f/(1.f+2.f*tmp*(1.f+tmp*tmp*tmp));
    2361             : 
    2362             :   // Apply the correction  -->   cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
    2363             :   Int_t padScan=2;      // +-2 pad-timebin window will be scanned
    2364           0 :   for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
    2365             :     //
    2366             :     //
    2367           0 :     Float_t deltaPad1  = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
    2368           0 :     Float_t amp1       = TMath::Exp(-(deltaPad1*deltaPad1)*rmsPad1I)*sumAmp1;  // normalized pad response function
    2369           0 :     Float_t qTotPad1   = amp1*qTot1;                                           // used as a factor to multipliy the response function
    2370             :       
    2371             :     // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
    2372             :     Int_t ampIndex = 0;
    2373           0 :     Float_t diffAmp  = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
    2374           0 :     for (Int_t j=0;j<20;j++) {
    2375           0 :       if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
    2376             :         {
    2377           0 :           diffAmp  = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
    2378             :           ampIndex = j;
    2379           0 :         }
    2380             :     }
    2381           0 :     if (!graphRes[ampIndex]) continue;
    2382           0 :     if (deltaTimebin+2 >= graphRes[ampIndex]->GetN()) continue;
    2383           0 :     if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
    2384             :      
    2385           0 :     for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
    2386             :       //
    2387             :       //
    2388           0 :       if (ipad1!=ipad0) continue;                                     // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
    2389             :       
    2390           0 :       Float_t deltaPad0  = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
    2391           0 :       Float_t amp0       = expf(-(deltaPad0*deltaPad0)*rmsPad0I)*sumAmp0;  // normalized pad resp function
    2392           0 :       Float_t qMaxPad0   = amp0*qTot0;
    2393             :            
    2394             :       // Add 5 timebin range contribution around the max peak (-+2 tb window)
    2395           0 :       for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
    2396             : 
    2397           0 :         if (itb<0) continue; 
    2398           0 :         if (itb>=graphRes[ampIndex]->GetN()) continue;
    2399             :        
    2400             :         // calculate contribution to qTot
    2401           0 :         Float_t tailCorr =  TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
    2402           0 :         if (ipad1!=padcl0) { 
    2403           0 :           ionTailTotal += TMath::Min(qMaxPad0,tailCorr);   // for side pad
    2404           0 :         } else {             
    2405           0 :           ionTailTotal += tailCorr;                        // for center pad
    2406             :         }
    2407             :         // calculate contribution to qMax
    2408           0 :         if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;   
    2409             :         
    2410           0 :       } // end of tb correction loop which is applied over 5 tb range
    2411             : 
    2412           0 :     } // end of cl0 loop
    2413           0 :   } // end of cl1 loop
    2414             :   
    2415           0 : }
    2416             : 
    2417             : //_____________________________________________________________________________
    2418             : Int_t AliTPCtracker::LoadOuterSectors() {
    2419             :   //-----------------------------------------------------------------
    2420             :   // This function fills outer TPC sectors with clusters.
    2421             :   //-----------------------------------------------------------------
    2422          16 :   Int_t nrows = fOuterSec->GetNRows();
    2423             :   UInt_t index=0;
    2424         304 :   for (Int_t sec = 0;sec<fkNOS;sec++)
    2425       27936 :     for (Int_t row = 0;row<nrows;row++){
    2426       13824 :       AliTPCtrackerRow*  tpcrow = &(fOuterSec[sec%fkNOS][row]);  
    2427       13824 :       Int_t sec2 = sec+2*fkNIS;
    2428             :       //left
    2429       13824 :       Int_t ncl = tpcrow->GetN1();
    2430       43732 :       while (ncl--) {
    2431        8042 :         AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
    2432        8042 :         index=(((sec2<<8)+row)<<16)+ncl;
    2433        8042 :         tpcrow->InsertCluster(c,index);
    2434             :       }
    2435             :       //right
    2436       13824 :       ncl = tpcrow->GetN2();
    2437       49260 :       while (ncl--) {
    2438       10806 :         AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
    2439       10806 :         index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
    2440       10806 :         tpcrow->InsertCluster(c,index);
    2441             :       }
    2442             :       //
    2443             :       // write indexes for fast acces
    2444             :       //
    2445    14128128 :       for (Int_t i=510;i--;) tpcrow->SetFastCluster(i,-1);
    2446       65344 :       for (Int_t i=0;i<tpcrow->GetN();i++){
    2447       18848 :         Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
    2448       18848 :         tpcrow->SetFastCluster(zi,i);  // write index
    2449             :       }
    2450             :       Int_t last = 0;
    2451    14128128 :       for (Int_t i=0;i<510;i++){
    2452     7050240 :         if (tpcrow->GetFastCluster(i)<0)
    2453     7033150 :           tpcrow->SetFastCluster(i,last);
    2454             :         else
    2455       17090 :           last = tpcrow->GetFastCluster(i);
    2456             :       }
    2457             :     }  
    2458           8 :   fN=fkNOS;
    2459           8 :   fSectors=fOuterSec;
    2460           8 :   return 0;
    2461             : }
    2462             : 
    2463             : 
    2464             : //_____________________________________________________________________________
    2465             : Int_t  AliTPCtracker::LoadInnerSectors() {
    2466             :   //-----------------------------------------------------------------
    2467             :   // This function fills inner TPC sectors with clusters.
    2468             :   //-----------------------------------------------------------------
    2469          16 :   Int_t nrows = fInnerSec->GetNRows();
    2470             :   UInt_t index=0;
    2471         304 :   for (Int_t sec = 0;sec<fkNIS;sec++)
    2472       18432 :     for (Int_t row = 0;row<nrows;row++){
    2473        9072 :       AliTPCtrackerRow*  tpcrow = &(fInnerSec[sec%fkNIS][row]);
    2474             :       //
    2475             :       //left
    2476        9072 :       Int_t ncl = tpcrow->GetN1();
    2477       69400 :       while (ncl--) {
    2478       25628 :         AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
    2479       25628 :         index=(((sec<<8)+row)<<16)+ncl;
    2480       25628 :         tpcrow->InsertCluster(c,index);
    2481             :       }
    2482             :       //right
    2483        9072 :       ncl = tpcrow->GetN2();
    2484       59088 :       while (ncl--) {
    2485       20472 :         AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
    2486       20472 :         index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
    2487       20472 :         tpcrow->InsertCluster(c,index);
    2488             :       }
    2489             :       //
    2490             :       // write indexes for fast acces
    2491             :       //
    2492     9271584 :       for (Int_t i=0;i<510;i++)
    2493     4626720 :         tpcrow->SetFastCluster(i,-1);
    2494      110344 :       for (Int_t i=0;i<tpcrow->GetN();i++){
    2495       46100 :         Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
    2496       46100 :         tpcrow->SetFastCluster(zi,i);  // write index
    2497             :       }
    2498             :       Int_t last = 0;
    2499     9271584 :       for (Int_t i=0;i<510;i++){
    2500     4626720 :         if (tpcrow->GetFastCluster(i)<0)
    2501     4586956 :           tpcrow->SetFastCluster(i,last);
    2502             :         else
    2503       39764 :           last = tpcrow->GetFastCluster(i);
    2504             :       }
    2505             : 
    2506             :     }  
    2507             :    
    2508           8 :   fN=fkNIS;
    2509           8 :   fSectors=fInnerSec;
    2510           8 :   return 0;
    2511             : }
    2512             : 
    2513             : 
    2514             : 
    2515             : //_________________________________________________________________________
    2516             : AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
    2517             :   //--------------------------------------------------------------------
    2518             :   //       Return pointer to a given cluster
    2519             :   //--------------------------------------------------------------------
    2520      883542 :   if (index<0) return 0; // no cluster
    2521      441771 :   Int_t sec=(index&0xff000000)>>24; 
    2522      441771 :   Int_t row=(index&0x00ff0000)>>16; 
    2523      441771 :   Int_t ncl=(index&0x00007fff)>>00;
    2524             : 
    2525             :   const AliTPCtrackerRow * tpcrow=0;
    2526             :   TClonesArray * clrow =0;
    2527             : 
    2528      883542 :   if (sec<0 || sec>=fkNIS*4) {
    2529           0 :     AliWarning(Form("Wrong sector %d",sec));
    2530           0 :     return 0x0;
    2531             :   }
    2532             : 
    2533      441771 :   if (sec<fkNIS*2){
    2534      172991 :     AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
    2535      172991 :     if (tracksec.GetNRows()<=row) return 0;
    2536      172991 :     tpcrow = &(tracksec[row]);
    2537      172991 :     if (tpcrow==0) return 0;
    2538             : 
    2539      172991 :     if (sec<fkNIS) {
    2540       84911 :       if (tpcrow->GetN1()<=ncl) return 0;
    2541       84911 :       clrow = tpcrow->GetClusters1();
    2542       84911 :     }
    2543             :     else {
    2544       88080 :       if (tpcrow->GetN2()<=ncl) return 0;
    2545       88080 :       clrow = tpcrow->GetClusters2();
    2546             :     }
    2547      172991 :   }
    2548             :   else {
    2549      268780 :     AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
    2550      268780 :     if (tracksec.GetNRows()<=row) return 0;
    2551      268780 :     tpcrow = &(tracksec[row]);
    2552      268780 :     if (tpcrow==0) return 0;
    2553             : 
    2554      268780 :     if (sec-2*fkNIS<fkNOS) {
    2555      135699 :       if (tpcrow->GetN1()<=ncl) return 0;
    2556      135699 :       clrow = tpcrow->GetClusters1();
    2557      135699 :     }
    2558             :     else {
    2559      133081 :       if (tpcrow->GetN2()<=ncl) return 0;
    2560      133081 :       clrow = tpcrow->GetClusters2();
    2561             :     }
    2562      268780 :   }
    2563             : 
    2564      441771 :   return (AliTPCclusterMI*)clrow->At(ncl);
    2565             :   
    2566      441771 : }
    2567             : 
    2568             : 
    2569             : 
    2570             : Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
    2571             :   //-----------------------------------------------------------------
    2572             :   // This function tries to find a track prolongation to next pad row
    2573             :   //-----------------------------------------------------------------
    2574             :   //
    2575             :   const double kRoadY = 1., kRoadZ = 1.;
    2576      179588 :   Double_t  x= GetXrow(nr), ymax=GetMaxY(nr);
    2577             :   //
    2578             :   //
    2579             :   AliTPCclusterMI *cl=0;
    2580       89794 :   Int_t tpcindex= t.GetClusterIndex2(nr);
    2581             :   //
    2582             :   // update current shape info every 5 pad-row
    2583             :   //  if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
    2584       89794 :     GetShape(&t,nr);    
    2585             :     //}
    2586             :   //  
    2587       89794 :   if (fIteration>0 && tpcindex>=-1){  //if we have already clusters 
    2588             :     //        
    2589       37240 :     if (tpcindex==-1) return 0; //track in dead zone
    2590       33152 :     if (tpcindex >= 0){     //
    2591       33152 :       cl = t.GetClusterPointer(nr);         // cluster might not be there during track finding, but is attached in refits
    2592       66304 :       if (cl==0) cl = GetClusterMI(tpcindex); 
    2593       33152 :       t.SetCurrentClusterIndex1(tpcindex); 
    2594       33152 :     }
    2595       33152 :     if (cl){      
    2596       33152 :       Int_t relativesector = ((tpcindex&0xff000000)>>24)%18;  // if previously accepted cluster in different sector
    2597       33152 :       Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
    2598             :       //
    2599       33152 :       if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
    2600       44776 :       if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
    2601             :       
    2602       33152 :       if (TMath::Abs(angle-t.GetAlpha())>0.001){
    2603         130 :         Double_t rotation = angle-t.GetAlpha();
    2604         130 :         t.SetRelativeSector(relativesector);
    2605         130 :         if (!t.Rotate(rotation)) {
    2606           0 :           t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
    2607           0 :           return 0;
    2608             :         }       
    2609         130 :       }
    2610       33152 :       if (!t.PropagateTo(cl->GetX())) { // RS: go directly to cluster X
    2611           0 :         t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
    2612           0 :         return 0;
    2613             :       }
    2614             :       //
    2615       33152 :       t.SetCurrentCluster(cl); 
    2616       33152 :       t.SetRow(nr); // RS: memorise row
    2617       33152 :       Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
    2618       33152 :       if ((tpcindex&0x8000)==0) accept =0;
    2619       33152 :       if (accept<3) { 
    2620             :         //if founded cluster is acceptible
    2621       33098 :         if (cl->IsUsed(11)) {  // id cluster is shared inrease uncertainty
    2622         652 :           t.SetErrorY2(t.GetErrorY2()+0.03);
    2623         652 :           t.SetErrorZ2(t.GetErrorZ2()+0.03); 
    2624         652 :           t.SetErrorY2(t.GetErrorY2()*3);
    2625         652 :           t.SetErrorZ2(t.GetErrorZ2()*3); 
    2626         652 :         }
    2627       33098 :         t.SetNFoundable(t.GetNFoundable()+1);
    2628       33098 :         UpdateTrack(&t,accept);
    2629       33098 :         return 1;
    2630             :       }
    2631             :       else { // Remove old cluster from track
    2632          54 :         t.SetClusterIndex(nr, -3);
    2633             :         //RS t.SetClusterPointer(nr, 0);
    2634             :       }
    2635          54 :     }
    2636             :   }
    2637       57422 :   if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;  // cut on angle
    2638       53892 :   if (fIteration>1 && IsFindable(t)){
    2639             :     // not look for new cluster during refitting    
    2640        2010 :     t.SetNFoundable(t.GetNFoundable()+1);
    2641        2010 :     return 0;
    2642             :   }
    2643             :   //
    2644       49872 :   UInt_t index=0;
    2645             :   //  if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
    2646             :   //
    2647       49872 :   if (fAccountDistortions && !DistortX(&t,x,nr)) {if (fIteration==0) t.SetRemoval(10); return 0;}
    2648       49908 :   if (!t.PropagateTo(x))                         {if (fIteration==0) t.SetRemoval(10); return 0;}
    2649       49860 :   t.SetRow(nr); //RS:? memorise reached row?
    2650             :   //
    2651       49860 :   double y=t.GetY(), z=t.GetZ();
    2652             :   double yEdgeDist =  y;
    2653       49860 :   if  (fAccountDistortions) yEdgeDist -= GetYSectEdgeDist(t.GetRelativeSector(),nr,y,z);
    2654             :   Bool_t rot = kFALSE;
    2655       68230 :   if (y>0 && yEdgeDist>ymax) { //RS y sign here is used to deduce which edge is used
    2656          82 :     t.SetRelativeSector((t.GetRelativeSector() + 1) % fN);
    2657          86 :     if (!t.Rotate(fSectors->GetAlpha())) return 0;
    2658             :     rot = kTRUE;
    2659          78 :   }
    2660       81268 :   else if (y<0 && yEdgeDist<-ymax) {
    2661         126 :     t.SetRelativeSector((t.GetRelativeSector() + fN - 1) % fN);
    2662         134 :     if (!t.Rotate(-fSectors->GetAlpha())) return 0;
    2663             :     rot = kTRUE;
    2664         118 :   }
    2665       49848 :   if (rot) {
    2666         196 :     x = GetXrow(nr);
    2667         196 :     if (fAccountDistortions && !DistortX(&t,x,nr)) {if (fIteration==0) t.SetRemoval(10); return 0;}
    2668         202 :     if (!t.PropagateTo(x))                         {if (fIteration==0) t.SetRemoval(10); return 0; }
    2669         194 :     y = t.GetY();
    2670             :     yEdgeDist =  y;
    2671         194 :     if (fAccountDistortions) yEdgeDist -= GetYSectEdgeDist(t.GetRelativeSector(),nr,y,z);
    2672             :   }
    2673             :   //
    2674       49846 :   if (!IsActive(t.GetRelativeSector(),nr)) { // RS:? How distortions affect this
    2675        1320 :     t.SetInDead(kTRUE);
    2676        1320 :     t.SetClusterIndex2(nr,-1); 
    2677        1320 :     return 0;
    2678             :   }
    2679             :   //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
    2680       48526 :   Bool_t isActive  = IsActive(t.GetRelativeSector(),nr); //RS:? Why do we check this again?
    2681      194104 :   Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? 
    2682      129288 :     fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0 : 
    2683       16290 :     fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
    2684             :   
    2685       97052 :   if (!isActive || !isActive2) return 0;
    2686             : 
    2687       48526 :   const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
    2688       97052 :   if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
    2689             :   //
    2690             :   // RS: account for eventual modifications in dead zone definition due to distortions
    2691       48526 :   double margin = (y>0 ? ymax-yEdgeDist : ymax + yEdgeDist);
    2692       48526 :   if (margin<krow.GetDeadZone()){
    2693        1062 :     t.SetInDead(kTRUE);
    2694        1062 :     t.SetClusterIndex2(nr,-1); 
    2695        1062 :     return 0;
    2696             :   } 
    2697             :   else {
    2698       94850 :     if (IsFindable(t))  t.SetNFoundable(t.GetNFoundable()+1);
    2699          78 :     else                return 0;
    2700             :   }   
    2701             :   //calculate 
    2702      137358 :   if (krow && (cl=krow.FindNearest2(y,z,kRoadY+fClExtraRoadY,kRoadZ+fClExtraRoadZ,index)) ) t.SetCurrentClusterIndex1(krow.GetIndex(index));
    2703       47386 :   if (cl) {
    2704       42586 :     t.SetCurrentCluster(cl); 
    2705             :     //    t.SetRow(nr); //RS: memorise row | already set at propagation
    2706       42586 :     if (fIteration==2&&cl->IsUsed(10)) return 0; 
    2707       42586 :     Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
    2708       42586 :     if (fIteration==2&&cl->IsUsed(11)) {
    2709           0 :       t.SetErrorY2(t.GetErrorY2()+0.03);
    2710           0 :       t.SetErrorZ2(t.GetErrorZ2()+0.03); 
    2711           0 :       t.SetErrorY2(t.GetErrorY2()*3);
    2712           0 :       t.SetErrorZ2(t.GetErrorZ2()*3); 
    2713           0 :     }
    2714             :     /*    
    2715             :     if (t.fCurrentCluster->IsUsed(10)){
    2716             :       //
    2717             :       //     
    2718             : 
    2719             :       t.fNShared++;
    2720             :       if (t.fNShared>0.7*t.GetNumberOfClusters()) {
    2721             :         t.fRemoval =10;
    2722             :         return 0;
    2723             :       }
    2724             :     }
    2725             :     */
    2726       84422 :     if (accept<3) UpdateTrack(&t,accept);
    2727             : 
    2728       42586 :   } else {  
    2729        8820 :     if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
    2730             :     
    2731             :   }
    2732       47386 :   return 1;
    2733      139666 : }
    2734             : 
    2735             : 
    2736             : 
    2737             : //_________________________________________________________________________
    2738             : Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
    2739             : {
    2740             :   // Get track space point by index
    2741             :   // return false in case the cluster doesn't exist
    2742       16802 :   AliTPCclusterMI *cl = GetClusterMI(index);
    2743        8401 :   if (!cl) return kFALSE;
    2744        8401 :   Int_t sector = (index&0xff000000)>>24;
    2745             :   //  Int_t row = (index&0x00ff0000)>>16;
    2746             :   Float_t xyz[3];
    2747             :   //  xyz[0] = fkParam->GetPadRowRadii(sector,row);
    2748        8401 :   xyz[0] = cl->GetX();
    2749        8401 :   xyz[1] = cl->GetY();
    2750        8401 :   xyz[2] = cl->GetZ();
    2751        8401 :   Float_t sin,cos;
    2752        8401 :   fkParam->AdjustCosSin(sector,cos,sin);
    2753        8401 :   Float_t x = cos*xyz[0]-sin*xyz[1];
    2754        8401 :   Float_t y = cos*xyz[1]+sin*xyz[0];
    2755        8401 :   Float_t cov[6];
    2756        8401 :   Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
    2757       11738 :   if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
    2758        8401 :   Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
    2759       11738 :   if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
    2760        8401 :   cov[0] = sin*sin*sigmaY2;
    2761        8401 :   cov[1] = -sin*cos*sigmaY2;
    2762        8401 :   cov[2] = 0.;
    2763        8401 :   cov[3] = cos*cos*sigmaY2;
    2764        8401 :   cov[4] = 0.;
    2765        8401 :   cov[5] = sigmaZ2;
    2766        8401 :   p.SetXYZ(x,y,xyz[2],cov);
    2767             :   AliGeomManager::ELayerID iLayer;
    2768             :   Int_t idet;
    2769        8401 :   if (sector < fkParam->GetNInnerSector()) {
    2770             :     iLayer = AliGeomManager::kTPC1;
    2771             :     idet = sector;
    2772        3337 :   }
    2773             :   else {
    2774             :     iLayer = AliGeomManager::kTPC2;
    2775        5064 :     idet = sector - fkParam->GetNInnerSector();
    2776             :   }
    2777        8401 :   UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
    2778        8401 :   p.SetVolumeID(volid);
    2779             :   return kTRUE;
    2780       16802 : }
    2781             : 
    2782             : 
    2783             : 
    2784             : Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t,  Int_t nr) {
    2785             :   //-----------------------------------------------------------------
    2786             :   // This function tries to find a track prolongation to next pad row
    2787             :   //-----------------------------------------------------------------
    2788       87280 :   t.SetCurrentCluster(0);
    2789       43640 :   t.SetCurrentClusterIndex1(-3);   
    2790             :    
    2791      130920 :   Int_t     row = (fAccountDistortions ? GetRowNumber(&t):GetRowNumber(t.GetX()))-1;  //RS: with distortions cannot rely on X
    2792       43640 :   Double_t  ymax= GetMaxY(nr);
    2793             : 
    2794       53738 :   if (row < nr) return 1; // don't prolongate if not information until now -
    2795             : 
    2796             :   const double kRoadY = 1., kRoadZ = 1.;
    2797             : 
    2798       33542 :   Double_t x= GetXrow(nr);
    2799       33542 :   if (fAccountDistortions && !DistortX(&t,x,nr)) return 0; // RS: if needed, account distortion
    2800             :   //
    2801       34110 :   if (!t.PropagateTo(x)) return 0;
    2802       32974 :   t.SetRow(nr); //RS: memorise row
    2803             :   //
    2804       32974 :   double y=t.GetY(), z=t.GetZ();
    2805             :   double yEdgeDist =  y;
    2806       32974 :   if  (fAccountDistortions) yEdgeDist -= GetYSectEdgeDist(t.GetRelativeSector(),nr,y,z);
    2807       46872 :   if (y>0 && yEdgeDist>ymax) { //RS y sign is used to determine which edge is used
    2808          38 :     t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
    2809          40 :     if (!t.Rotate(fSectors->GetAlpha())) return 0;
    2810          36 :     t.SetRow(-1); //RS: after rotation the row is not known
    2811          36 :     return 1;
    2812             :   }
    2813       52012 :   else if (y<0 && yEdgeDist<-ymax) {
    2814          96 :     t.SetRelativeSector((t.GetRelativeSector()+fN-1) % fN);
    2815         142 :     if (!t.Rotate(-fSectors->GetAlpha())) return 0;
    2816          50 :     t.SetRow(-1); //RS: after rotation the row is not known
    2817          50 :     return 1;
    2818             :   }
    2819             :   //
    2820       32860 :   if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
    2821             : 
    2822       32820 :   if (!IsActive(t.GetRelativeSector(),nr)) {
    2823         714 :     t.SetInDead(kTRUE);
    2824         714 :     t.SetClusterIndex2(nr,-1); 
    2825         714 :     return 0;
    2826             :   }
    2827             :   //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
    2828             : 
    2829       32106 :   AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
    2830       32106 :   double margin = (y>0 ? ymax-yEdgeDist : ymax + yEdgeDist);
    2831       32106 :   if (margin<krow.GetDeadZone()) {
    2832         858 :     t.SetInDead(kTRUE);
    2833         858 :     t.SetClusterIndex2(nr,-1); 
    2834         858 :     return 0;
    2835             :   } 
    2836             :   else {
    2837             :     //      if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker())) 
    2838       62492 :     if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
    2839           4 :     else return 0;      
    2840             :   }
    2841             : 
    2842             :   // update current
    2843       46800 :   if ( (nr%2==0) || t.GetNumberOfClusters()<2){
    2844             :     //    t.fCurrentSigmaY = GetSigmaY(&t);
    2845             :     //t.fCurrentSigmaZ = GetSigmaZ(&t);
    2846       15688 :     GetShape(&t,nr);
    2847       15688 :   }
    2848             :     
    2849             :   AliTPCclusterMI *cl=0;
    2850             :   Int_t index=0;
    2851             :   //
    2852             :   Double_t roady = 1.;
    2853             :   Double_t roadz = 1.;
    2854             :   //
    2855             : 
    2856       31244 :   if (!cl){
    2857       31244 :     index = t.GetClusterIndex2(nr);    
    2858       31244 :     if ( (index >= 0) && (index&0x8000)==0){
    2859             :       //RS cl = t.GetClusterPointer(nr);
    2860             :       //RS if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
    2861           0 :       if ( index >= 0 ) cl = GetClusterMI(index);
    2862           0 :       t.SetCurrentClusterIndex1(index);
    2863           0 :       if (cl) {
    2864           0 :         t.SetCurrentCluster(cl);
    2865           0 :         return 1;
    2866             :       }
    2867             :     }
    2868             :   }
    2869             : 
    2870             :   //  if (index<0) return 0;
    2871       31244 :   UInt_t uindex = TMath::Abs(index);
    2872             : 
    2873       31244 :   if (krow) {
    2874             :     //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);      
    2875       31244 :     cl = krow.FindNearest2(y,z,kRoadY+fClExtraRoadY,kRoadZ+fClExtraRoadZ,uindex);      
    2876       31244 :   }
    2877             : 
    2878       60144 :   if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));   
    2879       31244 :   t.SetCurrentCluster(cl);
    2880             : 
    2881             :   return 1;
    2882      108426 : }
    2883             : 
    2884             : 
    2885             : Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
    2886             :   //-----------------------------------------------------------------
    2887             :   // This function tries to find a track prolongation to next pad row
    2888             :   //-----------------------------------------------------------------
    2889             : 
    2890             :   //update error according neighborhoud
    2891             : 
    2892       87280 :   if (t.GetCurrentCluster()) {
    2893       28900 :     t.SetRow(nr); 
    2894       28900 :     Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
    2895             :     
    2896       28900 :     if (t.GetCurrentCluster()->IsUsed(10)){
    2897             :       //
    2898             :       //
    2899             :       //  t.fErrorZ2*=2;
    2900             :       //  t.fErrorY2*=2;
    2901         116 :       t.SetNShared(t.GetNShared()+1);
    2902         116 :       if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
    2903           6 :         t.SetRemoval(10);
    2904           6 :         return 0;
    2905             :       }
    2906             :     }   
    2907       28894 :     if (fIteration>0) accept = 0;
    2908       57320 :     if (accept<3)  UpdateTrack(&t,accept);  
    2909             :  
    2910       28894 :   } else {
    2911       14740 :     if (fIteration==0){
    2912             :       //RS: with distortions related cluster errors the track error may grow, don't use this cut
    2913             :       //if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16 + fExtraClErrYZ2 )) t.SetRemoval(10); 
    2914       22132 :       if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);      
    2915             : 
    2916       29480 :       if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
    2917             :     }
    2918             :   }
    2919       43634 :   return 1;
    2920       43640 : }
    2921             : 
    2922             : 
    2923             : 
    2924             : //_____________________________________________________________________________
    2925             : Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
    2926             :   //-----------------------------------------------------------------
    2927             :   // This function tries to find a track prolongation.
    2928             :   //-----------------------------------------------------------------
    2929             :   // Double_t xt=t.GetX(); // RS: with distortions we cannot rely on rowID from X
    2930             :   //
    2931        3654 :   Double_t alpha=t.GetAlpha();
    2932        3654 :   if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
    2933        4766 :   if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
    2934             :   //
    2935        3654 :   t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
    2936             :     
    2937       10962 :   Int_t first = fAccountDistortions ? GetRowNumber(&t):GetRowNumber(t.GetX());  //RS: with distortions cannot rely on X
    2938             :   //Int_t first = GetRowNumber(xt);
    2939        3654 :   if (!fromSeeds)
    2940        3518 :     first -= step;
    2941        3654 :   if (first < 0)
    2942           0 :     first = 0;
    2943      113624 :   for (Int_t nr= first; nr>=rf; nr-=step) {
    2944             :     // update kink info
    2945       51478 :     if (t.GetKinkIndexes()[0]>0){
    2946        2544 :       for (Int_t i=0;i<3;i++){
    2947        1272 :         Int_t index = t.GetKinkIndexes()[i];
    2948        1908 :         if (index==0) break;
    2949         636 :         if (index<0) continue;
    2950             :         //
    2951         636 :         AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
    2952         636 :         if (!kink){
    2953           0 :           printf("PROBLEM\n");
    2954           0 :         }
    2955             :         else{
    2956         636 :           Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
    2957         636 :           if (kinkrow==nr){
    2958           4 :             AliExternalTrackParam paramd(t);
    2959           4 :             kink->SetDaughter(paramd);
    2960           4 :             kink->SetStatus(2,5);
    2961           4 :             kink->Update();
    2962           4 :           }
    2963             :         }
    2964         636 :       }
    2965         636 :     }
    2966             : 
    2967       51750 :     if (nr==80) t.UpdateReference();
    2968       51478 :     if (nr<fInnerSec->GetNRows()) 
    2969       18682 :       fSectors = fInnerSec;
    2970             :     else
    2971       32796 :       fSectors = fOuterSec;
    2972       51478 :     if (FollowToNext(t,nr)==0) 
    2973        6264 :       if (!t.IsActive()) 
    2974          98 :         return 0;
    2975             :     
    2976             :   }   
    2977        3556 :   return 1;
    2978        3654 : }
    2979             : 
    2980             : 
    2981             : 
    2982             : 
    2983             : 
    2984             : 
    2985             : Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
    2986             :   //-----------------------------------------------------------------
    2987             :   // This function tries to find a track prolongation.
    2988             :   //-----------------------------------------------------------------
    2989             :   //
    2990             :   //  Double_t xt=t.GetX();   //RS: with distortions cannot rely on row from X
    2991        2268 :   Double_t alpha=t.GetAlpha();
    2992        2268 :   if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
    2993        2890 :   if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
    2994        2268 :   t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
    2995             :     
    2996        2268 :   Int_t first = t.GetFirstPoint();
    2997        6804 :   Int_t ri = fAccountDistortions ? GetRowNumber(&t) :  GetRowNumber(t.GetX());  //RS: with distortions cannot rely on X
    2998             :   //  Int_t ri = GetRowNumber(xt); 
    2999        2268 :   if (!fromSeeds)
    3000        2132 :     ri += 1;
    3001             : 
    3002        4390 :   if (first<ri) first = ri;
    3003             :   //
    3004        2268 :   if (first<0) first=0;
    3005       81168 :   for (Int_t nr=first; nr<=rf; nr++) {
    3006             :     //    if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
    3007       38316 :     if (t.GetKinkIndexes()[0]<0){
    3008        2544 :       for (Int_t i=0;i<3;i++){
    3009        1272 :         Int_t index = t.GetKinkIndexes()[i];
    3010        1908 :         if (index==0) break;
    3011         636 :         if (index>0) continue;
    3012         636 :         index = TMath::Abs(index);
    3013         636 :         AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
    3014         636 :         if (!kink){
    3015           0 :           printf("PROBLEM\n");
    3016           0 :         }
    3017             :         else{
    3018         636 :           Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
    3019         636 :           if (kinkrow==nr){
    3020           8 :             AliExternalTrackParam paramm(t);
    3021           8 :             kink->SetMother(paramm);
    3022           8 :             kink->SetStatus(2,1);
    3023           8 :             kink->Update();
    3024           8 :           }
    3025             :         }
    3026         636 :       }      
    3027         636 :     }
    3028             :     //
    3029       38316 :     if (nr<fInnerSec->GetNRows()) 
    3030       14676 :       fSectors = fInnerSec;
    3031             :     else
    3032       23640 :       fSectors = fOuterSec;
    3033             : 
    3034       38316 :     FollowToNext(t,nr);                                                             
    3035             :   }   
    3036        2268 :   return 1;
    3037           0 : }
    3038             : 
    3039             : 
    3040             : 
    3041             : 
    3042             :    
    3043             : Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
    3044             : {
    3045             :   // overlapping factor
    3046             :   //
    3047           0 :   sum1=0;
    3048           0 :   sum2=0;
    3049             :   Int_t sum=0;
    3050             :   //
    3051           0 :   Float_t dz2 =(s1->GetZ() - s2->GetZ());
    3052           0 :   dz2*=dz2;  
    3053             : 
    3054           0 :   Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
    3055           0 :   dy2*=dy2;
    3056           0 :   Float_t distance = TMath::Sqrt(dz2+dy2);
    3057           0 :   if (distance>4.) return 0; // if there are far away  - not overlap - to reduce combinatorics
    3058             :  
    3059             :   //  Int_t offset =0;
    3060           0 :   Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
    3061           0 :   Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
    3062           0 :   if (lastpoint>=kMaxRow) 
    3063             :     lastpoint = kMaxRow-1;
    3064           0 :   if (firstpoint<0) 
    3065           0 :     firstpoint = 0;
    3066           0 :   if (firstpoint>lastpoint) {
    3067             :     firstpoint =lastpoint;
    3068             :     //    lastpoint  = kMaxRow-1;
    3069           0 :   }
    3070             :     
    3071             :   
    3072             :   // for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
    3073             :   //   if (s1->GetClusterIndex2(i)>0) sum1++;
    3074             :   //   if (s2->GetClusterIndex2(i)>0) sum2++;
    3075             :   //   if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
    3076             :   //     sum++;
    3077             :   //   }
    3078             :   // }
    3079             :   // RS: faster version + fix(?): clusterindex starts from 0 
    3080           0 :   for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
    3081           0 :     int ind1=s1->GetClusterIndex2(i), ind2=s2->GetClusterIndex2(i);
    3082           0 :     if (ind1>=0) sum1++;
    3083           0 :     if (ind2>=0) sum2++;
    3084           0 :     if (ind1==ind2 && ind1>=0) sum++;
    3085             :   }
    3086           0 :   if (sum<5) return 0;
    3087             :   
    3088           0 :   Float_t summin = TMath::Min(sum1+1,sum2+1);
    3089           0 :   Float_t ratio = (sum+1)/Float_t(summin);
    3090             :   return ratio;
    3091           0 : }
    3092             : 
    3093             : void  AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
    3094             : {
    3095             :   // shared clusters
    3096             :   //
    3097             :   Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
    3098        1418 :   if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
    3099         262 :   Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
    3100         262 :   Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
    3101             :   
    3102             :   //
    3103             :   Int_t sumshared=0;
    3104             :   //
    3105             :   //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
    3106             :   //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
    3107             :   Int_t firstpoint = 0;
    3108             :   Int_t lastpoint = kMaxRow;
    3109             :   //
    3110             :   //  if (firstpoint>=lastpoint-5) return;;
    3111             : 
    3112       83840 :   for (Int_t i=firstpoint;i<lastpoint;i++){
    3113             :     //    if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
    3114       45484 :     if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>=0) {
    3115         320 :       sumshared++;
    3116         320 :     }
    3117             :   }
    3118         262 :   if (sumshared>cutN0){
    3119             :     // sign clusters
    3120             :     //
    3121        3200 :     for (Int_t i=firstpoint;i<lastpoint;i++){
    3122             :       //      if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
    3123        1950 :       if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>=0) {
    3124         288 :         const AliTPCTrackerPoints::Point *p1  = s1->GetTrackPoint(i);
    3125         288 :         const AliTPCTrackerPoints::Point *p2  = s2->GetTrackPoint(i);; 
    3126         576 :         if (s1->IsActive()&&s2->IsActive()){
    3127         288 :           s1->SetShared(i);
    3128         288 :           s2->SetShared(i);
    3129         288 :         }       
    3130         288 :       }
    3131             :     }
    3132          10 :   }
    3133             :   //  
    3134         262 :   if (sumshared>cutN0){
    3135          20 :     for (Int_t i=0;i<4;i++){
    3136          10 :       if (s1->GetOverlapLabel(3*i)==0){
    3137          10 :         s1->SetOverlapLabel(3*i,  s2->GetLabel());
    3138          10 :         s1->SetOverlapLabel(3*i+1,sumshared);
    3139          10 :         s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
    3140          10 :         break;
    3141             :       } 
    3142             :     }
    3143          20 :     for (Int_t i=0;i<4;i++){
    3144          10 :       if (s2->GetOverlapLabel(3*i)==0){
    3145          10 :         s2->SetOverlapLabel(3*i,  s1->GetLabel());
    3146          10 :         s2->SetOverlapLabel(3*i+1,sumshared);
    3147          10 :         s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
    3148          10 :         break;
    3149             :       } 
    3150             :     }    
    3151          10 :   }
    3152         822 : }
    3153             : 
    3154             : void  AliTPCtracker::SignShared(TObjArray * arr)
    3155             : {
    3156             :   //
    3157             :   //sort trackss according sectors
    3158             :   //  
    3159         836 :   for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
    3160         394 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
    3161         516 :     if (!pt) continue;
    3162             :     //if (pt) RotateToLocal(pt);
    3163         272 :     pt->SetSort(0);
    3164         272 :   }
    3165          16 :   arr->UnSort();
    3166          16 :   arr->Sort();  // sorting according relative sectors
    3167          16 :   arr->Expand(arr->GetEntries());
    3168             :   //
    3169             :   //
    3170          16 :   Int_t nseed=arr->GetEntriesFast();
    3171         576 :   for (Int_t i=0; i<nseed; i++) {
    3172         272 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
    3173         272 :     if (!pt) continue;
    3174        7072 :     for (Int_t j=0;j<12;j++){
    3175        3264 :       pt->SetOverlapLabel(j,0);
    3176             :     }
    3177         272 :   }
    3178         576 :   for (Int_t i=0; i<nseed; i++) {
    3179         272 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
    3180         272 :     if (!pt) continue;
    3181         272 :     if (pt->GetRemoval()>10) continue;
    3182        5360 :     for (Int_t j=i+1; j<nseed; j++){
    3183        2408 :       AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
    3184        4256 :       if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
    3185             :       //      if (pt2){
    3186         560 :       if (pt2->GetRemoval()<=10) {
    3187             :         //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
    3188         560 :         SignShared(pt,pt2);
    3189         560 :       }
    3190         560 :     }  
    3191         272 :   }
    3192          16 : }
    3193             : 
    3194             : 
    3195             : void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
    3196             : {
    3197             :   //
    3198             :   //sort tracks in array according mode criteria
    3199          16 :   Int_t nseed = arr->GetEntriesFast();    
    3200         288 :   for (Int_t i=0; i<nseed; i++) {
    3201         136 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
    3202         136 :     if (!pt) {
    3203           0 :       continue;
    3204             :     }
    3205         136 :     pt->SetSort(mode);
    3206         136 :   }
    3207           8 :   arr->UnSort();
    3208           8 :   arr->Sort();
    3209           8 : }
    3210             : 
    3211             : 
    3212             : void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1,  Float_t factor2, Int_t minimal)
    3213             : {
    3214             :   //
    3215             :   // Loop over all tracks and remove overlaped tracks (with lower quality)
    3216             :   // Algorithm:
    3217             :   //    1. Unsign clusters
    3218             :   //    2. Sort tracks according quality
    3219             :   //       Quality is defined by the number of cluster between first and last points 
    3220             :   //       
    3221             :   //    3. Loop over tracks - decreasing quality order
    3222             :   //       a.) remove - If the fraction of shared cluster less than factor (1- n or 2) 
    3223             :   //       b.) remove - If the minimal number of clusters less than minimal and not ITS
    3224             :   //       c.) if track accepted - sign clusters
    3225             :   //
    3226             :   //Called in - AliTPCtracker::Clusters2Tracks()
    3227             :   //          - AliTPCtracker::PropagateBack()
    3228             :   //          - AliTPCtracker::RefitInward()
    3229             :   //
    3230             :   // Arguments:
    3231             :   //   factor1 - factor for constrained
    3232             :   //   factor2 -        for non constrained tracks 
    3233             :   //            if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
    3234             :   //
    3235          80 :   UnsignClusters();
    3236             :   //
    3237          40 :   Int_t nseed = arr->GetEntriesFast();  
    3238             :   //  Float_t quality = new Float_t[nseed];
    3239             :   //  Int_t   * indexes = new Int_t[nseed];
    3240          40 :   Float_t quality[nseed]; //RS Use stack allocations
    3241          40 :   Int_t   indexes[nseed];
    3242             :   Int_t good =0;
    3243             :   //
    3244             :   //
    3245        2236 :   for (Int_t i=0; i<nseed; i++) {
    3246        1078 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
    3247        1078 :     if (!pt){
    3248         242 :       quality[i]=-1;
    3249         242 :       continue;
    3250             :     }
    3251         836 :     pt->UpdatePoints();    //select first last max dens points
    3252         836 :     Float_t * points = pt->GetPoints();
    3253         836 :     if (points[3]<0.8) quality[i] =-1;
    3254         836 :     quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
    3255             :     //prefer high momenta tracks if overlaps
    3256         836 :     quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5); 
    3257         836 :   }
    3258          40 :   TMath::Sort(nseed,quality,indexes);
    3259             :   //
    3260             :   //
    3261        2236 :   for (Int_t itrack=0; itrack<nseed; itrack++) {
    3262        1078 :     Int_t trackindex = indexes[itrack];
    3263        1078 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);   
    3264        1320 :     if (!pt) continue;
    3265             :     //
    3266         836 :     if (quality[trackindex]<0){
    3267           0 :       MarkSeedFree( arr->RemoveAt(trackindex) );
    3268           0 :       continue;
    3269             :     }
    3270             :     //
    3271             :     //
    3272         836 :     Int_t first = Int_t(pt->GetPoints()[0]);
    3273         836 :     Int_t last  = Int_t(pt->GetPoints()[2]);
    3274         836 :     Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
    3275             :     //
    3276         836 :     Int_t found,foundable,shared;
    3277         836 :     GetSeedClusterStatistic(pt, first,last, found, foundable,shared,kFALSE); //RS: seeds don't keep their clusters
    3278             :     //RS 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
    3279             :     //MI  pt->GetClusterStatistic(0,kMaxRow, found, foundable,shared,kFALSE);
    3280             :     Bool_t itsgold =kFALSE;
    3281         836 :     if (pt->GetESD()){
    3282         272 :       Int_t dummy[12];
    3283         416 :       if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
    3284         272 :     }
    3285         836 :     if (!itsgold){
    3286             :       //
    3287         692 :       if (Float_t(shared+1)/Float_t(found+1)>factor){
    3288         140 :         if (pt->GetKinkIndexes()[0]!=0) continue;  //don't remove tracks  - part of the kinks
    3289         140 :         if( (AliTPCReconstructor::StreamLevel()&kStreamRemoveUsed)>0){ // flag:stream  information about TPC tracks which were descarded (double track removal)
    3290           0 :           TTreeSRedirector &cstream = *fDebugStreamer;
    3291           0 :           cstream<<"RemoveUsed"<<
    3292           0 :             "iter="<<fIteration<<
    3293           0 :             "pt.="<<pt<<
    3294             :             "\n";
    3295           0 :         }
    3296         140 :         MarkSeedFree( arr->RemoveAt(trackindex) );
    3297         140 :         continue;
    3298             :       }      
    3299         606 :       if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){  //remove short tracks
    3300           8 :         if (pt->GetKinkIndexes()[0]!=0) continue;  //don't remove tracks  - part of the kinks
    3301           8 :         if( (AliTPCReconstructor::StreamLevel()&kStreamRemoveShort)>0){ // flag:stream  information about TPC tracks which were discarded (short track removal)
    3302           0 :           TTreeSRedirector &cstream = *fDebugStreamer;
    3303           0 :           cstream<<"RemoveShort"<<
    3304           0 :             "iter="<<fIteration<<
    3305           0 :             "pt.="<<pt<<
    3306             :             "\n";
    3307           0 :         }
    3308           8 :         MarkSeedFree( arr->RemoveAt(trackindex) );
    3309           8 :         continue;
    3310             :       }
    3311             :     }
    3312             : 
    3313         688 :     good++;
    3314             :     //if (sharedfactor>0.4) continue;
    3315         700 :     if (pt->GetKinkIndexes()[0]>0) continue;
    3316             :     //Remove tracks with undefined properties - seems
    3317         676 :     if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ? 
    3318             :     //
    3319      159172 :     for (Int_t i=first; i<last; i++) {
    3320       78910 :       Int_t index=pt->GetClusterIndex2(i);
    3321             :       // if (index<0 || index&0x8000 ) continue;
    3322      159922 :       if (index<0 || index&0x8000 ) continue;
    3323       67942 :       AliTPCclusterMI *c= GetClusterMI(index); //RS pt->GetClusterPointer(i);        
    3324       67942 :       if (!c) continue;
    3325       67942 :       c->Use(10);  
    3326       67942 :     }    
    3327        1512 :   }
    3328          40 :   fNtracks = good;
    3329          40 :   if (fDebug>0){
    3330           0 :     Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
    3331           0 :   }
    3332             :   //  delete []quality; // RS was moved to stack allocation
    3333             :   //  delete []indexes;
    3334          40 : }
    3335             : 
    3336             : void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray) 
    3337             : {
    3338             :   //
    3339             :   // Dump clusters after reco
    3340             :   // signed and unsigned cluster can be visualized   
    3341             :   // 1. Unsign all cluster
    3342             :   // 2. Sign all used clusters
    3343             :   // 3. Dump clusters
    3344           0 :   UnsignClusters();
    3345           0 :   Int_t nseed = trackArray->GetEntries();
    3346           0 :   for (Int_t i=0; i<nseed; i++){
    3347           0 :     AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);    
    3348           0 :     if (!pt) {
    3349           0 :       continue;
    3350             :     }    
    3351           0 :     Bool_t isKink=pt->GetKinkIndex(0)!=0;
    3352           0 :     for (Int_t j=0; j<kMaxRow; ++j) {
    3353           0 :       Int_t index=pt->GetClusterIndex2(j);
    3354           0 :       if (index<0) continue;
    3355           0 :       AliTPCclusterMI *c= GetClusterMI(index); //RS pt->GetClusterPointer(j);
    3356           0 :       if (!c) continue;
    3357           0 :       if (isKink) c->Use(100);   // kink
    3358           0 :       c->Use(10);                // by default usage 10
    3359           0 :     }
    3360           0 :   }
    3361             :   //
    3362           0 :   Int_t eventNr = fEvent->GetEventNumberInFile();
    3363             : 
    3364           0 :   for (Int_t sec=0;sec<fkNIS;sec++){
    3365           0 :     for (Int_t row=0;row<fInnerSec->GetNRows();row++){
    3366           0 :       TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
    3367           0 :       for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){    
    3368           0 :         AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
    3369           0 :         Float_t gx[3];  cl->GetGlobalXYZ(gx);
    3370           0 :         (*fDebugStreamer)<<"clDump"<< 
    3371           0 :           "eventNr="<<eventNr<<
    3372           0 :           "iter="<<iter<<
    3373           0 :           "cl.="<<cl<<      
    3374           0 :           "gx0="<<gx[0]<<
    3375           0 :           "gx1="<<gx[1]<<
    3376           0 :           "gx2="<<gx[2]<<
    3377             :           "\n";
    3378           0 :       }
    3379           0 :       cla = fInnerSec[sec][row].GetClusters2();
    3380           0 :       for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
    3381           0 :         AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
    3382           0 :         Float_t gx[3];  cl->GetGlobalXYZ(gx);
    3383           0 :         (*fDebugStreamer)<<"clDump"<< 
    3384           0 :           "eventNr="<<eventNr<<
    3385           0 :           "iter="<<iter<<
    3386           0 :           "cl.="<<cl<<
    3387           0 :           "gx0="<<gx[0]<<
    3388           0 :           "gx1="<<gx[1]<<
    3389           0 :           "gx2="<<gx[2]<<
    3390             :           "\n";
    3391           0 :       }
    3392             :     }
    3393             :   }
    3394             :   
    3395           0 :   for (Int_t sec=0;sec<fkNOS;sec++){
    3396           0 :     for (Int_t row=0;row<fOuterSec->GetNRows();row++){
    3397           0 :       TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
    3398           0 :       for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
    3399           0 :         Float_t gx[3];  
    3400           0 :         AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
    3401           0 :         cl->GetGlobalXYZ(gx);
    3402           0 :         (*fDebugStreamer)<<"clDump"<< 
    3403           0 :           "eventNr="<<eventNr<<
    3404           0 :           "iter="<<iter<<
    3405           0 :           "cl.="<<cl<<
    3406           0 :           "gx0="<<gx[0]<<
    3407           0 :           "gx1="<<gx[1]<<
    3408           0 :           "gx2="<<gx[2]<<
    3409             :           "\n";      
    3410           0 :       }
    3411           0 :       cla = fOuterSec[sec][row].GetClusters2();
    3412           0 :       for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
    3413           0 :         Float_t gx[3];  
    3414           0 :         AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
    3415           0 :         cl->GetGlobalXYZ(gx);
    3416           0 :         (*fDebugStreamer)<<"clDump"<< 
    3417           0 :           "eventNr="<<eventNr<<
    3418           0 :           "iter="<<iter<<
    3419           0 :           "cl.="<<cl<<
    3420           0 :           "gx0="<<gx[0]<<
    3421           0 :           "gx1="<<gx[1]<<
    3422           0 :           "gx2="<<gx[2]<<
    3423             :           "\n";      
    3424           0 :       }
    3425             :     }
    3426             :   }
    3427             :   
    3428           0 : }
    3429             : void AliTPCtracker::UnsignClusters() 
    3430             : {
    3431             :   //
    3432             :   // loop over all clusters and unsign them
    3433             :   //
    3434             :   
    3435        2496 :   for (Int_t sec=0;sec<fkNIS;sec++){
    3436      147456 :     for (Int_t row=0;row<fInnerSec->GetNRows();row++){
    3437       72576 :       TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
    3438      555200 :       for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
    3439             :         //      if (cl[icl].IsUsed(10))         
    3440      205024 :         ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
    3441       72576 :       cla = fInnerSec[sec][row].GetClusters2();
    3442      472704 :       for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
    3443             :         //if (cl[icl].IsUsed(10))       
    3444      163776 :         ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
    3445             :     }
    3446             :   }
    3447             :   
    3448        2432 :   for (Int_t sec=0;sec<fkNOS;sec++){
    3449      223488 :     for (Int_t row=0;row<fOuterSec->GetNRows();row++){
    3450      110592 :       TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
    3451      349856 :       for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
    3452             :         //if (cl[icl].IsUsed(10))       
    3453       64336 :         ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
    3454      110592 :       cla = fOuterSec[sec][row].GetClusters2();
    3455      394080 :       for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
    3456             :         //if (cl[icl].IsUsed(10))       
    3457       86448 :         ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
    3458             :     }
    3459             :   }
    3460             :   
    3461          64 : }
    3462             : 
    3463             : 
    3464             : 
    3465             : void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
    3466             : {
    3467             :   //
    3468             :   //sign clusters to be "used"
    3469             :   //
    3470             :   // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
    3471             :   // loop over "primaries"
    3472             :   
    3473             :   Float_t sumdens=0;
    3474             :   Float_t sumdens2=0;
    3475             :   Float_t sumn   =0;
    3476             :   Float_t sumn2  =0;
    3477             :   Float_t sumchi =0;
    3478             :   Float_t sumchi2 =0;
    3479             : 
    3480             :   Float_t sum    =0;
    3481             : 
    3482        1392 :   TStopwatch timer;
    3483         696 :   timer.Start();
    3484             : 
    3485         696 :   Int_t nseed = arr->GetEntriesFast();
    3486       40608 :   for (Int_t i=0; i<nseed; i++) {
    3487       19608 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
    3488       19608 :     if (!pt) {
    3489           0 :       continue;
    3490             :     }    
    3491       19866 :     if (!(pt->IsActive())) continue;
    3492       38700 :     Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
    3493       58042 :     if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
    3494       18966 :       sumdens += dens;
    3495       18966 :       sumdens2+= dens*dens;
    3496       37932 :       sumn    += pt->GetNumberOfClusters();
    3497       56898 :       sumn2   += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
    3498       37932 :       Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
    3499       18966 :       if (chi2>5) chi2=5;
    3500       18966 :       sumchi  +=chi2;
    3501       18966 :       sumchi2 +=chi2*chi2;
    3502       18966 :       sum++;
    3503       18966 :     }
    3504       19350 :   }
    3505             : 
    3506             :   Float_t mdensity = 0.9;
    3507             :   Float_t meann    = 130;
    3508             :   Float_t meanchi  = 1;
    3509             :   Float_t sdensity = 0.1;
    3510             :   Float_t smeann    = 10;
    3511             :   Float_t smeanchi  =0.4;
    3512             :   
    3513             : 
    3514         696 :   if (sum>20){
    3515         680 :     mdensity = sumdens/sum;
    3516         680 :     meann    = sumn/sum;
    3517         680 :     meanchi  = sumchi/sum;
    3518             :     //
    3519         680 :     sdensity = sumdens2/sum-mdensity*mdensity;
    3520         680 :     if (sdensity >= 0)
    3521         680 :        sdensity = TMath::Sqrt(sdensity);
    3522             :     else
    3523             :        sdensity = 0.1;
    3524             :     //
    3525         680 :     smeann   = sumn2/sum-meann*meann;
    3526         680 :     if (smeann >= 0)
    3527         680 :       smeann   = TMath::Sqrt(smeann);
    3528             :     else 
    3529             :       smeann   = 10;
    3530             :     //
    3531         680 :     smeanchi = sumchi2/sum - meanchi*meanchi;
    3532         680 :     if (smeanchi >= 0)
    3533         680 :       smeanchi = TMath::Sqrt(smeanchi);
    3534             :     else
    3535             :       smeanchi = 0.4;
    3536             :   }
    3537             : 
    3538             : 
    3539             :   //REMOVE  SHORT DELTAS or tracks going out of sensitive volume of TPC
    3540             :   //
    3541       40608 :   for (Int_t i=0; i<nseed; i++) {
    3542       19608 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
    3543       19608 :     if (!pt) {
    3544           0 :       continue;
    3545             :     }
    3546       57722 :     if (pt->GetBSigned()) continue;
    3547        1512 :     if (pt->GetBConstrain()) continue;    
    3548             :     //if (!(pt->IsActive())) continue;
    3549             :     /*
    3550             :     Int_t found,foundable,shared;    
    3551             :     pt->GetClusterStatistic(0,kMaxRow,found, foundable,shared);
    3552             :     if (shared/float(found)>0.3) {
    3553             :       if (shared/float(found)>0.9 ){
    3554             :         //MarkSeedFree( arr->RemoveAt(i) );
    3555             :       }
    3556             :       continue;
    3557             :     }
    3558             :     */
    3559             :     Bool_t isok =kFALSE;
    3560        2768 :     if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
    3561          76 :       isok = kTRUE;
    3562        1976 :     if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
    3563         296 :       isok =kTRUE;
    3564        2076 :     if  (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
    3565         206 :       isok =kTRUE;
    3566        1388 :     if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
    3567           0 :       isok =kTRUE;
    3568             :     
    3569         692 :     if (isok)     
    3570      138880 :       for (Int_t j=0; j<kMaxRow; ++j) {      
    3571       69006 :         Int_t index=pt->GetClusterIndex2(j);
    3572      115568 :         if (index<0) continue;
    3573       22444 :         AliTPCclusterMI *c= GetClusterMI(index);//pt->GetClusterPointer(j);
    3574       22444 :         if (!c) continue;
    3575             :         //if (!(c->IsUsed(10))) c->Use();  
    3576       22444 :         c->Use(10);  
    3577       22878 :       }
    3578         692 :   }
    3579             :   
    3580             :   
    3581             :   //
    3582         696 :   Double_t maxchi  = meanchi+2.*smeanchi;
    3583             : 
    3584       40608 :   for (Int_t i=0; i<nseed; i++) {
    3585       19608 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);    
    3586       19608 :     if (!pt) {
    3587           0 :       continue;
    3588             :     }    
    3589             :     //if (!(pt->IsActive())) continue;
    3590       57722 :     if (pt->GetBSigned()) continue;
    3591        2204 :     Double_t chi     = pt->GetChi2()/pt->GetNumberOfClusters();
    3592        1384 :     if (chi>maxchi) continue;
    3593             : 
    3594             :     Float_t bfactor=1;
    3595        1640 :     Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
    3596             :    
    3597             :     //sign only tracks with enoug big density at the beginning
    3598             :     
    3599        2204 :     if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue; 
    3600             :     
    3601             :     
    3602         632 :     Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
    3603         632 :     Double_t minn    = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
    3604             :    
    3605             :     //    if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
    3606         808 :     if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
    3607           0 :       minn=0;
    3608             : 
    3609        2126 :     if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
    3610             :       //Int_t noc=pt->GetNumberOfClusters();
    3611         230 :       pt->SetBSigned(kTRUE);
    3612       73600 :       for (Int_t j=0; j<kMaxRow; ++j) {
    3613             : 
    3614       36570 :         Int_t index=pt->GetClusterIndex2(j);
    3615       41778 :         if (index<0) continue;
    3616       31362 :         AliTPCclusterMI *c= GetClusterMI(index); //RS pt->GetClusterPointer(j);
    3617       31362 :         if (!c) continue;
    3618             :         //      if (!(c->IsUsed(10))) c->Use();  
    3619       31362 :         c->Use(10);  
    3620       31362 :       }
    3621         230 :     }
    3622         632 :   }
    3623             :   //  gLastCheck = nseed;
    3624             :   //  arr->Compress();
    3625         696 :   if (fDebug>0){
    3626           0 :     timer.Print();
    3627             :   }
    3628         696 : }
    3629             : 
    3630             : 
    3631             : 
    3632             : Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
    3633             : {
    3634             :   //
    3635             :   // back propagation of ESD tracks
    3636             :   //
    3637             :   //return 0;
    3638          16 :   if (!event) return 0;
    3639           8 :   fEvent = event;
    3640           8 :   fEventHLT = 0;
    3641             :   // extract correction object for multiplicity dependence of dEdx
    3642           8 :   TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
    3643             : 
    3644           8 :   AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
    3645           8 :   if (!transform) {
    3646           0 :     AliFatal("Tranformations not in RefitInward");
    3647           0 :     return 0;
    3648             :   }
    3649           8 :   transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
    3650           8 :   const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
    3651           8 :   Int_t nContribut = event->GetNumberOfTracks();
    3652             :   TGraphErrors * graphMultDependenceDeDx = 0x0;
    3653          16 :   if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
    3654           0 :     if (recoParam->GetUseTotCharge()) {
    3655           0 :       graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
    3656           0 :     } else {
    3657           0 :       graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
    3658             :     }
    3659             :   }
    3660             :   //
    3661           8 :   ReadSeeds(event,2);
    3662           8 :   fIteration=2;
    3663             :   //PrepareForProlongation(fSeeds,1);
    3664           8 :   PropagateForward2(fSeeds);
    3665           8 :   RemoveUsed2(fSeeds,0.4,0.4,20);
    3666             : 
    3667           8 :   Int_t entriesSeed=fSeeds->GetEntries();
    3668           8 :   TObjArray arraySeed(entriesSeed);
    3669         288 :   for (Int_t i=0;i<entriesSeed;i++) {
    3670         272 :     arraySeed.AddAt(fSeeds->At(i),i);    
    3671             :   }
    3672           8 :   SignShared(&arraySeed);
    3673             :   //  FindCurling(fSeeds, event,2); // find multi found tracks
    3674           8 :   FindSplitted(fSeeds, event,2); // find multi found tracks
    3675           8 :   if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0)  FindMultiMC(fSeeds, fEvent,2); // flag: stream MC infomation about the multiple find track (ONLY for MC data)
    3676             : 
    3677             :   Int_t ntracks=0;
    3678           8 :   Int_t nseed = fSeeds->GetEntriesFast();
    3679             :   //
    3680             :   // RS: the cluster pointers are not permanently attached to the seed during the tracking, need to attach temporarily
    3681           8 :   AliTPCclusterMI* seedClusters[kMaxRow];
    3682             :   int seedsInFriends = 0;
    3683           8 :   int seedsInFriendsNorm = event->GetNTPCFriend2Store();
    3684          12 :   if (seedsInFriendsNorm>nseed) seedsInFriendsNorm = nseed; // all friends are stored
    3685             :   //
    3686           8 :   fClPointersPoolPtr = fClPointersPool;
    3687             :   //
    3688         288 :   for (Int_t i=0;i<nseed;i++) {
    3689         136 :     AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
    3690         136 :     if (!seed) continue;
    3691         276 :     if (seed->GetKinkIndex(0)>0)  UpdateKinkQualityD(seed);  // update quality informations for kinks
    3692         136 :     AliESDtrack *esd=event->GetTrack(i);
    3693             :     //
    3694             :     //RS: if needed, attach temporary cluster array
    3695         136 :     const AliTPCclusterMI** seedClustersSave = seed->GetClusters();
    3696         136 :     if (!seedClustersSave) { //RS: temporary attach clusters
    3697       43520 :       for (int ir=kMaxRow;ir--;) {
    3698       21624 :         int idx = seed->GetClusterIndex2(ir);
    3699       63404 :         seedClusters[ir] = idx<0 ? 0 : GetClusterMI(idx);
    3700             :       }
    3701         136 :       seed->SetClustersArrayTMP(seedClusters);
    3702         136 :     }
    3703             :     //
    3704             :     //
    3705         302 :     if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8) {
    3706           2 :       AliExternalTrackParam paramIn;
    3707           2 :       AliExternalTrackParam paramOut;
    3708             :       //
    3709           4 :       Int_t ncl = seed->RefitTrack(seed,&paramIn,&paramOut);
    3710             :       //
    3711           2 :       if ((AliTPCReconstructor::StreamLevel() & kStreamRecoverIn)>0) {  // flag: stream track information for track  failing in RefitInward function and recovered back
    3712           0 :         (*fDebugStreamer)<<"RecoverIn"<< 
    3713           0 :           "seed.="<<seed<<
    3714           0 :           "esd.="<<esd<<
    3715           0 :           "pin.="<<&paramIn<<
    3716           0 :           "pout.="<<&paramOut<<
    3717           0 :           "ncl="<<ncl<<
    3718             :           "\n";
    3719             :       }
    3720           2 :       if (ncl>15) {
    3721           2 :         seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
    3722           2 :         seed->SetNumberOfClusters(ncl);
    3723           2 :       }
    3724           2 :     }
    3725             : 
    3726         136 :     seed->PropagateTo(fkParam->GetInnerRadiusLow());
    3727         136 :     seed->SetRow(0);
    3728         136 :     seed->UpdatePoints();
    3729         136 :     AddCovariance(seed);
    3730         136 :     MakeESDBitmaps(seed, esd);
    3731         136 :     seed->CookdEdx(0.02,0.6);
    3732         136 :     CookLabel(seed,0.1); //For comparison only
    3733             :     //
    3734         136 :     if (((AliTPCReconstructor::StreamLevel()&kStreamRefitInward)>0) && seed!=0) {
    3735           0 :       TTreeSRedirector &cstream = *fDebugStreamer;
    3736           0 :       cstream<<"RefitInward"<<  // flag: stream track information in RefitInward function (after tracking Iteration 2)
    3737           0 :         "Esd.="<<esd<<
    3738           0 :         "Track.="<<seed<<
    3739             :         "\n"; 
    3740           0 :     }
    3741         272 :     if (seed->GetNumberOfClusters()>15) {
    3742         136 :       esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit); 
    3743         136 :       esd->SetTPCPoints(seed->GetPoints());
    3744         136 :       esd->SetTPCPointsF(seed->GetNFoundable());
    3745         136 :       Int_t   ndedx = seed->GetNCDEDX(0);
    3746         136 :       Float_t sdedx = seed->GetSDEDX(0);
    3747         136 :       Float_t dedx  = seed->GetdEdx();
    3748             :       // apply mutliplicity dependent dEdx correction if available
    3749         136 :       if (graphMultDependenceDeDx) {
    3750           0 :         Double_t corrGain =  AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
    3751           0 :         dedx += (1 - corrGain)*50.; // MIP is normalized to 50
    3752           0 :       }
    3753         136 :       esd->SetTPCsignal(dedx, sdedx, ndedx);
    3754             :       //
    3755             :       // fill new dEdx information
    3756             :       //
    3757         136 :       Double32_t signal[4]; 
    3758         136 :       Double32_t signalMax[4]; 
    3759         136 :       Char_t ncl[3]; 
    3760         136 :       Char_t nrows[3];
    3761             :       //
    3762        1088 :       for(Int_t iarr=0;iarr<3;iarr++) {
    3763         408 :         signal[iarr] = seed->GetDEDXregion(iarr+1);
    3764         408 :         signalMax[iarr] = seed->GetDEDXregion(iarr+5);
    3765         408 :         ncl[iarr] = seed->GetNCDEDX(iarr+1);
    3766         408 :         nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
    3767             :       }
    3768         136 :       signal[3] = seed->GetDEDXregion(4);
    3769         136 :       signalMax[3] = seed->GetDEDXregion(8);
    3770             :       
    3771             :       //
    3772         272 :       AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
    3773         136 :       infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
    3774         136 :       infoTpcPid->SetTPCSignalsQmax(signalMax);
    3775         136 :       esd->SetTPCdEdxInfo(infoTpcPid);
    3776             :       //
    3777             :       // add seed to the esd track in Calib level
    3778             :       //
    3779         340 :       Bool_t storeFriend = seedsInFriendsNorm>0 && (!esd->GetFriendNotStored()) 
    3780          68 :         && seedsInFriends<(kMaxFriendTracks-1) 
    3781         136 :         && gRandom->Rndm()<(kMaxFriendTracks)/Float_t(seedsInFriendsNorm);
    3782             :       //      if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
    3783             :       //AliInfoF("Store: %d Stored %d / %d FrOff: %d",storeFriend,seedsInFriends,seedsInFriendsNorm,esd->GetFriendNotStored());
    3784         136 :       if (storeFriend){ // RS: seed is needed for calibration, regardless on streamlevel
    3785          68 :         seedsInFriends++;
    3786             :         // RS: this is the only place where the seed is created not in the pool, 
    3787             :         // since it should belong to ESDevent
    3788             :         //AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE); 
    3789             :         //esd->AddCalibObject(seedCopy);
    3790             :         //
    3791             :         //RS to avoid the cloning the seeds and clusters we will declare the seed to own its
    3792             :         // clusters and reattach the clusters pointers from the pool, so they are saved in the friends
    3793          68 :         seed->SetClusterOwner(kTRUE);
    3794          68 :         memcpy(fClPointersPoolPtr,seedClusters,kMaxRow*sizeof(AliTPCclusterMI*));
    3795          68 :         seed->SetClustersArrayTMP(fClPointersPoolPtr);
    3796          68 :         esd->AddCalibObject(seed);
    3797          68 :         fClPointersPoolPtr += kMaxRow;
    3798          68 :       }
    3799          68 :       else seed->SetClustersArrayTMP((AliTPCclusterMI**)seedClustersSave);
    3800             :       //
    3801         136 :       ntracks++;
    3802         136 :     }
    3803             :     else{
    3804             :       //printf("problem\n");
    3805             :     }
    3806             :     //
    3807             :     //RS if seed does not own clusters, then it was not added to friends: detach temporary clusters !!!
    3808         340 :     if (!seedClustersSave && !seed->GetClusterOwner()) seed->SetClustersArrayTMP(0); 
    3809             :     //
    3810         136 :   }
    3811             :   //FindKinks(fSeeds,event);
    3812           8 :   if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0)  DumpClusters(2,fSeeds);  // dump clusters at the end of process (signed with useage flags)
    3813           8 :   Info("RefitInward","Number of refitted tracks %d",ntracks);
    3814             : 
    3815           8 :   AliCosmicTracker::FindCosmic(event, kTRUE);
    3816             : 
    3817           8 :   FillClusterOccupancyInfo();
    3818             : 
    3819             :   return 0;
    3820          16 : }
    3821             : 
    3822             : 
    3823             : Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
    3824             : {
    3825             :   //
    3826             :   // back propagation of ESD tracks
    3827             :   //
    3828          16 :   if (!event) return 0;
    3829           8 :   fEvent = event;
    3830           8 :   fEventHLT = 0;
    3831           8 :   fIteration = 1;
    3832           8 :   ReadSeeds(event,1);
    3833           8 :   PropagateBack(fSeeds); 
    3834           8 :   RemoveUsed2(fSeeds,0.4,0.4,20);
    3835             :   //FindCurling(fSeeds, fEvent,1);  
    3836           8 :   FindSplitted(fSeeds, event,1); // find multi found tracks
    3837           8 :   if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0)  FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
    3838             :   //
    3839             :   // RS: the cluster pointers are not permanently attached to the seed during the tracking, need to attach temporarily
    3840           8 :   AliTPCclusterMI* seedClusters[kMaxRow];
    3841             :   //
    3842           8 :   Int_t nseed = fSeeds->GetEntriesFast();
    3843             :   Int_t ntracks=0;
    3844         288 :   for (Int_t i=0;i<nseed;i++){
    3845         136 :     AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
    3846         138 :     if (!seed) continue;
    3847         134 :     AliESDtrack *esd=event->GetTrack(i);
    3848         134 :     if (!esd) continue; //never happen
    3849             :     //
    3850             :     //RS: if needed, attach temporary cluster array
    3851         134 :     const AliTPCclusterMI** seedClustersSave = seed->GetClusters();
    3852         134 :     if (!seedClustersSave) { //RS: temporary attach clusters
    3853       42880 :       for (int ir=kMaxRow;ir--;) {
    3854       21306 :         int idx = seed->GetClusterIndex2(ir);
    3855       59486 :         seedClusters[ir] = idx<0 ? 0 : GetClusterMI(idx);
    3856             :       }
    3857         134 :       seed->SetClustersArrayTMP(seedClusters);
    3858         134 :     }
    3859             :     //
    3860         138 :     if (seed->GetKinkIndex(0)<0)  UpdateKinkQualityM(seed);  // update quality informations for kinks
    3861         134 :     seed->UpdatePoints();
    3862         134 :     AddCovariance(seed);
    3863         142 :     if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
    3864           0 :       AliExternalTrackParam paramIn;
    3865           0 :       AliExternalTrackParam paramOut;
    3866           0 :       Int_t ncl = seed->RefitTrack(seed,&paramIn,&paramOut);
    3867           0 :       if ((AliTPCReconstructor::StreamLevel()&kStreamRecoverBack)>0) { // flag: stream track information for track  faling PropagateBack function and recovered back (RefitTrack)
    3868           0 :         (*fDebugStreamer)<<"RecoverBack"<<
    3869           0 :           "seed.="<<seed<<
    3870           0 :           "esd.="<<esd<<
    3871           0 :           "pin.="<<&paramIn<<
    3872           0 :           "pout.="<<&paramOut<<
    3873           0 :           "ncl="<<ncl<<
    3874             :           "\n";
    3875             :       }
    3876           0 :       if (ncl>15) {
    3877           0 :         seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
    3878           0 :         seed->SetNumberOfClusters(ncl);
    3879           0 :       }
    3880           0 :     }
    3881         134 :     seed->CookdEdx(0.02,0.6);
    3882         134 :     CookLabel(seed,0.1); //For comparison only
    3883         134 :     if (seed->GetNumberOfClusters()>15){
    3884         134 :       esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
    3885         134 :       esd->SetTPCPoints(seed->GetPoints());
    3886         134 :       esd->SetTPCPointsF(seed->GetNFoundable());
    3887         134 :       Int_t   ndedx = seed->GetNCDEDX(0);
    3888         134 :       Float_t sdedx = seed->GetSDEDX(0);
    3889         134 :       Float_t dedx  = seed->GetdEdx();
    3890         134 :       esd->SetTPCsignal(dedx, sdedx, ndedx);
    3891         134 :       ntracks++;
    3892         134 :       Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
    3893             :       // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number      
    3894         134 :       if (((AliTPCReconstructor::StreamLevel()&kStreamCPropagateBack)>0) && esd) {
    3895           0 :         (*fDebugStreamer)<<"PropagateBack"<<  // flag: stream track information in PropagateBack function (after tracking Iteration 1)
    3896           0 :           "Tr0.="<<seed<<
    3897           0 :           "esd.="<<esd<<
    3898           0 :           "EventNrInFile="<<eventnumber<<
    3899             :           "\n";       
    3900           0 :       }
    3901         134 :     }
    3902             :     //
    3903         268 :     if (!seedClustersSave) seed->SetClustersArrayTMP(0); //RS detach temporary clusters !!!
    3904             :     //
    3905         134 :   }
    3906           8 :   if (AliTPCReconstructor::StreamLevel()&kStreamClDump)  DumpClusters(1,fSeeds); // flag:stream clusters at the end of process (signed with usage flag)
    3907             :   //FindKinks(fSeeds,event);
    3908           8 :   Info("PropagateBack","Number of back propagated tracks %d",ntracks);
    3909           8 :   fEvent =0;
    3910           8 :   fEventHLT = 0;
    3911             : 
    3912             :   return 0;
    3913          16 : }
    3914             : 
    3915             : 
    3916             : Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
    3917             : {
    3918             :   //
    3919             :   // Post process events 
    3920             :   //
    3921          16 :   if (!event) return 0;
    3922             : 
    3923             :   //
    3924             :   // Set TPC event status
    3925             :   // 
    3926             : 
    3927             :   // event affected by HV dip
    3928             :   // reset TPC status
    3929           8 :   if(IsTPCHVDipEvent(event)) { 
    3930           0 :     event->ResetDetectorStatus(AliDAQ::kTPC);
    3931           0 :   }
    3932             :  
    3933             :   //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
    3934             : 
    3935           8 :   return 0;
    3936           8 : }
    3937             : 
    3938             : 
    3939             :  void AliTPCtracker::DeleteSeeds()
    3940             : {
    3941             :   //
    3942          44 :   fSeeds->Clear();
    3943          22 :   ResetSeedsPool();
    3944             :   //  delete fSeeds; // RS avoid unnecessary deletes
    3945             :   // fSeeds =0;
    3946          22 : }
    3947             : 
    3948             : void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
    3949             : {
    3950             :   //
    3951             :   //read seeds from the event
    3952             :   
    3953          32 :   Int_t nentr=event->GetNumberOfTracks();
    3954          16 :   if (fDebug>0){
    3955           0 :     Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
    3956           0 :   }
    3957          16 :   if (fSeeds) 
    3958          16 :     DeleteSeeds();
    3959          16 :   if (!fSeeds) fSeeds = new TObjArray(nentr);
    3960          24 :   else if (fSeeds->GetSize()<nentr) fSeeds->Expand(nentr);  //RS reuse array
    3961             :   //
    3962          16 :   UnsignClusters();
    3963             :   //  Int_t ntrk=0;  
    3964         640 :   for (Int_t i=0; i<nentr; i++) {
    3965         304 :     AliESDtrack *esd=event->GetTrack(i);
    3966         304 :     ULong_t status=esd->GetStatus();
    3967         336 :     if (!(status&AliESDtrack::kTPCin)) continue;
    3968         272 :     AliTPCtrack t(*esd);
    3969         272 :     t.SetNumberOfClusters(0);
    3970             :     //    AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
    3971         816 :     AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
    3972         272 :     seed->SetPoolID(fLastSeedID);
    3973         544 :     seed->SetUniqueID(esd->GetID());
    3974         272 :     AddCovariance(seed);   //add systematic ucertainty
    3975        2176 :     for (Int_t ikink=0;ikink<3;ikink++) {
    3976         816 :       Int_t index = esd->GetKinkIndex(ikink);
    3977         816 :       seed->GetKinkIndexes()[ikink] = index;
    3978        1616 :       if (index==0) continue;
    3979          16 :       index = TMath::Abs(index);
    3980          16 :       AliESDkink * kink = fEvent->GetKink(index-1);
    3981          48 :       if (kink&&esd->GetKinkIndex(ikink)<0){
    3982           8 :         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
    3983           8 :         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,0);
    3984             :       }
    3985          48 :       if (kink&&esd->GetKinkIndex(ikink)>0){
    3986           8 :         if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
    3987           8 :         if ((status & AliESDtrack::kITSout) != 0)   kink->SetStatus(1,4);
    3988             :       }
    3989             : 
    3990          16 :     }
    3991             :     // RS: resetting is done in the AliTPCtrack constructor 
    3992             :     // if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.); 
    3993             :     // if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
    3994             :     //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
    3995             :     //  fSeeds->AddAt(0,i);
    3996             :     //  MarkSeedFree( seed );
    3997             :     //  continue;    
    3998             :     //}
    3999             :     
    4000             :     //
    4001             :     //
    4002             :     // rotate to the local coordinate system
    4003             :     //   
    4004         272 :     fSectors=fInnerSec; fN=fkNIS;    
    4005         272 :     Double_t alpha=seed->GetAlpha();
    4006         272 :     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
    4007         370 :     if (alpha < 0.            ) alpha += 2.*TMath::Pi();
    4008         272 :     Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
    4009         272 :     alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
    4010         544 :     alpha-=seed->GetAlpha();  
    4011         272 :     if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
    4012         370 :     if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
    4013         272 :     if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
    4014           0 :       AliWarning(Form("Rotating track over %f",alpha));
    4015           0 :       if (!seed->Rotate(alpha)) {
    4016           0 :         MarkSeedFree( seed );
    4017           0 :         continue;
    4018             :       }
    4019             :     }
    4020         272 :     seed->SetESD(esd);
    4021             :     // sign clusters
    4022         544 :     if (esd->GetKinkIndex(0)<=0){
    4023       84480 :       for (Int_t irow=0;irow<kMaxRow;irow++){
    4024       41976 :         Int_t index = seed->GetClusterIndex2(irow);    
    4025       41976 :         if (index >= 0){ 
    4026             :           //
    4027       33148 :           AliTPCclusterMI * cl = GetClusterMI(index);
    4028             :           //RS seed->SetClusterPointer(irow,cl);
    4029       33148 :           if (cl){
    4030       66296 :             if ((index & 0x8000)==0){
    4031       65336 :               cl->Use(10);  // accepted cluster        
    4032             :             }else{
    4033         960 :               cl->Use(6);   // close cluster not accepted
    4034             :             }   
    4035             :           }else{
    4036           0 :             Info("ReadSeeds","Not found cluster");
    4037             :           }
    4038       33148 :         }
    4039             :       }
    4040         264 :     }
    4041         272 :     fSeeds->AddAt(seed,i);
    4042         544 :   }
    4043          16 : }
    4044             : 
    4045             : //_____________________________________________________________________________
    4046             : void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
    4047             :                                  Float_t deltay, Int_t ddsec) {
    4048             :   //-----------------------------------------------------------------
    4049             :   // This function creates track seeds.
    4050             :   // SEEDING WITH VERTEX CONSTRAIN 
    4051             :   //-----------------------------------------------------------------
    4052             :   // cuts[0]   - fP4 cut
    4053             :   // cuts[1]   - tan(phi)  cut
    4054             :   // cuts[2]   - zvertex cut
    4055             :   // cuts[3]   - fP3 cut
    4056             : 
    4057             :   const double kRoadY = 1., kRoadZ = 0.6;
    4058             : 
    4059             :   Int_t nin0  = 0;
    4060             :   Int_t nin1  = 0;
    4061             :   Int_t nin2  = 0;
    4062             :   Int_t nin   = 0;
    4063             :   Int_t nout1 = 0;
    4064             :   Int_t nout2 = 0;
    4065             : 
    4066       12384 :   Double_t x[5], c[15];
    4067             :   //  Int_t di = i1-i2;
    4068             :   //
    4069        6192 :   AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
    4070        6192 :   seed->SetPoolID(fLastSeedID);
    4071        6192 :   Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
    4072        6192 :   Double_t cs=cos(alpha), sn=sin(alpha);
    4073             :   //
    4074             :   //  Double_t x1 =fOuterSec->GetX(i1);
    4075             :   //Double_t xx2=fOuterSec->GetX(i2);
    4076             :   
    4077        6192 :   Double_t x1 =GetXrow(i1);
    4078        6192 :   Double_t xx2=GetXrow(i2);
    4079             : 
    4080        6192 :   Double_t x3=GetX(), y3=GetY(), z3=GetZ();
    4081             : 
    4082        6192 :   Int_t imiddle = (i2+i1)/2;    //middle pad row index
    4083        6192 :   Double_t xm = GetXrow(imiddle); // radius of middle pad-row
    4084        6192 :   const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
    4085             :   //
    4086             :   Int_t ns =sec;   
    4087             : 
    4088        6192 :   const AliTPCtrackerRow& kr1=GetRow(ns,i1);
    4089        6192 :   Double_t ymax  = GetMaxY(i1)-kr1.GetDeadZone()-1.5;  
    4090        6192 :   Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;  
    4091             : 
    4092             :   //
    4093             :   // change cut on curvature if it can't reach this layer
    4094             :   // maximal curvature set to reach it
    4095        6192 :   Double_t dvertexmax  = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
    4096        6192 :   if (dvertexmax*0.5*cuts[0]>0.85){
    4097           8 :     cuts[0] = 0.85/(dvertexmax*0.5+1.);
    4098           8 :   }
    4099        6192 :   Double_t r2min = 1/(cuts[0]*cuts[0]);  //minimal square of radius given by cut
    4100             : 
    4101             :   //  Int_t ddsec = 1;
    4102        6192 :   if (deltay>0) ddsec = 0; 
    4103             :   // loop over clusters  
    4104       32836 :   for (Int_t is=0; is < kr1; is++) {
    4105             :     //
    4106       10226 :     if (kr1[is]->IsUsed(10)) continue;
    4107        6708 :     if (kr1[is]->IsDisabled()) {
    4108             :       continue;
    4109             :     }
    4110             : 
    4111        6708 :     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
    4112             :     //if (TMath::Abs(y1)>ymax) continue;
    4113             : 
    4114        6708 :     if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge
    4115             : 
    4116             :     // find possible directions    
    4117        6708 :     Float_t anglez = (z1-z3)/(x1-x3); 
    4118        6708 :     Float_t extraz = z1 - anglez*(x1-xx2);  // extrapolated z      
    4119             :     //
    4120             :     //
    4121             :     //find   rotation angles relative to line given by vertex and point 1
    4122        6708 :     Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
    4123        6708 :     Double_t dvertex  = TMath::Sqrt(dvertex2);
    4124        6708 :     Double_t angle13  = TMath::ATan((y1-y3)/(x1-x3));
    4125        6708 :     Double_t cs13     = cos(-angle13), sn13 = sin(-angle13);            
    4126             :     
    4127             :     //
    4128             :     // loop over 2 sectors
    4129        6708 :     Int_t dsec1=-ddsec;
    4130             :     Int_t dsec2= ddsec;
    4131       11178 :     if (y1<0)  dsec2= 0;
    4132        8946 :     if (y1>0)  dsec1= 0;
    4133             :     
    4134             :     Double_t dddz1=0;  // direction of delta inclination in z axis
    4135             :     Double_t dddz2=0;
    4136        6708 :     if ( (z1-z3)>0)
    4137        3102 :       dddz1 =1;    
    4138             :     else
    4139             :       dddz2 =1;
    4140             :     //
    4141       31116 :     for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
    4142        8850 :       Int_t sec2 = sec + dsec;
    4143             :       // 
    4144             :       //      AliTPCtrackerRow&  kr2  = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
    4145             :       //AliTPCtrackerRow&  kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
    4146        8850 :       AliTPCtrackerRow&  kr2  = GetRow((sec2+fkNOS)%fkNOS,i2);
    4147        8850 :       AliTPCtrackerRow&  kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
    4148        8850 :       Int_t  index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
    4149        8850 :       Int_t  index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
    4150             : 
    4151             :       // rotation angles to p1-p3
    4152        8850 :       Double_t cs13r     = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;            
    4153             :       Double_t x2,   y2,   z2; 
    4154             :       //
    4155             :       //      Double_t dymax = maxangle*TMath::Abs(x1-xx2);
    4156             : 
    4157             :       //
    4158        8850 :       Double_t dxx0 =  (xx2-x3)*cs13r;
    4159        8850 :       Double_t dyy0 =  (xx2-x3)*sn13r;
    4160       41978 :       for (Int_t js=index1; js < index2; js++) {
    4161        8026 :         const AliTPCclusterMI *kcl = kr2[js];
    4162       10314 :         if (kcl->IsUsed(10)) continue;       
    4163        5738 :         if (kcl->IsDisabled()) {
    4164           0 :           continue;
    4165             :         }
    4166             :         //
    4167             :         //calcutate parameters
    4168             :         //      
    4169        5738 :         Double_t yy0 =  dyy0 +(kcl->GetY()-y3)*cs13r;
    4170             :         // stright track
    4171        5738 :         if (TMath::Abs(yy0)<0.000001) continue;
    4172        5738 :         Double_t xx0 =  dxx0 -(kcl->GetY()-y3)*sn13r;
    4173        5738 :         Double_t y0  =  0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
    4174        5738 :         Double_t r02 = (0.25+y0*y0)*dvertex2;   
    4175             :         //curvature (radius) cut
    4176        9614 :         if (r02<r2min) continue;             
    4177             :        
    4178        1862 :         nin0++; 
    4179             :         //
    4180        1862 :         Double_t c0  = 1/TMath::Sqrt(r02);
    4181        2698 :         if (yy0>0) c0*=-1.;  
    4182             :                
    4183             :        
    4184             :         //Double_t dfi0   = 2.*TMath::ASin(dvertex*c0*0.5);
    4185             :         //Double_t dfi1   = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
    4186        1862 :         Double_t dfi0   = 2.*asinf(dvertex*c0*0.5);
    4187        1862 :         Double_t dfi1   = 2.*asinf(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);  
    4188             :         //
    4189             :         //
    4190        1862 :         Double_t z0  =  kcl->GetZ();  
    4191        1862 :         Double_t zzzz2    = z1-(z1-z3)*dfi1/dfi0;
    4192        3416 :         if (TMath::Abs(zzzz2-z0)>0.5) continue;       
    4193         308 :         nin1++;              
    4194             :         //      
    4195         308 :         Double_t dip    = (z1-z0)*c0/dfi1;        
    4196         308 :         Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
    4197             :         //
    4198         308 :         y2 = kcl->GetY(); 
    4199         308 :         if (dsec==0){
    4200             :           x2 = xx2; 
    4201         282 :           z2 = kcl->GetZ();    
    4202         282 :         }
    4203             :         else
    4204             :           {
    4205             :             // rotation 
    4206          26 :             z2 = kcl->GetZ();  
    4207          26 :             x2= xx2*cs-y2*sn*dsec;
    4208          26 :             y2=+xx2*sn*dsec+y2*cs;
    4209             :           }
    4210             :         
    4211         308 :         x[0] = y1;
    4212         308 :         x[1] = z1;
    4213         308 :         x[2] = x0;
    4214         308 :         x[3] = dip;
    4215         308 :         x[4] = c0;
    4216             :         //
    4217             :         //
    4218             :         // do we have cluster at the middle ?
    4219         308 :         Double_t ym,zm;
    4220         308 :         GetProlongation(x1,xm,x,ym,zm);
    4221         308 :         UInt_t dummy; 
    4222             :         AliTPCclusterMI * cm=0;
    4223         308 :         if (TMath::Abs(ym)-ymaxm<0){   
    4224         282 :           cm = krm.FindNearest2(ym,zm,kRoadY+fClExtraRoadY,kRoadZ+fClExtraRoadZ,dummy);
    4225         500 :           if ((!cm) || (cm->IsUsed(10))) {     
    4226          78 :             continue;
    4227             :           }
    4228             :         }
    4229             :         else{     
    4230             :           // rotate y1 to system 0
    4231             :           // get state vector in rotated system 
    4232          26 :           Double_t yr1  = (-0.5*sn13+y0*cs13)*dvertex*c0;
    4233          26 :           Double_t xr2  =  x0*cs+yr1*sn*dsec;
    4234          26 :           Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
    4235             :           //
    4236          26 :           GetProlongation(xx2,xm,xr,ym,zm);
    4237          26 :           if (TMath::Abs(ym)-ymaxm<0){
    4238           2 :             cm = kr2m.FindNearest2(ym,zm,kRoadY+fClExtraRoadY,kRoadZ+fClExtraRoadZ,dummy);
    4239           2 :             if ((!cm) || (cm->IsUsed(10))) {   
    4240           2 :               continue;
    4241             :             }
    4242             :           }
    4243          50 :         }
    4244             :        
    4245             : 
    4246             :         // Double_t dym = 0;
    4247             :         // Double_t dzm = 0;
    4248             :         // if (cm){
    4249             :         //   dym = ym - cm->GetY();
    4250             :         //   dzm = zm - cm->GetZ();
    4251             :         // }
    4252         228 :         nin2++;
    4253             : 
    4254             : 
    4255             :         //
    4256             :         //
    4257         228 :         Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
    4258         228 :         Double_t sy2=kcl->GetSigmaY2()*2.,     sz2=kcl->GetSigmaZ2()*2.;
    4259             :         //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
    4260         228 :         Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
    4261             :         //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
    4262             : 
    4263         228 :         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
    4264         228 :         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
    4265         228 :         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
    4266         228 :         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
    4267         228 :         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
    4268         228 :         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
    4269             :         
    4270         228 :         Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
    4271         228 :         Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
    4272         228 :         Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
    4273         228 :         Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
    4274             :         
    4275         228 :         c[0]=sy1;
    4276         228 :         c[1]=0.;       c[2]=sz1;
    4277         228 :         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
    4278         228 :         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
    4279         228 :                        c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
    4280         228 :         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
    4281         228 :         c[13]=f30*sy1*f40+f32*sy2*f42;
    4282         228 :         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
    4283             :         
    4284             :         //      if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
    4285             :         
    4286         228 :         UInt_t index=kr1.GetIndex(is);
    4287         454 :         if (seed) {MarkSeedFree(seed); seed = 0;}
    4288         228 :         AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
    4289         228 :         seed->SetPoolID(fLastSeedID);
    4290         228 :         seed->SetRow(i1); //RS: memorise current row
    4291         228 :         track->SetIsSeeding(kTRUE);
    4292         228 :         track->SetSeed1(i1);
    4293         228 :         track->SetSeed2(i2);
    4294         228 :         track->SetSeedType(3);
    4295             : 
    4296             :        
    4297             :         //if (dsec==0) {
    4298         228 :           FollowProlongation(*track, (i1+i2)/2,1);
    4299         228 :           Int_t foundable,found,shared;   
    4300         228 :           GetSeedClusterStatistic(track,(i1+i2)/2,i1, found, foundable, shared, kTRUE); //RS: seeds don't keep their clusters
    4301             :           //RS track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
    4302         680 :           if ((found<0.55*foundable)  || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
    4303           2 :             MarkSeedFree(seed); seed = 0;
    4304           2 :             continue;
    4305             :           }
    4306             :           //}
    4307             :         
    4308         226 :         nin++;
    4309         226 :         FollowProlongation(*track, i2,1);
    4310             :         
    4311             :         
    4312             :         //Int_t rc = 1;
    4313         226 :         track->SetBConstrain(1);
    4314             :         //      track->fLastPoint = i1+fInnerSec->GetNRows();  // first cluster in track position
    4315         226 :         track->SetLastPoint(i1);  // first cluster in track position
    4316         226 :         track->SetFirstPoint(track->GetLastPoint());
    4317             :         
    4318         440 :         if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
    4319         214 :             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
    4320         214 :             track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
    4321          12 :           MarkSeedFree(seed); seed = 0;
    4322          12 :           continue;
    4323             :         }
    4324         214 :         nout1++;
    4325         214 :         Double_t zv, bz=GetBz();
    4326         214 :         if ( !track->GetZAt(0.,bz,zv) )       { MarkSeedFree( seed ); seed = 0; continue; }
    4327             :         //
    4328         214 :         if (fDisableSecondaries) {
    4329           0 :           if (TMath::Abs(zv)>fPrimaryDCAZCut) { MarkSeedFree( seed ); seed = 0; continue; }
    4330           0 :           double yv; 
    4331           0 :           if ( !track->GetZAt(0.,bz,yv) )     { MarkSeedFree( seed ); seed = 0; continue; }
    4332           0 :           if (TMath::Abs(zv)>fPrimaryDCAZCut) { MarkSeedFree( seed ); seed = 0; continue; }
    4333           0 :         }
    4334             :         
    4335             :         //
    4336             :         // Z VERTEX CONDITION
    4337         214 :         if (TMath::Abs(zv-z3)>cuts[2]) {
    4338           4 :           FollowProlongation(*track, TMath::Max(i2-20,0));
    4339           4 :           if ( !track->GetZAt(0.,bz,zv) ) continue;
    4340           4 :           if (TMath::Abs(zv-z3)>cuts[2]){
    4341           2 :             FollowProlongation(*track, TMath::Max(i2-40,0));
    4342           2 :             if ( !track->GetZAt(0.,bz,zv) ) continue;
    4343           4 :             if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
    4344             :               // make seed without constrain
    4345           2 :               AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
    4346           2 :               FollowProlongation(*track2, i2,1);
    4347           2 :               track2->SetBConstrain(kFALSE);
    4348           2 :               track2->SetSeedType(1);
    4349           2 :               arr->AddLast(track2); 
    4350           2 :               MarkSeedFree( seed ); seed = 0;
    4351             :               continue;         
    4352             :             }
    4353             :             else{
    4354           0 :               MarkSeedFree( seed ); seed = 0;
    4355           0 :               continue;
    4356             :             
    4357             :             }
    4358             :           }
    4359             :         }
    4360             :       
    4361         212 :         track->SetSeedType(0);
    4362         212 :         arr->AddLast(track); // note, track is seed, don't free the seed
    4363         212 :         seed = new( NextFreeSeed() ) AliTPCseed;        
    4364         212 :         seed->SetPoolID(fLastSeedID);
    4365         212 :         nout2++;
    4366             :         // don't consider other combinations
    4367         212 :         if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
    4368         208 :           break;
    4369         754 :       }
    4370             :     }
    4371        6708 :   }
    4372        6192 :   if (fDebug>3){
    4373           0 :     Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
    4374           0 :   }
    4375       12370 :   if (seed) MarkSeedFree( seed );
    4376        6192 : }
    4377             : 
    4378             : //_____________________________________________________________________________
    4379             : void AliTPCtracker::MakeSeeds3Dist(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
    4380             :                                    Float_t deltay, Int_t ddsec) {
    4381             :   //-----------------------------------------------------------------
    4382             :   // This function creates track seeds, accounting for distortions
    4383             :   // SEEDING WITH VERTEX CONSTRAIN 
    4384             :   //-----------------------------------------------------------------
    4385             :   // cuts[0]   - fP4 cut
    4386             :   // cuts[1]   - tan(phi)  cut
    4387             :   // cuts[2]   - zvertex cut
    4388             :   // cuts[3]   - fP3 cut
    4389             :   const double kRoadY = 1., kRoadZ = 0.6;
    4390             : 
    4391             :   Int_t nin0  = 0;
    4392             :   Int_t nin1  = 0;
    4393             :   Int_t nin2  = 0;
    4394             :   Int_t nin   = 0;
    4395             :   Int_t nout1 = 0;
    4396             :   Int_t nout2 = 0;
    4397             : 
    4398           0 :   Double_t x[5], c[15];
    4399             :   //  Int_t di = i1-i2;
    4400             :   //
    4401           0 :   AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
    4402           0 :   seed->SetPoolID(fLastSeedID);
    4403           0 :   Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
    4404           0 :   Double_t cs=cos(alpha), sn=sin(alpha);
    4405             :   //
    4406           0 :   Double_t x1def = GetXrow(i1);
    4407           0 :   Double_t xx2def = GetXrow(i2);
    4408             : 
    4409           0 :   Double_t x3=GetX(), y3=GetY(), z3=GetZ();
    4410             : 
    4411           0 :   Int_t imiddle = (i2+i1)/2;    //middle pad row index
    4412           0 :   const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
    4413             :   //
    4414             :   Int_t ns =sec;   
    4415             : 
    4416           0 :   const AliTPCtrackerRow& kr1=GetRow(ns,i1);
    4417           0 :   Double_t ymax  = GetMaxY(i1)-kr1.GetDeadZone()-1.5;  
    4418           0 :   Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5; 
    4419             : 
    4420             :   //
    4421             :   // change cut on curvature if it can't reach this layer
    4422             :   // maximal curvature set to reach it
    4423           0 :   Double_t dvertexmax  = TMath::Sqrt((x1def-x3)*(x1def-x3)+(ymax+5-y3)*(ymax+5-y3));
    4424           0 :   if (dvertexmax*0.5*cuts[0]>0.85){
    4425           0 :     cuts[0] = 0.85/(dvertexmax*0.5+1.);
    4426           0 :   }
    4427           0 :   Double_t r2min = 1/(cuts[0]*cuts[0]);  //minimal square of radius given by cut
    4428             : 
    4429             :   //  Int_t ddsec = 1;
    4430           0 :   if (deltay>0) ddsec = 0; 
    4431             :   // loop over clusters  
    4432           0 :   for (Int_t is=0; is < kr1; is++) {
    4433             :     //
    4434           0 :     if (kr1[is]->IsUsed(10)) continue;
    4435           0 :     if (kr1[is]->IsDisabled()) {
    4436             :       continue;
    4437             :     }
    4438           0 :     const AliTPCclusterMI* clkr1 = kr1[is];
    4439           0 :     Double_t x1=clkr1->GetX(), y1=clkr1->GetY(), z1=clkr1->GetZ();    
    4440             :     //if (TMath::Abs(y1)>ymax) continue;
    4441             :     double y1EdgeDist = y1;
    4442           0 :     if  (fAccountDistortions) y1EdgeDist -= GetYSectEdgeDist(sec,ns,y1,z1);
    4443           0 :     if (deltay>0) {
    4444           0 :       double margin = (y1>0 ? ymax-y1EdgeDist : ymax + y1EdgeDist);
    4445           0 :       if (margin<deltay ) continue;  // seed only at the edge
    4446           0 :     }
    4447             :     //
    4448             :     // find possible directions
    4449           0 :     double dx13 = x1-x3, dy13 = y1-y3, dz13 = z1-z3;
    4450           0 :     double anglez = dz13/dx13;
    4451           0 :     double extraz = z1 - anglez*(x1-xx2def);  // extrapolated z      
    4452             :     //
    4453             :     //
    4454             :     //find   rotation angles relative to line given by vertex and point 1
    4455           0 :     Double_t dvertex2 = dx13*dx13+dy13*dy13;
    4456           0 :     Double_t dvertex  = TMath::Sqrt(dvertex2);
    4457           0 :     Double_t angle13  = TMath::ATan(dy13/dx13);
    4458           0 :     Double_t cs13     = cos(-angle13), sn13 = sin(-angle13);            
    4459             :     
    4460             :     //
    4461             :     // loop over 2 sectors
    4462           0 :     Int_t dsec1=-ddsec;
    4463             :     Int_t dsec2= ddsec;
    4464           0 :     if (y1<0)  dsec2= 0;
    4465           0 :     if (y1>0)  dsec1= 0;
    4466             :     
    4467             :     Double_t dddz1=0;  // direction of delta inclination in z axis
    4468             :     Double_t dddz2=0;
    4469           0 :     if ( dz13>0 ) dddz1 =1;    
    4470             :     else          dddz2 =1;
    4471             :     //
    4472           0 :     for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
    4473           0 :       Int_t sec2 = sec + dsec;
    4474             :       // 
    4475             :       //      AliTPCtrackerRow&  kr2  = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
    4476             :       //AliTPCtrackerRow&  kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
    4477           0 :       AliTPCtrackerRow&  kr2  = GetRow((sec2+fkNOS)%fkNOS,i2);
    4478           0 :       AliTPCtrackerRow&  kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
    4479           0 :       Int_t  index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
    4480           0 :       Int_t  index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
    4481             : 
    4482             :       // rotation angles to p1-p3
    4483           0 :       Double_t cs13r     = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;            
    4484             :       //
    4485             :       //      Double_t dymax = maxangle*TMath::Abs(x1-xx2);
    4486             :       //
    4487           0 :       for (Int_t js=index1; js < index2; js++) {
    4488           0 :         const AliTPCclusterMI *kcl = kr2[js];
    4489           0 :         if (kcl->IsUsed(10)) continue;       
    4490           0 :         if (kcl->IsDisabled()) {
    4491           0 :           continue;
    4492             :         }
    4493             :         //
    4494           0 :         double x2=kcl->GetX(), y2=kcl->GetY(), z2=kcl->GetZ();
    4495           0 :         double dy23 = y2-y3, dx23 = x2-x3;
    4496             :         //calcutate parameters
    4497           0 :         Double_t dxx0 =  dx23*cs13r;
    4498           0 :         Double_t dyy0 =  dx23*sn13r;
    4499             :         //      
    4500           0 :         Double_t yy0 =  dyy0 +dy23*cs13r;
    4501             :         // stright track
    4502           0 :         if (TMath::Abs(yy0)<0.000001) continue;
    4503           0 :         Double_t xx0 =  dxx0 -dy23*sn13r;
    4504           0 :         Double_t y0  =  0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
    4505           0 :         Double_t r02 = (0.25+y0*y0)*dvertex2;   
    4506             :         //curvature (radius) cut
    4507           0 :         if (r02<r2min) continue;             
    4508             :        
    4509           0 :         nin0++; 
    4510             :         //
    4511           0 :         Double_t c0  = 1/TMath::Sqrt(r02);
    4512           0 :         if (yy0>0) c0*=-1.;  
    4513             :        
    4514           0 :         Double_t dfi0   = 2.*TMath::ASin(dvertex*c0*0.5);
    4515           0 :         Double_t dfi1   = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
    4516             :         //      Double_t dfi0   = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
    4517             :         //      Double_t dfi1   = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);  
    4518             :         //
    4519           0 :         Double_t zzzz2    = z1-dz13*dfi1/dfi0;
    4520           0 :         if (TMath::Abs(zzzz2-z2)>0.5) continue;       
    4521           0 :         nin1++;              
    4522             :         //      
    4523           0 :         Double_t dip    = (z1-z2)*c0/dfi1;        
    4524           0 :         Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
    4525             :         //
    4526           0 :         if (dsec!=0) {
    4527             :           // rotation
    4528             :           double xt2 = x2;
    4529           0 :           x2= xt2*cs-y2*sn*dsec;
    4530           0 :           y2=+xt2*sn*dsec+y2*cs;
    4531           0 :         }
    4532             :         
    4533           0 :         x[0] = y1;
    4534           0 :         x[1] = z1;
    4535           0 :         x[2] = x0;
    4536           0 :         x[3] = dip;
    4537           0 :         x[4] = c0;
    4538             :         //
    4539             :         //
    4540             :         // do we have cluster at the middle ?
    4541           0 :         Double_t xm = GetXrow(imiddle), ym, zm; // radius of middle pad-row
    4542           0 :         GetProlongation(x1,xm,x,ym,zm);
    4543             :         // account for distortion
    4544           0 :         double dxDist = GetDistortionX(xm,ym,zm,sec,imiddle);
    4545           0 :         if (TMath::Abs(dxDist)>0.05) GetProlongation(x1,xm+dxDist,x,ym,zm); //RS:? can we use straight line here?
    4546           0 :         UInt_t dummy; 
    4547             :         AliTPCclusterMI * cm=0;
    4548           0 :         double ymEdgeDist = ym;
    4549           0 :         if (fAccountDistortions) ymEdgeDist -= GetYSectEdgeDist(sec,imiddle,ym,zm); // ym shifted by edge distortion
    4550           0 :         if ( (ym>0&&ymEdgeDist<ymaxm) || (ym<=0&&ymEdgeDist>-ymaxm) ) { //RS  //    if (TMath::Abs(ym)-ymaxm<0){
    4551           0 :           cm = krm.FindNearest2(ym,zm,kRoadY+fClExtraRoadY,kRoadZ+fClExtraRoadZ,dummy);
    4552           0 :           if ((!cm) || (cm->IsUsed(10))) continue;
    4553             :         }
    4554             :         else{     
    4555             :           // rotate y1 to system 0
    4556             :           // get state vector in rotated system 
    4557           0 :           Double_t yr1  = (-0.5*sn13+y0*cs13)*dvertex*c0;
    4558           0 :           Double_t xr2  =  x0*cs+yr1*sn*dsec;
    4559           0 :           Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
    4560             :           //
    4561           0 :           GetProlongation(kcl->GetX(),xm,xr,ym,zm);
    4562           0 :           double dxDist = GetDistortionX(xm,ym,zm,sec2,imiddle);
    4563           0 :           if (TMath::Abs(dxDist)>0.05) GetProlongation(x1,xm+dxDist,x,ym,zm); //RS:? can we use straight line here?
    4564             :           //
    4565           0 :           ymEdgeDist = ym;
    4566           0 :           if (fAccountDistortions) ymEdgeDist -= GetYSectEdgeDist(sec2,imiddle,ym,zm); // ym shifted by edge distortion
    4567           0 :           if ( (ym>0&&ymEdgeDist<ymaxm) || (ym<=0&&ymEdgeDist>-ymaxm) ) { //RS //if (TMath::Abs(ym)-ymaxm<0){
    4568           0 :             cm = kr2m.FindNearest2(ym,zm,kRoadY+fClExtraRoadY,kRoadZ+fClExtraRoadZ,dummy);
    4569           0 :             if ((!cm) || (cm->IsUsed(10))) continue;
    4570             :           }
    4571           0 :         }
    4572             :        
    4573             :         // Double_t dym = 0;
    4574             :         // Double_t dzm = 0;
    4575             :         // if (cm){
    4576             :         //   dym = ym - cm->GetY();
    4577             :         //   dzm = zm - cm->GetZ();
    4578             :         // }
    4579           0 :         nin2++;
    4580             : 
    4581             : 
    4582             :         //
    4583             :         //
    4584           0 :         Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
    4585           0 :         Double_t sy2=kcl->GetSigmaY2()*2.,     sz2=kcl->GetSigmaZ2()*2.;
    4586             :         //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
    4587           0 :         Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
    4588             :         //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
    4589             : 
    4590           0 :         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
    4591           0 :         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
    4592           0 :         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
    4593           0 :         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
    4594           0 :         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
    4595           0 :         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
    4596             :         
    4597           0 :         Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
    4598           0 :         Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
    4599           0 :         Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
    4600           0 :         Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
    4601             :         
    4602           0 :         c[0]=sy1;
    4603           0 :         c[1]=0.;       c[2]=sz1;
    4604           0 :         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
    4605           0 :         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
    4606           0 :                        c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
    4607           0 :         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
    4608           0 :         c[13]=f30*sy1*f40+f32*sy2*f42;
    4609           0 :         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
    4610             :         
    4611             :         //      if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
    4612             :         
    4613           0 :         UInt_t index=kr1.GetIndex(is);
    4614           0 :         if (seed) {MarkSeedFree(seed); seed = 0;}
    4615           0 :         AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
    4616           0 :         seed->SetPoolID(fLastSeedID);
    4617           0 :         seed->SetRow(i1); //RS: memorise current row
    4618           0 :         track->SetIsSeeding(kTRUE);
    4619           0 :         track->SetSeed1(i1);
    4620           0 :         track->SetSeed2(i2);
    4621           0 :         track->SetSeedType(3);
    4622             : 
    4623             :        
    4624             :         //if (dsec==0) {
    4625           0 :           FollowProlongation(*track, (i1+i2)/2,1);
    4626           0 :           Int_t foundable,found,shared;
    4627           0 :           GetSeedClusterStatistic(track,(i1+i2)/2,i1, found, foundable, shared, kTRUE); //RS: seeds don't keep their clusters
    4628             :           //RS track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
    4629           0 :           if ((found<0.55*foundable)  || shared>0.5*found) {
    4630             :             //RS: with distortions related cluster errors the track error may grow, don't use this cut
    4631             :             //|| (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
    4632           0 :             MarkSeedFree(seed); seed = 0;
    4633           0 :             continue;
    4634             :           }
    4635             :           //}
    4636             :         
    4637           0 :         nin++;
    4638           0 :         FollowProlongation(*track, i2,1);
    4639             :         
    4640             :         
    4641             :         //Int_t rc = 1;
    4642           0 :         track->SetBConstrain(1);
    4643             :         //      track->fLastPoint = i1+fInnerSec->GetNRows();  // first cluster in track position
    4644           0 :         track->SetLastPoint(i1);  // first cluster in track position
    4645           0 :         track->SetFirstPoint(track->GetLastPoint());
    4646             :         
    4647           0 :         if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
    4648           0 :             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
    4649           0 :             track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
    4650           0 :           MarkSeedFree(seed); seed = 0;
    4651           0 :           continue;
    4652             :         }
    4653           0 :         nout1++;
    4654           0 :         Double_t zv, bz=GetBz();
    4655           0 :         if ( !track->GetZAt(0.,bz,zv) )       { MarkSeedFree( seed ); seed = 0; continue; }
    4656             :         //
    4657           0 :         if (fDisableSecondaries) {
    4658           0 :           if (TMath::Abs(zv)>fPrimaryDCAZCut) { MarkSeedFree( seed ); seed = 0; continue; }
    4659           0 :           double yv; 
    4660           0 :           if ( !track->GetZAt(0.,bz,yv) )     { MarkSeedFree( seed ); seed = 0; continue; }
    4661           0 :           if (TMath::Abs(zv)>fPrimaryDCAZCut) { MarkSeedFree( seed ); seed = 0; continue; }
    4662           0 :         }
    4663             :         
    4664             :         //
    4665             :         // Z VERTEX CONDITION
    4666           0 :         if (TMath::Abs(zv-z3)>cuts[2]) {
    4667           0 :           FollowProlongation(*track, TMath::Max(i2-20,0));
    4668           0 :           if ( !track->GetZAt(0.,bz,zv) ) continue;
    4669           0 :           if (TMath::Abs(zv-z3)>cuts[2]){
    4670           0 :             FollowProlongation(*track, TMath::Max(i2-40,0));
    4671           0 :             if ( !track->GetZAt(0.,bz,zv) ) continue;
    4672           0 :             if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
    4673             :               // make seed without constrain
    4674           0 :               AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
    4675           0 :               FollowProlongation(*track2, i2,1);
    4676           0 :               track2->SetBConstrain(kFALSE);
    4677           0 :               track2->SetSeedType(1);
    4678           0 :               arr->AddLast(track2); 
    4679           0 :               MarkSeedFree( seed ); seed = 0;
    4680             :               continue;         
    4681             :             }
    4682             :             else{
    4683           0 :               MarkSeedFree( seed ); seed = 0;
    4684           0 :               continue;
    4685             :             
    4686             :             }
    4687             :           }
    4688             :         }
    4689             :       
    4690           0 :         track->SetSeedType(0);
    4691           0 :         arr->AddLast(track); // note, track is seed, don't free the seed
    4692           0 :         seed = new( NextFreeSeed() ) AliTPCseed;        
    4693           0 :         seed->SetPoolID(fLastSeedID);
    4694           0 :         nout2++;
    4695             :         // don't consider other combinations
    4696           0 :         if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
    4697           0 :           break;
    4698           0 :       }
    4699             :     }
    4700           0 :   }
    4701           0 :   if (fDebug>3){
    4702           0 :     Info("MakeSeeds3Dist","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
    4703           0 :   }
    4704           0 :   if (seed) MarkSeedFree( seed );
    4705           0 : }
    4706             : 
    4707             : 
    4708             : void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
    4709             :                                  Float_t deltay) {
    4710             :   
    4711             : 
    4712             : 
    4713             :   //-----------------------------------------------------------------
    4714             :   // This function creates track seeds.
    4715             :   //-----------------------------------------------------------------
    4716             :   // cuts[0]   - fP4 cut
    4717             :   // cuts[1]   - tan(phi)  cut
    4718             :   // cuts[2]   - zvertex cut
    4719             :   // cuts[3]   - fP3 cut
    4720             : 
    4721             : 
    4722             :   Int_t nin0  = 0;
    4723             :   Int_t nin1  = 0;
    4724             :   Int_t nin2  = 0;
    4725             :   Int_t nin   = 0;
    4726             :   Int_t nout1 = 0;
    4727             :   Int_t nout2 = 0;
    4728             :   Int_t nout3 =0;
    4729       12672 :   Double_t x[5], c[15];
    4730             :   //
    4731             :   // make temporary seed
    4732        6336 :   AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
    4733        6336 :   seed->SetPoolID(fLastSeedID);
    4734        6336 :   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
    4735             :   //  Double_t cs=cos(alpha), sn=sin(alpha);
    4736             :   //
    4737             :   //
    4738             : 
    4739             :   // first 3 padrows
    4740        6336 :   Double_t x1 = GetXrow(i1-1);
    4741        6336 :   const    AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
    4742        6336 :   Double_t y1max  = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;  
    4743             :   //
    4744        6336 :   Double_t x1p = GetXrow(i1);
    4745        6336 :   const    AliTPCtrackerRow& kr1p=GetRow(sec,i1);
    4746             :   //
    4747        6336 :   Double_t x1m = GetXrow(i1-2);
    4748        6336 :   const    AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
    4749             : 
    4750             :   //
    4751             :   //last 3 padrow for seeding
    4752        6336 :   AliTPCtrackerRow&  kr3  = GetRow((sec+fkNOS)%fkNOS,i1-7);
    4753        6336 :   Double_t    x3   =  GetXrow(i1-7);
    4754             :   //  Double_t    y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;  
    4755             :   //
    4756        6336 :   AliTPCtrackerRow&  kr3p  = GetRow((sec+fkNOS)%fkNOS,i1-6);
    4757        6336 :   Double_t    x3p   = GetXrow(i1-6);
    4758             :   //
    4759        6336 :   AliTPCtrackerRow&  kr3m  = GetRow((sec+fkNOS)%fkNOS,i1-8);
    4760        6336 :   Double_t    x3m   = GetXrow(i1-8);
    4761             : 
    4762             :   //
    4763             :   //
    4764             :   // middle padrow
    4765        6336 :   Int_t im = i1-4;                           //middle pad row index
    4766        6336 :   Double_t xm         = GetXrow(im);         // radius of middle pad-row
    4767        6336 :   const AliTPCtrackerRow& krm=GetRow(sec,im);   //middle pad -row
    4768             :   //  Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;  
    4769             :   //
    4770             :   //
    4771        6336 :   Double_t deltax  = x1-x3;
    4772        6336 :   Double_t dymax   = deltax*cuts[1];
    4773        6336 :   Double_t dzmax   = deltax*cuts[3];
    4774             :   //
    4775             :   // loop over clusters  
    4776       32240 :   for (Int_t is=0; is < kr1; is++) {
    4777             :     //
    4778        9784 :     if (kr1[is]->IsUsed(10)) continue;       
    4779        5284 :     if (kr1[is]->IsDisabled()) {
    4780             :       continue;
    4781             :     }
    4782             : 
    4783        5284 :     Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();    
    4784             :     //
    4785        7728 :     if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue;  // seed only at the edge    
    4786             :     // 
    4787        4354 :     Int_t  index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
    4788        4354 :     Int_t  index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
    4789             :     //    
    4790             :     Double_t y3,   z3;
    4791             :     //
    4792             :     //
    4793        4354 :     UInt_t index;
    4794       27000 :     for (Int_t js=index1; js < index2; js++) {
    4795        9146 :       const AliTPCclusterMI *kcl = kr3[js];
    4796        9146 :       if (kcl->IsDisabled()) {
    4797           0 :         continue;
    4798             :       }
    4799             : 
    4800       11272 :       if (kcl->IsUsed(10)) continue;
    4801        7020 :       y3 = kcl->GetY(); 
    4802             :       // apply angular cuts
    4803        8114 :       if (TMath::Abs(y1-y3)>dymax) continue;
    4804             :       //x3 = x3; 
    4805        5926 :       z3 = kcl->GetZ();      
    4806        8278 :       if (TMath::Abs(z1-z3)>dzmax) continue;
    4807             :       //
    4808        3574 :       Double_t angley = (y1-y3)/(x1-x3);
    4809        3574 :       Double_t anglez = (z1-z3)/(x1-x3);
    4810             :       //
    4811        3574 :       Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
    4812        3574 :       Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
    4813             :       //
    4814        3574 :       Double_t yyym = angley*(xm-x1)+y1;
    4815        3574 :       Double_t zzzm = anglez*(xm-x1)+z1;
    4816             : 
    4817        3574 :       const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    4818        6566 :       if (!kcm) continue;
    4819         590 :       if (kcm->IsUsed(10)) continue;
    4820         574 :       if (kcm->IsDisabled()) {
    4821           0 :         continue;
    4822             :       }
    4823             : 
    4824         574 :       erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
    4825         574 :       errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
    4826             :       //
    4827             :       //
    4828             :       //
    4829             :       Int_t used  =0;
    4830             :       Int_t found =0;
    4831             :       //
    4832             :       // look around first
    4833        1148 :       const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
    4834         574 :                                                       anglez*(x1m-x1)+z1,
    4835         574 :                                                       erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    4836             :       //
    4837         574 :       if (kc1m){
    4838             :         found++;
    4839         460 :         if (kc1m->IsUsed(10)) used++;
    4840             :       }
    4841        1148 :       const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
    4842         574 :                                                       anglez*(x1p-x1)+z1,
    4843         574 :                                                       erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    4844             :       //
    4845         574 :       if (kc1p){
    4846         354 :         found++;
    4847         354 :         if (kc1p->IsUsed(10)) used++;
    4848             :       }
    4849         574 :       if (used>1)  continue;
    4850         672 :       if (found<1) continue; 
    4851             : 
    4852             :       //
    4853             :       // look around last
    4854         952 :       const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
    4855         476 :                                                       anglez*(x3m-x3)+z3,
    4856         476 :                                                       erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    4857             :       //
    4858         476 :       if (kc3m){
    4859         348 :         found++;
    4860         348 :         if (kc3m->IsUsed(10)) used++;
    4861             :       }
    4862             :       else 
    4863         128 :         continue;
    4864         696 :       const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
    4865         348 :                                                       anglez*(x3p-x3)+z3,
    4866         348 :                                                       erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    4867             :       //
    4868         348 :       if (kc3p){
    4869         334 :         found++;
    4870         334 :         if (kc3p->IsUsed(10)) used++;
    4871             :       }
    4872             :       else 
    4873          14 :         continue;
    4874         334 :       if (used>1)  continue;
    4875         334 :       if (found<3) continue;       
    4876             :       //
    4877             :       Double_t x2,y2,z2;
    4878             :       x2 = xm;
    4879         334 :       y2 = kcm->GetY();
    4880         334 :       z2 = kcm->GetZ();
    4881             :       //
    4882             :                         
    4883         334 :       x[0]=y1;
    4884         334 :       x[1]=z1;
    4885         334 :       x[4]=F1(x1,y1,x2,y2,x3,y3);
    4886             :       //if (TMath::Abs(x[4]) >= cuts[0]) continue;
    4887         334 :       nin0++;
    4888             :       //
    4889         334 :       x[2]=F2(x1,y1,x2,y2,x3,y3);
    4890         334 :       nin1++;
    4891             :       //
    4892         334 :       x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
    4893             :       //if (TMath::Abs(x[3]) > cuts[3]) continue;
    4894         334 :       nin2++;
    4895             :       //
    4896             :       //
    4897             :       Double_t sy1=0.1,  sz1=0.1;
    4898             :       Double_t sy2=0.1,  sz2=0.1;
    4899             :       Double_t sy3=0.1,  sy=0.1, sz=0.1;
    4900             :       
    4901         334 :       Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
    4902         334 :       Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
    4903         334 :       Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
    4904         334 :       Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
    4905         334 :       Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
    4906         334 :       Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
    4907             :       
    4908         334 :       Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
    4909         334 :       Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
    4910         334 :       Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
    4911         334 :       Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
    4912             :       
    4913         334 :       c[0]=sy1;
    4914         334 :       c[1]=0.;       c[2]=sz1; 
    4915         334 :       c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
    4916         334 :       c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
    4917         334 :       c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
    4918         334 :       c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
    4919         334 :       c[13]=f30*sy1*f40+f32*sy2*f42;
    4920         334 :       c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
    4921             :       
    4922             :       //        if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
    4923             :       
    4924         334 :       index=kr1.GetIndex(is);
    4925         504 :       if (seed) {MarkSeedFree( seed ); seed = 0;}
    4926         334 :       AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
    4927         334 :       seed->SetPoolID(fLastSeedID);
    4928         334 :       seed->SetRow(i1-1); //RS: memorise current row      
    4929         334 :       track->SetIsSeeding(kTRUE);
    4930             : 
    4931         334 :       nin++;      
    4932         334 :       FollowProlongation(*track, i1-7,1);
    4933         640 :       if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 || 
    4934         612 :           track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6+fExtraClErrYZ2){
    4935          28 :         MarkSeedFree( seed ); seed = 0;
    4936          28 :         continue;
    4937             :       }
    4938         306 :       nout1++;
    4939         306 :       nout2++;  
    4940             :       //Int_t rc = 1;
    4941         306 :       FollowProlongation(*track, i2,1);
    4942         306 :       track->SetBConstrain(0);
    4943         306 :       track->SetLastPoint(i1+fInnerSec->GetNRows());  // first cluster in track position
    4944         306 :       track->SetFirstPoint(track->GetLastPoint());
    4945             :       
    4946         418 :       if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
    4947         116 :           track->GetNumberOfClusters()<track->GetNFoundable()*0.7 || 
    4948         336 :           track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5+fExtraClErrYZ2) {
    4949         222 :         MarkSeedFree( seed ); seed = 0;
    4950         222 :         continue;
    4951             :       }
    4952             :    
    4953             :       {
    4954          84 :         FollowProlongation(*track, TMath::Max(i2-10,0),1);
    4955          84 :         AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
    4956          84 :         FollowProlongation(*track2, i2,1);
    4957          84 :         track2->SetBConstrain(kFALSE);
    4958          84 :         track2->SetSeedType(4);
    4959          84 :         arr->AddLast(track2);
    4960          84 :         MarkSeedFree( seed ); seed = 0;
    4961             :       }
    4962             :       
    4963             :    
    4964             :       //arr->AddLast(track); 
    4965             :       //seed = new AliTPCseed;  
    4966          84 :       nout3++;
    4967          84 :     }
    4968        4354 :   }
    4969             :   
    4970        6336 :   if (fDebug>3){
    4971           0 :     Info("MakeSeeds5","\nSeeding statiistic:\t%d\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2,nout3);
    4972           0 :   }
    4973       12502 :   if (seed) MarkSeedFree(seed);
    4974        6336 : }
    4975             : 
    4976             : void AliTPCtracker::MakeSeeds5Dist(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2,  Float_t cuts[4],
    4977             :                                  Float_t deltay) {
    4978             :   
    4979             : 
    4980             : 
    4981             :   //-----------------------------------------------------------------
    4982             :   // This function creates track seeds, accounting for distortions
    4983             :   //-----------------------------------------------------------------
    4984             :   // cuts[0]   - fP4 cut
    4985             :   // cuts[1]   - tan(phi)  cut
    4986             :   // cuts[2]   - zvertex cut
    4987             :   // cuts[3]   - fP3 cut
    4988             : 
    4989             : 
    4990             :   Int_t nin0  = 0;
    4991             :   Int_t nin1  = 0;
    4992             :   Int_t nin2  = 0;
    4993             :   Int_t nin   = 0;
    4994             :   Int_t nout1 = 0;
    4995             :   Int_t nout2 = 0;
    4996             :   Int_t nout3 =0;
    4997           0 :   Double_t x[5], c[15];
    4998             :   //
    4999             :   // make temporary seed
    5000           0 :   AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
    5001           0 :   seed->SetPoolID(fLastSeedID);
    5002           0 :   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
    5003             :   //  Double_t cs=cos(alpha), sn=sin(alpha);
    5004             :   //
    5005             :   //
    5006             : 
    5007             :   // first 3 padrows
    5008           0 :   Double_t x1Def = GetXrow(i1-1);
    5009           0 :   const    AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
    5010           0 :   Double_t y1max  = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;  
    5011             :   //
    5012           0 :   Double_t x1pDef = GetXrow(i1);
    5013           0 :   const    AliTPCtrackerRow& kr1p=GetRow(sec,i1);
    5014             :   //
    5015           0 :   Double_t x1mDef = GetXrow(i1-2);
    5016           0 :   const    AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
    5017             : 
    5018           0 :   double dx11mDef = x1Def-x1mDef;
    5019           0 :   double dx11pDef = x1Def-x1pDef;
    5020             :   //
    5021             :   //last 3 padrow for seeding
    5022           0 :   AliTPCtrackerRow&  kr3  = GetRow((sec+fkNOS)%fkNOS,i1-7);
    5023           0 :   Double_t    x3Def   =  GetXrow(i1-7);
    5024             :   //
    5025           0 :   AliTPCtrackerRow&  kr3p  = GetRow((sec+fkNOS)%fkNOS,i1-6);
    5026           0 :   Double_t    x3pDef   = GetXrow(i1-6);
    5027             :   //
    5028           0 :   AliTPCtrackerRow&  kr3m  = GetRow((sec+fkNOS)%fkNOS,i1-8);
    5029           0 :   Double_t    x3mDef   = GetXrow(i1-8);
    5030             : 
    5031             :   //
    5032           0 :   double dx33mDef = x3Def-x3mDef;
    5033           0 :   double dx33pDef = x3Def-x3pDef;
    5034             : 
    5035             :   //
    5036             :   // middle padrow
    5037           0 :   Int_t im = i1-4;                           //middle pad row index
    5038           0 :   Double_t xmDef         = GetXrow(im);         // radius of middle pad-row
    5039           0 :   const AliTPCtrackerRow& krm=GetRow(sec,im);   //middle pad -row
    5040             :   //
    5041             :   //
    5042           0 :   Double_t deltax  = x1Def-x3Def;
    5043           0 :   Double_t dymax   = deltax*cuts[1];
    5044           0 :   Double_t dzmax   = deltax*cuts[3];
    5045             :   //
    5046             :   // loop over clusters  
    5047           0 :   for (Int_t is=0; is < kr1; is++) {
    5048             :     //
    5049           0 :     if (kr1[is]->IsUsed(10)) continue;       
    5050           0 :     if (kr1[is]->IsDisabled()) {
    5051             :       continue;
    5052             :     }
    5053           0 :     const AliTPCclusterMI* clkr1 = kr1[is];
    5054           0 :     Double_t x1=clkr1->GetX(), y1=clkr1->GetY(), z1=clkr1->GetZ();    
    5055             :     //
    5056             :     double y1EdgeDist =  y1;
    5057           0 :     if  (fAccountDistortions) y1EdgeDist -= GetYSectEdgeDist(sec,i1-1,y1,z1);
    5058           0 :     if (deltay>0) {
    5059           0 :       double margin = (y1>0 ? y1max-y1EdgeDist : y1max + y1EdgeDist);
    5060           0 :       if (margin<deltay ) continue;  // seed only at the edge
    5061           0 :     }
    5062             : 
    5063             :     // 
    5064           0 :     Int_t  index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
    5065           0 :     Int_t  index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
    5066             :     //    
    5067             :     Double_t x3,y3,z3;
    5068             :     //
    5069             :     //
    5070           0 :     UInt_t index;
    5071           0 :     for (Int_t js=index1; js < index2; js++) {
    5072           0 :       const AliTPCclusterMI *kcl = kr3[js];
    5073           0 :       if (kcl->IsDisabled()) {
    5074           0 :         continue;
    5075             :       }
    5076             : 
    5077           0 :       if (kcl->IsUsed(10)) continue;
    5078           0 :       y3 = kcl->GetY(); 
    5079             :       // apply angular cuts
    5080           0 :       if (TMath::Abs(y1-y3)>dymax) continue;
    5081             :       //x3 = x3; 
    5082           0 :       z3 = kcl->GetZ();      
    5083           0 :       if (TMath::Abs(z1-z3)>dzmax) continue;
    5084             :       
    5085           0 :       x3 = kcl->GetX();
    5086             :       //
    5087           0 :       double dx13 = x1-x3;
    5088           0 :       if (TMath::Abs(dx13)<0.1) {
    5089             :         //AliErrorF("Wrong X correction? Sec%d : row%d@X=%.2f->%.2f (z=%.2f) row%d@X=%.2f->%.2f (z=%.2f)\n",sec,
    5090             :         //        i1-1,x1Def,x1,z1, i1-7,x3Def,x3,z3);
    5091           0 :         continue; // distortions should not make distance so small
    5092             :       }
    5093             : 
    5094           0 :       Double_t angley = (y1-y3)/dx13;
    5095           0 :       Double_t anglez = (z1-z3)/dx13;
    5096             :       //
    5097           0 :       Double_t erry = TMath::Abs(angley)*dx11mDef*0.5+0.5; // RS: use ideal X differences assuming
    5098           0 :       Double_t errz = TMath::Abs(anglez)*dx11mDef*0.5+0.5; // that the distortions are ~same on close rows
    5099             :       //
    5100           0 :       Double_t yyym = angley*(xmDef-x1Def)+y1; // RS: idem, assume distortions cancels in the difference
    5101           0 :       Double_t zzzm = anglez*(xmDef-x1Def)+z1;
    5102             : 
    5103           0 :       const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    5104           0 :       if (!kcm) continue;
    5105           0 :       if (kcm->IsUsed(10)) continue;
    5106           0 :       if (kcm->IsDisabled()) {
    5107           0 :         continue;
    5108             :       }
    5109             : 
    5110           0 :       erry = TMath::Abs(angley)*dx11mDef*0.4+0.5;
    5111           0 :       errz = TMath::Abs(anglez)*dx11mDef*0.4+0.5;
    5112             :       //
    5113             :       //
    5114             :       //
    5115             :       Int_t used  =0;
    5116             :       Int_t found =0;
    5117             :       //
    5118             :       // look around first
    5119           0 :       const AliTPCclusterMI *kc1m = kr1m.FindNearest2(-angley*dx11mDef+y1, // RS: idem, assume distortions cancels in the difference
    5120           0 :                                                       -anglez*dx11mDef+z1,
    5121           0 :                                                       erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    5122             :       //
    5123           0 :       if (kc1m){
    5124             :         found++;
    5125           0 :         if (kc1m->IsUsed(10)) used++;
    5126             :       }
    5127           0 :       const AliTPCclusterMI *kc1p = kr1p.FindNearest2(-angley*dx11pDef+y1, // RS: idem, assume distortions cancels in the difference
    5128           0 :                                                       -anglez*dx11pDef+z1,
    5129           0 :                                                       erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    5130             :       //
    5131           0 :       if (kc1p){
    5132           0 :         found++;
    5133           0 :         if (kc1p->IsUsed(10)) used++;
    5134             :       }
    5135           0 :       if (used>1)  continue;
    5136           0 :       if (found<1) continue; 
    5137             : 
    5138             :       //
    5139             :       // look around last
    5140           0 :       const AliTPCclusterMI *kc3m = kr3m.FindNearest2(-angley*dx33mDef+y3, // RS: idem, assume distortions cancels in the difference
    5141           0 :                                                       -anglez*dx33mDef+z3,
    5142           0 :                                                       erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    5143             :       //
    5144           0 :       if (kc3m){
    5145           0 :         found++;
    5146           0 :         if (kc3m->IsUsed(10)) used++;
    5147             :       }
    5148             :       else 
    5149           0 :         continue;
    5150           0 :       const AliTPCclusterMI *kc3p = kr3p.FindNearest2(-angley*dx33pDef+y3, // RS: idem, assume distortions cancels in the difference
    5151           0 :                                                       -anglez*dx33pDef+z3,
    5152           0 :                                                       erry+fClExtraRoadY,errz+fClExtraRoadZ,index);
    5153             :       //
    5154           0 :       if (kc3p){
    5155           0 :         found++;
    5156           0 :         if (kc3p->IsUsed(10)) used++;
    5157             :       }
    5158             :       else 
    5159           0 :         continue;
    5160           0 :       if (used>1)  continue;
    5161           0 :       if (found<3) continue;       
    5162             :       //
    5163             :       Double_t x2,y2,z2;
    5164           0 :       x2 = kcm->GetX();
    5165           0 :       y2 = kcm->GetY();
    5166           0 :       z2 = kcm->GetZ();
    5167             :       //
    5168             :                         
    5169           0 :       x[0]=y1;
    5170           0 :       x[1]=z1;
    5171           0 :       x[4]=F1(x1,y1,x2,y2,x3,y3);
    5172             :       //if (TMath::Abs(x[4]) >= cuts[0]) continue;
    5173           0 :       nin0++;
    5174             :       //
    5175           0 :       x[2]=F2(x1,y1,x2,y2,x3,y3);
    5176           0 :       nin1++;
    5177             :       //
    5178           0 :       x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
    5179             :       //if (TMath::Abs(x[3]) > cuts[3]) continue;
    5180           0 :       nin2++;
    5181             :       //
    5182             :       //
    5183             :       Double_t sy1=0.1,  sz1=0.1;
    5184             :       Double_t sy2=0.1,  sz2=0.1;
    5185             :       Double_t sy3=0.1,  sy=0.1, sz=0.1;
    5186             :       
    5187           0 :       Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
    5188           0 :       Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
    5189           0 :       Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
    5190           0 :       Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
    5191           0 :       Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
    5192           0 :       Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
    5193             :       
    5194           0 :       Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
    5195           0 :       Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
    5196           0 :       Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
    5197           0 :       Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
    5198             :       
    5199           0 :       c[0]=sy1;
    5200           0 :       c[1]=0.;       c[2]=sz1; 
    5201           0 :       c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
    5202           0 :       c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
    5203           0 :       c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
    5204           0 :       c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
    5205           0 :       c[13]=f30*sy1*f40+f32*sy2*f42;
    5206           0 :       c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
    5207             :       
    5208             :       //        if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
    5209             :       
    5210           0 :       index=kr1.GetIndex(is);
    5211           0 :       if (seed) {MarkSeedFree( seed ); seed = 0;}
    5212           0 :       AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
    5213           0 :       seed->SetPoolID(fLastSeedID);
    5214           0 :       seed->SetRow(i1-1); // RS: memorise current row      
    5215           0 :       track->SetIsSeeding(kTRUE);
    5216             : 
    5217           0 :       nin++;      
    5218           0 :       FollowProlongation(*track, i1-7,1);
    5219           0 :       if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 || 
    5220           0 :           track->GetNShared()>0.6*track->GetNumberOfClusters()) {
    5221             :         //RS: with distortions related cluster errors the track error may grow, don't use this cut
    5222             :         //|| ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
    5223           0 :         MarkSeedFree( seed ); seed = 0;
    5224           0 :         continue;
    5225             :       }
    5226           0 :       nout1++;
    5227           0 :       nout2++;  
    5228             :       //Int_t rc = 1;
    5229           0 :       FollowProlongation(*track, i2,1);
    5230           0 :       track->SetBConstrain(0);
    5231           0 :       track->SetLastPoint(i1+fInnerSec->GetNRows());  // first cluster in track position
    5232           0 :       track->SetFirstPoint(track->GetLastPoint());
    5233             :       
    5234           0 :       if (track->GetNumberOfClusters()<(i1-i2)*0.5 || 
    5235           0 :           track->GetNumberOfClusters()<track->GetNFoundable()*0.7 || 
    5236           0 :           track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6) {
    5237             :         //RS: with distortions related cluster errors the track error may grow, don't use this cut
    5238             :         //|| ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
    5239           0 :         MarkSeedFree( seed ); seed = 0;
    5240           0 :         continue;
    5241             :       }
    5242             :    
    5243             :       {
    5244           0 :         FollowProlongation(*track, TMath::Max(i2-10,0),1);
    5245           0 :         AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
    5246           0 :         FollowProlongation(*track2, i2,1);
    5247           0 :         track2->SetBConstrain(kFALSE);
    5248           0 :         track2->SetSeedType(4);
    5249           0 :         arr->AddLast(track2);
    5250           0 :         MarkSeedFree( seed ); seed = 0;
    5251             :       }
    5252             :       
    5253             :    
    5254             :       //arr->AddLast(track); 
    5255             :       //seed = new AliTPCseed;  
    5256           0 :       nout3++;
    5257           0 :     }
    5258           0 :   }
    5259             :   
    5260           0 :   if (fDebug>3){
    5261           0 :     Info("MakeSeeds5Dist","\nSeeding statiistic:\t%d\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2,nout3);
    5262           0 :   }
    5263           0 :   if (seed) MarkSeedFree(seed);
    5264           0 : }
    5265             : 
    5266             : 
    5267             : //_____________________________________________________________________________
    5268             : void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
    5269             :                                  Float_t deltay, Bool_t /*bconstrain*/) {
    5270             :   //-----------------------------------------------------------------
    5271             :   // This function creates track seeds - without vertex constraint
    5272             :   //-----------------------------------------------------------------
    5273             :   // cuts[0]   - fP4 cut        - not applied
    5274             :   // cuts[1]   - tan(phi)  cut
    5275             :   // cuts[2]   - zvertex cut    - not applied 
    5276             :   // cuts[3]   - fP3 cut
    5277             :   const double kRoadZ = 1.2, kRoadY = 1.2;
    5278             : 
    5279             :   Int_t nin0=0;
    5280             :   Int_t nin1=0;
    5281             :   Int_t nin2=0;
    5282             :   Int_t nin3=0;
    5283             :   //  Int_t nin4=0;
    5284             :   //Int_t nin5=0;
    5285             : 
    5286             :   
    5287             : 
    5288           0 :   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
    5289             :   //  Double_t cs=cos(alpha), sn=sin(alpha);
    5290           0 :   Int_t row0 = (i1+i2)/2;
    5291           0 :   Int_t drow = (i1-i2)/2;
    5292           0 :   const AliTPCtrackerRow& kr0=fSectors[sec][row0];
    5293             :   AliTPCtrackerRow * kr=0;
    5294             : 
    5295           0 :   AliTPCpolyTrack polytrack;
    5296           0 :   Int_t nclusters=fSectors[sec][row0];
    5297           0 :   AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
    5298           0 :   seed->SetPoolID(fLastSeedID);
    5299             : 
    5300             :   Int_t sumused=0;
    5301             :   Int_t cused=0;
    5302             :   Int_t cnused=0;
    5303           0 :   for (Int_t is=0; is < nclusters; is++) {  //LOOP over clusters
    5304             :     Int_t nfound =0;
    5305             :     Int_t nfoundable =0;
    5306           0 :     for (Int_t iter =1; iter<2; iter++){   //iterations
    5307           0 :       const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
    5308           0 :       const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];      
    5309           0 :       const AliTPCclusterMI * cl= kr0[is];
    5310           0 :       if (cl->IsDisabled()) {
    5311           0 :         continue;
    5312             :       }
    5313             : 
    5314           0 :       if (cl->IsUsed(10)) {
    5315           0 :         cused++;
    5316           0 :       }
    5317             :       else{
    5318           0 :         cnused++;
    5319             :       }
    5320           0 :       Double_t x = kr0.GetX();
    5321             :       // Initialization of the polytrack
    5322             :       nfound =0;
    5323             :       nfoundable =0;
    5324           0 :       polytrack.Reset();
    5325             :       //
    5326           0 :       Double_t y0= cl->GetY();
    5327           0 :       Double_t z0= cl->GetZ();
    5328             :       Float_t erry = 0;
    5329             :       Float_t errz = 0;
    5330             :       
    5331           0 :       Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
    5332           0 :       if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue;  // seed only at the edge
    5333             :       
    5334           0 :       erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;        
    5335           0 :       errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;      
    5336           0 :       polytrack.AddPoint(x,y0,z0,erry, errz);
    5337             : 
    5338             :       sumused=0;
    5339           0 :       if (cl->IsUsed(10)) sumused++;
    5340             : 
    5341             : 
    5342           0 :       Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
    5343           0 :       Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
    5344             :       //
    5345           0 :       x = krm.GetX();
    5346           0 :       AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady+fClExtraRoadY,roadz+fClExtraRoadZ);
    5347           0 :       if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
    5348           0 :         erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;            
    5349           0 :         errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
    5350           0 :         if (cl1->IsUsed(10))  sumused++;
    5351           0 :         polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
    5352             :       }
    5353             :       //
    5354           0 :       x = krp.GetX();
    5355           0 :       AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady+fClExtraRoadY,roadz+fClExtraRoadZ);
    5356           0 :       if (cl2) {
    5357           0 :         erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;            
    5358           0 :         errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
    5359           0 :         if (cl2->IsUsed(10)) sumused++;       
    5360           0 :         polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
    5361             :       }
    5362             :       //
    5363           0 :       if (sumused>0) continue;
    5364           0 :       nin0++;
    5365           0 :       polytrack.UpdateParameters();
    5366             :       // follow polytrack
    5367             :       //
    5368           0 :       Double_t yn,zn;
    5369           0 :       nfoundable = polytrack.GetN();
    5370             :       nfound     = nfoundable; 
    5371             :       //
    5372           0 :       for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
    5373           0 :         Float_t maxdist = 0.8*(1.+3./(ddrow));
    5374           0 :         for (Int_t delta = -1;delta<=1;delta+=2){
    5375           0 :           Int_t row = row0+ddrow*delta;
    5376           0 :           kr = &(fSectors[sec][row]);
    5377           0 :           Double_t xn = kr->GetX();
    5378           0 :           Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
    5379           0 :           polytrack.GetFitPoint(xn,yn,zn);
    5380           0 :           if (TMath::Abs(yn)>ymax1) continue;
    5381           0 :           nfoundable++;
    5382           0 :           AliTPCclusterMI * cln = kr->FindNearest(yn,zn,kRoadY+fClExtraRoadY,kRoadZ+fClExtraRoadZ);
    5383           0 :           if (cln) {
    5384           0 :             Float_t dist =  TMath::Sqrt(  (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
    5385           0 :             if (dist<maxdist){
    5386             :               /*
    5387             :               erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));           
    5388             :               errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
    5389             :               if (cln->IsUsed(10)) {
    5390             :                 //      printf("used\n");
    5391             :                 sumused++;
    5392             :                 erry*=2;
    5393             :                 errz*=2;
    5394             :               }
    5395             :               */
    5396             :               erry=0.1;
    5397             :               errz=0.1;
    5398           0 :               polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
    5399           0 :               nfound++;
    5400           0 :             }
    5401           0 :           }
    5402           0 :         }
    5403           0 :         if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable))  break;     
    5404           0 :         polytrack.UpdateParameters();
    5405           0 :       }           
    5406           0 :     }
    5407           0 :     if ( (sumused>3) || (sumused>0.5*nfound))  {
    5408             :       //printf("sumused   %d\n",sumused);
    5409           0 :       continue;
    5410             :     }
    5411           0 :     nin1++;
    5412           0 :     Double_t dy,dz;
    5413           0 :     polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
    5414           0 :     AliTPCpolyTrack track2;
    5415             :     
    5416           0 :     polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
    5417           0 :     if (track2.GetN()<0.5*nfoundable) continue;
    5418           0 :     nin2++;
    5419             : 
    5420           0 :     if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
    5421             :       //
    5422             :       // test seed with and without constrain
    5423           0 :       for (Int_t constrain=0; constrain<=0;constrain++){
    5424             :         // add polytrack candidate
    5425             : 
    5426           0 :         Double_t x[5], c[15];
    5427           0 :         Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
    5428           0 :         track2.GetBoundaries(x3,x1);    
    5429           0 :         x2 = (x1+x3)/2.;
    5430           0 :         track2.GetFitPoint(x1,y1,z1);
    5431           0 :         track2.GetFitPoint(x2,y2,z2);
    5432           0 :         track2.GetFitPoint(x3,y3,z3);
    5433             :         //
    5434             :         //is track pointing to the vertex ?
    5435           0 :         Double_t x0,y0,z0;
    5436             :         x0=0;
    5437           0 :         polytrack.GetFitPoint(x0,y0,z0);
    5438             : 
    5439           0 :         if (constrain) {
    5440           0 :           x2 = x3;
    5441           0 :           y2 = y3;
    5442           0 :           z2 = z3;
    5443             :           
    5444           0 :           x3 = 0;
    5445           0 :           y3 = 0;
    5446           0 :           z3 = 0;
    5447           0 :         }
    5448           0 :         x[0]=y1;
    5449           0 :         x[1]=z1;
    5450           0 :         x[4]=F1(x1,y1,x2,y2,x3,y3);
    5451             :                 
    5452             :         //      if (TMath::Abs(x[4]) >= cuts[0]) continue;  //
    5453           0 :         x[2]=F2(x1,y1,x2,y2,x3,y3);
    5454             :         
    5455             :         //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
    5456             :         //x[3]=F3(x1,y1,x2,y2,z1,z2);
    5457           0 :         x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
    5458             :         //if (TMath::Abs(x[3]) > cuts[3]) continue;
    5459             : 
    5460             :         
    5461             :         Double_t sy =0.1, sz =0.1;
    5462             :         Double_t sy1=0.02, sz1=0.02;
    5463             :         Double_t sy2=0.02, sz2=0.02;
    5464             :         Double_t sy3=0.02;
    5465             : 
    5466           0 :         if (constrain){
    5467           0 :           sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
    5468           0 :         }
    5469             :         
    5470           0 :         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
    5471           0 :         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
    5472           0 :         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
    5473           0 :         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
    5474           0 :         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
    5475           0 :         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
    5476             : 
    5477           0 :         Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
    5478           0 :         Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
    5479           0 :         Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
    5480           0 :         Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
    5481             : 
    5482             :         
    5483           0 :         c[0]=sy1;
    5484           0 :         c[1]=0.;       c[2]=sz1;
    5485           0 :         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
    5486           0 :         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
    5487           0 :         c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
    5488           0 :         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
    5489           0 :         c[13]=f30*sy1*f40+f32*sy2*f42;
    5490           0 :         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
    5491             :         
    5492             :         //Int_t row1 = fSectors->GetRowNumber(x1);
    5493           0 :         Int_t row1 = GetRowNumber(x1);
    5494             : 
    5495             :         UInt_t index=0;
    5496             :         //kr0.GetIndex(is);
    5497           0 :         if (seed) {MarkSeedFree( seed ); seed = 0;}
    5498           0 :         AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
    5499           0 :         seed->SetPoolID(fLastSeedID);
    5500           0 :         track->SetIsSeeding(kTRUE);
    5501           0 :         Int_t rc=FollowProlongation(*track, i2);        
    5502           0 :         if (constrain) track->SetBConstrain(1);
    5503             :         else
    5504           0 :           track->SetBConstrain(0);
    5505           0 :         track->SetLastPoint(row1+fInnerSec->GetNRows());  // first cluster in track position
    5506           0 :         track->SetFirstPoint(track->GetLastPoint());
    5507             : 
    5508           0 :         if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 || 
    5509           0 :             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
    5510           0 :             track->GetNShared()>0.4*track->GetNumberOfClusters()) {
    5511           0 :           MarkSeedFree( seed ); seed = 0;
    5512           0 :         }
    5513             :         else {
    5514           0 :           arr->AddLast(track); // track IS seed, don't free seed
    5515           0 :           seed = new( NextFreeSeed() ) AliTPCseed;
    5516           0 :           seed->SetPoolID(fLastSeedID);
    5517             :         }
    5518           0 :         nin3++;
    5519           0 :       }
    5520           0 :     }  // if accepted seed
    5521           0 :   }
    5522           0 :   if (fDebug>3){
    5523           0 :     Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
    5524             :   }
    5525           0 :   if (seed) MarkSeedFree( seed );
    5526           0 : }
    5527             : 
    5528             : //_____________________________________________________________________________
    5529             : void AliTPCtracker::MakeSeeds2Dist(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
    5530             :                                  Float_t deltay, Bool_t /*bconstrain*/) {
    5531             :   //-----------------------------------------------------------------
    5532             :   // This function creates track seeds, accounting for distortions - without vertex constraint
    5533             :   //-----------------------------------------------------------------
    5534             :   // cuts[0]   - fP4 cut        - not applied
    5535             :   // cuts[1]   - tan(phi)  cut
    5536             :   // cuts[2]   - zvertex cut    - not applied 
    5537             :   // cuts[3]   - fP3 cut
    5538             :   const double kRoadZ = 1.2, kRoadY = 1.2;
    5539             : 
    5540             :   Int_t nin0=0;
    5541             :   Int_t nin1=0;
    5542             :   Int_t nin2=0;
    5543             :   Int_t nin3=0;
    5544             :   //  Int_t nin4=0;
    5545             :   //Int_t nin5=0;
    5546             : 
    5547           0 :   AliFatal("This method is still not fully aware of distortions, should not be used");
    5548           0 :   Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
    5549             :   //  Double_t cs=cos(alpha), sn=sin(alpha);
    5550           0 :   Int_t row0 = (i1+i2)/2;
    5551           0 :   Int_t drow = (i1-i2)/2;
    5552           0 :   const AliTPCtrackerRow& kr0=fSectors[sec][row0];
    5553             :   AliTPCtrackerRow * kr=0;
    5554             : 
    5555           0 :   AliTPCpolyTrack polytrack;
    5556           0 :   Int_t nclusters=fSectors[sec][row0];
    5557           0 :   AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
    5558           0 :   seed->SetPoolID(fLastSeedID);
    5559             : 
    5560             :   Int_t sumused=0;
    5561             :   Int_t cused=0;
    5562             :   Int_t cnused=0;
    5563             :   Int_t rowMax = -1;
    5564             :   //
    5565           0 :   for (Int_t is=0; is < nclusters; is++) {  //LOOP over clusters
    5566             :     Int_t nfound =0;
    5567             :     Int_t nfoundable =0;
    5568           0 :     for (Int_t iter =1; iter<2; iter++){   //iterations
    5569           0 :       const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
    5570           0 :       const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];      
    5571           0 :       const AliTPCclusterMI * cl= kr0[is];
    5572           0 :       if (cl->IsDisabled()) {
    5573           0 :         continue;
    5574             :       }
    5575             : 
    5576           0 :       if (cl->IsUsed(10)) {
    5577           0 :         cused++;
    5578           0 :       }
    5579             :       else{
    5580           0 :         cnused++;
    5581             :       }
    5582             :       
    5583           0 :       Double_t x = cl->GetX(), xDist = x - kr0.GetX(); // approximate X distortion in proximity of cl
    5584             :       // Initialization of the polytrack
    5585             :       nfound =0;
    5586             :       nfoundable =0;
    5587           0 :       polytrack.Reset();
    5588             :       //
    5589           0 :       Double_t y0= cl->GetY();
    5590           0 :       Double_t z0= cl->GetZ();
    5591             :       Float_t erry = 0;
    5592             :       Float_t errz = 0;
    5593             :       
    5594           0 :       Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5; // RS: watch dead zones
    5595           0 :       if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue;  // seed only at the edge
    5596             :       
    5597           0 :       erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;        
    5598           0 :       errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;      
    5599           0 :       polytrack.AddPoint(x,y0,z0,erry, errz);
    5600             :       rowMax = row0;      
    5601             :       sumused=0;
    5602           0 :       if (cl->IsUsed(10)) sumused++;
    5603             : 
    5604             : 
    5605           0 :       Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
    5606           0 :       Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
    5607             :       //
    5608           0 :       x = krm.GetX() + xDist; // RS: assume distortion at krm is similar to that at kr
    5609           0 :       AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady+fClExtraRoadY,roadz+fClExtraRoadZ);
    5610           0 :       if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
    5611           0 :         erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;            
    5612           0 :         errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
    5613           0 :         if (cl1->IsUsed(10))  sumused++;
    5614             :         //RS: use real cluster X instead of approximately distorted
    5615           0 :         polytrack.AddPoint(cl1->GetX(),cl1->GetY(),cl1->GetZ(),erry,errz); 
    5616             :       }
    5617             :       //
    5618           0 :       x = krp.GetX() + xDist; // RS: assume distortion at krp is similar to that at kr
    5619           0 :       AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady+fClExtraRoadY,roadz+fClExtraRoadZ);
    5620           0 :       if (cl2) {
    5621           0 :         erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;            
    5622           0 :         errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
    5623           0 :         if (cl2->IsUsed(10)) sumused++;       
    5624             :         //RS: use real cluster X instead of approximately distorted
    5625           0 :         polytrack.AddPoint(cl2->GetX(),cl2->GetY(),cl2->GetZ(),erry,errz); 
    5626             :         rowMax = row0+iter;
    5627           0 :       }
    5628             :       //
    5629           0 :       if (sumused>0) continue;
    5630           0 :       nin0++;
    5631           0 :       polytrack.UpdateParameters();
    5632             :       // follow polytrack
    5633             :       //
    5634           0 :       Double_t yn,zn;
    5635           0 :       nfoundable = polytrack.GetN();
    5636             :       nfound     = nfoundable; 
    5637             :       //
    5638           0 :       for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
    5639           0 :         Float_t maxdist = 0.8*(1.+3./(ddrow));
    5640           0 :         for (Int_t delta = -1;delta<=1;delta+=2){
    5641           0 :           Int_t row = row0+ddrow*delta;
    5642           0 :           kr = &(fSectors[sec][row]);
    5643           0 :           Double_t xn = kr->GetX(); //RS: use row X as a first guess about distorted cluster x
    5644           0 :           Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5; // RS: watch dead zones
    5645           0 :           polytrack.GetFitPoint(xn,yn,zn);
    5646           0 :           double dxn = GetDistortionX(xn, yn, zn, sec, row);
    5647           0 :           if (TMath::Abs(dxn)>0.1) {    //RS: account for distortion
    5648           0 :             xn += dxn;  
    5649           0 :             polytrack.GetFitPoint(xn,yn,zn);    
    5650           0 :           }
    5651             :           //
    5652           0 :           if (TMath::Abs(yn)>ymax1) continue; // RS:? watch dead zones
    5653           0 :           nfoundable++;
    5654           0 :           AliTPCclusterMI * cln = kr->FindNearest(yn,zn,kRoadY+fClExtraRoadY,kRoadZ+fClExtraRoadZ);
    5655           0 :           if (cln) {
    5656           0 :             Float_t dist =  TMath::Sqrt(  (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
    5657           0 :             if (dist<maxdist){
    5658             :               /*
    5659             :               erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));           
    5660             :               errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
    5661             :               if (cln->IsUsed(10)) {
    5662             :                 //      printf("used\n");
    5663             :                 sumused++;
    5664             :                 erry*=2;
    5665             :                 errz*=2;
    5666             :               }
    5667             :               */
    5668             :               erry=0.1;
    5669             :               errz=0.1;
    5670           0 :               polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
    5671           0 :               if (row>rowMax) rowMax = row;
    5672           0 :               nfound++;
    5673           0 :             }
    5674           0 :           }
    5675           0 :         }
    5676           0 :         if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable))  break;     
    5677           0 :         polytrack.UpdateParameters();
    5678           0 :       }           
    5679           0 :     }
    5680           0 :     if ( (sumused>3) || (sumused>0.5*nfound))  {
    5681             :       //printf("sumused   %d\n",sumused);
    5682           0 :       continue;
    5683             :     }
    5684           0 :     nin1++;
    5685           0 :     Double_t dy,dz;
    5686           0 :     polytrack.GetFitDerivation(kr0.GetX(),dy,dz); // RS: Note: derivative is at ideal row X
    5687           0 :     AliTPCpolyTrack track2;
    5688             :     
    5689           0 :     polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
    5690           0 :     if (track2.GetN()<0.5*nfoundable) continue;
    5691           0 :     nin2++;
    5692             : 
    5693           0 :     if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
    5694             :       //
    5695             :       // test seed with and without constrain
    5696           0 :       for (Int_t constrain=0; constrain<=0;constrain++){
    5697             :         // add polytrack candidate
    5698             : 
    5699           0 :         Double_t x[5], c[15];
    5700           0 :         Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
    5701           0 :         track2.GetBoundaries(x3,x1);    
    5702           0 :         x2 = (x1+x3)/2.;
    5703           0 :         track2.GetFitPoint(x1,y1,z1);
    5704           0 :         track2.GetFitPoint(x2,y2,z2);
    5705           0 :         track2.GetFitPoint(x3,y3,z3);
    5706             :         //
    5707             :         //is track pointing to the vertex ?
    5708           0 :         Double_t x0,y0,z0;
    5709             :         x0=0;
    5710           0 :         polytrack.GetFitPoint(x0,y0,z0);
    5711             : 
    5712           0 :         if (constrain) {
    5713           0 :           x2 = x3;
    5714           0 :           y2 = y3;
    5715           0 :           z2 = z3;
    5716             :           
    5717           0 :           x3 = 0;
    5718           0 :           y3 = 0;
    5719           0 :           z3 = 0;
    5720           0 :         }
    5721           0 :         x[0]=y1;
    5722           0 :         x[1]=z1;
    5723           0 :         x[4]=F1(x1,y1,x2,y2,x3,y3);
    5724             :                 
    5725             :         //      if (TMath::Abs(x[4]) >= cuts[0]) continue;  //
    5726           0 :         x[2]=F2(x1,y1,x2,y2,x3,y3);
    5727             :         
    5728             :         //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
    5729             :         //x[3]=F3(x1,y1,x2,y2,z1,z2);
    5730           0 :         x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
    5731             :         //if (TMath::Abs(x[3]) > cuts[3]) continue;
    5732             : 
    5733             :         
    5734             :         Double_t sy =0.1, sz =0.1;
    5735             :         Double_t sy1=0.02, sz1=0.02;
    5736             :         Double_t sy2=0.02, sz2=0.02;
    5737             :         Double_t sy3=0.02;
    5738             : 
    5739           0 :         if (constrain){
    5740           0 :           sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
    5741           0 :         }
    5742             :         
    5743           0 :         Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
    5744           0 :         Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
    5745           0 :         Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
    5746           0 :         Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
    5747           0 :         Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
    5748           0 :         Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
    5749             : 
    5750           0 :         Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
    5751           0 :         Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
    5752           0 :         Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
    5753           0 :         Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
    5754             : 
    5755             :         
    5756           0 :         c[0]=sy1;
    5757           0 :         c[1]=0.;       c[2]=sz1;
    5758           0 :         c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
    5759           0 :         c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
    5760           0 :         c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
    5761           0 :         c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
    5762           0 :         c[13]=f30*sy1*f40+f32*sy2*f42;
    5763           0 :         c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
    5764             :         
    5765             :         //Int_t row1 = GetRowNumber(x1); // RS: this is now substituted by rowMax
    5766             : 
    5767             :         UInt_t index=0;
    5768             :         //kr0.GetIndex(is);
    5769           0 :         if (seed) {MarkSeedFree( seed ); seed = 0;}
    5770           0 :         AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
    5771           0 :         seed->SetPoolID(fLastSeedID);
    5772           0 :         seed->SetRow(rowMax); //RS: memorise row of x1
    5773           0 :         track->SetIsSeeding(kTRUE);
    5774           0 :         Int_t rc=FollowProlongation(*track, i2);        
    5775           0 :         if (constrain) track->SetBConstrain(1);
    5776             :         else
    5777           0 :           track->SetBConstrain(0);
    5778           0 :         track->SetLastPoint(rowMax); //row1+fInnerSec->GetNRows());  // first cluster in track position
    5779           0 :         track->SetFirstPoint(track->GetLastPoint());
    5780             : 
    5781           0 :         if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 || 
    5782           0 :             track->GetNumberOfClusters() < track->GetNFoundable()*0.6 || 
    5783           0 :             track->GetNShared()>0.4*track->GetNumberOfClusters()) {
    5784           0 :           MarkSeedFree( seed ); seed = 0;
    5785           0 :         }
    5786             :         else {
    5787           0 :           arr->AddLast(track); // track IS seed, don't free seed
    5788           0 :           seed = new( NextFreeSeed() ) AliTPCseed;
    5789           0 :           seed->SetPoolID(fLastSeedID);
    5790             :         }
    5791           0 :         nin3++;
    5792           0 :       }
    5793           0 :     }  // if accepted seed
    5794           0 :   }
    5795           0 :   if (fDebug>3){
    5796           0 :     Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
    5797             :   }
    5798           0 :   if (seed) MarkSeedFree( seed );
    5799           0 : }
    5800             : 
    5801             : 
    5802             : AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
    5803             : {
    5804             :   //
    5805             :   //
    5806             :   //reseed using track points
    5807         172 :   Int_t p0 = int(r0*track->GetNumberOfClusters());     // point 0 
    5808          86 :   Int_t p1 = int(r1*track->GetNumberOfClusters());
    5809          86 :   Int_t p2 = int(r2*track->GetNumberOfClusters());   // last point
    5810             :   Int_t pp2=0;
    5811          86 :   Double_t  x0[3],x1[3],x2[3];
    5812         688 :   for (Int_t i=0;i<3;i++){
    5813         258 :     x0[i]=-1;
    5814         258 :     x1[i]=-1;
    5815         258 :     x2[i]=-1;
    5816             :   }
    5817             : 
    5818             :   // find track position at given ratio of the length
    5819             :   Int_t  sec0=0, sec1=0, sec2=0;
    5820             :   Int_t index=-1;
    5821             :   Int_t clindex;
    5822       27520 :   for (Int_t i=0;i<kMaxRow;i++){
    5823       13674 :     if (track->GetClusterIndex2(i)>=0){
    5824        2068 :       index++;
    5825        2068 :       const AliTPCTrackerPoints::Point *trpoint =track->GetTrackPoint(i);
    5826        3756 :       if ( (index<p0) || x0[0]<0 ){
    5827         380 :         if (trpoint->GetX()>1){
    5828         380 :           clindex = track->GetClusterIndex2(i);
    5829         380 :           if (clindex >= 0){ 
    5830         380 :             x0[0] = trpoint->GetX();
    5831         380 :             x0[1] = trpoint->GetY();
    5832         380 :             x0[2] = trpoint->GetZ();
    5833         380 :             sec0  = ((clindex&0xff000000)>>24)%18;
    5834         380 :           }
    5835             :         }
    5836             :       }
    5837             : 
    5838        3084 :       if ( (index<p1) &&(trpoint->GetX()>1)){
    5839        1016 :         clindex = track->GetClusterIndex2(i);
    5840        1016 :         if (clindex >= 0){
    5841        1016 :           x1[0] = trpoint->GetX();
    5842        1016 :           x1[1] = trpoint->GetY();
    5843        1016 :           x1[2] = trpoint->GetZ();
    5844        1016 :           sec1  = ((clindex&0xff000000)>>24)%18;
    5845        1016 :         }
    5846             :       }
    5847        3912 :       if ( (index<p2) &&(trpoint->GetX()>1)){
    5848        1844 :         clindex = track->GetClusterIndex2(i);
    5849        1844 :         if (clindex >= 0){
    5850        1844 :           x2[0] = trpoint->GetX();
    5851        1844 :           x2[1] = trpoint->GetY();
    5852        1844 :           x2[2] = trpoint->GetZ(); 
    5853        1844 :           sec2  = ((clindex&0xff000000)>>24)%18;
    5854             :           pp2 = i;
    5855        1844 :         }
    5856             :       }
    5857        2068 :     }
    5858             :   }
    5859             :   
    5860             :   Double_t alpha, cs,sn, xx2,yy2;
    5861             :   //
    5862          86 :   alpha = (sec1-sec2)*fSectors->GetAlpha();
    5863          86 :   cs = TMath::Cos(alpha);
    5864          86 :   sn = TMath::Sin(alpha); 
    5865          86 :   xx2= x1[0]*cs-x1[1]*sn;
    5866          86 :   yy2= x1[0]*sn+x1[1]*cs;
    5867          86 :   x1[0] = xx2;
    5868          86 :   x1[1] = yy2;
    5869             :   //
    5870          86 :   alpha = (sec0-sec2)*fSectors->GetAlpha();
    5871          86 :   cs = TMath::Cos(alpha);
    5872          86 :   sn = TMath::Sin(alpha); 
    5873          86 :   xx2= x0[0]*cs-x0[1]*sn;
    5874          86 :   yy2= x0[0]*sn+x0[1]*cs;
    5875          86 :   x0[0] = xx2;
    5876          86 :   x0[1] = yy2;
    5877             :   //
    5878             :   //
    5879             :   //
    5880          86 :   Double_t x[5],c[15];
    5881             :   //
    5882          86 :   x[0]=x2[1];
    5883          86 :   x[1]=x2[2];
    5884          86 :   x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
    5885             :   //  if (x[4]>1) return 0;
    5886          86 :   x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
    5887          86 :   x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
    5888             :   //if (TMath::Abs(x[3]) > 2.2)  return 0;
    5889             :   //if (TMath::Abs(x[2]) > 1.99) return 0;
    5890             :   //  
    5891             :   Double_t sy =0.1,  sz =0.1;
    5892             :   //
    5893          86 :   Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
    5894          86 :   Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
    5895          86 :   Double_t sy3=0.01+track->GetSigmaY2();
    5896             :   //
    5897          86 :   Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
    5898          86 :   Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
    5899          86 :   Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
    5900          86 :   Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
    5901          86 :   Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
    5902          86 :   Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
    5903             :   //
    5904          86 :   Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
    5905          86 :   Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
    5906          86 :   Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
    5907          86 :   Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
    5908             :   
    5909             :   
    5910          86 :   c[0]=sy1;
    5911          86 :   c[1]=0.;       c[2]=sz1;
    5912          86 :   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
    5913          86 :   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
    5914          86 :   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
    5915          86 :   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
    5916          86 :   c[13]=f30*sy1*f40+f32*sy2*f42;
    5917          86 :   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
    5918             :   
    5919             :   //  Int_t row1 = fSectors->GetRowNumber(x2[0]);
    5920          86 :   AliTPCseed *seed = new( NextFreeSeed() )  AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
    5921          86 :   seed->SetPoolID(fLastSeedID);
    5922          86 :   seed->SetRow(pp2); //RS: memorise current row
    5923             :   //  Double_t y0,z0,y1,z1, y2,z2;
    5924             :   //seed->GetProlongation(x0[0],y0,z0);
    5925             :   // seed->GetProlongation(x1[0],y1,z1);
    5926             :   //seed->GetProlongation(x2[0],y2,z2);
    5927             :   //  seed =0;
    5928          86 :   seed->SetLastPoint(pp2);
    5929          86 :   seed->SetFirstPoint(pp2);
    5930             :   
    5931             : 
    5932          86 :   return seed;
    5933          86 : }
    5934             : 
    5935             : 
    5936             : AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
    5937             : {
    5938             :   //
    5939             :   //
    5940             :   //reseed using founded clusters 
    5941             :   //
    5942             :   // Find the number of clusters
    5943             :   Int_t nclusters = 0;
    5944           0 :   for (Int_t irow=0;irow<kMaxRow;irow++){
    5945           0 :     if (track->GetClusterIndex(irow)>0) nclusters++;
    5946             :   }
    5947             :   //
    5948           0 :   Int_t ipos[3];
    5949           0 :   ipos[0] = TMath::Max(int(r0*nclusters),0);             // point 0 cluster
    5950           0 :   ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1);   // 
    5951           0 :   ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1);   // last point
    5952             :   //
    5953             :   //
    5954           0 :   Double_t  xyz[3][3]={{0}};
    5955           0 :   Int_t     row[3]={0},sec[3]={0,0,0};
    5956             :   //
    5957             :   // find track row position at given ratio of the length
    5958             :   Int_t index=-1;
    5959           0 :   for (Int_t irow=0;irow<kMaxRow;irow++){    
    5960           0 :     if (track->GetClusterIndex2(irow)<0) continue;
    5961           0 :     index++;
    5962           0 :     for (Int_t ipoint=0;ipoint<3;ipoint++){
    5963           0 :       if (index<=ipos[ipoint]) row[ipoint] = irow;
    5964             :     }        
    5965           0 :   }
    5966             :   //
    5967             :   //Get cluster and sector position
    5968           0 :   for (Int_t ipoint=0;ipoint<3;ipoint++){
    5969           0 :     Int_t clindex = track->GetClusterIndex2(row[ipoint]);    
    5970           0 :     AliTPCclusterMI * cl = clindex<0 ? 0:GetClusterMI(clindex);
    5971           0 :     if (cl==0) {
    5972             :       //Error("Bug\n");
    5973             :       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
    5974           0 :       return 0;
    5975             :     }
    5976           0 :     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
    5977           0 :     xyz[ipoint][0]  = GetXrow(row[ipoint]);
    5978           0 :     xyz[ipoint][1]  = cl->GetY();
    5979           0 :     xyz[ipoint][2]  = cl->GetZ();
    5980           0 :   }
    5981             :   //
    5982             :   //
    5983             :   // Calculate seed state vector and covariance matrix
    5984             : 
    5985             :   Double_t alpha, cs,sn, xx2,yy2;
    5986             :   //
    5987           0 :   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
    5988           0 :   cs = TMath::Cos(alpha);
    5989           0 :   sn = TMath::Sin(alpha); 
    5990           0 :   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
    5991           0 :   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
    5992           0 :   xyz[1][0] = xx2;
    5993           0 :   xyz[1][1] = yy2;
    5994             :   //
    5995           0 :   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
    5996           0 :   cs = TMath::Cos(alpha);
    5997           0 :   sn = TMath::Sin(alpha); 
    5998           0 :   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
    5999           0 :   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
    6000           0 :   xyz[0][0] = xx2;
    6001           0 :   xyz[0][1] = yy2;
    6002             :   //
    6003             :   //
    6004             :   //
    6005           0 :   Double_t x[5],c[15];
    6006             :   //
    6007           0 :   x[0]=xyz[2][1];
    6008           0 :   x[1]=xyz[2][2];
    6009           0 :   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
    6010           0 :   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
    6011           0 :   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
    6012             :   //  
    6013             :   Double_t sy =0.1,  sz =0.1;
    6014             :   //
    6015             :   Double_t sy1=0.2, sz1=0.2;
    6016             :   Double_t sy2=0.2, sz2=0.2;
    6017             :   Double_t sy3=0.2;
    6018             :   //
    6019           0 :   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;
    6020           0 :   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;
    6021           0 :   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;
    6022           0 :   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;
    6023           0 :   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;
    6024           0 :   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;
    6025             :   //
    6026           0 :   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;
    6027           0 :   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;
    6028           0 :   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;
    6029           0 :   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;
    6030             :   
    6031             :   
    6032           0 :   c[0]=sy1;
    6033           0 :   c[1]=0.;       c[2]=sz1;
    6034           0 :   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
    6035           0 :   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
    6036           0 :   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
    6037           0 :   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
    6038           0 :   c[13]=f30*sy1*f40+f32*sy2*f42;
    6039           0 :   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
    6040             :   
    6041             :   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
    6042           0 :   AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
    6043           0 :   seed->SetPoolID(fLastSeedID);
    6044           0 :   seed->SetRow(row[2]); //RS: memorise row
    6045           0 :   seed->SetLastPoint(row[2]);
    6046           0 :   seed->SetFirstPoint(row[2]);  
    6047             :   return seed;
    6048           0 : }
    6049             : 
    6050             : 
    6051             : AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
    6052             : {
    6053             :   //
    6054             :   //
    6055             :   //reseed using founded clusters 
    6056             :   //
    6057          52 :   Double_t  xyz[3][3];
    6058          52 :   Int_t     row[3]={0,0,0};
    6059          52 :   Int_t     sec[3]={0,0,0};
    6060             :   //
    6061             :   // forward direction
    6062          52 :   if (forward){
    6063         112 :     for (Int_t irow=r0;irow<kMaxRow;irow++){
    6064          56 :       if (track->GetClusterIndex(irow)>0){
    6065          52 :         row[0] = irow;
    6066          52 :         break;
    6067             :       }
    6068             :     }
    6069         384 :     for (Int_t irow=kMaxRow;irow>r0;irow--){
    6070         192 :       if (track->GetClusterIndex(irow)>0){
    6071          52 :         row[2] = irow;
    6072          52 :         break;
    6073             :       }
    6074             :     }
    6075         104 :     for (Int_t irow=row[2]-15;irow>row[0];irow--){
    6076          52 :       if (track->GetClusterIndex(irow)>0){
    6077          52 :         row[1] = irow;
    6078          52 :         break;
    6079             :       }
    6080             :     }
    6081             :     //
    6082          52 :   }
    6083          52 :   if (!forward){
    6084           0 :     for (Int_t irow=0;irow<r0;irow++){
    6085           0 :       if (track->GetClusterIndex(irow)>0){
    6086           0 :         row[0] = irow;
    6087           0 :         break;
    6088             :       }
    6089             :     }
    6090           0 :     for (Int_t irow=r0;irow>0;irow--){
    6091           0 :       if (track->GetClusterIndex(irow)>0){
    6092           0 :         row[2] = irow;
    6093           0 :         break;
    6094             :       }
    6095             :     }    
    6096           0 :     for (Int_t irow=row[2]-15;irow>row[0];irow--){
    6097           0 :       if (track->GetClusterIndex(irow)>0){
    6098           0 :         row[1] = irow;
    6099           0 :         break;
    6100             :       }
    6101             :     } 
    6102           0 :   }
    6103             :   //
    6104          52 :   if ((row[2]-row[0])<20) return 0;
    6105          52 :   if (row[1]==0) return 0;
    6106             :   //
    6107             :   //
    6108             :   //Get cluster and sector position
    6109         468 :   for (Int_t ipoint=0;ipoint<3;ipoint++){
    6110         156 :     Int_t clindex = track->GetClusterIndex2(row[ipoint]);
    6111         468 :     AliTPCclusterMI * cl = clindex<0 ? 0:GetClusterMI(clindex);
    6112         156 :     if (cl==0) {
    6113             :       //Error("Bug\n");
    6114             :       //      AliTPCclusterMI * cl = GetClusterMI(clindex);
    6115           0 :       return 0;
    6116             :     }
    6117         156 :     sec[ipoint]     = ((clindex&0xff000000)>>24)%18;
    6118         156 :     xyz[ipoint][0]  = GetXrow(row[ipoint]);
    6119         156 :     const AliTPCTrackerPoints::Point * point = track->GetTrackPoint(row[ipoint]);    
    6120         156 :     if (point&&ipoint<2){
    6121             :       //
    6122         104 :        xyz[ipoint][1]  = point->GetY();
    6123         104 :        xyz[ipoint][2]  = point->GetZ();
    6124         104 :     }
    6125             :     else{
    6126          52 :       xyz[ipoint][1]  = cl->GetY();
    6127          52 :       xyz[ipoint][2]  = cl->GetZ();
    6128             :     }
    6129         156 :   }
    6130             :   //
    6131             :   //
    6132             :   //
    6133             :   //
    6134             :   // Calculate seed state vector and covariance matrix
    6135             : 
    6136             :   Double_t alpha, cs,sn, xx2,yy2;
    6137             :   //
    6138          52 :   alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
    6139          52 :   cs = TMath::Cos(alpha);
    6140          52 :   sn = TMath::Sin(alpha); 
    6141          52 :   xx2= xyz[1][0]*cs-xyz[1][1]*sn;
    6142          52 :   yy2= xyz[1][0]*sn+xyz[1][1]*cs;
    6143          52 :   xyz[1][0] = xx2;
    6144          52 :   xyz[1][1] = yy2;
    6145             :   //
    6146          52 :   alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
    6147          52 :   cs = TMath::Cos(alpha);
    6148          52 :   sn = TMath::Sin(alpha); 
    6149          52 :   xx2= xyz[0][0]*cs-xyz[0][1]*sn;
    6150          52 :   yy2= xyz[0][0]*sn+xyz[0][1]*cs;
    6151          52 :   xyz[0][0] = xx2;
    6152          52 :   xyz[0][1] = yy2;
    6153             :   //
    6154             :   //
    6155             :   //
    6156          52 :   Double_t x[5],c[15];
    6157             :   //
    6158          52 :   x[0]=xyz[2][1];
    6159          52 :   x[1]=xyz[2][2];
    6160          52 :   x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
    6161          52 :   x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
    6162          52 :   x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
    6163             :   //  
    6164             :   Double_t sy =0.1,  sz =0.1;
    6165             :   //
    6166             :   Double_t sy1=0.2, sz1=0.2;
    6167             :   Double_t sy2=0.2, sz2=0.2;
    6168             :   Double_t sy3=0.2;
    6169             :   //
    6170          52 :   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;
    6171          52 :   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;
    6172          52 :   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;
    6173          52 :   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;
    6174          52 :   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;
    6175          52 :   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;
    6176             :   //
    6177          52 :   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;
    6178          52 :   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;
    6179          52 :   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;
    6180          52 :   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;
    6181             :   
    6182             :   
    6183          52 :   c[0]=sy1;
    6184          52 :   c[1]=0.;       c[2]=sz1;
    6185          52 :   c[3]=f20*sy1;  c[4]=0.;       c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
    6186          52 :   c[6]=f30*sy1;  c[7]=f31*sz1;  c[8]=f30*sy1*f20+f32*sy2*f22;
    6187          52 :   c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
    6188          52 :   c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
    6189          52 :   c[13]=f30*sy1*f40+f32*sy2*f42;
    6190          52 :   c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
    6191             :   
    6192             :   //  Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
    6193          52 :   AliTPCseed *seed=new( NextFreeSeed() )  AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
    6194          52 :   seed->SetPoolID(fLastSeedID);
    6195          52 :   seed->SetRow(row[2]); //RS: memorise row
    6196          52 :   seed->SetLastPoint(row[2]);
    6197          52 :   seed->SetFirstPoint(row[2]);  
    6198        6100 :   for (Int_t i=row[0];i<row[2];i++){
    6199        2998 :     seed->SetClusterIndex(i, track->GetClusterIndex(i));
    6200             :   }
    6201             : 
    6202             :   return seed;
    6203         104 : }
    6204             : 
    6205             : 
    6206             : 
    6207             : void  AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
    6208             : {
    6209             :   //
    6210             :   //  find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
    6211             :   //                      USES MC LABELS
    6212             :   //  Use AliTPCReconstructor::StreamLevel()& kStreamFindMultiMC if you want to tune parameters - cuts
    6213             :   //
    6214             :   //  Two reasons to have multiple find tracks
    6215             :   //  1. Curling tracks can be find more than once
    6216             :   //  2. Splitted tracks 
    6217             :   //     a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)        
    6218             :   //     b.) Edge effect on the sector boundaries
    6219             :   //
    6220             :   //
    6221             :   //  Algorithm done in 2 phases - because of CPU consumption
    6222             :   //  it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated                           
    6223             :   //
    6224             :   //  Algorihm for curling tracks sign:
    6225             :   //    1 phase -makes a very rough fast cuts to minimize combinatorics
    6226             :   //                 a.) opposite sign
    6227             :   //                 b.) one of the tracks - not pointing to the primary vertex - 
    6228             :   //                 c.) delta tan(theta)
    6229             :   //                 d.) delta phi
    6230             :   //    2 phase - calculates DCA between tracks  - time consument
    6231             : 
    6232             :   //
    6233             :   //    fast cuts 
    6234             :   //
    6235             :   //    General cuts    - for splitted tracks and for curling tracks
    6236             :   //
    6237             :   const Float_t kMaxdPhi      = 0.2;  // maximal distance in phi
    6238             :   //
    6239             :   //    Curling tracks cuts
    6240             :   //
    6241             :   //
    6242             :   //
    6243             :   //
    6244           0 :   Int_t nentries = array->GetEntriesFast();  
    6245           0 :   if (!fHelixPool) fHelixPool = new TClonesArray("AliHelix",nentries+50);
    6246           0 :   fHelixPool->Clear();
    6247           0 :   TClonesArray& helixes = *fHelixPool;
    6248           0 :   Float_t  xm[nentries];
    6249           0 :   Float_t  dz0[nentries];
    6250           0 :   Float_t  dz1[nentries];
    6251             :   //
    6252             :   //
    6253           0 :   TStopwatch timer;
    6254           0 :   timer.Start();
    6255             :   //
    6256             :   // Find track COG in x direction - point with best defined parameters
    6257             :   //
    6258           0 :   for (Int_t i=0;i<nentries;i++){
    6259           0 :     AliTPCseed* track = (AliTPCseed*)array->At(i);    
    6260           0 :     if (!track) continue;
    6261           0 :     track->SetCircular(0);
    6262           0 :     new (helixes[i]) AliHelix(*track);
    6263             :     Int_t ncl=0;
    6264           0 :     xm[i]=0;
    6265           0 :     Float_t dz[2];
    6266           0 :     track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
    6267           0 :     dz0[i]=dz[0];
    6268           0 :     dz1[i]=dz[1];
    6269           0 :     for (Int_t icl=0; icl<kMaxRow; icl++){
    6270           0 :       int tpcindex= track->GetClusterIndex2(icl);
    6271           0 :       const AliTPCclusterMI * cl = (tpcindex<0) ? 0:GetClusterMI(tpcindex);
    6272             :       //RS      AliTPCclusterMI * cl =  track->GetClusterPointer(icl);
    6273           0 :       if (cl) {
    6274           0 :         xm[i]+=cl->GetX();
    6275           0 :         ncl++;
    6276           0 :       }
    6277             :     }
    6278           0 :     if (ncl>0) xm[i]/=Float_t(ncl);
    6279           0 :   }  
    6280             :   //
    6281           0 :   for (Int_t i0=0;i0<nentries;i0++){
    6282           0 :     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
    6283           0 :     if (!track0) continue;    
    6284           0 :     AliHelix* hlxi0 = (AliHelix*)helixes[i0];
    6285           0 :     Float_t xc0 = hlxi0->GetHelix(6);
    6286           0 :     Float_t yc0 = hlxi0->GetHelix(7);
    6287           0 :     Float_t r0  = hlxi0->GetHelix(8);
    6288           0 :     Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
    6289           0 :     Float_t fi0 = TMath::ATan2(yc0,xc0);
    6290             :     
    6291           0 :     for (Int_t i1=i0+1;i1<nentries;i1++){
    6292           0 :       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
    6293           0 :       if (!track1) continue;      
    6294           0 :       Int_t lab0=track0->GetLabel();
    6295           0 :       Int_t lab1=track1->GetLabel();
    6296           0 :       if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
    6297             :       //
    6298           0 :       AliHelix* hlxi1 = (AliHelix*)helixes[i1];
    6299           0 :       Float_t xc1 = hlxi1->GetHelix(6);
    6300           0 :       Float_t yc1 = hlxi1->GetHelix(7);
    6301           0 :       Float_t r1  = hlxi1->GetHelix(8);
    6302           0 :       Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
    6303           0 :       Float_t fi1 = TMath::ATan2(yc1,xc1);
    6304             :       //
    6305           0 :       Float_t dfi = fi0-fi1;
    6306             :       //
    6307             :       //
    6308           0 :       if (dfi>1.5*TMath::Pi())  dfi-=TMath::Pi();  // take care about edge effect 
    6309           0 :       if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi();  // 
    6310           0 :       if (TMath::Abs(dfi)>kMaxdPhi&&hlxi0->GetHelix(4)*hlxi1->GetHelix(4)<0){
    6311             :         //
    6312             :         // if short tracks with undefined sign 
    6313           0 :         fi1 =  -TMath::ATan2(yc1,-xc1);
    6314           0 :         dfi = fi0-fi1;
    6315           0 :       }
    6316           0 :       Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
    6317             :       
    6318             :       //
    6319             :       // debug stream to tune "fast cuts" 
    6320             :       //
    6321           0 :       Double_t dist[3];   // distance at X 
    6322           0 :       Double_t mdist[3]={0,0,0};  // mean distance X+-40cm
    6323           0 :       track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
    6324           0 :       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
    6325           0 :       track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
    6326           0 :       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
    6327           0 :       track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
    6328           0 :       for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
    6329           0 :       for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
    6330             :       
    6331           0 :       Float_t sum =0;
    6332           0 :       Float_t sums=0;
    6333           0 :       for (Int_t icl=0; icl<kMaxRow; icl++){
    6334           0 :         Int_t tpcindex0 = track0->GetClusterIndex2(icl);
    6335           0 :         Int_t tpcindex1 = track1->GetClusterIndex2(icl);
    6336             :         //RS AliTPCclusterMI * cl0 =  track0->GetClusterPointer(icl);
    6337             :         //RS AliTPCclusterMI * cl1 =  track1->GetClusterPointer(icl);
    6338             :         //RS if (cl0&&cl1) {
    6339           0 :         if (tpcindex0>=0 && tpcindex1>=0) {
    6340           0 :           sum++;
    6341           0 :           if (tpcindex0==tpcindex1) sums++; //RS if (cl0==cl1) sums++;
    6342             :         }
    6343             :       }
    6344             :       //
    6345           0 :       if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) {  // flag: stream MC infomation about the multiple find track (ONLY for MC data)
    6346           0 :       TTreeSRedirector &cstream = *fDebugStreamer;
    6347           0 :       cstream<<"Multi"<<
    6348           0 :         "iter="<<iter<<
    6349           0 :         "lab0="<<lab0<<
    6350           0 :         "lab1="<<lab1<<   
    6351           0 :         "Tr0.="<<track0<<       // seed0
    6352           0 :         "Tr1.="<<track1<<       // seed1
    6353           0 :         "h0.="<<hlxi0<<
    6354           0 :         "h1.="<<hlxi1<<
    6355             :         //
    6356           0 :         "sum="<<sum<<           //the sum of rows with cl in both
    6357           0 :         "sums="<<sums<<         //the sum of shared clusters
    6358           0 :         "xm0="<<xm[i0]<<        // the center of track
    6359           0 :         "xm1="<<xm[i1]<<        // the x center of track
    6360             :         // General cut variables                   
    6361           0 :         "dfi="<<dfi<<           // distance in fi angle
    6362           0 :         "dtheta="<<dtheta<<     // distance int theta angle
    6363             :         //
    6364           0 :         "dz00="<<dz0[i0]<<
    6365           0 :         "dz01="<<dz0[i1]<<
    6366           0 :         "dz10="<<dz1[i1]<<
    6367           0 :         "dz11="<<dz1[i1]<<
    6368           0 :         "dist0="<<dist[0]<<     //distance x
    6369           0 :         "dist1="<<dist[1]<<     //distance y
    6370           0 :         "dist2="<<dist[2]<<     //distance z
    6371           0 :         "mdist0="<<mdist[0]<<   //distance x
    6372           0 :         "mdist1="<<mdist[1]<<   //distance y
    6373           0 :         "mdist2="<<mdist[2]<<   //distance z
    6374             :         //
    6375           0 :         "r0="<<r0<<
    6376           0 :         "rc0="<<rc0<<
    6377           0 :         "fi0="<<fi0<<
    6378           0 :         "fi1="<<fi1<<
    6379           0 :         "r1="<<r1<<
    6380           0 :         "rc1="<<rc1<<
    6381             :         "\n";
    6382           0 :         }
    6383           0 :     }
    6384           0 :   }    
    6385           0 :   if (fHelixPool) fHelixPool->Clear();
    6386             :   //  delete [] helixes; // RS moved to stack
    6387             :   //  delete [] xm;
    6388             :   //  delete [] dz0;
    6389             :   //  delete [] dz1;
    6390           0 :   if (AliTPCReconstructor::StreamLevel()>0) {
    6391           0 :     AliInfo("Time for curling tracks removal DEBUGGING MC");
    6392           0 :     timer.Print();
    6393             :   }
    6394           0 : }
    6395             : 
    6396             : 
    6397             : 
    6398             : void  AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
    6399             :   //
    6400             :   // Find Splitted tracks and remove the one with worst quality  
    6401             :   // Corresponding debug streamer to tune selections - "Splitted2"
    6402             :   // Algorithm:
    6403             :   // 0. Sort tracks according quality
    6404             :   // 1. Propagate the tracks to the reference radius
    6405             :   // 2. Double_t loop to select close tracks (only to speed up process)
    6406             :   // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
    6407             :   // 4. Delete temporary parameters
    6408             :   // 
    6409          48 :   const Double_t xref=GetXrow(63);  // reference radius -IROC/OROC boundary
    6410             :   //    rough cuts
    6411             :   const Double_t kCutP1=10;       // delta Z cut 10 cm 
    6412             :   const Double_t kCutP2=0.15;     // delta snp(fi) cut 0.15 
    6413             :   const Double_t kCutP3=0.15;     // delta tgl(theta) cut 0.15
    6414             :   const Double_t kCutAlpha=0.15;  // delta alpha cut
    6415             :   Int_t firstpoint = 0;
    6416             :   Int_t lastpoint = kMaxRow;
    6417             :   //
    6418          24 :   Int_t nentries = array->GetEntriesFast();  
    6419          28 :   if (!fETPPool) fETPPool = new TClonesArray("AliExternalTrackParam",nentries+50);
    6420          22 :   else fETPPool->Clear();
    6421          24 :   TClonesArray &params = *fETPPool;
    6422             :   //
    6423             :   //
    6424          24 :   TStopwatch timer;
    6425          24 :   timer.Start();
    6426             :   //
    6427             :   //0.  Sort tracks according quality
    6428             :   //1.  Propagate the ext. param to reference radius
    6429          24 :   Int_t nseed = array->GetEntriesFast();  
    6430          24 :   if (nseed<=0) return;
    6431          24 :   Float_t quality[nseed];
    6432          24 :   Int_t   indexes[nseed];
    6433        1108 :   for (Int_t i=0; i<nseed; i++) {
    6434         530 :     AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);    
    6435         530 :     if (!pt){
    6436         124 :       quality[i]=-1;
    6437         124 :       continue;
    6438             :     }
    6439         406 :     pt->UpdatePoints();    //select first last max dens points
    6440         406 :     Float_t * points = pt->GetPoints();
    6441         406 :     if (points[3]<0.8) quality[i] =-1;
    6442         812 :     quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
    6443             :     //prefer high momenta tracks if overlaps
    6444         812 :     quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
    6445        1218 :     AliExternalTrackParam* parI = new (params[i]) AliExternalTrackParam(*pt);
    6446             :     // params[i]=(*pt);
    6447         406 :     AliTracker::PropagateTrackParamOnlyToBxByBz(parI,xref,5.,kTRUE);
    6448             :     //    AliTracker::PropagateTrackToBxByBz(parI,xref,pt->GetMass(),1.,kTRUE); //RS What is the point of 2nd propagation
    6449         406 :   }
    6450          24 :   TMath::Sort(nseed,quality,indexes);
    6451             :   //
    6452             :   // 3. Loop over pair of tracks
    6453             :   //
    6454        1108 :   for (Int_t i0=0; i0<nseed; i0++) {
    6455         530 :     Int_t index0=indexes[i0];
    6456         654 :     if (!(array->UncheckedAt(index0))) continue;
    6457         406 :     AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);  
    6458         406 :     if (!s1->IsActive()) continue;
    6459         812 :     AliExternalTrackParam &par0=*(AliExternalTrackParam*)params[index0];
    6460       12324 :     for (Int_t i1=i0+1; i1<nseed; i1++) {
    6461        5756 :       Int_t index1=indexes[i1];
    6462        7922 :       if (!(array->UncheckedAt(index1))) continue;
    6463        3590 :       AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);  
    6464        3590 :       if (!s2->IsActive()) continue;
    6465        3590 :       if (s2->GetKinkIndexes()[0]!=0)
    6466         186 :         if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
    6467        7156 :       AliExternalTrackParam &par1=*(AliExternalTrackParam*)params[index1];
    6468       12378 :       if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
    6469        6930 :       if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
    6470        2788 :       if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
    6471        1308 :       Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
    6472         508 :       if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
    6473         804 :       if (TMath::Abs(dAlpha)>kCutAlpha) continue;
    6474             :       //
    6475          68 :       Int_t sumShared=0;
    6476          68 :       Int_t nall0=0;
    6477          68 :       Int_t nall1=0;
    6478          68 :       Int_t firstShared=lastpoint, lastShared=firstpoint;
    6479          68 :       Int_t firstRow=lastpoint, lastRow=firstpoint;
    6480             :       //
    6481             :       // for (Int_t i=firstpoint;i<lastpoint;i++){
    6482             :       //        if (s1->GetClusterIndex2(i)>0) nall0++;
    6483             :       //        if (s2->GetClusterIndex2(i)>0) nall1++;
    6484             :       //        if  (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
    6485             :       //          if (i<firstRow) firstRow=i;
    6486             :       //          if (i>lastRow)  lastRow=i;
    6487             :       //        }
    6488             :       //        if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
    6489             :       //          if (i<firstShared) firstShared=i;
    6490             :       //          if (i>lastShared)  lastShared=i;
    6491             :       //          sumShared++;
    6492             :       //        }
    6493             :       // }
    6494             :       //
    6495             :       // RS: faster version + fix(?)  ">" -> ">="
    6496       21760 :       for (Int_t i=firstpoint;i<lastpoint;i++){
    6497       10812 :         int ind1=s1->GetClusterIndex2(i),ind2=s2->GetClusterIndex2(i);
    6498       20246 :         if (ind1>=0) nall0++; // RS: ">" -> ">="
    6499       18092 :         if (ind2>=0) nall1++;
    6500       10812 :         if  (ind1>=0 && ind2>=0) {
    6501        6762 :           if (i<firstRow) firstRow=i;
    6502       13344 :           if (i>lastRow)  lastRow=i;
    6503             :         }
    6504       10812 :         if ( (ind1==ind2) && ind1>=0) {
    6505         354 :           if (i<firstShared) firstShared=i;
    6506         664 :           if (i>lastShared)  lastShared=i;
    6507         338 :           sumShared++;
    6508         338 :         }
    6509             :       }
    6510             : 
    6511          68 :       Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
    6512          68 :       Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
    6513             :       
    6514          68 :       if ((AliTPCReconstructor::StreamLevel()&kStreamSplitted2)>0){ // flag:stream information about discarded TPC tracks pair algorithm 
    6515           0 :         TTreeSRedirector &cstream = *fDebugStreamer;
    6516           0 :         Int_t n0=s1->GetNumberOfClusters();
    6517           0 :         Int_t n1=s2->GetNumberOfClusters();
    6518           0 :         Int_t n0F=s1->GetNFoundable();
    6519           0 :         Int_t n1F=s2->GetNFoundable();
    6520           0 :         Int_t lab0=s1->GetLabel();
    6521           0 :         Int_t lab1=s2->GetLabel();
    6522             : 
    6523           0 :         cstream<<"Splitted2"<<    // flag:stream information about discarded TPC tracks pair algorithm 
    6524           0 :           "iter="<<fIteration<<
    6525           0 :           "lab0="<<lab0<<        // MC label if exist
    6526           0 :           "lab1="<<lab1<<        // MC label if exist
    6527           0 :           "index0="<<index0<<
    6528           0 :           "index1="<<index1<<
    6529           0 :           "ratio0="<<ratio0<<      // shared ratio
    6530           0 :           "ratio1="<<ratio1<<      // shared ratio
    6531           0 :           "p0.="<<&par0<<        // track parameters
    6532           0 :           "p1.="<<&par1<<
    6533           0 :           "s0.="<<s1<<           // full seed
    6534           0 :           "s1.="<<s2<<
    6535           0 :           "n0="<<n0<<     // number of clusters track 0
    6536           0 :           "n1="<<n1<<     // number of clusters track 1
    6537           0 :           "nall0="<<nall0<<     // number of clusters track 0
    6538           0 :           "nall1="<<nall1<<     // number of clusters track 1
    6539           0 :           "n0F="<<n0F<<   // number of findable
    6540           0 :           "n1F="<<n1F<<   // number of findable
    6541           0 :           "shared="<<sumShared<<    // number of shared clusters
    6542           0 :           "firstS="<<firstShared<<  // first and the last shared row
    6543           0 :           "lastS="<<lastShared<<
    6544           0 :           "firstRow="<<firstRow<<   // first and the last row with cluster
    6545           0 :           "lastRow="<<lastRow<<     //
    6546             :           "\n";
    6547           0 :       }
    6548             :       //
    6549             :       // remove track with lower quality
    6550             :       //
    6551         204 :       if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
    6552         136 :           ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
    6553             :         //
    6554             :         //
    6555             :         //
    6556           0 :         MarkSeedFree( array->RemoveAt(index1) );
    6557             :       }
    6558        5824 :     }
    6559         936 :   }
    6560             :   //
    6561             :   // 4. Delete temporary array
    6562             :   //
    6563          48 :   if (fETPPool) fETPPool->Clear();
    6564             :   // delete [] params; // RS moved to stack
    6565             :   //  delete [] quality;
    6566             :   //  delete [] indexes;
    6567             : 
    6568          48 : }
    6569             : 
    6570             : 
    6571             : 
    6572             : void  AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
    6573             : {
    6574             :   //
    6575             :   //  find Curling tracks
    6576             :   //  Use AliTPCReconstructor::StreamLevel()&kStreamFindCurling if you want to tune parameters - cuts
    6577             :   //
    6578             :   //
    6579             :   //  Algorithm done in 2 phases - because of CPU consumption
    6580             :   //  it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated                           
    6581             :   //  see detal in MC part what can be used to cut
    6582             :   //
    6583             :   //    
    6584             :   //
    6585             :   const Float_t kMaxC         = 400;  // maximal curvature to of the track
    6586             :   const Float_t kMaxdTheta    = 0.15;  // maximal distance in theta
    6587             :   const Float_t kMaxdPhi      = 0.15;  // maximal distance in phi
    6588             :   const Float_t kPtRatio      = 0.3; // ratio between pt
    6589             :   const Float_t kMinDCAR      = 2.;   // distance to the primary vertex in r - see cpipe cut      
    6590             : 
    6591             :   //
    6592             :   //    Curling tracks cuts
    6593             :   //
    6594             :   //
    6595             :   const Float_t kMaxDeltaRMax = 40;   // distance in outer radius
    6596             :   const Float_t kMaxDeltaRMin = 5.;   // distance in lower radius - see cpipe cut
    6597             :   const Float_t kMinAngle     = 2.9;  // angle between tracks
    6598             :   const Float_t kMaxDist      = 5;    // biggest distance 
    6599             :   //
    6600             :   // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
    6601             :   /* 
    6602             :      Fast cuts:
    6603             :      TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
    6604             :      TCut cmax("cmax","abs(Tr0.GetC())>1/400");
    6605             :      TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
    6606             :      TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
    6607             :      TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");    
    6608             :      //
    6609             :      TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
    6610             :      TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
    6611             :      //
    6612             :      Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill 
    6613             :      Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
    6614             :      //
    6615             :      Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
    6616             : 
    6617             :   */
    6618             :   //  
    6619             :   //
    6620             :   //
    6621           0 :   Int_t nentries = array->GetEntriesFast();
    6622           0 :   if (!fHelixPool) fHelixPool = new TClonesArray("AliHelix",nentries+100);
    6623           0 :   fHelixPool->Clear();
    6624           0 :   TClonesArray& helixes = *fHelixPool;
    6625             : 
    6626           0 :   for (Int_t i=0;i<nentries;i++){
    6627           0 :     AliTPCseed* track = (AliTPCseed*)array->At(i);    
    6628           0 :     if (!track) continue;
    6629           0 :     track->SetCircular(0);
    6630           0 :     new (helixes[i]) AliHelix(*track);
    6631           0 :   }
    6632             :   //
    6633             :   //
    6634           0 :   TStopwatch timer;
    6635           0 :   timer.Start();
    6636           0 :   Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
    6637             : 
    6638             :   //
    6639             :   // Find tracks
    6640             :   //
    6641             :   //
    6642           0 :   for (Int_t i0=0;i0<nentries;i0++){
    6643           0 :     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
    6644           0 :     if (!track0) continue;    
    6645           0 :     if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
    6646           0 :     AliHelix* hlxi0 = (AliHelix*)helixes[i0];
    6647           0 :     Float_t xc0 = hlxi0->GetHelix(6);
    6648           0 :     Float_t yc0 = hlxi0->GetHelix(7);
    6649           0 :     Float_t r0  = hlxi0->GetHelix(8);
    6650           0 :     Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
    6651           0 :     Float_t fi0 = TMath::ATan2(yc0,xc0);
    6652             :     
    6653           0 :     for (Int_t i1=i0+1;i1<nentries;i1++){
    6654           0 :       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
    6655           0 :       if (!track1) continue;      
    6656           0 :       if (TMath::Abs(track1->GetC())<1/kMaxC) continue;    
    6657           0 :       AliHelix* hlxi1 = (AliHelix*)helixes[i1];
    6658           0 :       Float_t xc1 = hlxi1->GetHelix(6);
    6659           0 :       Float_t yc1 = hlxi1->GetHelix(7);
    6660           0 :       Float_t r1  = hlxi1->GetHelix(8);
    6661           0 :       Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
    6662           0 :       Float_t fi1 = TMath::ATan2(yc1,xc1);
    6663             :       //
    6664           0 :       Float_t dfi = fi0-fi1;
    6665             :       //
    6666             :       //
    6667           0 :       if (dfi>1.5*TMath::Pi())  dfi-=TMath::Pi();  // take care about edge effect 
    6668           0 :       if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi();  // 
    6669           0 :       Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
    6670             :       //
    6671             :       //
    6672             :       // FIRST fast cuts
    6673           0 :       if (track0->GetBConstrain()&&track1->GetBConstrain())  continue;  // not constrained
    6674           0 :       if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0)   continue; // not the same sign
    6675           0 :       if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
    6676           0 :       if ( TMath::Abs(dfi)>kMaxdPhi) continue;  //distance in phi
    6677           0 :       if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
    6678             :       //
    6679           0 :       Float_t pt0 = track0->GetSignedPt();
    6680           0 :       Float_t pt1 = track1->GetSignedPt();
    6681           0 :       if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;      
    6682           0 :       if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
    6683           0 :       if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
    6684           0 :       if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
    6685             :       //
    6686             :       //
    6687             :       // Now find closest approach
    6688             :       //
    6689             :       //
    6690             :       //
    6691           0 :       Int_t npoints = hlxi0->GetRPHIintersections(*hlxi1, phase, radius,10);
    6692           0 :       if (npoints==0) continue;
    6693           0 :       hlxi0->GetClosestPhases(*hlxi1, phase);
    6694             :       //
    6695           0 :       Double_t xyz0[3];
    6696           0 :       Double_t xyz1[3];
    6697           0 :       Double_t hangles[3];
    6698           0 :       hlxi0->Evaluate(phase[0][0],xyz0);
    6699           0 :       hlxi1->Evaluate(phase[0][1],xyz1);
    6700             : 
    6701           0 :       hlxi0->GetAngle(phase[0][0],*hlxi1,phase[0][1],hangles);
    6702           0 :       Double_t deltah[2],deltabest;
    6703           0 :       if (TMath::Abs(hangles[2])<kMinAngle) continue;
    6704             : 
    6705           0 :       if (npoints>0){
    6706             :         Int_t ibest=0;
    6707           0 :         hlxi0->ParabolicDCA(*hlxi1,phase[0][0],phase[0][1],radius[0],deltah[0],2);
    6708           0 :         if (npoints==2){
    6709           0 :           hlxi0->ParabolicDCA(*hlxi1,phase[1][0],phase[1][1],radius[1],deltah[1],2);
    6710           0 :           if (deltah[1]<deltah[0]) ibest=1;
    6711             :         }
    6712           0 :         deltabest  = TMath::Sqrt(deltah[ibest]);
    6713           0 :         hlxi0->Evaluate(phase[ibest][0],xyz0);
    6714           0 :         hlxi1->Evaluate(phase[ibest][1],xyz1);
    6715           0 :         hlxi0->GetAngle(phase[ibest][0],*hlxi1,phase[ibest][1],hangles);
    6716           0 :         Double_t radiusbest = TMath::Sqrt(radius[ibest]);
    6717             :         //
    6718           0 :         if (deltabest>kMaxDist) continue;
    6719             :         //      if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
    6720             :         Bool_t sign =kFALSE;
    6721           0 :         if (hangles[2]>kMinAngle) sign =kTRUE;
    6722             :         //
    6723           0 :         if (sign){
    6724             :           //      circular[i0] = kTRUE;
    6725             :           //      circular[i1] = kTRUE;
    6726           0 :           if (track0->OneOverPt()<track1->OneOverPt()){
    6727           0 :             track0->SetCircular(track0->GetCircular()+1);
    6728           0 :             track1->SetCircular(track1->GetCircular()+2);
    6729           0 :           }
    6730             :           else{
    6731           0 :             track1->SetCircular(track1->GetCircular()+1);
    6732           0 :             track0->SetCircular(track0->GetCircular()+2);
    6733             :           }
    6734             :         }               
    6735           0 :         if ((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0){  // flag: stream track infroamtion if the FindCurling tracks method        
    6736             :           //
    6737             :           //debug stream to tune "fine" cuts    
    6738           0 :           Int_t lab0=track0->GetLabel();
    6739           0 :           Int_t lab1=track1->GetLabel();
    6740           0 :           TTreeSRedirector &cstream = *fDebugStreamer;
    6741           0 :           cstream<<"Curling2"<<
    6742           0 :             "iter="<<iter<<
    6743           0 :             "lab0="<<lab0<<
    6744           0 :             "lab1="<<lab1<<   
    6745           0 :             "Tr0.="<<track0<<
    6746           0 :             "Tr1.="<<track1<<
    6747             :             //
    6748           0 :             "r0="<<r0<<
    6749           0 :             "rc0="<<rc0<<
    6750           0 :             "fi0="<<fi0<<
    6751           0 :             "r1="<<r1<<
    6752           0 :             "rc1="<<rc1<<
    6753           0 :             "fi1="<<fi1<<
    6754           0 :             "dfi="<<dfi<<
    6755           0 :             "dtheta="<<dtheta<<
    6756             :             //
    6757           0 :             "npoints="<<npoints<<                      
    6758           0 :             "hangles0="<<hangles[0]<<
    6759           0 :             "hangles1="<<hangles[1]<<
    6760           0 :             "hangles2="<<hangles[2]<<                    
    6761           0 :             "xyz0="<<xyz0[2]<<
    6762           0 :             "xyzz1="<<xyz1[2]<<
    6763           0 :             "radius="<<radiusbest<<
    6764           0 :             "deltabest="<<deltabest<< 
    6765           0 :             "phase0="<<phase[ibest][0]<<
    6766           0 :             "phase1="<<phase[ibest][1]<<
    6767             :             "\n";               
    6768             : 
    6769           0 :         }
    6770           0 :       }
    6771           0 :     }
    6772           0 :   }
    6773           0 :   if (fHelixPool) fHelixPool->Clear();
    6774             :   //  delete [] helixes; //RS moved to stack
    6775           0 :   if (AliTPCReconstructor::StreamLevel()>1) {
    6776           0 :     AliInfo("Time for curling tracks removal");
    6777           0 :     timer.Print();
    6778             :   }
    6779           0 : }
    6780             : 
    6781             : 
    6782             : void  AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
    6783             : {
    6784             :   //
    6785             :   //  find kinks
    6786             :   //
    6787             :   //
    6788             :   // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
    6789             :   // to check later
    6790             : 
    6791          16 :   TObjArray kinks(10000);
    6792           8 :   Int_t nentries = array->GetEntriesFast();
    6793           8 :   Char_t   sign[nentries];
    6794           8 :   UChar_t  nclusters[nentries];
    6795           8 :   Float_t  alpha[nentries];
    6796           8 :   UChar_t  usage[nentries];
    6797           8 :   Float_t  zm[nentries];
    6798           8 :   Float_t  z0[nentries]; 
    6799           8 :   Float_t  fim[nentries];
    6800           8 :   Bool_t   shared[nentries];
    6801           8 :   Bool_t   circular[nentries];
    6802           8 :   Float_t dca[nentries];
    6803          16 :   AliKink  *kink         = new AliKink();
    6804             :   //
    6805          14 :   if (!fHelixPool) fHelixPool = new TClonesArray("AliHelix",nentries+100);
    6806           8 :   fHelixPool->Clear();
    6807           8 :   TClonesArray& helixes = *fHelixPool;
    6808             : 
    6809             :   //const AliESDVertex * primvertex = esd->GetVertex();
    6810             :   //
    6811             :   //  nentries = array->GetEntriesFast();
    6812             :   //
    6813             :   
    6814             :   //
    6815             :   //
    6816         552 :   for (Int_t i=0;i<nentries;i++){
    6817         268 :     sign[i]=0;
    6818         268 :     usage[i]=0;
    6819         536 :     AliTPCseed* track = (AliTPCseed*)array->At(i);    
    6820         388 :     if (!track) continue;
    6821         148 :     track->SetCircular(0);
    6822         148 :     shared[i] = kFALSE;
    6823         148 :     track->UpdatePoints();
    6824         296 :     if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
    6825             :     }
    6826         296 :     nclusters[i]=track->GetNumberOfClusters();
    6827         296 :     alpha[i] = track->GetAlpha();
    6828         444 :     AliHelix* hlxi = new (helixes[i]) AliHelix(*track);
    6829         148 :     Double_t xyz[3];
    6830         148 :     hlxi->Evaluate(0,xyz);
    6831         296 :     sign[i] = (track->GetC()>0) ? -1:1;
    6832         148 :     Double_t x,y,z;
    6833             :     x=160;
    6834         296 :     if (track->GetProlongation(x,y,z)){
    6835         122 :       zm[i]  = z;
    6836         122 :       fim[i] = alpha[i]+TMath::ATan2(y,x);
    6837         122 :     }
    6838             :     else{
    6839          52 :       zm[i]  = track->GetZ();
    6840          26 :       fim[i] = alpha[i];
    6841             :     }   
    6842         148 :     z0[i]=1000;
    6843         148 :     circular[i]= kFALSE;
    6844         434 :     if (track->GetProlongation(0,y,z))  z0[i] = z;
    6845         296 :     dca[i] = track->GetD(0,0);    
    6846         148 :   }
    6847             :   //
    6848             :   //
    6849           8 :   TStopwatch timer;
    6850           8 :   timer.Start();
    6851             :   Int_t ncandidates =0;
    6852             :   Int_t nall =0;
    6853             :   Int_t ntracks=0; 
    6854           8 :   Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
    6855             : 
    6856             :   //
    6857             :   // Find circling track
    6858             :   //
    6859         552 :   for (Int_t i0=0;i0<nentries;i0++){
    6860         536 :     AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
    6861         388 :     if (!track0) continue;    
    6862         310 :     if (track0->GetNumberOfClusters()<40) continue;
    6863         370 :     if (TMath::Abs(1./track0->GetC())>200) continue;
    6864          64 :     AliHelix* hlxi0 = (AliHelix*)helixes[i0];
    6865             :     //
    6866         632 :     for (Int_t i1=i0+1;i1<nentries;i1++){
    6867         568 :       AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
    6868         328 :       if (!track1) continue;
    6869         576 :       if (track1->GetNumberOfClusters()<40)                  continue;
    6870         442 :       if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
    6871         134 :       if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
    6872         268 :       if (TMath::Abs(1./track1->GetC())>200) continue;
    6873         462 :       if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0)      continue;
    6874         250 :       if (track1->GetTgl()*track0->GetTgl()>0)      continue;
    6875         138 :       if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
    6876          46 :       if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
    6877          46 :       if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
    6878             :       //
    6879          46 :       Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
    6880          46 :       if (mindcar<5)   continue;
    6881          46 :       Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
    6882          60 :       if (mindcaz<5) continue;
    6883          32 :       if (mindcar+mindcaz<20) continue;
    6884             :       //
    6885          64 :       AliHelix* hlxi1 = (AliHelix*)helixes[i1];
    6886             :       //
    6887          32 :       Float_t xc0 = hlxi0->GetHelix(6);
    6888          32 :       Float_t yc0 = hlxi0->GetHelix(7);
    6889          32 :       Float_t r0  = hlxi0->GetHelix(8);
    6890          32 :       Float_t xc1 = hlxi1->GetHelix(6);
    6891          32 :       Float_t yc1 = hlxi1->GetHelix(7);
    6892          32 :       Float_t r1  = hlxi1->GetHelix(8);
    6893             :         
    6894          32 :       Float_t rmean = (r0+r1)*0.5;
    6895          32 :       Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
    6896             :       //if (delta>30) continue;
    6897          50 :       if (delta>rmean*0.25) continue;
    6898          14 :       if (TMath::Abs(r0-r1)/rmean>0.3) continue; 
    6899             :       //
    6900          28 :       Int_t npoints = hlxi0->GetRPHIintersections(*hlxi1, phase, radius,10);
    6901          14 :       if (npoints==0) continue;
    6902          14 :       hlxi0->GetClosestPhases(*hlxi1, phase);
    6903             :       //
    6904          14 :       Double_t xyz0[3];
    6905          14 :       Double_t xyz1[3];
    6906          14 :       Double_t hangles[3];
    6907          14 :       hlxi0->Evaluate(phase[0][0],xyz0);
    6908          14 :       hlxi1->Evaluate(phase[0][1],xyz1);
    6909             : 
    6910          14 :       hlxi0->GetAngle(phase[0][0],*hlxi1,phase[0][1],hangles);
    6911          14 :       Double_t deltah[2],deltabest;
    6912          14 :       if (hangles[2]<2.8) continue;
    6913          14 :       if (npoints>0){
    6914             :         Int_t ibest=0;
    6915          14 :         hlxi0->ParabolicDCA(*hlxi1,phase[0][0],phase[0][1],radius[0],deltah[0],2);
    6916          14 :         if (npoints==2){
    6917          12 :           hlxi0->ParabolicDCA(*hlxi1,phase[1][0],phase[1][1],radius[1],deltah[1],2);
    6918          22 :           if (deltah[1]<deltah[0]) ibest=1;
    6919             :         }
    6920          14 :         deltabest  = TMath::Sqrt(deltah[ibest]);
    6921          14 :         hlxi0->Evaluate(phase[ibest][0],xyz0);
    6922          14 :         hlxi1->Evaluate(phase[ibest][1],xyz1);
    6923          14 :         hlxi0->GetAngle(phase[ibest][0],*hlxi1,phase[ibest][1],hangles);
    6924          14 :         Double_t radiusbest = TMath::Sqrt(radius[ibest]);
    6925             :         //
    6926          14 :         if (deltabest>6) continue;
    6927          32 :         if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
    6928             :         Bool_t lsign =kFALSE;
    6929          16 :         if (hangles[2]>3.06) lsign =kTRUE;
    6930             :         //
    6931           8 :         if (lsign){
    6932           8 :           circular[i0] = kTRUE;
    6933           8 :           circular[i1] = kTRUE;
    6934          24 :           if (track0->OneOverPt()<track1->OneOverPt()){
    6935           2 :             track0->SetCircular(track0->GetCircular()+1);
    6936           2 :             track1->SetCircular(track1->GetCircular()+2);
    6937           2 :           }
    6938             :           else{
    6939           6 :             track1->SetCircular(track1->GetCircular()+1);
    6940           6 :             track0->SetCircular(track0->GetCircular()+2);
    6941             :           }
    6942             :         }               
    6943          16 :         if (lsign&&((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0)){   
    6944             :           //debug stream          
    6945           0 :           Int_t lab0=track0->GetLabel();
    6946           0 :           Int_t lab1=track1->GetLabel();
    6947           0 :           TTreeSRedirector &cstream = *fDebugStreamer;
    6948           0 :           cstream<<"Curling"<<
    6949           0 :             "lab0="<<lab0<<
    6950           0 :             "lab1="<<lab1<<   
    6951           0 :             "Tr0.="<<track0<<
    6952           0 :             "Tr1.="<<track1<<        
    6953           0 :             "dca0="<<dca[i0]<<
    6954           0 :             "dca1="<<dca[i1]<<
    6955           0 :             "mindcar="<<mindcar<<
    6956           0 :             "mindcaz="<<mindcaz<<
    6957           0 :             "delta="<<delta<<
    6958           0 :             "rmean="<<rmean<<
    6959           0 :             "npoints="<<npoints<<                      
    6960           0 :             "hangles0="<<hangles[0]<<
    6961           0 :             "hangles2="<<hangles[2]<<                    
    6962           0 :             "xyz0="<<xyz0[2]<<
    6963           0 :             "xyzz1="<<xyz1[2]<<
    6964           0 :             "z0="<<z0[i0]<<
    6965           0 :             "z1="<<z0[i1]<<
    6966           0 :             "radius="<<radiusbest<<
    6967           0 :             "deltabest="<<deltabest<< 
    6968           0 :             "phase0="<<phase[ibest][0]<<
    6969           0 :             "phase1="<<phase[ibest][1]<<
    6970             :             "\n";               
    6971           0 :         }
    6972          22 :       }
    6973         160 :     }
    6974          32 :   }
    6975             :   //
    6976             :   //  Finf kinks loop
    6977             :   // 
    6978             :   //
    6979         552 :   for (Int_t i =0;i<nentries;i++){
    6980         268 :     if (sign[i]==0) continue;
    6981         296 :     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
    6982         148 :     if (track0==0) {
    6983           0 :       AliInfo("seed==0");
    6984           0 :       continue;
    6985             :     }
    6986         148 :     ntracks++;
    6987             :     //
    6988             :     Double_t cradius0 = 40*40;
    6989             :     Double_t cradius1 = 270*270;
    6990             :     Double_t cdist1=8.;
    6991             :     Double_t cdist2=8.;
    6992             :     Double_t cdist3=0.55; 
    6993         296 :     AliHelix* hlxi = (AliHelix*)helixes[i];
    6994        5720 :     for (Int_t j =i+1;j<nentries;j++){
    6995        2712 :       nall++;
    6996        2712 :       if (sign[j]*sign[i]<1) continue;
    6997         722 :       int ncltot = nclusters[i];
    6998         722 :       ncltot += nclusters[j];
    6999        1124 :       if ( ncltot>200) continue;
    7000         340 :       if ( ncltot<80) continue;
    7001         386 :       if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
    7002         534 :       if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
    7003             :       //AliTPCseed * track1 = (AliTPCseed*)array->At(j);  Double_t phase[2][2],radius[2];    
    7004         108 :       AliHelix* hlxj = (AliHelix*)helixes[j];
    7005          54 :       Int_t npoints = hlxi->GetRPHIintersections(*hlxj, phase, radius,20);
    7006          54 :       if (npoints<1) continue;
    7007             :       // cuts on radius      
    7008         108 :       if (npoints==1){
    7009         114 :         if (radius[0]<cradius0||radius[0]>cradius1) continue;
    7010             :       }
    7011             :       else{
    7012          70 :         if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
    7013             :       }
    7014             :       //      
    7015          20 :       Double_t delta1=10000,delta2=10000;
    7016             :       // cuts on the intersection radius
    7017          20 :       hlxi->LinearDCA(*hlxj,phase[0][0],phase[0][1],radius[0],delta1);
    7018          20 :       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
    7019          20 :       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
    7020          20 :       if (npoints==2){ 
    7021          16 :         hlxi->LinearDCA(*hlxj,phase[1][0],phase[1][1],radius[1],delta2);
    7022          16 :         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
    7023          16 :         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex   
    7024             :       }
    7025             :       //
    7026          20 :       Double_t distance1 = TMath::Min(delta1,delta2);
    7027          30 :       if (distance1>cdist1) continue;  // cut on DCA linear approximation
    7028             :       //
    7029          10 :       npoints = hlxi->GetRPHIintersections(*hlxj, phase, radius,20);
    7030          10 :       hlxi->ParabolicDCA(*hlxj,phase[0][0],phase[0][1],radius[0],delta1);
    7031          10 :       if (radius[0]<20&&delta1<1) continue; //intersection at vertex
    7032          10 :       if (radius[0]<10&&delta1<3) continue; //intersection at vertex
    7033             :       //
    7034          10 :       if (npoints==2){ 
    7035           8 :         hlxi->ParabolicDCA(*hlxj,phase[1][0],phase[1][1],radius[1],delta2);  
    7036           8 :         if (radius[1]<20&&delta2<1) continue;  //intersection at vertex
    7037           8 :         if (radius[1]<10&&delta2<3) continue;  //intersection at vertex   
    7038             :       }            
    7039          10 :       distance1 = TMath::Min(delta1,delta2);
    7040             :       Float_t rkink =0;
    7041          10 :       if (delta1<delta2){
    7042           8 :         rkink = TMath::Sqrt(radius[0]);
    7043           8 :       }
    7044             :       else{
    7045           2 :         rkink = TMath::Sqrt(radius[1]);
    7046             :       }
    7047          10 :       if (distance1>cdist2) continue;
    7048             :       //
    7049             :       //
    7050          20 :       AliTPCseed * track1 = (AliTPCseed*)array->At(j);
    7051             :       //
    7052             :       //
    7053          10 :       Int_t row0 = GetRowNumber(rkink); 
    7054          12 :       if (row0<10)  continue;
    7055           8 :       if (row0>150) continue;
    7056             :       //
    7057             :       //
    7058             :       Float_t dens00=-1,dens01=-1;
    7059             :       Float_t dens10=-1,dens11=-1;
    7060             :       //
    7061           8 :       Int_t found,foundable;//,ishared;
    7062             :       //RS Seed don't keep their cluster pointers, cache cluster usage stat. for fast evaluation
    7063             :       // FillSeedClusterStatCache(track0); // RS: Use this slow method only if sharing stat. is needed and used
    7064             :       //
    7065             :       //GetCachedSeedClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE); // RS make sure FillSeedClusterStatCache is called
    7066             :       //RS track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
    7067           8 :       track0->GetClusterStatistic(0,row0-5, found, foundable);
    7068          16 :       if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
    7069             :       //
    7070             :       //GetCachedSeedClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE); // RS make sure FillSeedClusterStatCache is called
    7071             :       //RS track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
    7072           8 :       track0->GetClusterStatistic(row0+5,155, found, foundable);
    7073          16 :       if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
    7074             :       //
    7075             :       //
    7076             :       //RS Seed don't keep their cluster pointers, cache cluster usage stat. for fast evaluation
    7077             :       // FillSeedClusterStatCache(track1); // RS: Use this slow method only if sharing stat. is needed and used
    7078             :       //
    7079             :       //GetCachedSeedClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE); // RS make sure FillSeedClusterStatCache is called
    7080             :       //RS track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
    7081           8 :       track1->GetClusterStatistic(0,row0-5, found, foundable);
    7082          16 :       if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
    7083             :       //
    7084             :       //GetCachedSeedClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE); // RS make sure FillSeedClusterStatCache is called
    7085             :       //RS track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
    7086           8 :       track1->GetClusterStatistic(row0+5,155, found, foundable);
    7087          16 :       if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
    7088             :       //
    7089           8 :       if (dens00<dens10 && dens01<dens11) continue;
    7090          18 :       if (dens00>dens10 && dens01>dens11) continue;
    7091           6 :       if (TMath::Max(dens00,dens10)<0.1)  continue;
    7092           6 :       if (TMath::Max(dens01,dens11)<0.3)  continue;
    7093             :       //
    7094           6 :       if (TMath::Min(dens00,dens10)>0.6)  continue;
    7095           8 :       if (TMath::Min(dens01,dens11)>0.6)  continue;
    7096             : 
    7097             :       //
    7098             :       AliTPCseed * ktrack0, *ktrack1;
    7099           4 :       if (dens00>dens10){
    7100             :         ktrack0 = track0;
    7101             :         ktrack1 = track1;
    7102           4 :       }
    7103             :       else{
    7104             :         ktrack0 = track1;
    7105             :         ktrack1 = track0;
    7106             :       }
    7107           8 :       if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
    7108           4 :       AliExternalTrackParam paramm(*ktrack0);
    7109           4 :       AliExternalTrackParam paramd(*ktrack1);
    7110          20 :       if (row0>60&&ktrack1->GetReference().GetX()>90.)new (&paramd) AliExternalTrackParam(ktrack1->GetReference()); 
    7111             :       //
    7112             :       //
    7113           4 :       kink->SetMother(paramm);
    7114           4 :       kink->SetDaughter(paramd);
    7115           4 :       kink->Update();
    7116             : 
    7117           4 :       Float_t x[3] = { static_cast<Float_t>(kink->GetPosition()[0]),static_cast<Float_t>(kink->GetPosition()[1]),static_cast<Float_t>(kink->GetPosition()[2])};
    7118           4 :       Int_t index[4];
    7119           4 :       fkParam->Transform0to1(x,index);
    7120           4 :       fkParam->Transform1to2(x,index);
    7121           4 :       row0 = GetRowNumber(x[0]); 
    7122             : 
    7123           4 :       if (kink->GetR()<100) continue;
    7124           4 :       if (kink->GetR()>240) continue;
    7125           8 :       if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue;  //out of fiducial volume
    7126           4 :       if (kink->GetDistance()>cdist3) continue;
    7127           4 :       Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1];  // rough direction estimate
    7128           4 :       if (dird<0) continue;
    7129             : 
    7130           4 :       Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1];  // rough direction estimate
    7131           4 :       if (dirm<0) continue;
    7132           4 :       Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
    7133           4 :       if (mpt<0.2) continue;
    7134             : 
    7135           4 :       if (mpt<1){
    7136             :         //for high momenta momentum not defined well in first iteration
    7137           8 :         Double_t qt   =  TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
    7138           4 :         if (qt>0.35) continue; 
    7139           4 :       }
    7140             :       
    7141           8 :       kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
    7142           8 :       kink->SetLabel(CookLabel(ktrack1,0.4,row0,kMaxRow),1);
    7143           4 :       if (dens00>dens10){
    7144           4 :         kink->SetTPCDensity(dens00,0,0);
    7145           4 :         kink->SetTPCDensity(dens01,0,1);
    7146           4 :         kink->SetTPCDensity(dens10,1,0);
    7147           4 :         kink->SetTPCDensity(dens11,1,1);
    7148           4 :         kink->SetIndex(i,0);
    7149           4 :         kink->SetIndex(j,1);
    7150           4 :       }
    7151             :       else{
    7152           0 :         kink->SetTPCDensity(dens10,0,0);
    7153           0 :         kink->SetTPCDensity(dens11,0,1);
    7154           0 :         kink->SetTPCDensity(dens00,1,0);
    7155           0 :         kink->SetTPCDensity(dens01,1,1);
    7156           0 :         kink->SetIndex(j,0);
    7157           0 :         kink->SetIndex(i,1);
    7158             :       }
    7159             : 
    7160           4 :       if (mpt<1||kink->GetAngle(2)>0.1){
    7161             :         //      angle and densities  not defined yet
    7162           8 :         if (kink->GetTPCDensityFactor()<0.8) continue;
    7163           8 :         if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
    7164           8 :         if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
    7165           4 :         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
    7166           4 :         if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
    7167             : 
    7168           8 :         Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
    7169           8 :         criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
    7170           4 :         criticalangle= 3*TMath::Sqrt(criticalangle);
    7171           6 :         if (criticalangle>0.02) criticalangle=0.02;
    7172           8 :         if (kink->GetAngle(2)<criticalangle) continue;
    7173           0 :       }
    7174             :       //
    7175           0 :       Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2)));  // overlap region defined
    7176             :       Float_t shapesum =0;
    7177             :       Float_t sum = 0;
    7178           0 :       for ( Int_t row = row0-drow; row<row0+drow;row++){
    7179           0 :         if (row<0) continue;
    7180           0 :         if (row>155) continue;
    7181             :         //RS if (ktrack0->GetClusterPointer(row)) {
    7182           0 :         if (ktrack0->GetClusterIndex2(row)>=0) {
    7183           0 :           const AliTPCTrackerPoints::Point *point = ktrack0->GetTrackPoint(row);
    7184           0 :           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
    7185           0 :           sum++;
    7186           0 :         }
    7187             :         //RS if (ktrack1->GetClusterPointer(row)){
    7188           0 :         if (ktrack1->GetClusterIndex2(row)>=0) {
    7189           0 :           const AliTPCTrackerPoints::Point *point =ktrack1->GetTrackPoint(row);
    7190           0 :           shapesum+=point->GetSigmaY()+point->GetSigmaZ();
    7191           0 :           sum++;
    7192           0 :         }       
    7193             :       }
    7194           0 :       if (sum<4){
    7195           0 :         kink->SetShapeFactor(-1.);
    7196           0 :       }
    7197             :       else{
    7198           0 :         kink->SetShapeFactor(shapesum/sum);
    7199             :       }      
    7200             :       //      esd->AddKink(kink);
    7201             :       //
    7202             :       //      kink->SetMother(paramm);
    7203             :       //kink->SetDaughter(paramd);
    7204             :       
    7205           0 :       Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
    7206           0 :       chi2P2*=chi2P2;
    7207           0 :       chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
    7208           0 :       Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
    7209           0 :       chi2P3*=chi2P3;
    7210           0 :       chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
    7211             :       //
    7212           0 :       if ((AliTPCReconstructor::StreamLevel()&kStreamFindKinks)>0) {   // flag: stream track infroamtion in the FindKinks method
    7213           0 :         (*fDebugStreamer)<<"kinkLpt"<<
    7214           0 :           "chi2P2="<<chi2P2<<
    7215           0 :           "chi2P3="<<chi2P3<<
    7216           0 :           "p0.="<<&paramm<<
    7217           0 :           "p1.="<<&paramd<<
    7218           0 :           "k.="<<kink<<
    7219             :           "\n";
    7220             :       }
    7221           0 :       if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
    7222           0 :         continue;
    7223             :       }
    7224             :       //
    7225           0 :       kinks.AddLast(kink);
    7226           0 :       kink = new AliKink;
    7227           0 :       ncandidates++;
    7228          32 :     }
    7229         148 :   }
    7230             :   //
    7231             :   // sort the kinks according quality - and refit them towards vertex
    7232             :   //
    7233           8 :   Int_t       nkinks    = kinks.GetEntriesFast();
    7234           8 :   Float_t    quality[nkinks];
    7235           8 :   Int_t      indexes[nkinks];
    7236           8 :   AliTPCseed *mothers[nkinks];
    7237           8 :   AliTPCseed *daughters[nkinks];
    7238           8 :   memset(mothers,0,nkinks*sizeof(AliTPCseed*));
    7239           8 :   memset(daughters,0,nkinks*sizeof(AliTPCseed*));
    7240             :   //
    7241             :   //
    7242          16 :   for (Int_t i=0;i<nkinks;i++){
    7243           0 :     quality[i] =100000;
    7244           0 :     AliKink *kinkl = (AliKink*)kinks.At(i);
    7245             :     //
    7246             :     // refit kinks towards vertex
    7247             :     // 
    7248           0 :     Int_t index0 = kinkl->GetIndex(0);
    7249           0 :     Int_t index1 = kinkl->GetIndex(1);
    7250           0 :     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
    7251           0 :     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
    7252             :     //
    7253           0 :     Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
    7254             :     //
    7255             :     // Refit Kink under if too small angle
    7256             :     //
    7257           0 :     if (kinkl->GetAngle(2)<0.05){
    7258             :       //
    7259             :       // RS: if possible, remove kink before reseeding
    7260           0 :       if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
    7261           0 :         delete kinks.RemoveAt(i);
    7262           0 :         continue;
    7263             :       }
    7264             :       //
    7265           0 :       kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
    7266           0 :       Int_t row0 = kinkl->GetTPCRow0();
    7267           0 :       Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
    7268             :       //
    7269           0 :       Int_t last  = row0-drow;
    7270           0 :       if (last<40) last=40;
    7271           0 :       if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
    7272           0 :       AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
    7273             :       //
    7274           0 :       Int_t first = row0+drow;
    7275           0 :       if (first>130) first=130;
    7276           0 :       if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
    7277           0 :       AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
    7278             :       //
    7279           0 :       if (seed0 && seed1) {
    7280           0 :         kinkl->SetStatus(1,8);
    7281           0 :         if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
    7282           0 :         row0 = GetRowNumber(kinkl->GetR());
    7283           0 :         sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
    7284           0 :         mothers[i]   = seed0;
    7285           0 :         daughters[i] = seed1;
    7286             :       }
    7287             :       else {
    7288           0 :         delete kinks.RemoveAt(i);
    7289           0 :         if (seed0) MarkSeedFree( seed0 );
    7290           0 :         if (seed1) MarkSeedFree( seed1 );
    7291           0 :         continue;
    7292             :       }
    7293           0 :     }
    7294             :     //
    7295           0 :     if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.);  //the longest -clossest will win
    7296           0 :   }
    7297           8 :   TMath::Sort(nkinks,quality,indexes,kFALSE);
    7298             :   //
    7299             :   //remove double find kinks
    7300             :   //
    7301          16 :   for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
    7302           0 :     AliKink * kink0 = (AliKink*) kinks.At(indexes[ikink0]);
    7303           0 :     if (!kink0) continue;
    7304             :     //
    7305           0 :     for (Int_t ikink1=0;ikink1<ikink0;ikink1++){ 
    7306           0 :       kink0 = (AliKink*) kinks.At(indexes[ikink0]);
    7307           0 :       if (!kink0) continue;
    7308           0 :       AliKink * kink1 = (AliKink*) kinks.At(indexes[ikink1]);
    7309           0 :       if (!kink1) continue;
    7310             :       // if not close kink continue
    7311           0 :       if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
    7312           0 :       if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
    7313           0 :       if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
    7314             :       //
    7315           0 :       AliTPCseed &mother0   =  mothers[indexes[ikink0]]   ? *mothers[indexes[ikink0]]   : *((AliTPCseed*)array->At(kink0->GetIndex(0)));
    7316           0 :       AliTPCseed &daughter0 =  daughters[indexes[ikink0]] ? *daughters[indexes[ikink0]] : *((AliTPCseed*)array->At(kink0->GetIndex(1)));
    7317           0 :       AliTPCseed &mother1   =  mothers[indexes[ikink1]]   ? *mothers[indexes[ikink1]]   : *((AliTPCseed*)array->At(kink1->GetIndex(0)));
    7318           0 :       AliTPCseed &daughter1 =  daughters[indexes[ikink1]] ? *daughters[indexes[ikink1]] : *((AliTPCseed*)array->At(kink1->GetIndex(1)));
    7319             : 
    7320           0 :       Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
    7321             :       //
    7322             :       Int_t same  = 0;
    7323             :       Int_t both  = 0;
    7324             :       Int_t samem = 0;
    7325             :       Int_t bothm = 0;
    7326             :       Int_t samed = 0;
    7327             :       Int_t bothd = 0;
    7328             :       //
    7329           0 :       for (Int_t i=0;i<row0;i++){
    7330           0 :         if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
    7331           0 :           both++;
    7332           0 :           bothm++;
    7333           0 :           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
    7334           0 :             same++;
    7335           0 :             samem++;
    7336           0 :           }
    7337             :         }
    7338             :       }
    7339             : 
    7340           0 :       for (Int_t i=row0;i<158;i++){
    7341             :         //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug? 
    7342           0 :         if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
    7343           0 :           both++;
    7344           0 :           bothd++;
    7345           0 :           if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
    7346           0 :             same++;
    7347           0 :             samed++;
    7348           0 :           }
    7349             :         }
    7350             :       }
    7351           0 :       Float_t ratio = Float_t(same+1)/Float_t(both+1);
    7352           0 :       Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
    7353           0 :       Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
    7354           0 :       if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
    7355           0 :         Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
    7356           0 :         Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
    7357           0 :         if (sum1>sum0){
    7358           0 :           shared[kink0->GetIndex(0)]= kTRUE;
    7359           0 :           shared[kink0->GetIndex(1)]= kTRUE;   
    7360           0 :           delete kinks.RemoveAt(indexes[ikink0]);
    7361           0 :           break;
    7362             :         }
    7363             :         else{
    7364           0 :           shared[kink1->GetIndex(0)]= kTRUE;
    7365           0 :           shared[kink1->GetIndex(1)]= kTRUE;   
    7366           0 :           delete kinks.RemoveAt(indexes[ikink1]);
    7367             :         }
    7368           0 :       }
    7369           0 :     }
    7370           0 :   }
    7371             : 
    7372             : 
    7373          16 :   for (Int_t i=0;i<nkinks;i++){
    7374           0 :     AliKink * kinkl = (AliKink*) kinks.At(indexes[i]);
    7375           0 :     if (!kinkl) continue;
    7376           0 :     kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
    7377           0 :     Int_t index0 = kinkl->GetIndex(0);
    7378           0 :     Int_t index1 = kinkl->GetIndex(1);
    7379           0 :     if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
    7380           0 :     kinkl->SetMultiple(usage[index0],0);
    7381           0 :     kinkl->SetMultiple(usage[index1],1);
    7382           0 :     if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
    7383           0 :     if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
    7384           0 :     if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
    7385           0 :     if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
    7386             : 
    7387           0 :     AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
    7388           0 :     AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
    7389           0 :     if (!ktrack0 || !ktrack1) continue;
    7390           0 :     Int_t index = esd->AddKink(kinkl);
    7391             :     //
    7392             :     //
    7393           0 :     if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) {  //best kink
    7394           0 :       if ( (mothers[indexes[i]]) && daughters[indexes[i]] && 
    7395           0 :            mothers[indexes[i]]->GetNumberOfClusters()>20 &&  // where they reseeded?
    7396           0 :            daughters[indexes[i]]->GetNumberOfClusters()>20 && 
    7397           0 :           (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
    7398           0 :         *ktrack0 = *mothers[indexes[i]];
    7399           0 :         *ktrack1 = *daughters[indexes[i]];
    7400             :       }
    7401             :     }
    7402             :     //
    7403           0 :     ktrack0->SetKinkIndex(usage[index0],-(index+1));
    7404           0 :     ktrack1->SetKinkIndex(usage[index1], (index+1));
    7405           0 :     usage[index0]++;
    7406           0 :     usage[index1]++;
    7407           0 :   }
    7408             :   //
    7409             :   // Remove tracks corresponding to shared kink's
    7410             :   //
    7411         552 :   for (Int_t i=0;i<nentries;i++){
    7412         536 :     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
    7413         388 :     if (!track0) continue;
    7414         296 :     if (track0->GetKinkIndex(0)!=0) continue;
    7415         148 :     if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
    7416         148 :   }
    7417             : 
    7418             :   //
    7419             :   //
    7420           8 :   RemoveUsed2(array,0.5,0.4,30);
    7421           8 :   UnsignClusters();
    7422         552 :   for (Int_t i=0;i<nentries;i++){
    7423         536 :     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
    7424         402 :     if (!track0) continue;
    7425         134 :     track0->CookdEdx(0.02,0.6);
    7426         134 :     track0->CookPID();
    7427         134 :   }
    7428             :   //
    7429             :   // RS use stack allocation instead of the heap
    7430          16 :   AliTPCseed mother,daughter;
    7431           8 :   AliKink kinkl;
    7432             :   //
    7433         552 :   for (Int_t i=0;i<nentries;i++){
    7434         536 :     AliTPCseed * track0 = (AliTPCseed*)array->At(i);
    7435         400 :     if (!track0) continue;
    7436         352 :     if (track0->Pt()<1.4) continue;
    7437             :     //remove double high momenta tracks - overlapped with kink candidates
    7438             :     Int_t ishared=0;
    7439             :     Int_t all   =0;
    7440       17220 :     for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
    7441        8554 :       Int_t tpcindex = track0->GetClusterIndex2(icl);
    7442        9448 :       if (tpcindex<0) continue;
    7443        7660 :       AliTPCclusterMI *cl = GetClusterMI(tpcindex);
    7444        7660 :       all++;
    7445        7946 :       if (cl->IsUsed(10)) ishared++;
    7446        7660 :     }
    7447          56 :     if (Float_t(ishared+1)/Float_t(all+1)>0.5) {  
    7448           4 :       MarkSeedFree( array->RemoveAt(i) );
    7449           2 :       continue;
    7450             :     }
    7451             :     //
    7452         110 :     if (track0->GetKinkIndex(0)!=0) continue;
    7453         104 :     if (track0->GetNumberOfClusters()<80) continue;
    7454             : 
    7455             :     // AliTPCseed *pmother = new AliTPCseed(); // RS use stack allocation
    7456             :     // AliTPCseed *pdaughter = new AliTPCseed();
    7457             :     // AliKink *pkink = new AliKink;
    7458             :     //
    7459         104 :     if (CheckKinkPoint(track0,mother,daughter, kinkl)){
    7460          44 :       if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
    7461             :         //      delete pmother; // RS used stack allocation
    7462             :         //      delete pdaughter;
    7463             :         //      delete pkink;
    7464           4 :         continue;  //too short tracks
    7465             :       }
    7466          16 :       if (mother.Pt()<1.4) {
    7467             :         //      delete pmother; // RS used stack allocation
    7468             :         //      delete pdaughter;
    7469             :         //      delete pkink;
    7470           0 :         continue;
    7471             :       }
    7472           8 :       Int_t row0= kinkl.GetTPCRow0();
    7473          18 :       if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
    7474             :         //      delete pmother; // RS used stack allocation
    7475             :         //      delete pdaughter;
    7476             :         //      delete pkink;
    7477           4 :         continue;
    7478             :       }
    7479             :       //
    7480           4 :       Int_t index = esd->AddKink(&kinkl);      
    7481           4 :       mother.SetKinkIndex(0,-(index+1));
    7482           4 :       daughter.SetKinkIndex(0,index+1);
    7483           8 :       if (mother.GetNumberOfClusters()>50) {
    7484           8 :         MarkSeedFree( array->RemoveAt(i) );
    7485          12 :         AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
    7486           4 :         mtc->SetPoolID(fLastSeedID);
    7487           4 :         array->AddAt(mtc,i);
    7488           4 :       }
    7489             :       else{
    7490           0 :         AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
    7491           0 :         mtc->SetPoolID(fLastSeedID);
    7492           0 :         array->AddLast(mtc);
    7493             :       }
    7494          12 :       AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
    7495           4 :       dtc->SetPoolID(fLastSeedID);
    7496           4 :       array->AddLast(dtc);      
    7497         732 :       for (Int_t icl=0;icl<row0;icl++) {
    7498         362 :         Int_t tpcindex= mother.GetClusterIndex2(icl);
    7499         420 :         if (tpcindex<0) continue;
    7500         304 :         AliTPCclusterMI *cl = GetClusterMI(tpcindex);
    7501         608 :         if (cl) cl->Use(20);
    7502         304 :       }
    7503             :       //
    7504         548 :       for (Int_t icl=row0;icl<158;icl++) {
    7505         270 :         Int_t tpcindex= mother.GetClusterIndex2(icl);
    7506         404 :         if (tpcindex<0) continue;
    7507         136 :         AliTPCclusterMI *cl = GetClusterMI(tpcindex);
    7508         272 :         if (cl) cl->Use(20);
    7509         136 :       }
    7510             :       //
    7511           4 :     }
    7512             :     //delete pmother; // RS used stack allocation
    7513             :     //delete pdaughter;
    7514             :     //delete pkink;
    7515          44 :   }
    7516             : 
    7517          16 :   for (int i=nkinks;i--;) {
    7518           0 :     if (mothers[i]) MarkSeedFree( mothers[i] );
    7519           0 :     if (daughters[i]) MarkSeedFree( daughters[i] );
    7520             :   }
    7521             :   //  delete [] daughters;
    7522             :   //  delete [] mothers;
    7523             :   //
    7524             :   // RS: most of heap array are converted to stack arrays
    7525             :   //  delete [] dca;
    7526             :   //  delete []circular;
    7527             :   //  delete []shared;
    7528             :   //  delete []quality;
    7529             :   //  delete []indexes;
    7530             :   //
    7531          16 :   delete kink;
    7532             :   //  delete[]fim;
    7533             :   //  delete[] zm;
    7534             :   //  delete[] z0;
    7535             :   //  delete [] usage;
    7536             :   //  delete[] alpha;
    7537             :   //  delete[] nclusters;
    7538             :   //  delete[] sign;
    7539             :   // delete[] helixes;
    7540          16 :   if (fHelixPool) fHelixPool->Clear();
    7541           8 :   kinks.Delete();
    7542             :   //delete kinks;
    7543             : 
    7544          32 :   AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
    7545           8 :   timer.Print();
    7546           8 : }
    7547             : 
    7548             : Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
    7549             : {
    7550             :   //
    7551             :   // refit kink towards to the vertex
    7552             :   //
    7553             :   //
    7554           0 :   AliKink &kink=(AliKink &)knk;
    7555             : 
    7556           0 :   Int_t row0 = GetRowNumber(kink.GetR());
    7557           0 :   FollowProlongation(mother,0);
    7558           0 :   mother.Reset(kFALSE);
    7559             :   //
    7560           0 :   FollowProlongation(daughter,row0);
    7561           0 :   daughter.Reset(kFALSE);
    7562           0 :   FollowBackProlongation(daughter,158);
    7563           0 :   daughter.Reset(kFALSE);
    7564           0 :   Int_t first = TMath::Max(row0-20,30); 
    7565           0 :   Int_t last  = TMath::Min(row0+20,140);
    7566             :   //
    7567             :   const Int_t kNdiv =5;
    7568           0 :   AliTPCseed  param0[kNdiv];  // parameters along the track
    7569           0 :   AliTPCseed  param1[kNdiv];  // parameters along the track
    7570           0 :   AliKink     kinks[kNdiv];   // corresponding kink parameters
    7571             :   //
    7572           0 :   Int_t rows[kNdiv];
    7573           0 :   for (Int_t irow=0; irow<kNdiv;irow++){
    7574           0 :     rows[irow] = first +((last-first)*irow)/(kNdiv-1);
    7575             :   }
    7576             :   // store parameters along the track
    7577             :   //
    7578           0 :   for (Int_t irow=0;irow<kNdiv;irow++){
    7579           0 :     FollowBackProlongation(mother, rows[irow]);
    7580           0 :     FollowProlongation(daughter,rows[kNdiv-1-irow]);       
    7581           0 :     param0[irow] = mother;
    7582           0 :     param1[kNdiv-1-irow] = daughter;
    7583             :   }
    7584             :   //
    7585             :   // define kinks 
    7586           0 :   for (Int_t irow=0; irow<kNdiv-1;irow++){
    7587           0 :     if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
    7588           0 :     kinks[irow].SetMother(param0[irow]);
    7589           0 :     kinks[irow].SetDaughter(param1[irow]);
    7590           0 :     kinks[irow].Update();
    7591             :   }
    7592             :   //
    7593             :   // choose kink with best "quality"
    7594             :   Int_t index =-1;
    7595             :   Double_t mindist = 10000;
    7596           0 :   for (Int_t irow=0;irow<kNdiv;irow++){
    7597           0 :     if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
    7598           0 :     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
    7599           0 :     if (TMath::Abs(kinks[irow].GetR())<100.) continue;
    7600             :     //
    7601           0 :     Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
    7602           0 :     normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
    7603           0 :     if (normdist < mindist){
    7604             :       mindist = normdist;
    7605             :       index = irow;
    7606           0 :     }
    7607           0 :   }
    7608             :   //
    7609           0 :   if (index==-1) return 0;
    7610             :   //
    7611             :   //
    7612           0 :   param0[index].Reset(kTRUE);
    7613           0 :   FollowProlongation(param0[index],0);
    7614             :   //
    7615           0 :   mother = param0[index];
    7616           0 :   daughter = param1[index];  // daughter in vertex
    7617             :   //
    7618           0 :   kink.SetMother(mother);
    7619           0 :   kink.SetDaughter(daughter);
    7620           0 :   kink.Update();
    7621           0 :   kink.SetTPCRow0(GetRowNumber(kink.GetR()));
    7622           0 :   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
    7623           0 :   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
    7624           0 :   kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
    7625           0 :   kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),kMaxRow),1);
    7626           0 :   mother.SetLabel(kink.GetLabel(0));
    7627           0 :   daughter.SetLabel(kink.GetLabel(1));
    7628             : 
    7629           0 :   return 1;
    7630           0 : }
    7631             : 
    7632             : 
    7633             : void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
    7634             :   //
    7635             :   // update Kink quality information for mother after back propagation
    7636             :   //
    7637           8 :   if (seed->GetKinkIndex(0)>=0) return; 
    7638          16 :   for (Int_t ikink=0;ikink<3;ikink++){
    7639           8 :     Int_t index = seed->GetKinkIndex(ikink);
    7640          12 :     if (index>=0) break;
    7641           4 :     index = TMath::Abs(index)-1;
    7642           4 :     AliESDkink * kink = fEvent->GetKink(index);
    7643           4 :     kink->SetTPCDensity(-1,0,0);
    7644           4 :     kink->SetTPCDensity(1,0,1);
    7645             :     //
    7646           4 :     Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
    7647           4 :     if (row0<15) row0=15;
    7648             :     //
    7649           4 :     Int_t row1 = kink->GetTPCRow0() + 2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
    7650           4 :     if (row1>145) row1=145;
    7651             :     //
    7652           4 :     Int_t found,foundable;//,shared;
    7653             :     //GetSeedClusterStatistic(seed,0,row0, found, foundable,shared,kFALSE); //RS: seeds don't keep their clusters
    7654             :     //RS seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
    7655           4 :     seed->GetClusterStatistic(0,row0, found, foundable);
    7656           8 :     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
    7657             :     //
    7658             :     //GetSeedClusterStatistic(seed,row1,155, found, foundable,shared,kFALSE); //RS: seeds don't keep their clusters
    7659             :     //RS seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
    7660           4 :     seed->GetClusterStatistic(row1,155, found, foundable);
    7661           8 :     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
    7662           4 :   }
    7663             :     
    7664           4 : }
    7665             : 
    7666             : void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
    7667             :   //
    7668             :   // update Kink quality information for daughter after refit
    7669             :   //
    7670           8 :   if (seed->GetKinkIndex(0)<=0) return; 
    7671          16 :   for (Int_t ikink=0;ikink<3;ikink++){
    7672           8 :     Int_t index = seed->GetKinkIndex(ikink);
    7673          12 :     if (index<=0) break;
    7674           4 :     index = TMath::Abs(index)-1;
    7675           4 :     AliESDkink * kink = fEvent->GetKink(index);
    7676           4 :     kink->SetTPCDensity(-1,1,0);
    7677           4 :     kink->SetTPCDensity(-1,1,1);
    7678             :     //
    7679           4 :     Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
    7680           4 :     if (row0<15) row0=15;
    7681             :     //
    7682           4 :     Int_t row1 = kink->GetTPCRow0() +2 +  Int_t( 0.5/ (0.05+kink->GetAngle(2)));
    7683           4 :     if (row1>145) row1=145;
    7684             :     //
    7685           4 :     Int_t found,foundable;//,shared;
    7686             :     //GetSeedClusterStatistic(0,row0, found, foundable,shared,kFALS); //RS: seeds don't keep their clusters
    7687             :     //seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
    7688           4 :     seed->GetClusterStatistic(0,row0, found, foundable);
    7689           8 :     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
    7690             :     //
    7691             :     //GetSeedClusterStatistic(row1,155, found, foundable,shared,kFALSE); //RS: seeds don't keep their clusters
    7692             :     // seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
    7693           4 :     seed->GetClusterStatistic(row1,155, found, foundable);
    7694           8 :     if (foundable>5)   kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
    7695           4 :   }
    7696             :     
    7697           4 : }
    7698             : 
    7699             : 
    7700             : Int_t  AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
    7701             : {
    7702             :   //
    7703             :   // check kink point for given track
    7704             :   // if return value=0 kink point not found
    7705             :   // otherwise seed0 correspond to mother particle
    7706             :   //           seed1 correspond to daughter particle
    7707             :   //           kink  parameter of kink point
    7708         104 :   AliKink &kink=(AliKink &)knk;
    7709             : 
    7710          52 :   Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
    7711          52 :   Int_t first = seed->GetFirstPoint(); 
    7712          52 :   Int_t last  = seed->GetLastPoint();
    7713          52 :   if (last-first<20) return 0;          // shortest length - 2*30 = 60 pad-rows
    7714             : 
    7715             :   
    7716          52 :   AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE);  //middle of chamber
    7717          52 :   if (!seed1) return 0;
    7718          52 :   FollowProlongation(*seed1,seed->GetLastPoint()-20);
    7719          52 :   seed1->Reset(kTRUE);
    7720          52 :   FollowProlongation(*seed1,158);
    7721          52 :   seed1->Reset(kTRUE);  
    7722          52 :   last = seed1->GetLastPoint();
    7723             :   //
    7724          52 :   AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
    7725          52 :   seed0->SetPoolID(fLastSeedID);
    7726          52 :   seed0->Reset(kFALSE);
    7727          52 :   seed0->Reset();
    7728             :   //
    7729        2132 :   AliTPCseed  param0[20];  // parameters along the track
    7730        2132 :   AliTPCseed  param1[20];  // parameters along the track
    7731        2132 :   AliKink     kinks[20];   // corresponding kink parameters
    7732          52 :   Int_t rows[20];
    7733        2184 :   for (Int_t irow=0; irow<20;irow++){
    7734        1040 :     rows[irow] = first +((last-first)*irow)/19;
    7735             :   }
    7736             :   // store parameters along the track
    7737             :   //
    7738        2184 :   for (Int_t irow=0;irow<20;irow++){
    7739        1040 :     FollowBackProlongation(*seed0, rows[irow]);
    7740        1040 :     FollowProlongation(*seed1,rows[19-irow]);       
    7741        1040 :     param0[irow] = *seed0;
    7742        1040 :     param1[19-irow] = *seed1;
    7743             :   }
    7744             :   //
    7745             :   // define kinks 
    7746        2080 :   for (Int_t irow=0; irow<19;irow++){
    7747         988 :     kinks[irow].SetMother(param0[irow]);
    7748         988 :     kinks[irow].SetDaughter(param1[irow]);
    7749         988 :     kinks[irow].Update();
    7750             :   }
    7751             :   //
    7752             :   // choose kink with biggest change of angle
    7753             :   Int_t index =-1;
    7754             :   Double_t maxchange= 0;
    7755        1976 :   for (Int_t irow=1;irow<19;irow++){
    7756         936 :     if (TMath::Abs(kinks[irow].GetR())>240.) continue;
    7757         906 :     if (TMath::Abs(kinks[irow].GetR())<110.) continue;
    7758        1412 :     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
    7759         706 :     if ( quality > maxchange){
    7760             :       maxchange = quality;
    7761             :       index = irow;
    7762             :       //
    7763         258 :     }
    7764         706 :   }
    7765          52 :   MarkSeedFree( seed0 );
    7766          52 :   MarkSeedFree( seed1 );
    7767          52 :   if (index<0) return 0;
    7768             :   //
    7769          52 :   Int_t row0    = GetRowNumber(kinks[index].GetR());   //row 0 estimate
    7770         156 :   seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
    7771          52 :   seed0->SetPoolID(fLastSeedID);
    7772         156 :   seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
    7773          52 :   seed1->SetPoolID(fLastSeedID);
    7774          52 :   seed0->Reset(kFALSE);
    7775          52 :   seed1->Reset(kFALSE);
    7776          52 :   seed0->ResetCovariance(10.);
    7777          52 :   seed1->ResetCovariance(10.);
    7778          52 :   FollowProlongation(*seed0,0);
    7779          52 :   FollowBackProlongation(*seed1,158);
    7780          52 :   mother = *seed0; // backup mother at position 0
    7781          52 :   seed0->Reset(kFALSE);  
    7782          52 :   seed1->Reset(kFALSE);
    7783          52 :   seed0->ResetCovariance(10.);
    7784          52 :   seed1->ResetCovariance(10.);
    7785             :   //
    7786          52 :   first = TMath::Max(row0-20,0);
    7787          52 :   last  = TMath::Min(row0+20,158);
    7788             :   //
    7789        2184 :   for (Int_t irow=0; irow<20;irow++){
    7790        1040 :     rows[irow] = first +((last-first)*irow)/19;
    7791             :   }
    7792             :   // store parameters along the track
    7793             :   //
    7794        2184 :   for (Int_t irow=0;irow<20;irow++){
    7795        1040 :     FollowBackProlongation(*seed0, rows[irow]);
    7796        1040 :     FollowProlongation(*seed1,rows[19-irow]);       
    7797        1040 :     param0[irow] = *seed0;
    7798        1040 :     param1[19-irow] = *seed1;
    7799             :   }
    7800             :   //
    7801             :   // define kinks 
    7802        2080 :   for (Int_t irow=0; irow<19;irow++){
    7803         988 :     kinks[irow].SetMother(param0[irow]);
    7804         988 :     kinks[irow].SetDaughter(param1[irow]);
    7805             :     //    param0[irow].Dump();
    7806             :     //param1[irow].Dump();
    7807         988 :     kinks[irow].Update();
    7808             :   }
    7809             :   //
    7810             :   // choose kink with biggest change of angle
    7811             :   index =-1;
    7812             :   maxchange= 0;
    7813        2184 :   for (Int_t irow=0;irow<20;irow++){
    7814        1040 :     if (TMath::Abs(kinks[irow].GetR())>250.) continue;
    7815        1012 :     if (TMath::Abs(kinks[irow].GetR())<90.) continue;
    7816        1748 :     Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
    7817         874 :     if ( quality > maxchange){
    7818             :       maxchange = quality;
    7819             :       index = irow;
    7820             :       //
    7821         266 :     }
    7822         874 :   }
    7823             :   //
    7824             :   //
    7825         208 :   if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
    7826           0 :     MarkSeedFree( seed0 );
    7827           0 :     MarkSeedFree( seed1 );
    7828           0 :     return 0;
    7829             :   }
    7830             : 
    7831             :   //  Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
    7832             :   
    7833          52 :   kink.SetMother(param0[index]);
    7834          52 :   kink.SetDaughter(param1[index]);
    7835          52 :   kink.Update();
    7836             : 
    7837         156 :   Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
    7838          52 :   chi2P2*=chi2P2;
    7839          52 :   chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
    7840         156 :   Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
    7841          52 :   chi2P3*=chi2P3;
    7842          52 :   chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
    7843             :   //
    7844          52 :   if (AliTPCReconstructor::StreamLevel()&kStreamFindKinks) { // flag: stream track infroamtion in the FindKinks method
    7845           0 :     (*fDebugStreamer)<<"kinkHpt"<<
    7846           0 :       "chi2P2="<<chi2P2<<
    7847           0 :       "chi2P3="<<chi2P3<<
    7848           0 :       "p0.="<<&param0[index]<<
    7849           0 :       "p1.="<<&param1[index]<<
    7850           0 :       "k.="<<&kink<<
    7851             :       "\n";
    7852             :   }
    7853         104 :   if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
    7854          40 :     MarkSeedFree( seed0 );
    7855          40 :     MarkSeedFree( seed1 );
    7856          40 :     return 0; 
    7857             :   }
    7858             : 
    7859             : 
    7860          12 :   row0    = GetRowNumber(kink.GetR());   
    7861          12 :   kink.SetTPCRow0(row0);
    7862          24 :   kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
    7863          24 :   kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
    7864          12 :   kink.SetIndex(-10,0);
    7865          36 :   kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
    7866          24 :   kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
    7867          24 :   kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
    7868             :   //
    7869             :   //
    7870             :   //  new (&mother) AliTPCseed(param0[index]);
    7871          12 :   daughter = param1[index];
    7872          12 :   daughter.SetLabel(kink.GetLabel(1));  
    7873          12 :   param0[index].Reset(kTRUE);
    7874          12 :   FollowProlongation(param0[index],0);    
    7875          12 :   mother = param0[index];
    7876          12 :   mother.SetLabel(kink.GetLabel(0));
    7877          24 :   if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
    7878           0 :     mother=*seed;
    7879             :   }
    7880          12 :   MarkSeedFree( seed0 );
    7881          12 :   MarkSeedFree( seed1 );
    7882             :   //
    7883          12 :   return 1;
    7884        3432 : }
    7885             : 
    7886             : 
    7887             : 
    7888             : 
    7889             : AliTPCseed*  AliTPCtracker::ReSeed(AliTPCseed *t)
    7890             : {
    7891             :   //
    7892             :   // reseed - refit -  track
    7893             :   //
    7894             :   Int_t first = 0;
    7895             :   //  Int_t last  = fSectors->GetNRows()-1;
    7896             :   //
    7897           0 :   if (fSectors == fOuterSec){
    7898           0 :     first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
    7899             :     //last  = 
    7900           0 :   }
    7901             :   else
    7902           0 :     first = t->GetFirstPoint();
    7903             :   //
    7904           0 :   AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
    7905           0 :   FollowBackProlongation(*t,fSectors->GetNRows()-1);
    7906           0 :   t->Reset(kFALSE);
    7907           0 :   FollowProlongation(*t,first);
    7908           0 :   return seed;
    7909             : }
    7910             : 
    7911             : 
    7912             : 
    7913             : 
    7914             : 
    7915             : 
    7916             : 
    7917             : //_____________________________________________________________________________
    7918             : Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
    7919             :   //-----------------------------------------------------------------
    7920             :   // This function reades track seeds.
    7921             :   //-----------------------------------------------------------------
    7922           0 :   TDirectory *savedir=gDirectory; 
    7923             : 
    7924             :   TFile *in=(TFile*)inp;
    7925           0 :   if (!in->IsOpen()) {
    7926           0 :      cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
    7927           0 :      return 1;
    7928             :   }
    7929             : 
    7930           0 :   in->cd();
    7931           0 :   TTree *seedTree=(TTree*)in->Get("Seeds");
    7932           0 :   if (!seedTree) {
    7933           0 :      cerr<<"AliTPCtracker::ReadSeeds(): ";
    7934           0 :      cerr<<"can't get a tree with track seeds !\n";
    7935           0 :      return 2;
    7936             :   }
    7937           0 :   AliTPCtrack *seed=new AliTPCtrack; 
    7938           0 :   seedTree->SetBranchAddress("tracks",&seed);
    7939             :   
    7940           0 :   if (fSeeds==0) fSeeds=new TObjArray(15000);
    7941             : 
    7942           0 :   Int_t n=(Int_t)seedTree->GetEntries();
    7943           0 :   for (Int_t i=0; i<n; i++) {
    7944           0 :      seedTree->GetEvent(i);
    7945           0 :      AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
    7946           0 :      sdc->SetPoolID(fLastSeedID);
    7947           0 :      fSeeds->AddLast(sdc);
    7948             :   }
    7949             :   
    7950           0 :   delete seed; // RS: this seed is not from the pool, delete it !!!
    7951           0 :   delete seedTree; 
    7952           0 :   savedir->cd();
    7953             :   return 0;
    7954           0 : }
    7955             : 
    7956             : Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
    7957             : {
    7958             :   //
    7959             :   // clusters to tracks
    7960          22 :   if (fSeeds) DeleteSeeds();
    7961           2 :   else ResetSeedsPool();
    7962           8 :   fEvent = esd; 
    7963           8 :   fEventHLT = hltEvent;
    7964           8 :   fAccountDistortions = AliTPCReconstructor::GetRecoParam()->GetAccountDistortions();
    7965           8 :   if (AliTPCReconstructor::GetRecoParam()->GetUseOulierClusterFilter()) FilterOutlierClusters();  
    7966           8 :   AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;  
    7967           8 :   transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
    7968           8 :   transform->SetCurrentTimeStamp( GetTimeStamp());
    7969           8 :   transform->SetCurrentRun( GetRunNumber());
    7970             : 
    7971             :   //transform->SetCurrentTimeStamp( esd->GetTimeStamp());
    7972             :   //transform->SetCurrentRun(esd->GetRunNumber());
    7973             :   //
    7974           8 :   if (AliTPCReconstructor::GetExtendedRoads()){
    7975           0 :     fClExtraRoadY = AliTPCReconstructor::GetExtendedRoads()[0];
    7976           0 :     fClExtraRoadZ = AliTPCReconstructor::GetExtendedRoads()[1];
    7977           0 :     AliInfoF("Additional errors for roads: Y:%f Z:%f",fClExtraRoadY,fClExtraRoadZ);
    7978           0 :   }
    7979          24 :   const Double_t *errCluster = (AliTPCReconstructor::GetSystematicErrorCluster()) ?  
    7980           0 :     AliTPCReconstructor::GetSystematicErrorCluster() : 
    7981           8 :     AliTPCReconstructor::GetRecoParam()->GetSystematicErrorCluster();
    7982             :   //
    7983           8 :   fExtraClErrY2 = errCluster[0]*errCluster[0];
    7984           8 :   fExtraClErrZ2 = errCluster[1]*errCluster[1];
    7985           8 :   fExtraClErrYZ2 = fExtraClErrY2 + fExtraClErrZ2;
    7986          40 :   AliInfoF("Additional errors for clusters: Y:%f Z:%f",errCluster[0],errCluster[1]);
    7987             :   //
    7988           8 :   if (AliTPCReconstructor::GetPrimaryDCACut()) {
    7989           0 :     fPrimaryDCAYCut = AliTPCReconstructor::GetPrimaryDCACut()[0];
    7990           0 :     fPrimaryDCAZCut = AliTPCReconstructor::GetPrimaryDCACut()[1];
    7991           0 :     fDisableSecondaries = kTRUE;
    7992           0 :     AliInfoF("Only primaries will be tracked with DCAY=%f and DCAZ=%f cuts",fPrimaryDCAYCut,fPrimaryDCAZCut);
    7993           0 :   }
    7994             :   //
    7995           8 :   Clusters2Tracks();
    7996           8 :   fEventHLT = 0;
    7997           8 :   if (!fSeeds) return 1;
    7998           8 :   FillESD(fSeeds);
    7999           8 :   if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0)  DumpClusters(0,fSeeds);
    8000           8 :   return 0;
    8001             :   //
    8002           8 : }
    8003             : 
    8004             : Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
    8005             : {
    8006             :   //
    8007             :   // clusters to tracks
    8008           0 :   return Clusters2TracksHLT( esd, 0);
    8009             : }
    8010             : 
    8011             : //_____________________________________________________________________________
    8012             : Int_t AliTPCtracker::Clusters2Tracks() {
    8013             :   //-----------------------------------------------------------------
    8014             :   // This is a track finder.
    8015             :   //-----------------------------------------------------------------
    8016          16 :   TDirectory *savedir=gDirectory; 
    8017           8 :   TStopwatch timer;
    8018             : 
    8019           8 :   fIteration = 0;
    8020          16 :   fSeeds = Tracking();
    8021             : 
    8022           8 :   if (fDebug>0){
    8023           0 :     Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
    8024             :   }
    8025             :   //activate again some tracks
    8026         864 :   for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
    8027         280 :     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
    8028         280 :     if (!pt) continue;    
    8029         280 :     Int_t nc=t.GetNumberOfClusters();
    8030         280 :     if (nc<20) {
    8031           0 :       MarkSeedFree( fSeeds->RemoveAt(i) );
    8032           0 :       continue;
    8033             :     } 
    8034         280 :     CookLabel(pt,0.1);
    8035         280 :     if (pt->GetRemoval()==10) {
    8036          12 :       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
    8037           6 :         pt->Desactivate(10);  // make track again active  // MvL: should be 0 ?
    8038             :       else{
    8039           0 :         pt->Desactivate(20);         
    8040           0 :         MarkSeedFree( fSeeds->RemoveAt(i) );
    8041             :       }
    8042             :     } 
    8043         280 :   }
    8044             :   //
    8045           8 :   RemoveUsed2(fSeeds,0.85,0.85,0);
    8046          24 :   if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
    8047             :   //FindCurling(fSeeds, fEvent,0);  
    8048           8 :   if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)  FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
    8049           8 :   RemoveUsed2(fSeeds,0.5,0.4,20);
    8050           8 :   FindSplitted(fSeeds, fEvent,0); // find multi found tracks
    8051           8 :   if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)  FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
    8052             : 
    8053             :  //  //
    8054             : //   // refit short tracks
    8055             : //   //
    8056           8 :   Int_t nseed=fSeeds->GetEntriesFast();
    8057             :   //
    8058             :   Int_t found = 0;
    8059         532 :   for (Int_t i=0; i<nseed; i++) {
    8060         258 :     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
    8061         380 :     if (!pt) continue;    
    8062         136 :     Int_t nc=t.GetNumberOfClusters();
    8063         136 :     if (nc<15) {
    8064           0 :       MarkSeedFree( fSeeds->RemoveAt(i) );
    8065           0 :       continue;
    8066             :     }
    8067         136 :     CookLabel(pt,0.1); //For comparison only
    8068             :     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
    8069         136 :     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
    8070         136 :       found++;      
    8071         136 :       if (fDebug>0) cerr<<found<<'\r';      
    8072         136 :       pt->SetLab2(i);
    8073         136 :     }
    8074             :     else
    8075           0 :       MarkSeedFree( fSeeds->RemoveAt(i) );
    8076         136 :   }
    8077             : 
    8078             :   
    8079             :   //RemoveOverlap(fSeeds,0.99,7,kTRUE);  
    8080           8 :   SignShared(fSeeds);  
    8081             :   //RemoveUsed(fSeeds,0.9,0.9,6);
    8082             :   // 
    8083           8 :   nseed=fSeeds->GetEntriesFast();
    8084             :   found = 0;
    8085         288 :   for (Int_t i=0; i<nseed; i++) {
    8086         136 :     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
    8087         136 :     if (!pt) continue;    
    8088         136 :     Int_t nc=t.GetNumberOfClusters();
    8089         136 :     if (nc<15) {
    8090           0 :       MarkSeedFree( fSeeds->RemoveAt(i) );
    8091           0 :       continue;
    8092             :     }
    8093         136 :     t.SetUniqueID(i);
    8094         136 :     t.CookdEdx(0.02,0.6);
    8095             :     //    CheckKinkPoint(&t,0.05);
    8096             :     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
    8097         136 :     if ((pt->IsActive() || (pt->GetRemoval()==10) )){
    8098         136 :       found++;
    8099         136 :       if (fDebug>0){
    8100           0 :         cerr<<found<<'\r';      
    8101             :       }
    8102         136 :       pt->SetLab2(i);
    8103         136 :     }
    8104             :     else
    8105           0 :       MarkSeedFree( fSeeds->RemoveAt(i) );
    8106             :     //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
    8107             :     //if (seed1){
    8108             :     //  FollowProlongation(*seed1,0);
    8109             :     //  Int_t n = seed1->GetNumberOfClusters();
    8110             :     //  printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
    8111             :     //  printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
    8112             :     //
    8113             :     //}
    8114             :     //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
    8115             :     
    8116         136 :   }
    8117             : 
    8118           8 :   SortTracks(fSeeds, 1);
    8119             :   
    8120             :   /*    
    8121             :   fIteration = 1;
    8122             :   PrepareForBackProlongation(fSeeds,5.);
    8123             :   PropagateBack(fSeeds);
    8124             :   printf("Time for back propagation: \t");timer.Print();timer.Start();
    8125             :   
    8126             :   fIteration = 2;
    8127             :   
    8128             :   PrepareForProlongation(fSeeds,5.);
    8129             :   PropagateForard2(fSeeds);
    8130             :    
    8131             :   printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
    8132             :   // RemoveUsed(fSeeds,0.7,0.7,6);
    8133             :   //RemoveOverlap(fSeeds,0.9,7,kTRUE);
    8134             :    
    8135             :   nseed=fSeeds->GetEntriesFast();
    8136             :   found = 0;
    8137             :   for (Int_t i=0; i<nseed; i++) {
    8138             :     AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;    
    8139             :     if (!pt) continue;    
    8140             :     Int_t nc=t.GetNumberOfClusters();
    8141             :     if (nc<15) {
    8142             :       MarkSeedFree( fSeeds->RemoveAt(i) );
    8143             :       continue;
    8144             :     }
    8145             :     t.CookdEdx(0.02,0.6);
    8146             :     //    CookLabel(pt,0.1); //For comparison only
    8147             :     //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
    8148             :     if ((pt->IsActive() || (pt->fRemoval==10) )){
    8149             :       cerr<<found++<<'\r';      
    8150             :     }
    8151             :     else
    8152             :       MarkSeedFree( fSeeds->RemoveAt(i) );
    8153             :     pt->fLab2 = i;
    8154             :   }
    8155             :   */
    8156             :  
    8157             :   //  fNTracks = found;
    8158           8 :   if (fDebug>0){
    8159           0 :     Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
    8160             :   }
    8161             :   //
    8162             :   //  cerr<<"Number of found tracks : "<<"\t"<<found<<endl;  
    8163           8 :   Info("Clusters2Tracks","Number of found tracks %d",found);  
    8164           8 :   savedir->cd();
    8165             :   //  UnloadClusters();
    8166             :   //  
    8167             :   return 0;
    8168           8 : }
    8169             : 
    8170             : void AliTPCtracker::Tracking(TObjArray * arr)
    8171             : {
    8172             :   //
    8173             :   // tracking of the seeds
    8174             :   //
    8175        1392 :   fSectors = fOuterSec;
    8176         696 :   ParallelTracking(arr,150,63);
    8177         696 :   fSectors = fOuterSec;
    8178         696 :   ParallelTracking(arr,63,0);
    8179             : 
    8180         696 : }
    8181             : 
    8182             : TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
    8183             : {
    8184             :   //
    8185             :   //
    8186             :   //tracking routine
    8187        1398 :   static TObjArray arrTracks;
    8188             :   TObjArray * arr = &arrTracks;
    8189             :   // 
    8190             :   //  AliInfoF(">> %d | s:%d i1:%d i2:%d dy:%f dsec:%d",arr->GetEntriesFast(),seedtype,i1,i2,dy,dsec); // RSTMP
    8191             : 
    8192             : 
    8193         696 :   fSectors = fOuterSec;
    8194         696 :   TStopwatch timer;
    8195         696 :   timer.Start();
    8196       26448 :   for (Int_t sec=0;sec<fkNOS;sec++){
    8197       25056 :     if (fAccountDistortions) {
    8198       12528 :       if (seedtype==3) MakeSeeds3Dist(arr,sec,i1,i2,cuts,dy, dsec);                  
    8199           0 :       if (seedtype==4) MakeSeeds5Dist(arr,sec,i1,i2,cuts,dy);    
    8200           0 :       if (seedtype==2) MakeSeeds2Dist(arr,sec,i1,i2,cuts,dy); //RS
    8201             :     }
    8202             :     else {
    8203       18720 :       if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);              
    8204       18864 :       if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);    
    8205       12528 :       if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy); //RS
    8206             :     }
    8207             :     //
    8208             :   }
    8209         696 :   if (fDebug>0){
    8210           0 :     Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
    8211           0 :     timer.Print();
    8212           0 :     timer.Start();
    8213             :   }
    8214         696 :   Tracking(arr);  
    8215         696 :   if (fDebug>0){
    8216           0 :     timer.Print();
    8217             :   }
    8218             :   //  AliInfoF("<< %d | s:%d i1:%d i2:%d dy:%f dsec:%d",arr->GetEntriesFast(),seedtype,i1,i2,dy,dsec); // RSTMP
    8219             :   return arr;
    8220         696 : }
    8221             : 
    8222             : TObjArray * AliTPCtracker::Tracking()
    8223             : {
    8224             :   // tracking
    8225             :   //
    8226          16 :   if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
    8227           8 :   TStopwatch timer;
    8228           8 :   timer.Start();
    8229           8 :   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
    8230             : 
    8231           8 :   TObjArray * seeds = fSeeds;
    8232          14 :   if (!seeds) seeds = new TObjArray;
    8233           6 :   else seeds->Clear();
    8234           8 :   TObjArray * arr=0;
    8235          16 :   Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
    8236          16 :   Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
    8237          16 :   Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
    8238             :   
    8239             :   Int_t gap =20;
    8240           8 :   Float_t cuts[4];
    8241           8 :   cuts[0] = 0.002;
    8242           8 :   cuts[1] = 1.5;
    8243           8 :   cuts[2] = 3.;
    8244           8 :   cuts[3] = 3.;
    8245             :   Float_t fnumber  = 3.0;
    8246             :   Float_t fdensity = 3.0;
    8247             : 
    8248             :   // make HLT seeds
    8249          16 :   if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
    8250           0 :     arr = MakeSeedsHLT( fEventHLT );
    8251           0 :     if( arr ){
    8252           0 :       SumTracks(seeds,arr);     
    8253           0 :       delete arr;
    8254           0 :       arr=0;
    8255             :       //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
    8256             :       //SignClusters(seeds,fnumber,fdensity);    
    8257           0 :     }
    8258             :   }
    8259             :   
    8260             :   //  
    8261             :   //find primaries  
    8262           8 :   cuts[0]=0.0066;
    8263          64 :   for (Int_t delta = 0; delta<18; delta+=gapPrim){
    8264             :     //
    8265          24 :     cuts[0]=0.0070;
    8266          24 :     cuts[1] = 1.5;
    8267          48 :     arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
    8268          24 :     SumTracks(seeds,arr);   
    8269          24 :     SignClusters(seeds,fnumber,fdensity); 
    8270             :     //
    8271         144 :     for (Int_t i=2;i<6;i+=2){
    8272             :       // seed high pt tracks
    8273          48 :       cuts[0]=0.0022;
    8274          48 :       cuts[1]=0.3;
    8275          96 :       arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
    8276          48 :       SumTracks(seeds,arr);   
    8277          48 :       SignClusters(seeds,fnumber,fdensity);        
    8278             :     }
    8279             :   }
    8280             :   fnumber  = 4;
    8281             :   fdensity = 4.;
    8282             :   //  RemoveUsed(seeds,0.9,0.9,1);
    8283             :   //  UnsignClusters();
    8284             :   //  SignClusters(seeds,fnumber,fdensity);    
    8285             : 
    8286             :   //find primaries  
    8287           8 :   cuts[0]=0.0077;
    8288         288 :   for (Int_t delta = 20; delta<120; delta+=gapPrim){
    8289             :     //
    8290             :     // seed high pt tracks
    8291         136 :     cuts[0]=0.0060;
    8292         136 :     cuts[1]=0.3;
    8293         136 :     cuts[2]=6.;
    8294         272 :     arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
    8295         136 :     SumTracks(seeds,arr);   
    8296         136 :     SignClusters(seeds,fnumber,fdensity);            
    8297             : 
    8298         136 :     cuts[0]=0.003;
    8299         136 :     cuts[1]=0.3;
    8300         136 :     cuts[2]=6.;
    8301         272 :     arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
    8302         136 :     SumTracks(seeds,arr);   
    8303         136 :     SignClusters(seeds,fnumber,fdensity);            
    8304             :   }
    8305             : 
    8306           8 :   cuts[0] = 0.01;
    8307           8 :   cuts[1] = 2.0;
    8308           8 :   cuts[2] = 3.;
    8309           8 :   cuts[3] = 2.0;
    8310             :   fnumber  = 2.;
    8311             :   fdensity = 2.;
    8312             :   
    8313           8 :   if (fDebug>0){
    8314           0 :     Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
    8315           0 :     timer.Print();
    8316           0 :     timer.Start();
    8317             :   }
    8318             :   //  RemoveUsed(seeds,0.75,0.75,1);
    8319             :   //UnsignClusters();
    8320             :   //SignClusters(seeds,fnumber,fdensity);
    8321             :   
    8322           8 :   if (fDisableSecondaries) return seeds;
    8323             : 
    8324             :   // find secondaries
    8325             : 
    8326           8 :   cuts[0] = 0.3;
    8327           8 :   cuts[1] = 1.5;
    8328           8 :   cuts[2] = 3.;
    8329           8 :   cuts[3] = 1.5;
    8330             : 
    8331          16 :   arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
    8332           8 :   SumTracks(seeds,arr);   
    8333           8 :   SignClusters(seeds,fnumber,fdensity);   
    8334             :   //
    8335          16 :   arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
    8336           8 :   SumTracks(seeds,arr);   
    8337           8 :   SignClusters(seeds,fnumber,fdensity);   
    8338             :   //
    8339          16 :   arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
    8340           8 :   SumTracks(seeds,arr);   
    8341           8 :   SignClusters(seeds,fnumber,fdensity);   
    8342             :   //
    8343          16 :   arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
    8344           8 :   SumTracks(seeds,arr);   
    8345           8 :   SignClusters(seeds,fnumber,fdensity);   
    8346             :   //
    8347          16 :   arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
    8348           8 :   SumTracks(seeds,arr);   
    8349           8 :   SignClusters(seeds,fnumber,fdensity);   
    8350             :   //
    8351             :   //
    8352          16 :   arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
    8353           8 :   SumTracks(seeds,arr);   
    8354           8 :   SignClusters(seeds,fnumber,fdensity);   
    8355             :   //
    8356             : 
    8357             : 
    8358          80 :   for (Int_t delta = 9; delta<30; delta+=gapSec){
    8359             :     //
    8360          32 :     cuts[0] = 0.3;
    8361          32 :     cuts[1] = 1.5;
    8362          32 :     cuts[2] = 3.;
    8363          32 :     cuts[3] = 1.5;
    8364          64 :     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
    8365          32 :     SumTracks(seeds,arr);   
    8366          32 :     SignClusters(seeds,fnumber,fdensity);   
    8367             :     //
    8368          64 :     arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
    8369          32 :     SumTracks(seeds,arr);   
    8370          32 :     SignClusters(seeds,fnumber,fdensity); 
    8371             :     //
    8372             :   } 
    8373             :   fnumber  = 1;
    8374             :   fdensity = 1;
    8375             :   //
    8376             :   // change cuts
    8377             :   fnumber  = 2.;
    8378             :   fdensity = 2.;
    8379           8 :   cuts[0]=0.0080;
    8380             : 
    8381             : 
    8382             :   // find secondaries
    8383         256 :   for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
    8384             :     //
    8385         120 :     cuts[0] = 0.3;
    8386         120 :     cuts[1] = 3.5;
    8387         120 :     cuts[2] = 3.;
    8388         120 :     cuts[3] = 3.5;
    8389         240 :     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
    8390         120 :     SumTracks(seeds,arr);   
    8391         120 :     SignClusters(seeds,fnumber,fdensity);   
    8392             :     //
    8393         240 :     arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
    8394         120 :     SumTracks(seeds,arr);   
    8395         120 :     SignClusters(seeds,fnumber,fdensity);   
    8396             :   }
    8397             :  
    8398           8 :   if (fDebug>0){
    8399           0 :     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
    8400           0 :     timer.Print();
    8401           0 :     timer.Start();
    8402             :   }
    8403             : 
    8404           8 :   return seeds;
    8405             :   //
    8406             :       
    8407          16 : }
    8408             : 
    8409             : 
    8410             : TObjArray * AliTPCtracker::TrackingSpecial()
    8411             : {
    8412             :   //
    8413             :   // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
    8414             :   // no primary vertex seeding tried
    8415             :   //
    8416           0 :   TStopwatch timer;
    8417           0 :   timer.Start();
    8418           0 :   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
    8419             : 
    8420           0 :   TObjArray * seeds = fSeeds;
    8421           0 :   if (!seeds) seeds = new TObjArray;
    8422           0 :   else seeds->Clear();
    8423           0 :   TObjArray * arr=0;
    8424             :   
    8425             :   Int_t   gap  = 15;
    8426           0 :   Float_t cuts[4];
    8427             :   Float_t fnumber  = 3.0;
    8428             :   Float_t fdensity = 3.0;
    8429             :   
    8430             :   // find secondaries
    8431           0 :   cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC();   // max curvature
    8432           0 :   cuts[1] = 3.5;    // max tan(phi) angle for seeding
    8433           0 :   cuts[2] = 3.;     // not used (cut on z primary vertex)     
    8434           0 :   cuts[3] = 3.5;    // max tan(theta) angle for seeding
    8435             : 
    8436           0 :   for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
    8437             :     //
    8438           0 :     arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
    8439           0 :     SumTracks(seeds,arr);   
    8440           0 :     SignClusters(seeds,fnumber,fdensity);   
    8441             :   } 
    8442             :  
    8443           0 :   if (fDebug>0){
    8444           0 :     Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
    8445           0 :     timer.Print();
    8446           0 :     timer.Start();
    8447             :   }
    8448             : 
    8449             :   return seeds;
    8450             :   //
    8451             :       
    8452           0 : }
    8453             : 
    8454             : 
    8455             : void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
    8456             : {
    8457             :   //
    8458             :   //sum tracks to common container
    8459             :   //remove suspicious tracks
    8460             :   // RS: Attention: supplied tracks come in the static array, don't delete them
    8461        1392 :   Int_t nseed = arr2->GetEntriesFast();
    8462        1988 :   for (Int_t i=0;i<nseed;i++){
    8463         298 :     AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);    
    8464         298 :     if (pt){
    8465             :       //
    8466             :       // remove tracks with too big curvature
    8467             :       //
    8468         298 :       if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
    8469           0 :         MarkSeedFree( arr2->RemoveAt(i) );
    8470           0 :         continue;
    8471             :       }
    8472             :        // REMOVE VERY SHORT  TRACKS
    8473         298 :       if (pt->GetNumberOfClusters()<20){ 
    8474          18 :         MarkSeedFree( arr2->RemoveAt(i) );
    8475          18 :         continue;
    8476             :       }// patch 28 fev06
    8477             :       // NORMAL ACTIVE TRACK
    8478         280 :       if (pt->IsActive()){
    8479         274 :         arr1->AddLast(arr2->RemoveAt(i));
    8480         274 :         continue;
    8481             :       }
    8482             :       //remove not usable tracks
    8483           6 :       if (pt->GetRemoval()!=10){
    8484           0 :         MarkSeedFree( arr2->RemoveAt(i) );
    8485           0 :         continue;
    8486             :       }
    8487             :      
    8488             :       // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
    8489           6 :       if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
    8490           6 :         arr1->AddLast(arr2->RemoveAt(i));
    8491             :       else{      
    8492           0 :         MarkSeedFree( arr2->RemoveAt(i) );
    8493             :       }
    8494             :     }
    8495           6 :   }
    8496             :   // delete arr2;  arr2 = 0; // RS: this is static array, don't delete it
    8497         696 : }
    8498             : 
    8499             : 
    8500             : 
    8501             : void  AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
    8502             : {
    8503             :   //
    8504             :   // try to track in parralel
    8505             : 
    8506        2784 :   Int_t nseed=arr->GetEntriesFast();
    8507             :   //prepare seeds for tracking
    8508        3976 :   for (Int_t i=0; i<nseed; i++) {
    8509         596 :     AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt; 
    8510         596 :     if (!pt) continue;
    8511         612 :     if (!t.IsActive()) continue;
    8512             :     // follow prolongation to the first layer
    8513        1160 :     if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )  
    8514           0 :       FollowProlongation(t, rfirst+1);
    8515         580 :   }
    8516             : 
    8517             : 
    8518             :   //
    8519      214368 :   for (Int_t nr=rfirst; nr>=rlast; nr--){ 
    8520      105792 :     if (nr<fInnerSec->GetNRows()) 
    8521       43848 :       fSectors = fInnerSec;
    8522             :     else
    8523       61944 :       fSectors = fOuterSec;
    8524             :     // make indexes with the cluster tracks for given       
    8525             : 
    8526             :     // find nearest cluster
    8527      302176 :     for (Int_t i=0; i<nseed; i++) {
    8528       45296 :       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;       
    8529       45296 :       if (!pt) continue;
    8530       45594 :       if (nr==80) pt->UpdateReference();
    8531       46952 :       if (!pt->IsActive()) continue;
    8532             :       //      if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
    8533       43640 :       if (pt->GetRelativeSector()>17) {
    8534           0 :         continue;
    8535             :       }
    8536       43640 :       UpdateClusters(t,nr);
    8537       43640 :     }
    8538             :     // prolonagate to the nearest cluster - if founded
    8539      302176 :     for (Int_t i=0; i<nseed; i++) {
    8540       45296 :       AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i); 
    8541       45296 :       if (!pt) continue;
    8542       46952 :       if (!pt->IsActive()) continue; 
    8543             :       // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
    8544       43640 :       if (pt->GetRelativeSector()>17) {
    8545           0 :         continue;
    8546             :       }
    8547       43640 :       FollowToNextCluster(*pt,nr);
    8548       43640 :     }
    8549             :   }    
    8550        1392 : }
    8551             : 
    8552             : void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
    8553             : {
    8554             :   //
    8555             :   //
    8556             :   // if we use TPC track itself we have to "update" covariance
    8557             :   //
    8558           0 :   Int_t nseed= arr->GetEntriesFast();
    8559           0 :   for (Int_t i=0;i<nseed;i++){
    8560           0 :     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
    8561           0 :     if (pt) {
    8562           0 :       pt->Modify(fac);
    8563             :       //
    8564             :       //rotate to current local system at first accepted  point    
    8565           0 :       Int_t index  = pt->GetClusterIndex2(pt->GetFirstPoint()); 
    8566           0 :       Int_t sec    = (index&0xff000000)>>24;
    8567           0 :       sec = sec%18;
    8568           0 :       Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
    8569           0 :       if (angle1>TMath::Pi()) 
    8570           0 :         angle1-=2.*TMath::Pi();
    8571           0 :       Float_t angle2 = pt->GetAlpha();
    8572             :       
    8573           0 :       if (TMath::Abs(angle1-angle2)>0.001){
    8574           0 :         if (!pt->Rotate(angle1-angle2)) return;
    8575             :         //angle2 = pt->GetAlpha();
    8576             :         //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
    8577             :         //if (pt->GetAlpha()<0) 
    8578             :         //  pt->fRelativeSector+=18;
    8579             :         //sec = pt->fRelativeSector;
    8580             :       }
    8581             :         
    8582           0 :     }
    8583             :     
    8584           0 :   }
    8585             : 
    8586             : 
    8587           0 : }
    8588             : void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
    8589             : {
    8590             :   //
    8591             :   //
    8592             :   // if we use TPC track itself we have to "update" covariance
    8593             :   //
    8594           0 :   Int_t nseed= arr->GetEntriesFast();
    8595           0 :   for (Int_t i=0;i<nseed;i++){
    8596           0 :     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
    8597           0 :     if (pt) {
    8598           0 :       pt->Modify(fac);
    8599           0 :       pt->SetFirstPoint(pt->GetLastPoint()); 
    8600           0 :     }
    8601             :     
    8602             :   }
    8603             : 
    8604             : 
    8605           0 : }
    8606             : 
    8607             : Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
    8608             : {
    8609             :   //
    8610             :   // make back propagation
    8611             :   //
    8612          16 :   Int_t nseed= arr->GetEntriesFast();
    8613         288 :   for (Int_t i=0;i<nseed;i++){
    8614         136 :     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
    8615         272 :     if (pt&& pt->GetKinkIndex(0)<=0) { 
    8616             :       //AliTPCseed *pt2 = new AliTPCseed(*pt);
    8617         132 :       fSectors = fInnerSec;
    8618             :       //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
    8619             :       //fSectors = fOuterSec;
    8620         132 :       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);     
    8621             :       //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
    8622             :       //        Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
    8623             :       //        FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
    8624             :       //}
    8625         132 :     }
    8626         272 :     if (pt&& pt->GetKinkIndex(0)>0) {
    8627           4 :       AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
    8628           4 :       pt->SetFirstPoint(kink->GetTPCRow0());
    8629           4 :       fSectors = fInnerSec;
    8630           4 :       FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);  
    8631           4 :     }
    8632         136 :     CookLabel(pt,0.3);
    8633             :   }
    8634           8 :   return 0;
    8635             : }
    8636             : 
    8637             : 
    8638             : Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
    8639             : {
    8640             :   //
    8641             :   // make forward propagation
    8642             :   //
    8643          16 :   Int_t nseed= arr->GetEntriesFast();
    8644             :   //
    8645         288 :   for (Int_t i=0;i<nseed;i++){
    8646         136 :     AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
    8647         136 :     if (pt) { 
    8648         136 :       FollowProlongation(*pt,0,1,1);
    8649         136 :       CookLabel(pt,0.3);
    8650         136 :     }
    8651             :     
    8652             :   }
    8653           8 :  return 0;
    8654             : }
    8655             : 
    8656             : 
    8657             : Int_t AliTPCtracker::PropagateForward()
    8658             : {
    8659             :   //
    8660             :   // propagate track forward
    8661             :   //UnsignClusters();
    8662           0 :   Int_t nseed = fSeeds->GetEntriesFast();
    8663           0 :   for (Int_t i=0;i<nseed;i++){
    8664           0 :     AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
    8665           0 :     if (pt){
    8666             :       AliTPCseed &t = *pt;
    8667           0 :       Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
    8668           0 :       if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();  
    8669           0 :       if (alpha < 0.            ) alpha += 2.*TMath::Pi();  
    8670           0 :       t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
    8671           0 :     }
    8672             :   }
    8673             :   
    8674           0 :   fSectors = fOuterSec;
    8675           0 :   ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
    8676           0 :   fSectors = fInnerSec;
    8677           0 :   ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
    8678           0 :   return 1;
    8679             : }
    8680             : 
    8681             : 
    8682             : 
    8683             : 
    8684             : 
    8685             : 
    8686             : Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
    8687             : {
    8688             :   //
    8689             :   // make back propagation, in between row0 and row1
    8690             :   //
    8691             :   
    8692           0 :   if (pt) { 
    8693           0 :     fSectors = fInnerSec;
    8694             :     Int_t  r1;
    8695             :     //
    8696           0 :     if (row1<fSectors->GetNRows()) 
    8697           0 :       r1 = row1;
    8698             :     else 
    8699           0 :       r1 = fSectors->GetNRows()-1;
    8700             : 
    8701           0 :     if (row0<fSectors->GetNRows()&& r1>0 )
    8702           0 :       FollowBackProlongation(*pt,r1);
    8703           0 :     if (row1<=fSectors->GetNRows())
    8704           0 :       return 0;
    8705             :     //
    8706           0 :     r1 = row1 - fSectors->GetNRows();
    8707           0 :     if (r1<=0) return 0;
    8708           0 :     if (r1>=fOuterSec->GetNRows()) return 0;
    8709           0 :     fSectors = fOuterSec;
    8710           0 :     return FollowBackProlongation(*pt,r1);
    8711             :   }        
    8712           0 :   return 0;
    8713           0 : }
    8714             : 
    8715             : 
    8716             : 
    8717             : 
    8718             : void  AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
    8719             : {
    8720             :   // gets cluster shape
    8721             :   // 
    8722      210964 :   AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
    8723      105482 :   Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
    8724      274784 :   Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
    8725      105482 :   Double_t angulary  = seed->GetSnp();
    8726             : 
    8727      105482 :   if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
    8728        2812 :     angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
    8729        2812 :   }
    8730             : 
    8731      105482 :   angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
    8732      105482 :   Double_t angularz  = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
    8733             :   
    8734      105482 :   Double_t sigmay =  clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
    8735      105482 :   Double_t sigmaz =  clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
    8736      105482 :   seed->SetCurrentSigmaY2(sigmay*sigmay);
    8737      105482 :   seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
    8738             :   // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
    8739             : //   //  Float_t padlength =  fkParam->GetPadPitchLength(seed->fSector);
    8740             : //   Float_t padlength =  GetPadPitchLength(row);
    8741             : //   //
    8742             : //   Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
    8743             : //   seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);  
    8744             : //   //
    8745             : //   Float_t sresz = fkParam->GetZSigma();
    8746             : //   seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
    8747             :   /*
    8748             :   Float_t wy = GetSigmaY(seed);
    8749             :   Float_t wz = GetSigmaZ(seed);
    8750             :   wy*=wy;
    8751             :   wz*=wz;
    8752             :   if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
    8753             :     printf("problem\n");
    8754             :   }
    8755             :   */
    8756      105482 : }
    8757             : 
    8758             : 
    8759             : 
    8760             : //__________________________________________________________________________
    8761             : void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
    8762             :   //--------------------------------------------------------------------
    8763             :   //This function "cooks" a track label. If label<0, this track is fake.
    8764             :   //--------------------------------------------------------------------
    8765             :   //  AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
    8766             :   //  if(!t){
    8767             :   //  printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
    8768             :   //  return;
    8769             :   //  }
    8770        1916 :   AliTPCseed * t = (AliTPCseed*)tk; // RS avoid slow dynamic cast
    8771             : 
    8772         958 :   Int_t noc=t->GetNumberOfClusters();
    8773         958 :   if (noc<10){
    8774             :     //printf("\nnot founded prolongation\n\n\n");
    8775             :     //t->Dump();
    8776           2 :     return ;
    8777             :   }
    8778         956 :   Int_t lb[kMaxRow];
    8779         956 :   Int_t mx[kMaxRow];
    8780         956 :   AliTPCclusterMI *clusters[kMaxRow];
    8781             :   //
    8782      305920 :   for (Int_t i=0;i<kMaxRow;i++) {
    8783      152004 :     clusters[i]=0;
    8784      152004 :     lb[i]=mx[i]=0;
    8785             :   }
    8786             : 
    8787             :   Int_t i;
    8788             :   Int_t current=0;
    8789      439790 :   for (i=0; i<kMaxRow && current<noc; i++) {
    8790             :      
    8791      145912 :      Int_t index=t->GetClusterIndex2(i);
    8792      174182 :      if (index<=0) continue; 
    8793      121040 :      if (index&0x8000) continue;
    8794             :      //     
    8795      114244 :      clusters[current++]=GetClusterMI(index);
    8796             :      // if (t->GetClusterPointer(i)){
    8797             :      //   clusters[current]=t->GetClusterPointer(i);     
    8798             :      //   current++;
    8799             :      // }
    8800      114244 :   }
    8801             :   noc = current;
    8802             : 
    8803             :   Int_t lab=123456789;
    8804      230400 :   for (i=0; i<noc; i++) {
    8805      114244 :     AliTPCclusterMI *c=clusters[i];
    8806      114244 :     if (!c) continue;
    8807      114244 :     lab=TMath::Abs(c->GetLabel(0));
    8808             :     Int_t j;
    8809      401895 :     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
    8810      114244 :     lb[j]=lab;
    8811      114244 :     (mx[j])++;
    8812      114244 :   }
    8813             : 
    8814             :   Int_t max=0;
    8815      345662 :   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
    8816             :     
    8817      230400 :   for (i=0; i<noc; i++) {
    8818      114244 :     AliTPCclusterMI *c=clusters[i]; 
    8819      114244 :     if (!c) continue;
    8820      167618 :     if (TMath::Abs(c->GetLabel(1)) == lab ||
    8821      114287 :         TMath::Abs(c->GetLabel(2)) == lab ) max++;
    8822      114244 :   }
    8823         956 :   if (noc<=0) { lab=-1; return;}
    8824         967 :   if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
    8825             : 
    8826             :   else {
    8827         945 :      Int_t tail=Int_t(0.10*noc);
    8828             :      max=0;
    8829             :      Int_t ind=0;
    8830       35499 :      for (i=1; i<kMaxRow&&ind<tail; i++) {
    8831             :        //       AliTPCclusterMI *c=clusters[noc-i];
    8832       10888 :        AliTPCclusterMI *c=clusters[i];
    8833       10888 :        if (!c) continue;
    8834       11218 :        if (lab == TMath::Abs(c->GetLabel(0)) ||
    8835         566 :            lab == TMath::Abs(c->GetLabel(1)) ||
    8836       10888 :            lab == TMath::Abs(c->GetLabel(2))) max++;
    8837       10888 :        ind++;
    8838       10888 :      }
    8839         955 :      if (max < Int_t(0.5*tail)) lab=-lab;
    8840             :   }
    8841             : 
    8842         956 :   t->SetLabel(lab);
    8843             : 
    8844             :   //  delete[] lb;
    8845             :   //delete[] mx;
    8846             :   //delete[] clusters;
    8847        2870 : }
    8848             : 
    8849             : 
    8850             : //__________________________________________________________________________
    8851             : Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
    8852             :   //--------------------------------------------------------------------
    8853             :   //This function "cooks" a track label. If label<0, this track is fake.
    8854             :   //--------------------------------------------------------------------
    8855          64 :   Int_t noc=t->GetNumberOfClusters();
    8856          32 :   if (noc<10){
    8857             :     //printf("\nnot founded prolongation\n\n\n");
    8858             :     //t->Dump();
    8859           0 :     return -1;
    8860             :   }
    8861          32 :   Int_t lb[kMaxRow];
    8862          32 :   Int_t mx[kMaxRow];
    8863          32 :   AliTPCclusterMI *clusters[kMaxRow];
    8864             :   //
    8865       10240 :   for (Int_t i=0;i<kMaxRow;i++) {
    8866        5088 :     clusters[i]=0;
    8867        5088 :     lb[i]=mx[i]=0;
    8868             :   }
    8869             : 
    8870             :   Int_t i;
    8871             :   Int_t current=0;
    8872       15236 :   for (i=0; i<kMaxRow && current<noc; i++) {
    8873        5054 :     if (i<first) continue;
    8874        3740 :     if (i>last)  continue;
    8875        2544 :      Int_t index=t->GetClusterIndex2(i);
    8876        3122 :      if (index<=0) continue; 
    8877        2110 :      if (index&0x8000) continue;
    8878             :      //     
    8879        1822 :      clusters[current++]=GetClusterMI(index);
    8880             :      // if (t->GetClusterPointer(i)){
    8881             :      //   clusters[current]=t->GetClusterPointer(i);     
    8882             :      //   current++;
    8883             :      // }
    8884        1822 :   }
    8885             :   noc = current;
    8886             :   //if (noc<5) return -1;
    8887             :   Int_t lab=123456789;
    8888        3708 :   for (i=0; i<noc; i++) {
    8889        1822 :     AliTPCclusterMI *c=clusters[i];
    8890        1822 :     if (!c) continue;
    8891        1822 :     lab=TMath::Abs(c->GetLabel(0));
    8892             :     Int_t j;
    8893        6387 :     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
    8894        1822 :     lb[j]=lab;
    8895        1822 :     (mx[j])++;
    8896        1822 :   }
    8897             : 
    8898             :   Int_t max=0;
    8899        5565 :   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
    8900             :     
    8901        3708 :   for (i=0; i<noc; i++) {
    8902        1822 :     AliTPCclusterMI *c=clusters[i]; 
    8903        1822 :     if (!c) continue;
    8904        2688 :     if (TMath::Abs(c->GetLabel(1)) == lab ||
    8905        1822 :         TMath::Abs(c->GetLabel(2)) == lab ) max++;
    8906        1822 :   }
    8907          32 :   if (noc<=0) { lab=-1; return -1;}
    8908          32 :   if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
    8909             : 
    8910             :   else {
    8911          32 :      Int_t tail=Int_t(0.10*noc);
    8912             :      max=0;
    8913             :      Int_t ind=0;
    8914         600 :      for (i=1; i<kMaxRow&&ind<tail; i++) {
    8915             :        //       AliTPCclusterMI *c=clusters[noc-i];
    8916         168 :        AliTPCclusterMI *c=clusters[i];
    8917         168 :        if (!c) continue;
    8918         178 :        if (lab == TMath::Abs(c->GetLabel(0)) ||
    8919          15 :            lab == TMath::Abs(c->GetLabel(1)) ||
    8920         168 :            lab == TMath::Abs(c->GetLabel(2))) max++;
    8921         168 :        ind++;
    8922         168 :      }
    8923          33 :      if (max < Int_t(0.5*tail)) lab=-lab;
    8924             :   }
    8925             : 
    8926             :   //  t->SetLabel(lab);
    8927          32 :   return lab;
    8928             :   //  delete[] lb;
    8929             :   //delete[] mx;
    8930             :   //delete[] clusters;
    8931          64 : }
    8932             : 
    8933             : 
    8934             : Int_t  AliTPCtracker::GetRowNumber(Double_t x[3]) const 
    8935             : {
    8936             :   //return pad row number for given x vector
    8937           0 :   Float_t phi = TMath::ATan2(x[1],x[0]);
    8938           0 :   if(phi<0) phi=2.*TMath::Pi()+phi;
    8939             :   //  Get the local angle in the sector philoc
    8940             :   const Float_t kRaddeg = 180/3.14159265358979312;
    8941           0 :   Float_t phiangle   = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
    8942           0 :   Double_t localx    = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
    8943           0 :   return GetRowNumber(localx);
    8944             : }
    8945             : 
    8946             : 
    8947             : 
    8948             : void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
    8949             : {
    8950             :   //-----------------------------------------------------------------------
    8951             :   // Fill the cluster and sharing bitmaps of the track
    8952             :   //-----------------------------------------------------------------------
    8953             : 
    8954             :   Int_t firstpoint = 0;
    8955             :   Int_t lastpoint = kMaxRow;
    8956             :   //  AliTPCclusterMI    *cluster;
    8957             :   
    8958             :   Int_t nclsf = 0;
    8959         544 :   TBits clusterMap(kMaxRow);
    8960         272 :   TBits sharedMap(kMaxRow);
    8961         272 :   TBits fitMap(kMaxRow);
    8962       87040 :   for (int iter=firstpoint; iter<lastpoint; iter++) {
    8963             :     // Change to cluster pointers to see if we have a cluster at given padrow
    8964       43248 :     Int_t tpcindex= t->GetClusterIndex2(iter);
    8965       43248 :     if (tpcindex>=0) {
    8966       33420 :       clusterMap.SetBitNumber(iter, kTRUE);
    8967       67416 :       if (t->IsShared(iter)) sharedMap.SetBitNumber(iter,kTRUE); // RS shared flag moved to seed
    8968             :       //
    8969       33420 :       if ( (tpcindex&0x8000) == 0)  {
    8970       32534 :         fitMap.SetBitNumber(iter, kTRUE);
    8971       32534 :         nclsf++;
    8972       32534 :       }
    8973             :     }
    8974             :     // if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
    8975             :     //   fitMap.SetBitNumber(iter, kTRUE);
    8976             :     //   nclsf++;
    8977             :     // }
    8978             :   }
    8979         272 :   esd->SetTPCClusterMap(clusterMap);
    8980         272 :   esd->SetTPCSharedMap(sharedMap);
    8981         272 :   esd->SetTPCFitMap(fitMap);
    8982         544 :   if (nclsf != t->GetNumberOfClusters())
    8983         670 :     AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
    8984         272 : }
    8985             : 
    8986             : Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
    8987             :   //
    8988             :   // return flag if there is findable cluster at given position
    8989             :   //
    8990             :   Float_t kDeltaZ=10;
    8991      161444 :   Float_t z = track.GetZ();
    8992             :   
    8993      161432 :   if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) && 
    8994       80722 :       TMath::Abs(z)<fkParam->GetZLength(0) && 
    8995       80710 :       (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
    8996       80640 :     return kTRUE;
    8997          82 :   return kFALSE;      
    8998       80722 : }
    8999             : 
    9000             : 
    9001             : void AliTPCtracker::AddCovariance(AliTPCseed * seed){
    9002             :   //
    9003             :   // Adding systematic error estimate to the covariance matrix
    9004             :   //                !!!! the systematic error for element 4 is in 1/GeV 
    9005             :   // 03.03.2012     MI changed in respect to the previous versions
    9006             :   // in case systemtic errors defiend statically no correlation added (needed for CPass0)
    9007        2712 :   const Double_t *param = (AliTPCReconstructor::GetSystematicError()!=NULL) ? AliTPCReconstructor::GetSystematicError():AliTPCReconstructor::GetRecoParam()->GetSystematicError();
    9008             :   //
    9009             :   // use only the diagonal part if not specified otherwise
    9010        1356 :   if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation() || AliTPCReconstructor::GetSystematicError()) return AddCovarianceAdd(seed);
    9011             :   //
    9012         678 :   Double_t *covarS= (Double_t*)seed->GetCovariance();
    9013         678 :   Double_t factor[5]={1,1,1,1,1};
    9014         678 :   factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
    9015         678 :   factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
    9016         678 :   factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
    9017         678 :   factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
    9018         678 :   factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
    9019             :   //
    9020         678 :   factor[0]=factor[2];
    9021         678 :   factor[4]=factor[2];
    9022             :   // 0
    9023             :   // 1    2
    9024             :   // 3    4    5
    9025             :   // 6    7    8    9 
    9026             :   // 10   11   12   13   14
    9027        8136 :   for (Int_t i=0; i<5; i++){
    9028       27120 :     for (Int_t j=i; j<5; j++){
    9029       10170 :       Int_t index=seed->GetIndex(i,j);
    9030       10170 :       covarS[index]*=factor[i]*factor[j];
    9031             :     }
    9032             :   }
    9033        1356 : }
    9034             : 
    9035             : 
    9036             : void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
    9037             :   //
    9038             :   // Adding systematic error - as additive factor without correlation
    9039             :   //
    9040             :   //                !!!! the systematic error for element 4 is in 1/GeV 
    9041             :   // 03.03.2012     MI changed in respect to the previous versions
    9042             : 
    9043           0 :   const Double_t *param = (AliTPCReconstructor::GetSystematicError()!=NULL) ? AliTPCReconstructor::GetSystematicError():AliTPCReconstructor::GetRecoParam()->GetSystematicError();
    9044           0 :   Double_t *covarIn= (Double_t*)seed->GetCovariance();
    9045           0 :   Double_t covar[15];
    9046           0 :   for (Int_t i=0;i<15;i++) covar[i]=0;
    9047             :   // 0
    9048             :   // 1    2
    9049             :   // 3    4    5
    9050             :   // 6    7    8    9 
    9051             :   // 10   11   12   13   14
    9052           0 :   covar[0] = param[0]*param[0];
    9053           0 :   covar[2] = param[1]*param[1];
    9054           0 :   covar[5] = param[2]*param[2];
    9055           0 :   covar[9] = param[3]*param[3];
    9056           0 :   covar[14]= param[4]*param[4];
    9057             :   //
    9058           0 :   covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
    9059             :   //
    9060           0 :   covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
    9061           0 :   covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
    9062             :   //
    9063           0 :   covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
    9064           0 :   covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
    9065           0 :   covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
    9066             :   //
    9067           0 :   covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
    9068           0 :   covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
    9069           0 :   covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
    9070           0 :   covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
    9071             :   //
    9072           0 :   seed->AddCovariance(covar);
    9073           0 : }
    9074             : 
    9075             : //_____________________________________________________________________________
    9076             : Bool_t  AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
    9077             : {
    9078             :   //
    9079             :   // check events affected by TPC HV dip
    9080             :   //
    9081          16 :   if(!esdEvent) return kFALSE;
    9082             : 
    9083             :   // Init TPC OCDB
    9084           8 :   AliTPCcalibDB *db=AliTPCcalibDB::Instance();
    9085           8 :   if(!db) return kFALSE;
    9086           8 :   db->SetRun(esdEvent->GetRunNumber());
    9087             : 
    9088             :   // maximum allowed voltage before an event is identified as a dip event
    9089             :   // and scanning period
    9090           8 :   const Double_t kTPCHVdip          = db->GetParameters()->GetMaxDipVoltage(); 
    9091           8 :   const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
    9092           8 :   const Double_t tevSec             = esdEvent->GetTimeStamp();
    9093             :   
    9094        1176 :   for(Int_t sector=0; sector<72; sector++)
    9095             :   {
    9096             :     // don't use excluded chambers, since the state is not defined at all
    9097         576 :     if (!db->GetChamberHVStatus(sector)) continue;
    9098             :     
    9099             :     // get hv sensor of the chamber
    9100         576 :     AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
    9101        1152 :     if (!sensor) continue;
    9102           0 :     TGraph *grSensor=sensor->GetGraph();
    9103           0 :     if (!grSensor) continue;
    9104           0 :     if (grSensor->GetN()<1) continue;
    9105             :     
    9106             :     // get median
    9107           0 :     const Double_t median = db->GetChamberHighVoltageMedian(sector);
    9108           0 :     if(median < 1.) continue;
    9109             :     
    9110           0 :     for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
    9111           0 :       Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
    9112           0 :       if (tevSec-dipEventScanPeriod>nextTime) continue;
    9113           0 :       const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
    9114           0 :       if (deltaV>kTPCHVdip) {
    9115           0 :         AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
    9116           0 :         return kTRUE;
    9117             :       }
    9118           0 :       if (nextTime>tevSec+dipEventScanPeriod) break;
    9119           0 :     }
    9120           0 :   }
    9121             :   
    9122           8 :   return kFALSE;
    9123           8 : }
    9124             : 
    9125             : //________________________________________
    9126             : void AliTPCtracker::MarkSeedFree(TObject *sd) 
    9127             : {
    9128             :   // account that this seed is "deleted" 
    9129             :   //  AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
    9130             :   //  if (!seed) {
    9131             :   //    AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd)); 
    9132             :   //    return;
    9133             :   //  }
    9134       26940 :   AliTPCseed* seed = (AliTPCseed*)sd;
    9135       13470 :   int id = seed->GetPoolID();
    9136       13470 :   if (id<0) {
    9137           0 :     AliError(Form("Freeing of seed %p NOT from the pool is requested",sd)); 
    9138           0 :     return;
    9139             :   }
    9140             :   //  AliInfo(Form("%d %p",id, seed));
    9141       13470 :   fSeedsPool->RemoveAt(id);
    9142       13470 :   if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
    9143       13470 :   fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
    9144       26940 : }
    9145             : 
    9146             : //________________________________________
    9147             : TObject *&AliTPCtracker::NextFreeSeed()
    9148             : {
    9149             :   // return next free slot where the seed can be created
    9150       55504 :   fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
    9151             :   //  AliInfo(Form("%d",fLastSeedID));
    9152       13876 :   return (*fSeedsPool)[ fLastSeedID ];
    9153             :   //
    9154             : }
    9155             : 
    9156             : //________________________________________
    9157             : void AliTPCtracker::ResetSeedsPool()
    9158             : {
    9159             :   // mark all seeds in the pool as unused
    9160          48 :   AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
    9161          24 :   fNFreeSeeds = 0;
    9162          24 :   fSeedsPool->Clear(); // RS: nominally the seeds may allocate memory...
    9163             :   
    9164          24 : }
    9165             : 
    9166             : Int_t  AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
    9167             : {
    9168             :   AliTPCseed &t=*pt;
    9169           0 :   Double_t x= GetXrow(nrow);
    9170           0 :   Double_t  ymax= GetMaxY(nrow);
    9171             :   Int_t rotate = 0;
    9172             :   Int_t nRotations=0;
    9173             :   int ret = 1;
    9174           0 :   do{
    9175             :     rotate = 0;
    9176           0 :     if (!t.PropagateTo(x) ){
    9177             :       //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl; 
    9178             :       //t.Print();
    9179             :       ret = 0;
    9180           0 :       break;
    9181             :     }
    9182           0 :     t.SetRow(nrow);
    9183           0 :     Double_t y = t.GetY();
    9184             :     double yEdgeDist = y;
    9185           0 :     if  (fAccountDistortions) yEdgeDist -= GetYSectEdgeDist(t.GetRelativeSector(),nrow,y,t.GetZ());
    9186           0 :     if( y>0 && yEdgeDist>ymax) {
    9187           0 :       if( rotate!=-1 ) rotate=1;
    9188           0 :     } else if  (y<0 && yEdgeDist<-ymax) { 
    9189           0 :       if( rotate!=1 ) rotate = -1;
    9190             :     }
    9191           0 :     if( rotate==0 ) break;
    9192             :     //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
    9193           0 :     if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
    9194             :       //cout<<"can't rotate "<<endl; 
    9195             :       ret=0;
    9196           0 :       break;
    9197             :     }
    9198           0 :     nRotations+= rotate;
    9199           0 :   }while(rotate!=0);
    9200           0 :   if( nRotations!=0 ){
    9201           0 :     int newSec= t.GetRelativeSector()+nRotations;
    9202           0 :     if( newSec>=fN ) newSec-=fN;
    9203           0 :     else if( newSec<0 ) newSec +=fN; 
    9204             :     //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
    9205             :     //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
    9206           0 :     t.SetRelativeSector(newSec);
    9207           0 :   }
    9208           0 :   return ret;
    9209             : }
    9210             : 
    9211             : void  AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
    9212             : {
    9213             :   //
    9214             :   // try to track in parralel
    9215             : 
    9216           0 :   AliFatal("RS: This method is not yet aware of cluster pointers no present in the in-memory tracks");
    9217             : 
    9218           0 :   Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
    9219           0 :   fSectors=fInnerSec;
    9220             : 
    9221           0 :   Int_t nseed=arr->GetEntriesFast();
    9222             :   //cout<<"Parallel tracking My.."<<endl;
    9223           0 :   double shapeY2[kMaxRow], shapeZ2[kMaxRow];
    9224           0 :   Int_t clusterIndex[kMaxRow];
    9225             :  
    9226           0 :   for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
    9227             :     //if( iSeed!=1 ) continue;
    9228           0 :     AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
    9229           0 :     if (!pt) continue;
    9230             :     AliTPCseed &t=*pt;    
    9231             :     
    9232             :     //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
    9233             :     
    9234             :     // t.Print();
    9235             :     
    9236           0 :     for( int iter=0; iter<3; iter++ ){
    9237             :             
    9238           0 :       t.Reset();
    9239           0 :       t.SetLastPoint(0);  // first cluster in track position
    9240           0 :       t.SetFirstPoint(nRows-1);
    9241           0 :       t.ResetCovariance(.1);
    9242           0 :       t.SetNumberOfClusters(0);
    9243           0 :       for( int i=0; i<nRows; i++ ){
    9244           0 :         shapeY2[i]=1.;
    9245           0 :         shapeZ2[i]=1.;
    9246           0 :         clusterIndex[i]=-1;
    9247           0 :         t.SetClusterIndex2(i,-1); 
    9248           0 :         t.SetClusterIndex(i,-1); 
    9249             :       }
    9250             : 
    9251             :      // pick up the clusters
    9252             :       
    9253             :       Double_t roady = 20.;
    9254             :       Double_t roadz = 20.;
    9255             :       double roadr = 5;
    9256             : 
    9257           0 :       AliTPCseed t0(t);
    9258           0 :       t0.Reset();
    9259             :       int nClusters = 0;      
    9260             :       {
    9261           0 :         t0.SetRelativeSector(t.GetRelativeSector());
    9262           0 :         t0.SetLastPoint(0);  // first cluster in track position
    9263           0 :         t0.SetFirstPoint(kMaxRow);
    9264           0 :         for (Int_t nr=0; nr<nRows; nr++){ 
    9265           0 :           if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
    9266           0 :           else fSectors=fOuterSec;
    9267             : 
    9268           0 :           if( !PropagateToRowHLT(&t0, nr ) ){ break; }
    9269           0 :           if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
    9270             :             //cout<<"Snp is too big: "<<t0.GetSnp()<<endl; 
    9271             :             continue;
    9272             :           }
    9273           0 :           if (!IsActive(t0.GetRelativeSector(),nr)) {
    9274             :             continue;
    9275             :           }
    9276             :           
    9277           0 :           if( iter==0 ){
    9278           0 :             GetShape(&t0,nr); 
    9279           0 :             shapeY2[nr]=t0.GetCurrentSigmaY2();
    9280           0 :             shapeZ2[nr]=t0.GetCurrentSigmaZ2();
    9281           0 :           }
    9282             : 
    9283           0 :           AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
    9284           0 :           if( !krow ) continue; 
    9285             : 
    9286           0 :           t.SetClusterIndex2(nr,-3); // foundable
    9287           0 :           t.SetClusterIndex(nr,-3); 
    9288             : 
    9289             :           AliTPCclusterMI *cl=0;
    9290           0 :           UInt_t uindex = 0;
    9291           0 :           cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady+fClExtraRoadY,roadz+fClExtraRoadZ,uindex); 
    9292           0 :           if (!cl ) continue;
    9293           0 :           double dy = cl->GetY()-t0.GetY();
    9294           0 :           double dz = cl->GetZ()-t0.GetZ();
    9295           0 :           double dr = sqrt(dy*dy+dz*dz);
    9296           0 :           if( dr>roadr ){ 
    9297             :             //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
    9298           0 :             continue;
    9299             :           }
    9300             :           //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
    9301             : 
    9302           0 :           t0.SetClusterPointer(nr, cl);   
    9303           0 :           clusterIndex[nr] = krow.GetIndex(uindex);       
    9304           0 :           if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
    9305           0 :           t0.SetLastPoint(nr);
    9306           0 :           nClusters++;
    9307           0 :         }
    9308             :       }
    9309             : 
    9310           0 :       if( nClusters <3 ){
    9311             :         //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
    9312           0 :         break;
    9313             :       }
    9314           0 :       Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
    9315             : 
    9316             :       // find midpoint
    9317             :       {
    9318           0 :         Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
    9319             :         int dist=200;
    9320           0 :         for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
    9321             :           //if (t0.GetClusterIndex2(nr)<0) continue;
    9322           0 :           if( !t0.GetClusterPointer(nr) ) continue;       
    9323           0 :           int d = TMath::Abs(nr-midRow);
    9324           0 :           if( d < dist ){
    9325             :             dist = d;
    9326           0 :             basePoints[1] = nr;
    9327           0 :           }
    9328           0 :         }
    9329             :       }
    9330             : 
    9331             :       // first fit 3 base points
    9332             :       if( 1||iter<2 ){
    9333             :         //cout<<"Fit3: "<<endl;
    9334           0 :         for( int icl=0; icl<3; icl++){
    9335           0 :           int nr = basePoints[icl];
    9336             :           int lr=nr;
    9337           0 :           if( nr>=fInnerSec->GetNRows()){ 
    9338           0 :             lr = nr - fInnerSec->GetNRows();
    9339           0 :             fSectors=fOuterSec;
    9340           0 :           } else fSectors=fInnerSec;
    9341             :           
    9342           0 :           AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
    9343           0 :           if(!cl){
    9344             :             //cout<<"WRONG!!!!"<<endl; 
    9345           0 :             continue;
    9346             :           }
    9347           0 :           int iSec = cl->GetDetector() %fkNIS;
    9348           0 :           int rotate = iSec - t.GetRelativeSector();    
    9349           0 :           if( rotate!=0 ){
    9350             :             //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
    9351           0 :             if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
    9352             :               //cout<<"can't rotate "<<endl; 
    9353           0 :               break;
    9354             :             }
    9355           0 :             t.SetRelativeSector(iSec);
    9356           0 :           }
    9357           0 :           Double_t x= cl->GetX();
    9358           0 :           if (!t.PropagateTo(x)){
    9359             :             //cout<<"can't propagate to x="<<x<<endl; 
    9360           0 :             break;
    9361             :           }    
    9362           0 :           t.SetRow(nr); // RS: memorise row
    9363           0 :           if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
    9364             :             //cout<<"Snp is too big: "<<t.GetSnp()<<endl; 
    9365           0 :             break;
    9366             :           }
    9367             :           //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
    9368             :           
    9369           0 :           t.SetCurrentClusterIndex1(clusterIndex[nr]);
    9370           0 :           t.SetCurrentCluster(cl);
    9371           0 :           t.SetRow(lr); 
    9372             :           
    9373           0 :           t.SetErrorY2(shapeY2[nr]);
    9374           0 :           t.SetErrorZ2(shapeZ2[nr]);
    9375           0 :           if( icl==0 ){
    9376           0 :             double cov[15];
    9377           0 :             for( int j=0; j<15; j++ ) cov[j]=0;
    9378           0 :             cov[0]=10;
    9379           0 :             cov[2]=10;
    9380           0 :             cov[5]=.5;
    9381           0 :             cov[9]=.5;
    9382           0 :             cov[14]=1.;
    9383           0 :             t.AliExternalTrackParam::AddCovariance(cov);
    9384           0 :           }
    9385           0 :           if( !UpdateTrack(&t,0) ){
    9386             :             //cout<<"Can not update"<<endl;
    9387             :             //t.Print();
    9388           0 :             t.SetClusterIndex2(nr,-1); 
    9389           0 :             t.SetClusterIndex(nr,-1); 
    9390           0 :             t.SetClusterPointer(nr,0); 
    9391           0 :             break;
    9392             :           }             
    9393             :           //t.SetClusterPointer(nr, cl);
    9394           0 :         }
    9395             :         
    9396             :         //t.SetLastPoint(t0.GetLastPoint());
    9397             :         //t.SetFirstPoint(t0.GetFirstPoint());
    9398             : 
    9399             :         //cout<<"Fit: "<<endl;
    9400           0 :         for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
    9401             :           int lr=nr;
    9402           0 :           if( nr>=fInnerSec->GetNRows()){ 
    9403           0 :             lr = nr - fInnerSec->GetNRows();
    9404           0 :             fSectors=fOuterSec;
    9405           0 :           } else fSectors=fInnerSec;
    9406             :           
    9407             :           if(1|| iter<2 ){
    9408           0 :             if( nr == basePoints[0] ) continue;
    9409           0 :             if( nr == basePoints[1] ) continue;
    9410           0 :             if( nr == basePoints[2] ) continue;
    9411             :           }
    9412           0 :           AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
    9413           0 :           if(!cl) continue;
    9414             :           
    9415           0 :           int iSec = cl->GetDetector() %fkNIS;
    9416           0 :           int rotate = iSec - t.GetRelativeSector();    
    9417           0 :           if( rotate!=0 ){
    9418             :             //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
    9419           0 :             if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
    9420             :               //cout<<"can't rotate "<<endl; 
    9421           0 :               break;
    9422             :             }
    9423           0 :             t.SetRelativeSector(iSec);
    9424           0 :           }
    9425           0 :           Double_t x= cl->GetX();
    9426           0 :           if (!t.PropagateTo(x)){
    9427             :             //cout<<"can't propagate to x="<<x<<endl; 
    9428           0 :             break;
    9429             :           }    
    9430           0 :           if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
    9431             :             //cout<<"Snp is too big: "<<t.GetSnp()<<endl; 
    9432           0 :             break;
    9433             :           }     
    9434           0 :           t.SetRow(nr); //RS: memorise row
    9435             :           //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
    9436             : 
    9437           0 :           t.SetCurrentClusterIndex1(clusterIndex[nr]);
    9438           0 :           t.SetCurrentCluster(cl);
    9439           0 :           t.SetRow(lr); 
    9440           0 :           t.SetErrorY2(shapeY2[nr]);
    9441           0 :           t.SetErrorZ2(shapeZ2[nr]);
    9442             :           
    9443           0 :           if( !UpdateTrack(&t,0) ){
    9444             :             //cout<<"Can not update"<<endl;
    9445             :             //t.Print();
    9446           0 :             t.SetClusterIndex2(nr,-1); 
    9447           0 :             t.SetClusterIndex(nr,-1); 
    9448           0 :             break;
    9449             :           }             
    9450             :           //t.SetClusterPointer(nr, cl);
    9451           0 :         }
    9452             :       }
    9453             :       //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
    9454           0 :     }
    9455             : 
    9456             :     //cout<<"fitted track"<<iSeed<<endl;
    9457             :     //t.Print();
    9458             :     //cout<<"Statistics: "<<endl;    
    9459           0 :     Int_t foundable,found,shared;
    9460             :     //t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
    9461           0 :     t.GetClusterStatistic(0,nRows, found, foundable); //RS shared info is not used, use faster method
    9462           0 :     t.SetNFoundable(foundable);
    9463             :     //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
    9464             :     
    9465           0 :   }
    9466           0 : }
    9467             : 
    9468             : 
    9469             : TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
    9470             : {
    9471             :   // tracking
    9472             :   //  
    9473           0 :   AliFatal("RS: This method is not yet aware of cluster pointers no present in the in-memory tracks");
    9474           0 :   if( !hltEvent ) return 0;  
    9475             :  
    9476             : 
    9477           0 :   Int_t nentr=hltEvent->GetNumberOfTracks();
    9478             :  
    9479           0 :   AliInfo(Form("Using %d HLT tracks for seeding",nentr));
    9480             :  
    9481           0 :   TObjArray * seeds = new TObjArray(nentr);
    9482             : 
    9483           0 :   Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
    9484             :   Int_t index = 0;
    9485             :   
    9486           0 :   Int_t nTr=hltEvent->GetNumberOfTracks();      
    9487             :     
    9488           0 :   for( int itr=0; itr<nTr; itr++ ){
    9489             :     //if( itr!=97 ) continue;
    9490           0 :     const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
    9491           0 :     if( !param ) continue;
    9492             :     //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
    9493             :     //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
    9494           0 :     AliTPCtrack tr;    
    9495           0 :     tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
    9496           0 :     tr.SetNumberOfClusters(0);
    9497           0 :     AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
    9498             : 
    9499           0 :     Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
    9500           0 :     if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
    9501           0 :     if (alpha < 0.            ) alpha += 2.*TMath::Pi();
    9502             :     //
    9503           0 :     seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
    9504           0 :     Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
    9505             :  
    9506           0 :     if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
    9507           0 :     if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
    9508             : 
    9509           0 :     seed->Rotate(alphaSec - alpha);
    9510             :     
    9511           0 :     seed->SetPoolID(fLastSeedID);
    9512           0 :     seed->SetIsSeeding(kTRUE);
    9513           0 :     seed->SetSeed1(nup-1);
    9514           0 :     seed->SetSeed2(nup-2);
    9515           0 :     seed->SetSeedType(0);
    9516           0 :     seed->SetFirstPoint(-1);
    9517           0 :     seed->SetLastPoint(-1);
    9518           0 :     seeds->AddLast(seed); // note, track is seed, don't free the seed
    9519           0 :     index++;
    9520             :     //if( index>3 ) break;
    9521           0 :   }
    9522             :  
    9523             : 
    9524           0 :   fSectors = fOuterSec;
    9525             :   
    9526           0 :   TrackFollowingHLT(seeds );
    9527             : 
    9528           0 :   nTr = seeds->GetEntriesFast();
    9529           0 :   for( int itr=0; itr<nTr; itr++ ){
    9530           0 :     AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
    9531           0 :     if( !seed ) continue;
    9532             :     //FollowBackProlongation(*seed,0);
    9533             :     // cout<<seed->GetNumberOfClusters()<<endl;
    9534           0 :     Int_t foundable,found;//,shared;
    9535             :     //    seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE); //RS shared info is not used, use faster method
    9536           0 :     seed->GetClusterStatistic(0,nup, found, foundable);
    9537           0 :     seed->SetNFoundable(foundable);
    9538             :     //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
    9539             :     //if ((found<0.55*foundable)  || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
    9540             :     //MarkSeedFree(seeds->RemoveAt(itr)); 
    9541             :     //continue;
    9542             :     //}
    9543           0 :     if (seed->GetNumberOfClusters()<30 || 
    9544           0 :         seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 || 
    9545           0 :         seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
    9546           0 :       MarkSeedFree(seeds->RemoveAt(itr)); 
    9547           0 :       continue;
    9548             :     }      
    9549             : 
    9550           0 :     for( int ir=0; ir<nup; ir++){
    9551           0 :       AliTPCclusterMI *c = seed->GetClusterPointer(ir);      
    9552           0 :       if( c ) c->Use(10);
    9553             :     }
    9554           0 :   }
    9555           0 :   std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
    9556             :   return seeds;    
    9557           0 : }
    9558             : 
    9559             : void AliTPCtracker::FillClusterOccupancyInfo()
    9560             : {
    9561             :   //fill the cluster occupancy info into the ESD friend
    9562          16 :   AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
    9563           8 :   if (!esdFriend) return;
    9564             : 
    9565         304 :   for (Int_t isector=0; isector<18; isector++){
    9566         144 :     AliTPCtrackerSector &iroc = fInnerSec[isector];
    9567         144 :     AliTPCtrackerSector &oroc = fOuterSec[isector];
    9568             :     //all clusters
    9569         144 :     esdFriend->SetNclustersTPC(isector,   iroc.GetNClInSector(0));
    9570         144 :     esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
    9571         144 :     esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
    9572         144 :     esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
    9573             :     //clusters used in tracking
    9574         144 :     esdFriend->SetNclustersTPCused(isector,    iroc.GetNClUsedInSector(0));
    9575         144 :     esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
    9576         144 :     esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
    9577         144 :     esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));
    9578             :   }
    9579          16 : }
    9580             : 
    9581             : void AliTPCtracker::FillSeedClusterStatCache(const AliTPCseed* seed)
    9582             : {
    9583             :   //RS fill cache for seed's cluster statistics evaluation buffer
    9584           0 :   for (int i=kMaxRow;i--;) {
    9585           0 :     Int_t index = seed->GetClusterIndex2(i);
    9586           0 :     fClStatFoundable[i] = (index!=-1);
    9587           0 :     fClStatFound[i] = fClStatShared[i] = kFALSE;
    9588           0 :     if (index<0 || (index&0x8000)) continue;
    9589           0 :     const AliTPCclusterMI* cl = GetClusterMI(index);
    9590           0 :     if (cl->IsUsed(10)) fClStatShared[i] = kTRUE;
    9591           0 :   }
    9592           0 : }
    9593             : 
    9594             : void AliTPCtracker::GetCachedSeedClusterStatistic(Int_t first, Int_t last, Int_t &found, Int_t &foundable, Int_t &shared, Bool_t plus2) const
    9595             : {
    9596             :   //RS calculation of cached seed statistics
    9597           0 :   found       = 0;
    9598           0 :   foundable   = 0;
    9599           0 :   shared      = 0;
    9600             :   //
    9601           0 :   for (Int_t i=first;i<last; i++){
    9602           0 :     if (fClStatFoundable[i]) foundable++;
    9603             :     else continue;
    9604             :     //
    9605           0 :     if (fClStatFound[i]) found++;
    9606             :     else continue;
    9607             :     //
    9608           0 :     if (fClStatShared[i]) {
    9609           0 :       shared++;
    9610           0 :       continue;
    9611             :     }
    9612           0 :     if (!plus2) continue; //take also neighborhoud
    9613             :     //
    9614           0 :     if ( i>0 && fClStatShared[i-1]) {
    9615           0 :       shared++;
    9616           0 :       continue;
    9617             :     }
    9618           0 :     if ( i<(kMaxRow-1) && fClStatShared[i+1]) {
    9619           0 :       shared++;
    9620           0 :       continue;
    9621             :     }    
    9622             :   }
    9623           0 : }
    9624             : 
    9625             : void AliTPCtracker::GetSeedClusterStatistic(const AliTPCseed* seed, Int_t first, Int_t last, Int_t &found, Int_t &foundable, Int_t &shared, Bool_t plus2) const
    9626             : {
    9627             :   // RS: get cluster stat. on given region, faster for small regions than cachin the whole seed stat.
    9628             :   //
    9629        1064 :   found       = 0;
    9630        1064 :   foundable   = 0;
    9631        1064 :   shared      =0;
    9632      196160 :   for (Int_t i=first;i<last; i++){
    9633       97016 :     Int_t index = seed->GetClusterIndex2(i);
    9634      189308 :     if (index!=-1) foundable++;
    9635      110646 :     if (index&0x8000) continue;
    9636      166772 :     if (index>=0) found++;
    9637           0 :     else continue;
    9638       83386 :     const AliTPCclusterMI* cl = GetClusterMI(index);
    9639       83386 :     if (cl->IsUsed(10)) {
    9640       13178 :       shared++;
    9641       13178 :       continue;
    9642             :     }
    9643      138350 :     if (!plus2) continue; //take also neighborhoud
    9644             :     //
    9645        2066 :     if (i>0) {
    9646        2066 :       index = seed->GetClusterIndex2(i-1);
    9647        5944 :       cl = index<0 ? 0:GetClusterMI(index);
    9648        3878 :       if (cl && cl->IsUsed(10)) {
    9649           0 :         shared++;
    9650           0 :         continue;
    9651             :       }
    9652             :     }
    9653        2066 :     if (i<(kMaxRow-1)) {
    9654        2066 :       index = seed->GetClusterIndex2(i+1);
    9655        5938 :       cl = index<0 ? 0:GetClusterMI(index);      
    9656        3872 :       if (cl && cl->IsUsed(10)) {
    9657           0 :         shared++;
    9658           0 :         continue;
    9659             :       }
    9660             :     }
    9661             :     
    9662        2066 :   }
    9663        1064 : }
    9664             : 
    9665             : Bool_t AliTPCtracker::DistortX(const AliTPCseed* seed, double& x, int row)
    9666             : {
    9667             :   // distort X by the distorion at track location on given row
    9668             :   //
    9669             :   //RS:? think to unset fAccountDistortions if no maps are used
    9670           0 :   if (!AliTPCReconstructor::GetRecoParam()->GetUseCorrectionMap()) return kTRUE;
    9671           0 :   double xyz[3]; 
    9672             :   int rowInp = row;//RS
    9673           0 :   if (!seed->GetYZAt(x,AliTracker::GetBz(),&xyz[1])) return kFALSE; //RS:? Think to cache fBz?
    9674           0 :   xyz[0] = x;
    9675           0 :   int roc = seed->GetRelativeSector();
    9676           0 :   if (seed->GetZ()<0) roc += 18;
    9677           0 :   if (row>62) {
    9678           0 :     roc += 36;
    9679           0 :     row -= 63;
    9680           0 :   }
    9681           0 :   AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
    9682           0 :   AliTPCTransform *transform = calibDB->GetTransform();
    9683           0 :   if (!transform) AliFatal("Tranformations not in calibDB");
    9684           0 :   x += transform->GetCorrMapComponent(roc,row,xyz,0);
    9685             :   return kTRUE;
    9686           0 : }
    9687             : 
    9688             : Double_t AliTPCtracker::GetDistortionX(double x, double y, double z, int sec, int row)
    9689             : {
    9690             :   // get X distortion at location on given row
    9691             :   //
    9692           0 :   if (!AliTPCReconstructor::GetRecoParam()->GetUseCorrectionMap()) return 0;
    9693           0 :   double xyz[3] = {x,y,z}; 
    9694             :   int rowInp = row;
    9695             :   int secInp = sec;
    9696           0 :   if (z<0) sec += 18;
    9697           0 :   if (row>62) {
    9698           0 :     sec += 36;
    9699           0 :     row -= 63;
    9700           0 :   }
    9701           0 :   AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
    9702           0 :   AliTPCTransform *transform = calibDB->GetTransform() ;
    9703           0 :   if (!transform) AliFatal("Tranformations not in calibDB");
    9704           0 :   return transform->GetCorrMapComponent(sec,row,xyz,0);
    9705           0 : }
    9706             : 
    9707             : Double_t AliTPCtracker::GetYSectEdgeDist(int sec, int row, double y, double z) 
    9708             : {
    9709             :   // get the signed  shift for maxY of the sector/row accounting for distortion
    9710             :   // Slow way, to speed up
    9711           0 :   if (!AliTPCReconstructor::GetRecoParam()->GetUseCorrectionMap()) return 0;
    9712           0 :   double ymax = 0.9*GetMaxY(row); // evaluate distortions at 5% of pad lenght from the edge
    9713           0 :   if (y<0) ymax = -ymax;
    9714           0 :   double xyz[3] = {GetXrow(row),ymax,z}; 
    9715           0 :   if (z<0) sec += 18;
    9716           0 :   if (row>62) {
    9717           0 :     sec += 36;
    9718           0 :     row -= 63;
    9719           0 :   }
    9720           0 :   AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
    9721           0 :   AliTPCTransform *transform = calibDB->GetTransform();
    9722           0 :   if (!transform) AliFatal("Tranformations not in calibDB");
    9723             :   // change of distance from the edge due to the X shift 
    9724           0 :   double dxtg = transform->GetCorrMapComponent(sec,row,xyz,0)*AliTPCTransform::GetMaxY2X();
    9725           0 :   double dy = transform->GetCorrMapComponent(sec,row,xyz,1);
    9726           0 :   return dy + (y>0?dxtg:-dxtg);
    9727             :   //
    9728           0 : }
    9729             : 
    9730             : Int_t AliTPCtracker::GetTrackSector(double alpha)
    9731             : {
    9732             :   //convert alpha to sector
    9733           0 :   if (alpha<0) alpha += TMath::Pi()*2;
    9734           0 :   int sec = alpha/(TMath::Pi()/9);
    9735           0 :   return sec;
    9736             : }
    9737             : 
    9738             : void AliTPCtracker::CleanESDFriendsObjects(AliESDEvent* esd)
    9739             : {
    9740             :   // RS: remove seeds stored in friend's calib object contained w/o changing its ownership
    9741             :   //
    9742          16 :   AliInfo("Removing own seeds from friend tracks");
    9743           8 :   AliESDfriend* esdF = esd->FindFriend();
    9744           8 :   int ntr = esd->GetNumberOfTracks();
    9745         158 :   for (int itr=ntr;itr--;) {
    9746         142 :     AliESDtrack* trc = esd->GetTrack(itr);
    9747         142 :     AliESDfriendTrack* trcF = (AliESDfriendTrack*)trc->GetFriendTrack();
    9748         142 :     if (!trcF) continue;
    9749         142 :     AliTPCseed* seed = (AliTPCseed*)trcF->GetTPCseed();
    9750         142 :     if (seed) {
    9751          63 :       trcF->RemoveCalibObject((TObject*)seed);
    9752          63 :       seed->SetClusterOwner(kFALSE);
    9753          63 :       seed->SetClustersArrayTMP(0);
    9754          63 :     }
    9755         142 :   }
    9756             :   //
    9757           8 : }
    9758             : 
    9759             : //__________________________________________________________________
    9760             : void AliTPCtracker::CleanESDTracksObjects(TObjArray* trcList)
    9761             : {
    9762             :   // RS: remove seeds stored in friend's calib object contained w/o changing its ownership
    9763             :   //
    9764           8 :   int ntr = trcList->GetEntriesFast();
    9765          28 :   for (int itr=0;itr<ntr;itr++) {
    9766          10 :     TObject *obj = trcList->At(itr);
    9767          30 :     AliESDfriendTrack* trcF =  (obj->IsA()==AliESDtrack::Class()) ? 
    9768          10 :       (AliESDfriendTrack*)((AliESDtrack*)obj)->GetFriendTrack() : (AliESDfriendTrack*)obj;
    9769          10 :     if (!trcF) continue;
    9770          10 :     AliTPCseed* seed = (AliTPCseed*)trcF->GetTPCseed();
    9771          10 :     if (seed) {
    9772           5 :       trcF->RemoveCalibObject((TObject*)seed);
    9773           5 :       seed->SetClusterOwner(kFALSE);
    9774           5 :       seed->SetClustersArrayTMP(0);
    9775           5 :     }
    9776          10 :   }
    9777             :   //
    9778           4 : }

Generated by: LCOV version 1.11