]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/TPCLib/tracking-ca/AliHLTTPCCATracker.cxx
bug fix: reconstruction crash when the output buffer size exceed
[u/mrichter/AliRoot.git] / HLT / TPCLib / tracking-ca / AliHLTTPCCATracker.cxx
index 105ccf23fbd70ed159ed8fc86819c94f247507bd..33cbf568c0b0bda83933b8de8fbf2580358d6072 100644 (file)
 // @(#) $Id$
-//*************************************************************************
-// This file is property of and copyright by the ALICE HLT Project        * 
-// ALICE Experiment at CERN, All rights reserved.                         *
-//                                                                        *
-// Primary Authors: Jochen Thaeder <thaeder@kip.uni-heidelberg.de>        *
-//                  Ivan Kisel <kisel@kip.uni-heidelberg.de>              *
-//                  for The ALICE HLT Project.                            *
-//                                                                        *
-// Permission to use, copy, modify and distribute this software and its   *
-// documentation strictly for non-commercial purposes is hereby granted   *
-// without fee, provided that the above copyright notice appears in all   *
-// copies and that both the copyright notice and this permission notice   *
-// appear in the supporting documentation. The authors make no claims     *
-// about the suitability of this software for any purpose. It is          *
-// provided "as is" without express or implied warranty.                  *
-//*************************************************************************
+// **************************************************************************
+// This file is property of and copyright by the ALICE HLT Project          *
+// ALICE Experiment at CERN, All rights reserved.                           *
+//                                                                          *
+// Primary Authors: Sergey Gorbunov <sergey.gorbunov@kip.uni-heidelberg.de> *
+//                  Ivan Kisel <kisel@kip.uni-heidelberg.de>                *
+//                  for The ALICE HLT Project.                              *
+//                                                                          *
+// Permission to use, copy, modify and distribute this software and its     *
+// documentation strictly for non-commercial purposes is hereby granted     *
+// without fee, provided that the above copyright notice appears in all     *
+// copies and that both the copyright notice and this permission notice     *
+// appear in the supporting documentation. The authors make no claims       *
+// about the suitability of this software for any purpose. It is            *
+// provided "as is" without express or implied warranty.                    *
+//                                                                          *
+//***************************************************************************
 
 #include "AliHLTTPCCATracker.h"
-
-#include "AliHLTTPCCAHit.h"
-#include "AliHLTTPCCACell.h"
 #include "AliHLTTPCCAOutTrack.h"
+#include "AliHLTTPCCARow.h"
+#include "AliHLTTPCCATrack.h"
+#include "AliHLTTPCCATracklet.h"
+#include "AliHLTTPCCAMath.h"
+#include "MemoryAssignmentHelpers.h"
+
+#include "TStopwatch.h"
+#include "AliHLTTPCCAHitArea.h"
+#include "AliHLTTPCCANeighboursFinder.h"
+#include "AliHLTTPCCANeighboursCleaner.h"
+#include "AliHLTTPCCAStartHitsFinder.h"
+#include "AliHLTTPCCATrackletConstructor.h"
+#include "AliHLTTPCCATrackletSelector.h"
+#include "AliHLTTPCCAProcess.h"
+#include "AliHLTTPCCASliceTrack.h"
+#include "AliHLTTPCCASliceOutput.h"
+#include "AliHLTTPCCAClusterData.h"
+
+#include "AliHLTTPCCATrackParam.h"
 
-#include "TMath.h"
-//#include "Riostream.h"
-#include <vector>
-#ifndef __SUNPRO_CC
-#include <algo.h>
+#include "AliHLTTPCCAGPUConfig.h"
+
+#if !defined(HLTCA_GPUCODE)
+#include <iostream>
+#include <iomanip>
+#include <string.h>
 #endif
 
-//#define DRAW
+//#define DRAW1
 
-#ifdef DRAW
+#ifdef DRAW1
 #include "AliHLTTPCCADisplay.h"
-#include "TApplication.h"
-#include "TROOT.h"
-#include "TSystem.h"
-#endif //DRAW
+#endif //DRAW1
 
-ClassImp(AliHLTTPCCATracker);
+#ifdef HLTCA_INTERNAL_PERFORMANCE
+//#include "AliHLTTPCCAPerformance.h"
+#endif
 
+#ifdef HLTCA_STANDALONE
+#include "AliHLTTPCCAStandaloneFramework.h"
+#endif
 
-AliHLTTPCCATracker::AliHLTTPCCATracker()
-  :fParam(),fRows(0),fOutTrackHits(0),fNOutTrackHits(0),fOutTracks(0),fNOutTracks(0),fTrackCells(0),fNHitsTotal(0),fTracks(0),fNTracks(0)
-{
-  // constructor
-  fRows = new AliHLTTPCCARow[fParam.NRows()];
-  Initialize( fParam );
-}
+ClassImp( AliHLTTPCCATracker )
 
-AliHLTTPCCATracker::AliHLTTPCCATracker( const AliHLTTPCCATracker& )
-  :fParam(),fRows(0),fOutTrackHits(0),fNOutTrackHits(0),fOutTracks(0),fNOutTracks(0),fTrackCells(0),fNHitsTotal(0),fTracks(0),fNTracks(0)
-{
-  // dummy
-}
 
-AliHLTTPCCATracker &AliHLTTPCCATracker::operator=( const AliHLTTPCCATracker& )
-{
-  // dummy
-  return *this;
-}
+#if !defined(HLTCA_GPUCODE)
 
 AliHLTTPCCATracker::~AliHLTTPCCATracker()
 {
   // destructor
-  StartEvent();
-  delete[] fRows;
+       if (!fIsGPUTracker)
+       {
+               if (fCommonMem) delete fCommonMem;
+               if (fHitMemory) delete[] fHitMemory;
+               if (fTrackletMemory) delete[] fTrackletMemory;
+               if (fTrackMemory) delete[] fTrackMemory;
+               fCommonMem = NULL;
+               fHitMemory = fTrackMemory = NULL;
+       }
 }
 
 // ----------------------------------------------------------------------------------
-void AliHLTTPCCATracker::Initialize( AliHLTTPCCAParam &param )
+void AliHLTTPCCATracker::Initialize( const AliHLTTPCCAParam &param )
 {
-  // initialosation
-  StartEvent();
-  delete[] fRows;
-  fRows = 0;
+  // initialisation
   fParam = param;
   fParam.Update();
-  fRows = new AliHLTTPCCARow[fParam.NRows()];
-  for( Int_t irow=0; irow<fParam.NRows(); irow++ ){
-    fRows[irow].X() = fParam.RowXFirst() + irow*fParam.RowXStep();
-  }
+  fData.InitializeRows( fParam );
+
   StartEvent();
 }
 
 void AliHLTTPCCATracker::StartEvent()
 {
-  // start new event and fresh the memory  
-  delete[] fTracks;
-  delete[] fTrackCells;
-  delete[] fOutTrackHits;
-  delete[] fOutTracks;
-  fTracks = 0;
-  fTrackCells = 0;
-  fOutTrackHits = 0;
-  fOutTracks = 0;
-  fNTracks = 0;
-  fNOutTrackHits = 0;
-  fNOutTracks = 0;
-  fNHitsTotal = 0;
-  for( Int_t irow=0; irow<fParam.NRows(); irow++ ){
-    fRows[irow].Clear();
-  }
+  // start new event and fresh the memory
+
+  SetupCommonMemory();
 }
 
+void AliHLTTPCCATracker::SetGPUTracker()
+{
+       //Make this a GPU Tracker
+       fIsGPUTracker = true;
+       fData.SetGpuSliceData();
+}
 
-void AliHLTTPCCATracker::ReadHitRow( Int_t iRow, AliHLTTPCCAHit *Row, Int_t NHits )
+char* AliHLTTPCCATracker::SetGPUTrackerCommonMemory(char* const pGPUMemory)
 {
-  // read row of hits
-  AliHLTTPCCARow &row = fRows[iRow];
-  row.Hits() = new AliHLTTPCCAHit[NHits];
-  for( Int_t i=0; i<NHits; i++ ){ 
-    row.Hits()[i]=Row[i];
-    row.Hits()[i].ErrY()*= fParam.YErrorCorrection();
-    row.Hits()[i].ErrZ()*= fParam.ZErrorCorrection();
-  }
-  row.NHits() = NHits;
-  fNHitsTotal += NHits;
+       //Set up common Memory Pointer for GPU Tracker
+  fCommonMem = (commonMemoryStruct*) pGPUMemory;
+  return(pGPUMemory + sizeof(commonMemoryStruct));
 }
 
-void AliHLTTPCCATracker::Reconstruct()
+
+char* AliHLTTPCCATracker::SetGPUTrackerHitsMemory(char* pGPUMemory, int MaxNHits)
 {
-  // reconstruction of event
-  FindCells();
-  FindTracks();
+       //Set up Hits Memory Pointers for GPU Tracker
+       fHitMemory = (char*) pGPUMemory;
+       SetPointersHits(MaxNHits);
+       pGPUMemory += fHitMemorySize;
+       AssignMemory(fTrackletTmpStartHits, pGPUMemory, NHitsTotal());
+       AssignMemory(fRowStartHitCountOffset, pGPUMemory, Param().NRows());
+
+       return(pGPUMemory);
 }
 
+char* AliHLTTPCCATracker::SetGPUTrackerTrackletsMemory(char* pGPUMemory, int MaxNTracks)
+{
+       //Set up Tracklet Memory Pointers for GPU Tracker
+       fTrackletMemory = (char*) pGPUMemory;
+       SetPointersTracklets(MaxNTracks);
+       pGPUMemory += fTrackletMemorySize;
+       AssignMemory(fGPUTrackletTemp, pGPUMemory, MaxNTracks);
+       AssignMemory(fRowBlockTracklets, pGPUMemory, MaxNTracks * 2 * (Param().NRows() / HLTCA_GPU_SCHED_ROW_STEP + 1));
+       AssignMemory(fRowBlockPos, pGPUMemory, 2 * (Param().NRows() / HLTCA_GPU_SCHED_ROW_STEP + 1));
+       AssignMemory(fBlockStartingTracklet, pGPUMemory, HLTCA_GPU_BLOCK_COUNT);
+
+       return(pGPUMemory);
+}
 
-void AliHLTTPCCATracker::FindCells()
+char* AliHLTTPCCATracker::SetGPUTrackerTracksMemory(char* pGPUMemory, int MaxNTracks, int MaxNHits )
 {
-  // cell finder - neighbouring hits are grouped to cells
+       //Set up Tracks Memory Pointer for GPU Tracker
+       fTrackMemory = (char*) pGPUMemory;
+       SetPointersTracks(MaxNTracks, MaxNHits);
+       pGPUMemory += fTrackMemorySize;
 
-  for( Int_t irow=0; irow<fParam.NRows(); irow++ ){
-    AliHLTTPCCARow &row=fRows[irow];
-    Int_t nHits = row.NHits();
-    if( nHits<1 ) continue;
-    row.CellHitPointers() = new Int_t[ nHits ];
-    Int_t nPointers = 0;
-    std::vector<AliHLTTPCCACell> vCells; 
-    Bool_t vUsed[10000];
-    for (Int_t ih = 0; ih<nHits; ih++) vUsed[ih] = 0;
-  
-    for (Int_t ih = 0; ih<nHits; ih++){    
-      if( vUsed[ih] ) continue;
-      // cell start
-      AliHLTTPCCACell cell;
-      cell.FirstHitRef() = nPointers;
-      cell.NHits() = 1;
-      cell.IDown() = -1;
-      cell.IUp() = -1;
-      cell.IUsed() = 0;
-      row.CellHitPointers()[nPointers++] = ih;
-      vUsed[ih] = 1;
-      Int_t jLast = ih;
-      while( jLast<nHits-1 ){
-       AliHLTTPCCAHit &h  = row.Hits()[jLast];    
-       Double_t d2min = 1.e10;
-       Int_t jBest = -1;
-       for (Int_t j = jLast+1; j<nHits; j++){    
-         if( vUsed[j] ) continue;
-         AliHLTTPCCAHit &h1  = row.Hits()[j];
-         Double_t dy = TMath::Abs(h.Y() - h1.Y() );
-         if( dy>(h.ErrY()+h1.ErrY())*4. ) break;
-         Double_t dz = TMath::Abs(h.Z() - h1.Z() );
-         if( dz>(h.ErrZ()+h1.ErrZ())*4. ) continue;
-         Double_t d2 = dz*dz+dy*dy;
-         if( d2<d2min ){
-           d2min = d2;
-           jBest = j;
-         }
-       }
-       if( jBest<0 ) break;
-       row.CellHitPointers()[nPointers++] = jBest;
-       cell.NHits()++;
-       vUsed[jBest] = 1;     
-       jLast = jBest;
-      }
-
-      AliHLTTPCCAHit &h = row.GetCellHit(cell,0);
-      AliHLTTPCCAHit &h1= row.GetCellHit(cell,cell.NHits()-1);
-    
-      cell.Y() = .5*(h.Y() + h1.Y());
-      cell.Z() = .5*(h.Z() + h1.Z());
-      cell.ErrY() = .5*(TMath::Abs(h.Y() - h1.Y())/3 + h.ErrY() + h1.ErrY());
-      cell.ErrZ() = .5*(TMath::Abs(h.Z() - h1.Z())/3 + h.ErrZ() + h1.ErrZ());
-      vCells.push_back(cell);
-    }
-    
-    row.Cells() = new AliHLTTPCCACell[vCells.size()];
-    row.NCells() = vCells.size();
-    for( Int_t i=0; i<vCells.size(); i++ ) row.Cells()[i]=vCells[i];  
-  }
+       return(pGPUMemory);
 }
 
+void AliHLTTPCCATracker::DumpSliceData(std::ostream &out)
+{
+       //Dump Slice Input Data to File
+       out << "Slice Data:" << std::endl;
+       for (int i = 0;i < Param().NRows();i++)
+       {
+               out << "Row: " << i << std::endl;
+               for (int j = 0;j < Row(i).NHits();j++)
+               {
+                       if (j && j % 16 == 0) out << std::endl;
+                       out << j << '-' << Data().HitDataY(Row(i), j) << '-' << Data().HitDataZ(Row(i), j) << ", ";
+               }
+               out << std::endl;
+       }
+}
 
-void AliHLTTPCCATracker::FindTracks()
+void AliHLTTPCCATracker::DumpLinks(std::ostream &out)
 {
-  // the Cellular Automaton track finder
-  
-  if( fNHitsTotal < 1 ) return;
+       //Dump Links (after Neighbours Finder / Cleaner) to file
+       out << "Hit Links:" << std::endl;
+       for (int i = 0;i < Param().NRows();i++)
+       {
+               out << "Row: " << i << std::endl;
+               for (int j = 0;j < Row(i).NHits();j++)
+               {
+                       if (j && j % 32 == 0) out << std::endl;
+                       out << HitLinkUpData(Row(i), j) << "/" << HitLinkDownData(Row(i), j) << ", ";
+               }
+               out << std::endl;
+       }
+}
 
-#ifdef DRAW
-  if( !gApplication ){
-    TApplication *myapp = new TApplication("myapp",0,0);
-  }
-  AliHLTTPCCADisplay::Instance().SetCurrentSector( this );
-  AliHLTTPCCADisplay::Instance().DrawSector( this );
-  //for (Int_t i = 0; i<fHits.size(); i++) AliHLTTPCCADisplay::Instance().DrawHit( i );
-  //cout<<"hits"<<endl;
-  //AliHLTTPCCADisplay::Instance().Ask();
-  //AliHLTTPCCADisplay::Instance().Clear();
-  //AliHLTTPCCADisplay::Instance().DrawSector( this );
-  for( Int_t iRow=0; iRow<fParam.NRows(); iRow++ )
-    for (Int_t i = 0; i<fRows[iRow].NCells(); i++) 
-      AliHLTTPCCADisplay::Instance().DrawCell( iRow, i );
-  //cout<<"cells"<<endl;
-  AliHLTTPCCADisplay::Instance().Ask();
-  Int_t nConnectedCells = 0;
-#endif 
-
-  std::vector<AliHLTTPCCATrack> vTracks; 
-  std::vector<Int_t> vTrackCells; 
-  fTrackCells = new Int_t[2*fNHitsTotal];
-
-  for( Int_t iRow1=0; iRow1<fParam.NRows()-1; iRow1++ ){
-    AliHLTTPCCARow &row1 = fRows[iRow1];
-    Int_t lastRow2 = iRow1+3;
-    if( lastRow2>=fParam.NRows() ) lastRow2 = fParam.NRows()-1;    
-    for( Int_t iRow2=iRow1+1; iRow2<=lastRow2; iRow2++ ){
-      AliHLTTPCCARow &row2 = fRows[iRow2];
-      for (Int_t i1 = 0; i1<row1.NCells(); i1++){
-       AliHLTTPCCACell *c1  = &(row1.Cells()[i1]);
-       if( c1->IUp()>=0 ) continue;
-       Double_t sy1 = c1->ErrY()*c1->ErrY();
-       Double_t sz1 = c1->ErrZ()*c1->ErrZ();
-       for (Int_t i2 = 0; i2<row2.NCells(); i2++){
-         AliHLTTPCCACell *c2  = &(row2.Cells()[i2]);
-         Double_t sy2 = c2->ErrY()*c2->ErrY();
-         Double_t sz2 = c2->ErrZ()*c2->ErrZ();
-         Double_t dist1 = sqrt( (c1->Y()-c2->Y())*(c1->Y()-c2->Y())/(sy1+sy2) );
-         Double_t dist2 = sqrt( (c1->Z()-c2->Z())*(c1->Z()-c2->Z())/(sz1+sz2) );
-         if( dist1>3.5*fParam.CellConnectionFactor() ) continue;
-         if( dist2>3.5*fParam.CellConnectionFactor() ) continue;
-         if( c1->IUp() ==-1 ) c1->IUp() = (i2<<8)+iRow2;
-         else c1->IUp() = -2;
-         if( c2->IDown() ==-1 ) c2->IDown() = (i1<<8)+iRow1;
-         else c2->IDown() = -2;
+void AliHLTTPCCATracker::DumpHitWeights(std::ostream &out)
+{
+       //dump hit weights to file
+    out << "Hit Weights:" << std::endl;
+    for (int i = 0;i < Param().NRows();i++)
+    {
+       out << "Row: " << i << ":" << std::endl;
+       for (int j = 0;j < Row(i).NHits();j++)
+       {
+           if (j && j % 32 == 0) out << std::endl;
+           out << HitWeight(Row(i), j) << ", ";
        }
-      }
+       out << std::endl;
     }
-  }
+}
 
-  Int_t nOutTrackHits = 0;
-  Int_t nTrackCells = 0;
-  for( Int_t iRow1=0; iRow1<fParam.NRows(); iRow1++ ){
-    AliHLTTPCCARow &row1 = fRows[iRow1];
-    for (Int_t i1 = 0; i1<row1.NCells(); i1++){ 
-      AliHLTTPCCACell *c1  = &(row1.Cells()[i1]);
-      if( c1->IDown()==-2 || c1->IUp()==-2 ) continue;
-      if( c1->IUsed()>0 ) continue;
-      c1->IUsed() = 1;
-      AliHLTTPCCATrack track;
-      track.Used() = 0;
-      track.NCells() = 1;
-      track.IFirstCell() = nTrackCells;
-      fTrackCells[nTrackCells++] = (i1<<8)+iRow1;
-      AliHLTTPCCACell *last = c1;
-      Int_t lastRow = iRow1;
-      while( last->IUp() >=0 ){
-       Int_t iRow2 = last->IUp()%256;
-       AliHLTTPCCARow &row2 = fRows[iRow2];
-       AliHLTTPCCACell *next = &(row2.Cells()[last->IUp()>>8]);
-       if( next->IDown()==-2 || next->IUp()==-2 ) break;
-#ifdef DRAW
-       AliHLTTPCCADisplay::Instance().ConnectCells( lastRow,*last,iRow2,*next );
-       nConnectedCells++;
-#endif 
-       next->IUsed() = 1;      
-       fTrackCells[nTrackCells++] = last->IUp();
-       track.NCells()++;
-       last = next;
-       lastRow = iRow2;
-      } 
-      vTracks.push_back(track);
-    }
-  }
-  
-  Int_t nTracks = vTracks.size();
-  std::sort( vTracks.begin(), vTracks.end(), AliHLTTPCCATrack::CompareSize);
-  
-  fTracks = new AliHLTTPCCATrack[nTracks];
-  fNTracks = 0;
-  vTrackCells.clear();
-  Int_t * vMatchedTracks = new Int_t[nTracks];
-  for( Int_t itr=0; itr<nTracks; itr++ ){
-    AliHLTTPCCATrack &iTrack = vTracks[itr];
-    if( iTrack.Used() ) continue;    
-    FitTrack( iTrack );
-    if( iTrack.Param().Chi2() > fParam.TrackChi2Cut()*iTrack.Param().NDF() ) continue;    
-
-    Int_t iFirstRow =  GetTrackCellIRow( iTrack, 0);
-    Int_t iLastRow  =  GetTrackCellIRow( iTrack, iTrack.NCells()-1);
-    AliHLTTPCCACell *iFirstCell = &GetTrackCell( iTrack, 0);
-    AliHLTTPCCACell *iLastCell = &GetTrackCell( iTrack, iTrack.NCells()-1);
-    
-    Bool_t updated = 1;
-    Int_t nMatched = 0;
-    std::vector<Int_t> vMatchedCells;
-    while( updated ){
-      updated = 0;
-      for( Int_t jtr=1; jtr<nTracks; jtr++ ){
-       AliHLTTPCCATrack &jTrack = vTracks[jtr];
-       if( jTrack.Used() ) continue;
-       Int_t jFirstRow =  GetTrackCellIRow( jTrack, 0);
-       Int_t jLastRow =  GetTrackCellIRow( jTrack, jTrack.NCells()-1);
-       AliHLTTPCCACell *jFirstCell = &GetTrackCell( jTrack, 0);
-       AliHLTTPCCACell *jLastCell = &GetTrackCell( jTrack, jTrack.NCells()-1);
-
-       Int_t dFirstRow1 = TMath::Abs(iFirstRow-jLastRow);
-       Int_t dFirstRow2 = TMath::Abs(iFirstRow-jFirstRow);
-       Int_t dLastRow1 = TMath::Abs(iLastRow-jLastRow);
-       Int_t dLastRow2 = TMath::Abs(iLastRow-jFirstRow);
-       if( dFirstRow1 > fParam.MaxTrackMatchDRow() && 
-           dFirstRow2 > fParam.MaxTrackMatchDRow() &&
-           dLastRow1  > fParam.MaxTrackMatchDRow() && 
-           dLastRow2  > fParam.MaxTrackMatchDRow()    ) continue;
-       Int_t iCase=0;
-       AliHLTTPCCACell *iC, *jC;
-       if( dFirstRow1<dFirstRow2 && dFirstRow1<dLastRow1 && dFirstRow1<dLastRow2 ){
-         iCase = 0;
-         iC = iFirstCell;
-         jC = jLastCell;
-       }else if( dFirstRow2<dLastRow1 && dFirstRow2<dLastRow2 ){
-         iCase = 1;
-         iC = iFirstCell;
-         jC = jFirstCell;
-       }else if( dLastRow1<dLastRow2 ){
-         iCase = 2;
-         iC = iLastCell; 
-         jC = jLastCell;
-       }else{
-         iCase = 3;
-         iC = iLastCell; 
-         jC = jFirstCell;
+int AliHLTTPCCATracker::StarthitSortComparison(const void*a, const void* b)
+{
+       //qsort helper function to sort start hits
+       AliHLTTPCCAHitId* aa = (AliHLTTPCCAHitId*) a;
+       AliHLTTPCCAHitId* bb = (AliHLTTPCCAHitId*) b;
+
+       if (aa->RowIndex() != bb->RowIndex()) return(aa->RowIndex() - bb->RowIndex());
+       return(aa->HitIndex() - bb->HitIndex());
+}
+
+void AliHLTTPCCATracker::DumpStartHits(std::ostream &out)
+{
+       //sort start hits and dump to file
+       out << "Start Hits: (" << *NTracklets() << ")" << std::endl;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+       qsort(TrackletStartHits(), *NTracklets(), sizeof(AliHLTTPCCAHitId), StarthitSortComparison);
+#endif
+       for (int i = 0;i < *NTracklets();i++)
+       {
+               out << TrackletStartHit(i).RowIndex() << "-" << TrackletStartHit(i).HitIndex() << std::endl;
        }
+       out << std::endl;
+}
+
+void AliHLTTPCCATracker::DumpTrackHits(std::ostream &out)
+{
+       //dump tracks to file
+       out << "Tracks: (" << *NTracks() << ")" << std::endl;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+       for (int k = 0;k < Param().NRows();k++)
        {
-         Double_t dy = TMath::Abs(iC->Y() - jC->Y());
-         Double_t dz = TMath::Abs(iC->Z() - jC->Z());
-         Double_t sy1 = iC->ErrY()*iC->ErrY();
-         Double_t sz1 = iC->ErrZ()*iC->ErrZ();
-         Double_t sy2 = jC->ErrY()*jC->ErrY();
-         Double_t sz2 = jC->ErrZ()*jC->ErrZ();
-         Double_t dist1 = sqrt( (dy)/(sy1+sy2) );
-         Double_t dist2 = sqrt( (dz)/(sz1+sz2) );
-         if( dist1>3.5*5*fParam.CellConnectionFactor() ) continue;
-         if( dist2>3.5*5*fParam.CellConnectionFactor() ) continue;
+               for (int l = 0;l < Row(k).NHits();l++)
+               {
+#endif
+                       for (int j = 0;j < *NTracks();j++)
+                       {
+                               if (Tracks()[j].NHits() == 0 || !Tracks()[j].Alive()) continue;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+                               if (TrackHits()[Tracks()[j].FirstHitID()].RowIndex() == k && TrackHits()[Tracks()[j].FirstHitID()].HitIndex() == l)
+                               {
+#endif
+                                       for (int i = 0;i < Tracks()[j].NHits();i++)
+                                       {
+                                               out << TrackHits()[Tracks()[j].FirstHitID() + i].RowIndex() << "-" << TrackHits()[Tracks()[j].FirstHitID() + i].HitIndex() << ", ";
+                                       }
+                                       out << "(Track: " << j << ")" << std::endl;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+                               }
+                       }       
+#endif
+               }       
+#ifdef HLTCA_GPU_SORT_DUMPDATA
        }
-       AliHLTTPCCATrackPar t = iTrack.Param();
-       //t.Chi2() = 0;
-       //t.NDF() = 0;
-       for( Int_t i=0; i<jTrack.NCells() ; i++){
-         AliHLTTPCCACell &c = GetTrackCell(jTrack,i);  
-         AliHLTTPCCARow &row = GetTrackCellRow(jTrack,i);
-         for( Int_t j=0; j<c.NHits(); j++){
-           AliHLTTPCCAHit &h = row.GetCellHit(c,j);
-           Double_t m[3] = {row.X(), h.Y(), h.Z() };
-           Double_t mV[6] = {fParam.ErrX()*fParam.ErrX(), 0, h.ErrY()*h.ErrY(), 0, 0, h.ErrZ()*h.ErrZ() };
-           Double_t mV1[6];
-           t.TransportBz(fParam.Bz(),m);
-           t.GetConnectionMatrix(fParam.Bz(),m, mV1);
-           t.Filter(m, mV, mV1);
-         }
+#endif
+}
+
+void AliHLTTPCCATracker::DumpTrackletHits(std::ostream &out)
+{
+       //dump tracklets to file
+       out << "Tracklets: (" << *NTracklets() << ")" << std::endl;
+#ifdef HLTCA_GPU_SORT_DUMPDATA
+       AliHLTTPCCAHitId* tmpIds = new AliHLTTPCCAHitId[*NTracklets()];
+       AliHLTTPCCATracklet* tmpTracklets = new AliHLTTPCCATracklet[*NTracklets()];
+       memcpy(tmpIds, TrackletStartHits(), *NTracklets() * sizeof(AliHLTTPCCAHitId));
+       memcpy(tmpTracklets, Tracklets(), *NTracklets() * sizeof(AliHLTTPCCATracklet));
+#ifdef EXTERN_ROW_HITS
+       int* tmpHits = new int[*NTracklets() * Param().NRows()];
+       memcpy(tmpHits, TrackletRowHits(), *NTracklets() * Param().NRows() * sizeof(int));
+#endif
+       qsort(TrackletStartHits(), *NTracklets(), sizeof(AliHLTTPCCAHitId), StarthitSortComparison);
+       for (int i = 0;i < *NTracklets();i++)
+       {
+               for (int j = 0;j < *NTracklets();j++)
+               {
+                       if (tmpIds[i].RowIndex() == TrackletStartHit(j).RowIndex() && tmpIds[i].HitIndex() == TrackletStartHit(j).HitIndex())
+                       {
+                               memcpy(&Tracklets()[j], &tmpTracklets[i], sizeof(AliHLTTPCCATracklet));
+#ifdef EXTERN_ROW_HITS
+                               if (tmpTracklets[i].NHits())
+                               {
+                                       for (int k = tmpTracklets[i].FirstRow();k <= tmpTracklets[i].LastRow();k++)
+                                       {
+                                               fTrackletRowHits[k * *NTracklets() + j] = tmpHits[k * *NTracklets() + i];
+                                       }
+                               }
+#endif
+                               break;
+                       }
+               }
        }
-       if( t.Chi2() > fParam.TrackChi2Cut()*t.NDF() ) continue;
-       if( iCase==0 ){
-         iFirstRow = jFirstRow;
-         iFirstCell = jFirstCell;
-       }else if( iCase ==1 ){
-         iFirstRow = jLastRow;
-         iFirstCell = jLastCell;
-       }else if( iCase == 2 ){
-         iLastRow = jFirstRow;
-         iLastCell = jFirstCell;
-       }else{
-         iLastRow = jLastRow;
-         iLastCell = jLastCell;
+       delete[] tmpIds;
+       delete[] tmpTracklets;
+#ifdef EXTERN_ROW_HITS
+       delete[] tmpHits;
+#endif
+#endif
+       for (int j = 0;j < *NTracklets();j++)
+       {
+               out << "Tracklet " << j << " (Hits: " << std::setw(3) << Tracklets()[j].NHits() << ", Start: " << std::setw(3) << TrackletStartHit(j).RowIndex() << "-" << std::setw(3) << TrackletStartHit(j).HitIndex() << ") ";
+               if (Tracklets()[j].NHits() == 0);
+               else if (Tracklets()[j].LastRow() > Tracklets()[j].FirstRow() && (Tracklets()[j].FirstRow() >= Param().NRows() || Tracklets()[j].LastRow() >= Param().NRows()))
+               {
+#ifdef HLTCA_STANDALONE
+                       printf("\nError: First %d Last %d Num %d", Tracklets()[j].FirstRow(), Tracklets()[j].LastRow(), Tracklets()[j].NHits());
+#endif
+               }
+               else if (Tracklets()[j].NHits() && Tracklets()[j].LastRow() > Tracklets()[j].FirstRow())
+               {
+                       for (int i = Tracklets()[j].FirstRow();i <= Tracklets()[j].LastRow();i++)
+                       {
+                               //if (Tracklets()[j].RowHit(i) != -1)
+#ifdef EXTERN_ROW_HITS
+                                       out << i << "-" << fTrackletRowHits[i * fCommonMem->fNTracklets + j] << ", ";
+#else
+                                       out << i << "-" << Tracklets()[j].RowHit(i) << ", ";
+#endif
+                       }
+               }
+               out << std::endl;
        }
-       t.Normalize();
+}
 
-       for( Int_t i=0; i<jTrack.NCells(); i++){
-         vMatchedCells.push_back(fTrackCells[jTrack.IFirstCell()+i]);
-       }
-       //t.NDF()+= iTrack.Param().NDF();
-       //t.Chi2()+= iTrack.Param().Chi2();
-       iTrack.Param() = t;
-       vMatchedTracks[nMatched++] = jtr;
-       jTrack.Used()=1;
-       updated = 1;
-       break;
-      }
+
+void AliHLTTPCCATracker::SetupCommonMemory()
+{
+  // set up common memory
+
+  if (!fIsGPUTracker)
+  {
+    if ( !fCommonMem ) {
+      // the 1600 extra bytes are not used unless fCommonMemorySize increases with a later event
+      //fCommonMemory = reinterpret_cast<char*> ( new uint4 [ fCommonMemorySize/sizeof( uint4 ) + 100] );
+         fCommonMem = new commonMemoryStruct;
     }
 
-    if(0){
-      Double_t t0[7];
-      for( Int_t i=0; i<7; i++ ) t0[i] = iTrack.Param().Par()[i];
-      iTrack.Param().Init();
-      for( Int_t i=0; i<7; i++ ) iTrack.Param().Par()[i] = t0[i];
-      for( Int_t i=0; i<iTrack.NCells() ; i++){
-       AliHLTTPCCACell &c = GetTrackCell( iTrack, i);
-       AliHLTTPCCARow &row = GetTrackCellRow( iTrack, i);
-       for( Int_t j=0; j<c.NHits(); j++){
-         AliHLTTPCCAHit &h = row.GetCellHit(c,j);
-         Double_t m[3] = {row.X(), h.Y(), h.Z() };
-         Double_t mV[6] = {0, 0, h.ErrY()*h.ErrY(), 0, 0, h.ErrZ()*h.ErrZ() };
-         Double_t mV1[6];
-         iTrack.Param().TransportBz(fParam.Bz(), m, t0);
-         iTrack.Param().GetConnectionMatrix(fParam.Bz(), m, mV1, t0);
-         iTrack.Param().Filter(m, mV, mV1);
+       if (fHitMemory) delete[] fHitMemory;
+       if (fTrackletMemory) delete[] fTrackletMemory;
+       if (fTrackMemory) delete[] fTrackMemory;
+  }
+
+  fHitMemory = fTrackletMemory = fTrackMemory = 0;
+
+  fData.Clear();
+  fCommonMem->fNTracklets = 0;
+  fCommonMem->fNTracks = 0 ;
+  fCommonMem->fNTrackHits = 0;
+}
+
+void AliHLTTPCCATracker::ReadEvent( AliHLTTPCCAClusterData *clusterData )
+{
+  // read event
+
+  fClusterData = clusterData;
+
+  StartEvent();
+
+  //* Convert input hits, create grids, etc.
+  fData.InitFromClusterData( *clusterData );
+  {
+    if (!fIsGPUTracker)
+       {
+               SetPointersHits( fData.NumberOfHits() ); // to calculate the size
+               fHitMemory = reinterpret_cast<char*> ( new uint4 [ fHitMemorySize/sizeof( uint4 ) + 100] );
        }
-      }
-      iTrack.Param().Normalize();
-    }
-    //FitTrack(iTrack,5);
-    Int_t nHits = 0;
-    for( Int_t iCell=0; iCell<iTrack.NCells(); iCell++){
-      Int_t ind = fTrackCells[iTrack.IFirstCell()+iCell];
-      AliHLTTPCCARow &row = fRows[ind%256];
-      AliHLTTPCCACell &c = row.Cells()[ind>>8];
-      nHits+=c.NHits();
-    }
-    for( UInt_t i=0; i<vMatchedCells.size(); i++){
-      Int_t ind = vMatchedCells[i];
-      AliHLTTPCCARow &row = fRows[ind%256];
-      AliHLTTPCCACell &c = row.Cells()[ind>>8];
-      nHits+=c.NHits();
-    }
+    SetPointersHits( fData.NumberOfHits() ); // set pointers for hits
+  }
+}
+
+GPUhd() void  AliHLTTPCCATracker::SetPointersHits( int MaxNHits )
+{
+  // set all pointers to the event memory
+
+  char *mem = fHitMemory;
+
+  // extra arrays for tpc clusters
+
+#ifdef HLTCA_GPU_SORT_STARTHITS_2
+  AssignMemory( fTrackletStartHits, mem, MaxNHits + 32);
+#else
+  AssignMemory( fTrackletStartHits, mem, MaxNHits);
+#endif
 
-    if( nHits<5 ){
-      for( Int_t i=0; i<nMatched; i++ ) vTracks[vMatchedTracks[i]].Used()=0;
-      continue;
+  // calculate the size
+
+  fHitMemorySize = mem - fHitMemory;
+}
+
+GPUhd() void  AliHLTTPCCATracker::SetPointersTracklets( int MaxNTracklets )
+{
+  // set all pointers to the tracklets memory
+  char *mem = fTrackletMemory;
+
+  // memory for tracklets
+
+  AssignMemory( fTracklets, mem, MaxNTracklets );
+#ifdef EXTERN_ROW_HITS
+  AssignMemory( fTrackletRowHits, mem, MaxNTracklets * Param().NRows());
+#endif
+
+  fTrackletMemorySize = mem - fTrackletMemory;
+}
+
+
+GPUhd() void  AliHLTTPCCATracker::SetPointersTracks( int MaxNTracks, int MaxNHits )
+{
+  // set all pointers to the tracks memory
+  char *mem = fTrackMemory;
+
+  // memory for selected tracks
+
+  AssignMemory( fTracks, mem, MaxNTracks );
+  AssignMemory( fTrackHits, mem, 2 * MaxNHits );
+
+  // calculate the size
+
+  fTrackMemorySize = mem - fTrackMemory;
+}
+
+GPUh() int AliHLTTPCCATracker::CheckEmptySlice() const
+{
+       //Check if the Slice is empty, if so set the output apropriate and tell the reconstuct procesdure to terminate
+  if ( NHitsTotal() < 1 ) {
+    {
+      AliHLTTPCCASliceOutput::Allocate(*fOutput, 0, 0, fOutputControl);
+      AliHLTTPCCASliceOutput* useOutput = *fOutput;
+      if (useOutput == NULL) return(1);
+      useOutput->SetNTracks( 0 );
+      useOutput->SetNTrackClusters( 0 );
+      useOutput->SetNOutTracks(0);
+      useOutput->SetNOutTrackHits(0);
     }
-    iTrack.Used() = 1;
-    Int_t oldNCells = vTrackCells.size();
-    for( Int_t i=0; i<iTrack.NCells() ; i++){
-      vTrackCells.push_back(fTrackCells[iTrack.IFirstCell()+i]);
-    }      
-    iTrack.IFirstCell() = oldNCells;
-    for( UInt_t i=0; i<vMatchedCells.size(); i++){
-      vTrackCells.push_back(vMatchedCells[i]);
-      iTrack.NCells()++;
-    }      
-    fTracks[fNTracks++] = iTrack;  
-    nOutTrackHits+= nHits;  
+
+    return 1;
+  }
+  return 0;
+}
+
+void AliHLTTPCCATracker::RunNeighboursFinder()
+{
+       //Run the CPU Neighbours Finder
+       AliHLTTPCCAProcess<AliHLTTPCCANeighboursFinder>( Param().NRows(), 1, *this );
+}
+
+void AliHLTTPCCATracker::RunNeighboursCleaner()
+{
+       //Run the CPU Neighbours Cleaner
+       AliHLTTPCCAProcess<AliHLTTPCCANeighboursCleaner>( Param().NRows() - 2, 1, *this );
+}
+
+void AliHLTTPCCATracker::RunStartHitsFinder()
+{
+       //Run the CPU Start Hits Finder
+       AliHLTTPCCAProcess<AliHLTTPCCAStartHitsFinder>( Param().NRows() - 4, 1, *this );
+}
+
+void AliHLTTPCCATracker::RunTrackletConstructor()
+{
+       //Run CPU Tracklet Constructor
+  AliHLTTPCCATrackletConstructor::AliHLTTPCCATrackletConstructorNewCPU(*this);
+}
+
+void AliHLTTPCCATracker::RunTrackletSelector()
+{
+       //Run CPU Tracklet Selector
+  AliHLTTPCCAProcess<AliHLTTPCCATrackletSelector>( 1, fCommonMem->fNTracklets, *this );
+}
+
+#ifdef HLTCA_STANDALONE
+void AliHLTTPCCATracker::StandalonePerfTime(int i)
+{
+  //Query Performance Timer for Standalone Version of Tracker
+  if (fGPUDebugLevel >= 1)
+  {
+    AliHLTTPCCAStandaloneFramework::StandaloneQueryTime(&fPerfTimers[i]);
+  }
+}
+#else
+void AliHLTTPCCATracker::StandalonePerfTime(int /*i*/) {}
+#endif
+
+GPUh() void AliHLTTPCCATracker::Reconstruct()
+{
+  //* reconstruction of event
+  //std::cout<<"Reconstruct slice "<<fParam.ISlice()<<", nHits="<<NHitsTotal()<<std::endl;
+
+  fTimers[0] = 0; // find neighbours
+  fTimers[1] = 0; // construct tracklets
+  fTimers[2] = 0; // fit tracklets
+  fTimers[3] = 0; // prolongation of tracklets
+  fTimers[4] = 0; // selection
+  fTimers[5] = 0; // write output
+  fTimers[6] = 0;
+  fTimers[7] = 0;
+
+  //if( fParam.ISlice()<1 ) return; //SG!!!
+
+  TStopwatch timer0;
+
+  StandalonePerfTime(0);
+
+  if (CheckEmptySlice()) return;
+
+#ifdef DRAW1
+  //if( fParam.ISlice()==2 || fParam.ISlice()==3)
+    {
+  AliHLTTPCCADisplay::Instance().ClearView();
+  AliHLTTPCCADisplay::Instance().SetSliceView();
+  AliHLTTPCCADisplay::Instance().SetCurrentSlice( this );
+  AliHLTTPCCADisplay::Instance().DrawSlice( this, 1 );
+  if ( NHitsTotal() > 0 ) {
+    AliHLTTPCCADisplay::Instance().DrawSliceHits( kRed, .5 );
+    AliHLTTPCCADisplay::Instance().Ask();
+  }
+  }
+#endif //DRAW1
+
+       fCommonMem->fNTracklets = fCommonMem->fNTracks = fCommonMem->fNTrackHits = 0;
+
+#if !defined(HLTCA_GPUCODE)
+
+  if (fGPUDebugLevel >= 6)
+  {
+         *fGPUDebugOut << std::endl << std::endl << "Slice: " << Param().ISlice() << std::endl;
+         *fGPUDebugOut << "Slice Data:" << std::endl;
+         DumpSliceData(*fGPUDebugOut);
   }
-  delete [] vMatchedTracks;
 
-  //fTrackCells = new Int_t[vTrackCells.size()];
-  for( UInt_t i=0; i<vTrackCells.size(); i++ ) fTrackCells[i] = vTrackCells[i];
+  StandalonePerfTime(1);
+
+  RunNeighboursFinder();
+
+  StandalonePerfTime(2);
+
+  if (fGPUDebugLevel >= 6) DumpLinks(*fGPUDebugOut);
   
-#ifdef DRAW
-  if( nConnectedCells>0 ) AliHLTTPCCADisplay::Instance().Ask();
-#endif 
-
-
-  fOutTrackHits = new Int_t[nOutTrackHits];
-  fNOutTrackHits = 0;
-  fNOutTracks = fNTracks;
-  fOutTracks = new AliHLTTPCCAOutTrack[fNOutTracks];
-  for( Int_t itr=0; itr<fNOutTracks; itr++ ){
-    AliHLTTPCCATrack &t = fTracks[itr];
-#ifdef DRAW
-  AliHLTTPCCADisplay::Instance().DrawTrack( t );
-#endif 
-    AliHLTTPCCAOutTrack &tmp = fOutTracks[itr];
-    tmp.FirstHitRef() = fNOutTrackHits;
-    tmp.NHits() = 0;
-    tmp.Param() = t.Param();
-    for( Int_t iCell=0; iCell<t.NCells(); iCell++){
-      AliHLTTPCCACell &cell = GetTrackCell(t,iCell);
-      AliHLTTPCCARow &row = GetTrackCellRow(t,iCell);
-      for( Int_t iHit=0; iHit<cell.NHits(); iHit++ ){
-       AliHLTTPCCAHit &hit = row.GetCellHit(cell,iHit);
-       fOutTrackHits[fNOutTrackHits] = hit.ID();
-       fNOutTrackHits++;
-       tmp.NHits()++;
-      }
-    }
-  }  
+#ifdef HLTCA_INTERNAL_PERFORMANCE
+  //if( Param().ISlice()<=2 )
+  //AliHLTTPCCAPerformance::Instance().LinkPerformance( Param().ISlice() );
+#endif
+
+
+#ifdef DRAW1
+  if ( NHitsTotal() > 0 ) {
+    AliHLTTPCCADisplay::Instance().DrawSliceLinks( -1, -1, 1 );
+    AliHLTTPCCADisplay::Instance().Ask();
+  }
+#endif //DRAW1
+
+  RunNeighboursCleaner();
+
+  StandalonePerfTime(3);
+
+  if (fGPUDebugLevel >= 6) DumpLinks(*fGPUDebugOut);
+
+  RunStartHitsFinder();
+
+  StandalonePerfTime(4);
+  StandalonePerfTime(5);
+
+  if (fGPUDebugLevel >= 6) DumpStartHits(*fGPUDebugOut);
   
-#ifdef DRAW
-  AliHLTTPCCADisplay::Instance().Ask();
-  //AliHLTTPCCADisplay::Instance().DrawMCTracks(fParam.fISec);
-  //AliHLTTPCCADisplay::Instance().Update();
-  //AliHLTTPCCADisplay::Instance().Ask();
-#endif 
+  fData.ClearHitWeights();
+
+  SetPointersTracklets( fCommonMem->fNTracklets * 2 ); // to calculate the size
+  fTrackletMemory = reinterpret_cast<char*> ( new uint4 [ fTrackletMemorySize/sizeof( uint4 ) + 100] );
+  SetPointersTracklets( fCommonMem->fNTracklets * 2 ); // set pointers for hits
+
+  SetPointersTracks( fCommonMem->fNTracklets * 2, NHitsTotal() ); // to calculate the size
+  fTrackMemory = reinterpret_cast<char*> ( new uint4 [ fTrackMemorySize/sizeof( uint4 ) + 100] );
+  SetPointersTracks( fCommonMem->fNTracklets * 2, NHitsTotal() ); // set pointers for hits
+
+  StandalonePerfTime(6);
+  StandalonePerfTime(7);
+
+  RunTrackletConstructor();
+
+  StandalonePerfTime(8);
+
+  if (fGPUDebugLevel >= 6) DumpTrackletHits(*fGPUDebugOut);
+  if (fGPUDebugLevel >= 6) DumpHitWeights(*fGPUDebugOut);
+
+  //std::cout<<"Slice "<<Param().ISlice()<<": NHits="<<NHitsTotal()<<", NTracklets="<<*NTracklets()<<std::endl;
+
+  RunTrackletSelector();
+
+  StandalonePerfTime(9);
+
+  //std::cout<<"Slice "<<Param().ISlice()<<": N start hits/tracklets/tracks = "<<nStartHits<<" "<<nStartHits<<" "<<*fNTracks<<std::endl;
+
+  if (fGPUDebugLevel >= 6) DumpTrackHits(*fGPUDebugOut);
+
+  //std::cout<<"Memory used for slice "<<fParam.ISlice()<<" : "<<fCommonMemorySize/1024./1024.<<" + "<<fHitMemorySize/1024./1024.<<" + "<<fTrackMemorySize/1024./1024.<<" = "<<( fCommonMemorySize+fHitMemorySize+fTrackMemorySize )/1024./1024.<<" Mb "<<std::endl;
+
+  WriteOutput();
+
+  StandalonePerfTime(10);
+
+#endif
+
+#ifdef DRAW1
+  {
+    AliHLTTPCCADisplay &disp = AliHLTTPCCADisplay::Instance();
+    AliHLTTPCCATracker &slice = *this;
+    std::cout << "N out tracks = " << slice.NOutTracks() << std::endl;
+    AliHLTTPCCADisplay::Instance().SetSliceView();
+    AliHLTTPCCADisplay::Instance().SetCurrentSlice( this );
+    AliHLTTPCCADisplay::Instance().DrawSlice( this, 1 );
+    disp.DrawSliceHits( kRed, .5 );
+    disp.Ask();
+    for ( int itr = 0; itr < slice.NOutTracks(); itr++ ) {
+      std::cout << "track N " << itr << ", nhits=" << slice.OutTracks()[itr].NHits() << std::endl;
+      disp.DrawSliceOutTrack( itr, kBlue );      
+      //disp.Ask();
+      //int id = slice.OutTracks()[itr].OrigTrackID();
+      //AliHLTTPCCATrack &tr = Tracks()[id];
+      //for( int ih=0; ih<tr.NHits(); ih++ ){
+      //int ic = (fTrackHits[tr.FirstHitID()+ih]);
+      //std::cout<<ih<<" "<<ID2IRow(ic)<<" "<<ID2IHit(ic)<<std::endl;
+      //}
+      //disp.DrawSliceTrack( id, kBlue );
+      //disp.Ask();
+    }
+    disp.Ask();
+  }
+#endif //DRAW1
+
+  timer0.Stop();
+  fTimers[0] = timer0.CpuTime() / 100.;
+
 }
 
+GPUh() void AliHLTTPCCATracker::WriteOutput()
+{
+  // write output
+
+  TStopwatch timer;
 
+  //cout<<"output: nTracks = "<<*fNTracks<<", nHitsTotal="<<NHitsTotal()<<std::endl;
 
-void AliHLTTPCCATracker::FitTrack( AliHLTTPCCATrack &track, Int_t nIter )
-{    
-  // fit the track with nIter iterations
+  if (fOutputControl == NULL) fOutputControl = new AliHLTTPCCASliceOutput::outputControlStruct;
+  AliHLTTPCCASliceOutput::Allocate(*fOutput, fCommonMem->fNTracks, fCommonMem->fNTrackHits, fOutputControl);
+  AliHLTTPCCASliceOutput* useOutput = *fOutput;
+  if (useOutput == NULL) return;
 
-  AliHLTTPCCATrackPar &t = track.Param();
-  t.Init();
-  
-  AliHLTTPCCACell &c1 = GetTrackCell(track,0);
-  AliHLTTPCCACell &c2 = GetTrackCell(track,track.NCells()-1);
-  AliHLTTPCCARow &row1 = GetTrackCellRow(track,0);
-  AliHLTTPCCARow &row2 = GetTrackCellRow(track,track.NCells()-1);
-  Double_t t0[7];
-  t0[0]=row1.X();
-  t0[1]=c1.Y();
-  t0[2]=c1.Z();
-  t0[3]= row2.X() - row1.X();
-  t0[4]= c2.Y() - c1.Y();
-  t0[5]= c2.Z() - c1.Z();
-  Double_t tt = sqrt(t0[3]*t0[3]+t0[4]*t0[4]+t0[5]*t0[5]);
-  if( TMath::Abs(tt)>1.e-4 ){
-    t0[3]/=tt;
-    t0[4]/=tt;
-    t0[5]/=tt;
-  }else{
-    t0[4]=1;
+  if (fOutputControl->fDefaultOutput)
+  {
+         useOutput->SetNTracks( fCommonMem->fNTracks );
+         useOutput->SetNTrackClusters( fCommonMem->fNTrackHits );
+
+         int nStoredHits = 0;
+
+         for ( int iTr = 0; iTr < fCommonMem->fNTracks; iTr++ ) {
+               AliHLTTPCCATrack &iTrack = fTracks[iTr];
+
+               AliHLTTPCCASliceTrack out;
+               out.SetFirstClusterRef( nStoredHits );
+               out.SetNClusters( iTrack.NHits() );
+               out.SetParam( iTrack.Param() );
+
+               useOutput->SetTrack( iTr, out );
+
+               int iID = iTrack.FirstHitID();
+               for ( int ith = 0; ith < iTrack.NHits(); ith++ ) {
+                 const AliHLTTPCCAHitId &ic = fTrackHits[iID + ith];
+                 int iRow = ic.RowIndex();
+                 int ih = ic.HitIndex();
+
+                 const AliHLTTPCCARow &row = fData.Row( iRow );
+
+                 //float y0 = row.Grid().YMin();
+                 //float z0 = row.Grid().ZMin();
+                 //float stepY = row.HstepY();
+                 //float stepZ = row.HstepZ();
+                 //float x = row.X();
+
+                 //const uint4 *tmpint4 = RowData() + row.FullOffset();
+                 //const ushort2 *hits = reinterpret_cast<const ushort2*>(tmpint4);
+                 //ushort2 hh = hits[ih];
+                 //float y = y0 + hh.x*stepY;
+                 //float z = z0 + hh.y*stepZ;
+
+                 int clusterIndex = fData.ClusterDataIndex( row, ih );
+                 int clusterRowIndex = clusterIndex - fClusterData->RowOffset( iRow );
+
+                 if ( clusterIndex < 0 || clusterIndex >= fClusterData->NumberOfClusters() ) {
+                       //std::cout << inpIDtot << ", " << fClusterData->NumberOfClusters()
+                       //<< "; " << inpID << ", " << fClusterData->NumberOfClusters( iRow ) << std::endl;
+                       //abort();
+                       continue;
+                 }
+                 if ( clusterRowIndex < 0 || clusterRowIndex >= fClusterData->NumberOfClusters( iRow ) ) {
+                       //std::cout << inpIDtot << ", " << fClusterData->NumberOfClusters()
+                       //<< "; " << inpID << ", " << fClusterData->NumberOfClusters( iRow ) << std::endl;
+                       //abort();
+                       continue;
+                 }
+
+                 float origX = fClusterData->X( clusterIndex );
+                 float origY = fClusterData->Y( clusterIndex );
+                 float origZ = fClusterData->Z( clusterIndex );
+
+
+                 int id = fClusterData->Id( clusterIndex );
+
+                 float2 hUnpackedYZ;
+                 hUnpackedYZ.x = origY;
+                 hUnpackedYZ.y = origZ;
+                 float hUnpackedX = origX;
+
+                 useOutput->SetClusterId( nStoredHits, id  );
+                 useOutput->SetClusterRow( nStoredHits, ( unsigned char ) iRow  );
+                 useOutput->SetClusterUnpackedYZ( nStoredHits, hUnpackedYZ );
+                 useOutput->SetClusterUnpackedX( nStoredHits, hUnpackedX );
+                 nStoredHits++;
+               }
+         }
   }
-  t0[6] = 0;
 
-  for( Int_t iter=0; iter<nIter; iter++ ){
-    t.Init();
-    for( Int_t i=0; i<7; i++) t.Par()[i] = t0[i];
-    {
-      Double_t m[3] = {row1.X(), c1.Y(), c1.Z() };
-      t.TransportBz(fParam.Bz(),m,t0);
+
+  // old stuff
+  if (fOutputControl->fObsoleteOutput)
+  {
+         useOutput->SetNOutTrackHits(0);
+         useOutput->SetNOutTracks(0);
+
+
+         for ( int iTr = 0; iTr < fCommonMem->fNTracks; iTr++ ) {
+
+               const AliHLTTPCCATrack &iTrack = fTracks[iTr];
+
+               //std::cout<<"iTr = "<<iTr<<", nHits="<<iTrack.NHits()<<std::endl;
+
+               //if( !iTrack.Alive() ) continue;
+               if ( iTrack.NHits() < 3 ) continue;
+               AliHLTTPCCAOutTrack &out = useOutput->OutTracks()[useOutput->NOutTracks()];
+               out.SetFirstHitRef( useOutput->NOutTrackHits() );
+               out.SetNHits( 0 );
+               out.SetOrigTrackID( iTr );
+               AliHLTTPCCATrackParam tmpParam;
+               tmpParam.InitParam();
+               tmpParam.SetParam(iTrack.Param());
+               out.SetStartPoint( tmpParam );
+               out.SetEndPoint( tmpParam );
+
+               int iID = iTrack.FirstHitID();
+               int nOutTrackHitsOld = useOutput->NOutTrackHits();
+
+               for ( int ith = 0; ith < iTrack.NHits(); ith++ ) {
+                 const AliHLTTPCCAHitId &ic = fTrackHits[iID + ith];
+                 const AliHLTTPCCARow &row = Row( ic );
+                 int ih = ic.HitIndex();
+                 useOutput->SetOutTrackHit(useOutput->NOutTrackHits(), HitInputID( row, ih ));
+                 useOutput->SetNOutTrackHits(useOutput->NOutTrackHits() + 1 );
+                 //std::cout<<"write i,row,hit,id="<<ith<<", "<<ID2IRow(ic)<<", "<<ih<<", "<<HitInputID( row, ih )<<std::endl;
+                 if ( useOutput->NOutTrackHits() >= 10*NHitsTotal() ) {
+                       std::cout << "fNOutTrackHits>NHitsTotal()" << std::endl;
+                       //exit(0);
+                       return;//SG!!!
+                 }
+                 out.SetNHits( out.NHits() + 1 );
+               }
+               if ( out.NHits() >= 2 ) {
+                 useOutput->SetNOutTracks(useOutput->NOutTracks() + 1);
+               } else {
+                 useOutput->SetNOutTrackHits(nOutTrackHitsOld);
+               }
+         }
+  }
+
+  timer.Stop();
+  fTimers[5] += timer.CpuTime();
+}
+
+#endif
+
+GPUh() void AliHLTTPCCATracker::FitTrackFull( const AliHLTTPCCATrack &/**/, float * /**/ ) const
+{
+  // fit track with material
+#ifdef XXX
+  //* Fit the track
+  FitTrack( iTrack, tt0 );
+  if ( iTrack.NHits() <= 3 ) return;
+
+  AliHLTTPCCATrackParam &t = iTrack.Param();
+  AliHLTTPCCATrackParam t0 = t;
+
+  t.Chi2() = 0;
+  t.NDF() = -5;
+  bool first = 1;
+
+  int iID = iTrack.FirstHitID();
+  for ( int ih = 0; ih < iTrack.NHits(); ih++, iID++ ) {
+    const AliHLTTPCCAHitId &ic = fTrackHits[iID];
+    int iRow = ic.rowIndex();
+    const AliHLTTPCCARow &row = fData.Row( iRow );
+    if ( !t0.TransportToX( row.X() ) ) continue;
+    float dy, dz;
+    const AliHLTTPCCAHit &h = ic.hitIndex();
+
+    // check for wrong hits
+    if ( 0 ) {
+      dy = t0.GetY() - h.Y();
+      dz = t0.GetZ() - h.Z();
+
+      //if( dy*dy > 3.5*3.5*(/*t0.GetErr2Y() + */h.ErrY()*h.ErrY() ) ) continue;//SG!!!
+      //if( dz*dz > 3.5*3.5*(/*t0.GetErr2Z() + */h.ErrZ()*h.ErrZ() ) ) continue;
     }
-    t.Init();
-    for( Int_t i=0; i<7; i++ ) t.Par()[i] = t0[i];
-    
-    for( Int_t i=0; i<track.NCells() ; i++){
-      AliHLTTPCCACell &c = GetTrackCell(track,i);
-      AliHLTTPCCARow &row = GetTrackCellRow(track,i);
-      for( Int_t j=0; j<c.NHits(); j++){
-       AliHLTTPCCAHit &h = row.GetCellHit(c,j);
-       Double_t m[3] = {row.X(), h.Y(), h.Z() };
-       Double_t mV[6] = {fParam.ErrX()*fParam.ErrX(), 0, h.ErrY()*h.ErrY(), 0, 0, h.ErrZ()*h.ErrZ() };
-       Double_t mV1[6];
-       t.TransportBz(fParam.Bz(),m, t0);
-       t.GetConnectionMatrix(fParam.Bz(),m, mV1, t0);
-       t.Filter(m, mV, mV1);
-      }
+
+    if ( !t.TransportToX( row.X() ) ) continue;
+
+    //* Update the track
+
+    if ( first ) {
+      t.Cov()[ 0] = .5 * .5;
+      t.Cov()[ 1] = 0;
+      t.Cov()[ 2] = .5 * .5;
+      t.Cov()[ 3] = 0;
+      t.Cov()[ 4] = 0;
+      t.Cov()[ 5] = .2 * .2;
+      t.Cov()[ 6] = 0;
+      t.Cov()[ 7] = 0;
+      t.Cov()[ 8] = 0;
+      t.Cov()[ 9] = .2 * .2;
+      t.Cov()[10] = 0;
+      t.Cov()[11] = 0;
+      t.Cov()[12] = 0;
+      t.Cov()[13] = 0;
+      t.Cov()[14] = .2 * .2;
+      t.Chi2() = 0;
+      t.NDF() = -5;
     }
-    t.Normalize();
-    for( Int_t i=0; i<7; i++ ) t0[i] = t.Par()[i];
+    float err2Y, err2Z;
+    GetErrors2( iRow, t, err2Y, err2Z );
+
+    if ( !t.Filter2( h.Y(), h.Z(), err2Y, err2Z ) ) continue;
+
+    first = 0;
   }
+  /*
+  float cosPhi = iTrack.Param().GetCosPhi();
+  p0.Param().TransportToX(ID2Row( iTrack.PointID()[0] ).X());
+  p2.Param().TransportToX(ID2Row( iTrack.PointID()[1] ).X());
+  if( p0.Param().GetCosPhi()*cosPhi<0 ){ // change direction
+  float *par = p0.Param().Par();
+  float *cov = p0.Param().Cov();
+  par[2] = -par[2]; // sin phi
+  par[3] = -par[3]; // DzDs
+    par[4] = -par[4]; // kappa
+    cov[3] = -cov[3];
+    cov[4] = -cov[4];
+    cov[6] = -cov[6];
+    cov[7] = -cov[7];
+    cov[10] = -cov[10];
+    cov[11] = -cov[11];
+    p0.Param().CosPhi() = -p0.Param().GetCosPhi();
+  }
+  */
+#endif
 }
+
+GPUh() void AliHLTTPCCATracker::FitTrack( const AliHLTTPCCATrack &/*track*/, float * /*t0[]*/ ) const
+{
+  //* Fit the track
+#ifdef XXX
+  AliHLTTPCCAEndPoint &p2 = ID2Point( track.PointID()[1] );
+  const AliHLTTPCCAHit &c0 = ID2Hit( fTrackHits[p0.TrackHitID()].HitID() );
+  const AliHLTTPCCAHit &c1 = ID2Hit( fTrackHits[track.HitID()[1]].HitID() );
+  const AliHLTTPCCAHit &c2 = ID2Hit( fTrackHits[p2.TrackHitID()].HitID() );
+  const AliHLTTPCCARow &row0 = ID2Row( fTrackHits[p0.TrackHitID()].HitID() );
+  const AliHLTTPCCARow &row1 = ID2Row( fTrackHits[track.HitID()[1]].HitID() );
+  const AliHLTTPCCARow &row2 = ID2Row( fTrackHits[p2.TrackHitID()].HitID() );
+  float sp0[5] = {row0.X(), c0.Y(), c0.Z(), c0.ErrY(), c0.ErrZ() };
+  float sp1[5] = {row1.X(), c1.Y(), c1.Z(), c1.ErrY(), c1.ErrZ() };
+  float sp2[5] = {row2.X(), c2.Y(), c2.Z(), c2.ErrY(), c2.ErrZ() };
+  //std::cout<<"Fit track, points ="<<sp0[0]<<" "<<sp0[1]<<" / "<<sp1[0]<<" "<<sp1[1]<<" / "<<sp2[0]<<" "<<sp2[1]<<std::endl;
+  if ( track.NHits() >= 3 ) {
+    p0.Param().ConstructXYZ3( sp0, sp1, sp2, p0.Param().CosPhi(), t0 );
+    p2.Param().ConstructXYZ3( sp2, sp1, sp0, p2.Param().CosPhi(), t0 );
+    //p2.Param() = p0.Param();
+    //p2.Param().TransportToX(row2.X());
+    //p2.Param().Par()[1] = -p2.Param().Par()[1];
+    //p2.Param().Par()[4] = -p2.Param().Par()[4];
+  } else {
+    p0.Param().X() = row0.X();
+    p0.Param().Y() = c0.Y();
+    p0.Param().Z() = c0.Z();
+    p0.Param().Err2Y() = c0.ErrY() * c0.ErrY();
+    p0.Param().Err2Z() = c0.ErrZ() * c0.ErrZ();
+    p2.Param().X() = row2.X();
+    p2.Param().Y() = c2.Y();
+    p2.Param().Z() = c2.Z();
+    p2.Param().Err2Y() = c2.ErrY() * c2.ErrY();
+    p2.Param().Err2Z() = c2.ErrZ() * c2.ErrZ();
+  }
+#endif
+}
+
+
+GPUd() void AliHLTTPCCATracker::GetErrors2( int iRow, float z, float sinPhi, float cosPhi, float DzDs, float &Err2Y, float &Err2Z ) const
+{
+  //
+  // Use calibrated cluster error from OCDB
+  //
+
+  fParam.GetClusterErrors2( iRow, z, sinPhi, cosPhi, DzDs, Err2Y, Err2Z );
+  Err2Y*=fParam.ClusterError2CorrectionY();
+  Err2Z*=fParam.ClusterError2CorrectionZ();
+}
+
+GPUd() void AliHLTTPCCATracker::GetErrors2( int iRow, const AliHLTTPCCATrackParam &t, float &Err2Y, float &Err2Z ) const
+{
+  //
+  // Use calibrated cluster error from OCDB
+  //
+
+  fParam.GetClusterErrors2( iRow, t.GetZ(), t.SinPhi(), t.GetCosPhi(), t.DzDs(), Err2Y, Err2Z );
+}
+
+
+#if !defined(HLTCA_GPUCODE)
+
+GPUh() void AliHLTTPCCATracker::WriteEvent( std::ostream &out )
+{
+  // write event to the file
+  for ( int iRow = 0; iRow < fParam.NRows(); iRow++ ) {
+    out << fData.Row( iRow ).HitNumberOffset() << " " << fData.Row( iRow ).NHits() << std::endl;
+  }
+  out << NHitsTotal() << std::endl;
+
+  AliHLTResizableArray<float> y( NHitsTotal() ), z( NHitsTotal() );
+
+  for ( int iRow = 0; iRow < fParam.NRows(); iRow++ ) {
+    const AliHLTTPCCARow &row = Row( iRow );
+    float y0 = row.Grid().YMin();
+    float z0 = row.Grid().ZMin();
+    float stepY = row.HstepY();
+    float stepZ = row.HstepZ();
+    for ( int ih = 0; ih < fData.Row( iRow ).NHits(); ih++ ) {
+      int id = HitInputID( row, ih );
+      y[id] = y0 + HitDataY( row, ih ) * stepY;
+      z[id] = z0 + HitDataZ( row, ih ) * stepZ;
+    }
+  }
+  for ( int ih = 0; ih < NHitsTotal(); ih++ ) {
+    out << y[ih] << " " << z[ih] << std::endl;
+  }
+}
+
+GPUh() void AliHLTTPCCATracker::WriteTracks( std::ostream &out )
+{
+  //* Write tracks to file
+  AliHLTTPCCASliceOutput* useOutput = *fOutput;
+
+  out << fTimers[0] << std::endl;
+  out << useOutput->NOutTrackHits() << std::endl;
+  for ( int ih = 0; ih < useOutput->NOutTrackHits(); ih++ ) {
+    out << useOutput->OutTrackHit(ih) << " ";
+  }
+  out << std::endl;
+
+  out << useOutput->NOutTracks() << std::endl;
+
+  for ( int itr = 0; itr < useOutput->NOutTracks(); itr++ ) {
+    const AliHLTTPCCAOutTrack &t = useOutput->OutTrack(itr);
+    AliHLTTPCCATrackParam p1 = t.StartPoint();
+    AliHLTTPCCATrackParam p2 = t.EndPoint();
+    out << t.NHits() << " ";
+    out << t.FirstHitRef() << " ";
+    out << t.OrigTrackID() << " ";
+    out << std::endl;
+    out << p1.X() << " ";
+    out << p1.SignCosPhi() << " ";
+    out << p1.Chi2() << " ";
+    out << p1.NDF() << std::endl;
+    for ( int i = 0; i < 5; i++ ) out << p1.Par()[i] << " ";
+    out << std::endl;
+    for ( int i = 0; i < 15; i++ ) out << p1.Cov()[i] << " ";
+    out << std::endl;
+    out << p2.X() << " ";
+    out << p2.SignCosPhi() << " ";
+    out << p2.Chi2() << " ";
+    out << p2.NDF() << std::endl;
+    for ( int i = 0; i < 5; i++ ) out << p2.Par()[i] << " ";
+    out << std::endl;
+    for ( int i = 0; i < 15; i++ ) out << p2.Cov()[i] << " ";
+    out << std::endl;
+  }
+}
+
+GPUh() void AliHLTTPCCATracker::ReadTracks( std::istream &in )
+{
+  //* Read tracks  from file
+  AliHLTTPCCASliceOutput::Allocate(*fOutput, 4096, 16384, fOutputControl);//Just some max values
+  AliHLTTPCCASliceOutput* useOutput = *fOutput;
+
+  int tmpval;
+  in >> fTimers[0];
+  in >> tmpval;
+  useOutput->SetNOutTrackHits(tmpval);
+
+  for ( int ih = 0; ih < useOutput->NOutTrackHits(); ih++ ) {
+    in >> tmpval;
+       useOutput->SetOutTrackHit(ih, tmpval);
+  }
+  in >> tmpval;
+  useOutput->SetNOutTracks(tmpval);
+
+  for ( int itr = 0; itr < useOutput->NOutTracks(); itr++ ) {
+    AliHLTTPCCAOutTrack &t = useOutput->OutTracks()[itr];
+    AliHLTTPCCATrackParam p1, p2;
+    int i;
+    float f;
+    in >> i; t.SetNHits( i );
+    in >> i; t.SetFirstHitRef( i );
+    in >> i; t.SetOrigTrackID( i );
+    in >> f; p1.SetX( f );
+    in >> f; p1.SetSignCosPhi( f );
+    in >> f; p1.SetChi2( f );
+    in >> i; p1.SetNDF( i );
+    for ( int j = 0; j < 5; j++ ) { in >> f; p1.SetPar( j, f ); }
+    for ( int j = 0; j < 15; j++ ) { in >> f; p1.SetCov( j, f ); }
+    in >> f; p2.SetX( f );
+    in >> f; p2.SetSignCosPhi( f );
+    in >> f; p2.SetChi2( f );
+    in >> i; p2.SetNDF( i );
+    for ( int j = 0; j < 5; j++ ) { in >> f; p2.SetPar( j, f ); }
+    for ( int j = 0; j < 15; j++ ) { in >> f; p2.SetCov( j, f ); }
+    t.SetStartPoint( p1 );
+    t.SetEndPoint( p2 );
+  }
+}
+#endif