diff --git a/Reconstruction/SiliconTracking/CMakeLists.txt b/Reconstruction/SiliconTracking/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0f76fb016d2ffc54c7c2bfc183013669f1aa6786
--- /dev/null
+++ b/Reconstruction/SiliconTracking/CMakeLists.txt
@@ -0,0 +1,21 @@
+gaudi_subdir(SiliconTracking v0r0)
+
+find_package(GEAR REQUIRED)
+find_package(GSL REQUIRED ) 
+find_package(LCIO REQUIRED )
+find_package(EDM4HEP REQUIRED ) 
+
+gaudi_depends_on_subdirs(
+    Service/GearSvc
+    Service/EventSeeder
+    Service/TrackSystemSvc
+    Utilities/DataHelper
+)
+
+set(SiliconTracking_srcs src/*.cpp)
+
+# Modules
+gaudi_add_module(SiliconTracking ${SiliconTracking_srcs}
+    INCLUDE_DIRS GaudiKernel FWCore gear ${GSLx_INCLUDE_DIRS} ${LCIOx_INCLUDE_DIRS}
+    LINK_LIBRARIES TrackSystemSvcLib DataHelperLib GaudiKernel FWCore $ENV{GEAR}/lib/libgearsurf.so ${GSL_LIBRARIES} ${LCIO_LIBRARIES} 
+)
diff --git a/Reconstruction/SiliconTracking/CMakeLists.txt~ b/Reconstruction/SiliconTracking/CMakeLists.txt~
new file mode 100644
index 0000000000000000000000000000000000000000..49e8a2a273939f18b7d7a91e3fffc5910b8703b7
--- /dev/null
+++ b/Reconstruction/SiliconTracking/CMakeLists.txt~
@@ -0,0 +1,21 @@
+gaudi_subdir(SiliconTracking v0r0)
+
+find_package(GEAR REQUIRED)
+find_package(GSL REQUIRED ) 
+find_package(LCIO REQUIRED )
+find_package(EDM4HEP REQUIRED ) 
+
+gaudi_depends_on_subdirs(
+    Service/GearSvc
+    Service/EventSeeder
+    Service/TrackSystemSvc
+    Utilities/DataHelper
+)
+
+set(SiliconTracking_srcs src/*.cpp)
+
+# Modules
+gaudi_add_module(SiliconTracking ${SiliconTracking_srcs}
+    INCLUDE_DIRS GaudiKernel FWCore gear ${GSLx_INCLUDE_DIRS} ${LCIOx_INCLUDE_DIRS}
+    LINK_LIBRARIES TrackSystemSvcLib DataHelper GaudiKernel FWCore $ENV{GEAR}/lib/libgearsurf.so ${GSL_LIBRARIES} ${LCIO_LIBRARIES} 
+)
diff --git a/Reconstruction/SiliconTracking/src/SiliconTracking.cpp~ b/Reconstruction/SiliconTracking/src/SiliconTracking.cpp~
new file mode 100644
index 0000000000000000000000000000000000000000..7c22fc853a96a13ac71ee59cbc5e7ebb3501c7f1
--- /dev/null
+++ b/Reconstruction/SiliconTracking/src/SiliconTracking.cpp~
@@ -0,0 +1,3084 @@
+#include "SiliconTracking.h"
+#include "GearSvc/IGearSvc.h"
+#include "EventSeeder/IEventSeeder.h"
+#include "TrackSystemSvc/ITrackSystemSvc.h"
+#include "edm4hep/MCParticle.h"
+#include "edm4hep/TrackerHit.h"
+//#include "edm4hep/TrackerHitPlane.h"
+#include "edm4hep/Track.h"
+#include "edm4hep/TrackState.h"
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+#include <climits>
+
+#include <gear/GEAR.h>
+#include <gear/GearMgr.h>
+#include <gear/GearParameters.h>
+#include <gear/VXDLayerLayout.h>
+#include <gear/VXDParameters.h>
+#include "gear/FTDLayerLayout.h"
+#include "gear/FTDParameters.h"
+
+#include <gear/BField.h>
+
+#include <UTIL/BitField64.h>
+#include <UTIL/BitSet32.h>
+#include <UTIL/ILDConf.h>
+
+#include "TrackSystemSvc/MarlinTrkUtils.h"
+#include "TrackSystemSvc/HelixTrack.h"
+#include "TrackSystemSvc/HelixFit.h"
+#include "TrackSystemSvc/IMarlinTrack.h"
+//#include "MarlinTrk/Factory.h"
+
+//#include "TrackSystemSvc/MarlinTrkDiagnostics.h"
+//#ifdef MARLINTRK_DIAGNOSTICS_ON
+//#include "TrackSystemSvc/DiagnosticsController.h"
+//#endif
+
+//#include "MarlinCED.h"
+
+//#include "marlin/AIDAProcessor.h"
+
+//---- ROOT -----
+#include "TH1F.h"
+#include "TH2F.h"
+
+using namespace edm4hep ;
+//using namespace marlin ;
+using namespace MarlinTrk ;
+
+using std::min;
+using std::max;
+using std::abs;
+
+const int SiliconTracking::_output_track_col_quality_GOOD = 1;
+const int SiliconTracking::_output_track_col_quality_FAIR = 2;
+const int SiliconTracking::_output_track_col_quality_POOR = 3;
+
+const double SiliconTracking::TWOPI = 2*M_PI;
+
+DECLARE_COMPONENT( SiliconTracking )
+
+SiliconTracking::SiliconTracking(const std::string& name, ISvcLocator* svcLoc)
+: GaudiAlgorithm(name, svcLoc) {
+  
+  //_description = "Pattern recognition in silicon trackers";
+  
+  _fastfitter = new MarlinTrk::HelixFit();
+  
+  _encoder = new UTIL::BitField64(lcio::ILDCellID0::encoder_string);
+  
+  _petalBasedFTDWithOverlaps = false;
+  
+  // zero triplet counters
+  _ntriplets = _ntriplets_good = _ntriplets_2MCP = _ntriplets_3MCP = _ntriplets_1MCP_Bad = _ntriplets_bad = 0;
+
+  // Input Collections
+  // ^^^^^^^^^^^^^^^^^
+  declareProperty("HeaderCol", _headerColHdl);
+  declareProperty("MCParticleCollection", _inMCColHdl, "Handle of the Input MCParticle collection");
+  declareProperty("VTXHitCollection", _inVTXColHdl, "Handle of the Input VTX TrackerHits collection");
+  declareProperty("FTDPixelHitCollection", _inFTDPixelColHdl, "Handle of the Input FTD TrackerHits collection");
+  declareProperty("FTDSpacePointCollection", _inFTDSpacePointColHdl, "Handle of the Input FTD SpacePoints collection");
+  declareProperty("SITHitCollection", _inSITColHdl, "Handle of the Input SIT TrackerHits collection");
+    
+  // Output Collections
+  // ^^^^^^^^^^^^^^^^^^
+  declareProperty("SiTrackCollection", _outColHdl, "Handle of the SiTrack output collection");
+  //declareProperty("TrkHitRelCollection", _outRelColHdl, "Handle of TrackerHit Track relation collection");
+  // Steering parameters
+  // ^^^^^^^^^^^^^^^^^^^
+  
+  _output_track_col_quality = _output_track_col_quality_GOOD;
+  
+}
+
+
+
+StatusCode  SiliconTracking::initialize() { 
+  
+  _nRun = -1 ;
+  _nEvt = 0 ;
+  //printParameters() ;
+  
+  // set up the geometery needed by KalTest
+  //FIXME: for now do KalTest only - make this a steering parameter to use other fitters
+  auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc");
+  if ( !_trackSystemSvc ) {
+    error() << "Failed to find TrackSystemSvc ..." << endmsg;
+    return StatusCode::FAILURE;
+  }
+  _trksystem =  _trackSystemSvc->getTrackSystem();
+  
+  if( _trksystem == 0 ){
+    error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg;
+    return StatusCode::FAILURE;
+  }
+  
+  _trksystem->setOption( IMarlinTrkSystem::CFG::useQMS,        _MSOn ) ;
+  _trksystem->setOption( IMarlinTrkSystem::CFG::usedEdx,       _ElossOn) ;
+  _trksystem->setOption( IMarlinTrkSystem::CFG::useSmoothing,  _SmoothOn) ;
+  _trksystem->init() ;  
+  std::cout << "fucd ==============" << _trksystem << std::endl;
+#ifdef MARLINTRK_DIAGNOSTICS_ON
+  
+  void * dcv = _trksystem->getDiagnositicsPointer();
+  DiagnosticsController* dc = static_cast<DiagnosticsController*>(dcv);
+  dc->init(_MarlinTrkDiagnosticsName,_MarlinTrkDiagnosticsName, _runMarlinTrkDiagnostics);
+  
+#endif
+  
+  if(setupGearGeom()==StatusCode::FAILURE) return StatusCode::FAILURE;
+  
+  if (_useSIT == 0)
+    _nLayers = _nLayersVTX;
+  else 
+    _nLayers = _nLayersVTX + _nLayersSIT;
+  
+  // initialise the container to have separate vectors for up to _nHitsChi2 hits.
+  _tracksWithNHitsContainer.resize(_nHitsChi2);
+  
+  _dPhi = TWOPI/_nDivisionsInPhi;
+  _dTheta = 2.0/_nDivisionsInTheta;
+  _dPhiFTD = TWOPI/_nPhiFTD;
+  // I leave this for the moment, but 0.3 is c/1e9.
+  // For the cut it does not make too much of a difference
+  double cutOnR = _cutOnPt/(0.3*_bField);
+  cutOnR = 1000.*cutOnR;
+  _cutOnOmega = 1/cutOnR;
+  
+  _output_track_col_quality = 0;
+  
+  return GaudiAlgorithm::initialize();
+}
+
+StatusCode SiliconTracking::execute(){ 
+  
+  //_current_event = evt;
+  //_allHits.reserve(1000);
+
+  _output_track_col_quality = _output_track_col_quality_GOOD;
+  
+  // zero triplet counters
+  _ntriplets = _ntriplets_good = _ntriplets_2MCP = _ntriplets_3MCP = _ntriplets_1MCP_Bad = _ntriplets_bad = 0;
+  
+  // Clearing the working containers from the previous event
+  // FIXME: partly done at the end of the event, in CleanUp. Make it consistent.
+  //_tracksWithNHitsContainer.clear();
+  //_trackImplVec.clear();
+  
+  //_colTrackerHits.clear();
+  //_colNamesTrackerHits.clear();
+  //auto header = _headerColHdl.get()->at(0);
+  //int evtNo = header.getEventNumber();
+  //int runNo = header.getRunNumber();
+  //debug() << "Processing Run[" << runNo << "]::Event[" << evtNo << "]" << endmsg;
+
+  _trackImplVec.reserve(100);
+  _allHits.reserve(1000);
+
+  int successVTX = InitialiseVTX();
+  int successFTD = 0;
+  //int successFTD = InitialiseFTD();
+  if (successVTX == 1) {
+    
+    debug() << "      phi          theta        layer      nh o :   m :   i  :: o*m*i " << endmsg; 
+    
+    for (int iPhi=0; iPhi<_nDivisionsInPhi; ++iPhi) { 
+      for (int iTheta=0; iTheta<_nDivisionsInTheta;++iTheta) {
+        ProcessOneSector(iPhi,iTheta); // Process one VXD sector     
+      }
+    }
+    
+    debug() << "End of Processing VXD and SIT sectors" << endmsg;
+    
+  }
+  
+  if (successFTD == 1) {
+    debug() << "      phi          side        layer      nh o :   m :   i  :: o*m*i " << endmsg;
+    TrackingInFTD(); // Perform tracking in the FTD
+    debug() << "End of Processing FTD sectors" << endmsg;
+  }
+
+  //if(0){
+  if (successVTX == 1 || successFTD == 1) {
+    //if (successVTX == 1 ) {
+    for (int nHits = _nHitsChi2; nHits >= 3 ;// the three is hard coded, sorry.
+         // It's the minimal number to form a track
+         nHits--) {
+      Sorting( _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits ) );
+      
+    }
+    debug() <<  "End of Sorting " << endmsg;
+        
+    for (int nHits = _nHitsChi2; nHits >= 3 ;// the three is hard coded, sorry.
+         // It's the minimal number to form a track
+         nHits--) {
+      
+      TrackExtendedVec &tracksWithNHits = _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits );
+      for (TrackExtendedVec::iterator trackIter = tracksWithNHits.begin();
+           trackIter < tracksWithNHits.end(); trackIter++) {
+        CreateTrack( *trackIter );
+      }
+      debug() <<  "End of creating "<< nHits << " hits tracks " << endmsg;
+    }
+    
+    if (_attachFast == 0) {
+      if(successVTX) AttachRemainingVTXHitsSlow();
+      if(successFTD) AttachRemainingFTDHitsSlow();
+    }
+    else {
+      if(successVTX) AttachRemainingVTXHitsFast();
+      if(successFTD) AttachRemainingFTDHitsFast();
+    }
+    
+    debug() <<  "End of picking up remaining hits " << endmsg;
+
+    //edm4hep::TrackCollection* trkCol = nullptr; 
+    //edm4hep::LCRelationCollection* relCol = nullptr;
+    auto trkCol = _outColHdl.createAndPut();
+    //auto relCol = _outRelColHdl.createAndPut();
+    //std::cout << "fucd------------------" << std::endl;
+    /*
+    LCCollectionVec * trkCol = new LCCollectionVec(LCIO::TRACK);
+    // if we want to point back to the hits we need to set the flag
+    LCFlagImpl trkFlag(0) ;
+    trkFlag.setBit( LCIO::TRBIT_HITS ) ;
+    trkCol->setFlag( trkFlag.getFlag()  ) ;
+    
+    LCCollectionVec * relCol = NULL;
+    */
+    //FinalRefit(trkCol, relCol);
+    FinalRefit(trkCol);
+    //std::cout << "fucd------------------" << std::endl;
+    // set the quality of the output collection
+    switch (_output_track_col_quality) {
+
+      case _output_track_col_quality_FAIR:
+        //trkCol->parameters().setValue( "QualityCode" , "Fair"  ) ;
+        break;
+
+      case _output_track_col_quality_POOR:
+        //trkCol->parameters().setValue( "QualityCode" , "Poor"  ) ;
+        break;
+        
+      default:
+        //trkCol->parameters().setValue( "QualityCode" , "Good"  ) ;
+        break;
+    }
+    /*
+    if (_UseEventDisplay) {
+      this->drawEvent();
+    }
+    */
+  }
+  
+  // fill event based histogram
+  /*
+  if (_createDiagnosticsHistograms) {
+  
+    // triplet histos
+    _histos->fill1D(DiagnosticsHistograms::hntriplets, _ntriplets);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_good, _ntriplets_good);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_2MCP, _ntriplets_2MCP);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_3MCP, _ntriplets_3MCP);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_1MCP_Bad, _ntriplets_1MCP_Bad);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_bad, _ntriplets_bad);
+  
+  }
+  */
+  /*
+  const edm4hep::MCParticleCollection* mcCol = nullptr;
+  try{
+    mcCol =_inMCColHdl.get();
+  }
+  catch(...){
+  }
+  if(mcCol){
+    int id = 0;
+    for(auto mcP : *mcCol){
+      float pos[3];
+      float mom[3];
+      pos[0] = mcP.vertex()[0];
+      pos[1] = mcP.vertex()[1];
+      pos[2] = mcP.vertex()[2];
+      mom[0] = mcP.momentum()[0];
+      mom[1] = mcP.momentum()[1];
+      mom[2] = mcP.momentum()[2];
+      float           charge = mcP.getCharge();
+      HelixClass helix;
+      helix.Initialize_VP(pos,mom,charge,_bField);
+      float d0 = helix.getD0();
+      float z0 = helix.getZ0();
+      float omega = helix.getOmega();
+      float phi0 = helix.getPhi0();
+      float tanLambda = helix.getTanLambda();
+      std::cout <<"MCParticle: " << evtNo << " " << id << " " << sqrt(mom[0]*mom[0]+mom[1]*mom[1]) << " " << acos(mom[2]/sqrt(mom[0]*mom[0]+mom[1]*mom[1]+mom[2]*mom[2]))
+		<< " " << atan2(mom[1],mom[0])
+		<< " " << d0 << " " << phi0 << " " << omega << " " << z0 << " " << tanLambda << " " << mcP.vertex() << std::endl; 
+      id++;
+    }
+  }
+  
+  const edm4hep::TrackCollection* trkCol = nullptr;
+  try{
+    trkCol = _outColHdl.get();
+  }
+  catch(...){
+  }
+  if(trkCol){
+    int id = 0;
+    for(auto track : *trkCol){
+      int nstate = track->trackStates_size();
+      for(int i=0;i<nstate;i++){
+	edm4hep::TrackState trkState = track->getTrackStates(i);
+	if(trkState.location != 1) continue;
+	HelixClass helix_final;
+        helix_final.Initialize_Canonical(trkState.phi,trkState.D0,trkState.Z0,trkState.omega,trkState.tanLambda,_bField);
+        float trkPx = helix_final.getMomentum()[0];
+        float trkPy = helix_final.getMomentum()[1];
+	float trkPz = helix_final.getMomentum()[2];
+        float trkPt = sqrt(trkPx*trkPx+trkPy*trkPy);
+	std::cout << "Track parameter: " << evtNo << " " << id << " " << trkPt << " " << acos(trkPz/sqrt(trkPt*trkPt+trkPz*trkPz)) << " " << atan2(trkPy,trkPx)
+		  << " " << trkState.D0 << " " << trkState.phi << " " << trkState.omega << " " << trkState.Z0 << " " << trkState.tanLambda
+		  << " " << sqrt(trkState.covMatrix[0]) << " " << sqrt(trkState.covMatrix[2]) << " " << sqrt(trkState.covMatrix[5])
+		  << " " << sqrt(trkState.covMatrix[9]) << " " << sqrt(trkState.covMatrix[14]) << " " << std::endl;
+	id++;
+	break;
+      }
+    }
+  }
+  */
+  CleanUp();
+  debug() << "Event is done " << endmsg;
+  _nEvt++;
+  return StatusCode::SUCCESS;
+}
+
+
+void SiliconTracking::CleanUp() {
+  
+  _tracksWithNHitsContainer.clear();
+  
+  for (int il=0;il<_nLayers;++il) {
+    for (int ip=0;ip<_nDivisionsInPhi;++ip) {
+      for (int it=0;it<_nDivisionsInTheta; ++it) {
+        unsigned int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it;      
+        
+        if( iCode >= _sectors.size()){          
+          error() << "iCode index out of range: iCode =   " << iCode << " _sectors.size() = " << _sectors.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg;
+          continue;
+        }
+        
+        TrackerHitExtendedVec& hitVec = _sectors[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          delete hit;
+        }
+      }
+    }
+  }
+  
+  for (int iS=0;iS<2;++iS) {
+    for (unsigned int layer=0;layer<_nlayersFTD;++layer) {
+      for (int ip=0;ip<_nPhiFTD;++ip) {
+        unsigned int iCode = iS + 2*layer + 2*_nlayersFTD*ip;
+        
+        if( iCode >= _sectorsFTD.size()){
+          //error() << "iCode index out of range: iCode =   " << iCode << " _sectorsFTD.size() = " << _sectorsFTD.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg;
+          continue;
+        }
+        
+        TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          delete hit;
+        }
+      }
+    }
+  }
+  _trackImplVec.clear();
+  _allHits.clear();
+}
+
+int SiliconTracking::InitialiseFTD() {
+  
+  int success = 1;
+  
+  _nTotalFTDHits = 0;
+  _sectorsFTD.clear();
+  _sectorsFTD.resize(2*_nlayersFTD*_nPhiFTD);
+  
+  // Reading in FTD Pixel Hits Collection
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  const edm4hep::TrackerHitCollection* hitFTDPixelCol = nullptr;
+  try {
+    hitFTDPixelCol = _inFTDPixelColHdl.get();
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << _inFTDPixelColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+    success = 0;
+  }
+  
+  if(hitFTDPixelCol){
+    //LCCollection * hitCollection = evt->getCollection(_FTDPixelHitCollection.c_str());
+    
+    //_colNamesTrackerHits[hitCollection] = _FTDPixelHitCollection;    
+    // _colTrackerHits.push_back(hitCollection);
+    
+    int nelem = hitFTDPixelCol->size();
+    
+    debug() << "Number of FTD Pixel Hits = " << nelem << endmsg;
+    _nTotalFTDHits = nelem;
+    
+    //for (int ielem=0; ielem<nelem; ++ielem) {
+    for(auto hit : *hitFTDPixelCol){  
+    // edm4hep::TrackerHit* hit = hitFTDPixelCol->at(ielem);
+      
+      TrackerHitExtended * hitExt = new TrackerHitExtended( hit );
+      
+      //gear::Vector3D U(1.0,hit->getU()[1],hit->getU()[0],gear::Vector3D::spherical);
+      //gear::Vector3D V(1.0,hit->getV()[1],hit->getV()[0],gear::Vector3D::spherical);
+      gear::Vector3D U(1.0,hit.getCovMatrix()[1],hit.getCovMatrix()[0],gear::Vector3D::spherical);
+      gear::Vector3D V(1.0,hit.getCovMatrix()[4],hit.getCovMatrix()[3],gear::Vector3D::spherical);
+      gear::Vector3D Z(0.0,0.0,1.0);
+      
+      const float eps = 1.0e-07;
+      // V must be the global z axis 
+      if( fabs(V.dot(Z)) > eps ) {
+	error() << "SiliconTracking: VXD Hit measurment vectors V is not in the global X-Y plane. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+      exit(1);
+      }
+      
+      if( fabs(U.dot(Z)) > eps ) {
+	error() << "SiliconTracking: VXD Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+	exit(1);
+      }
+      
+      // SJA:FIXME Here dU and dV are almost certainly dX and dY ... should test ...
+      //double point_res_rphi = sqrt( hit->getdU()*hit->getdU() + hit->getdV()*hit->getdV() );
+      double point_res_rphi = sqrt( hit.getCovMatrix()[2]*hit.getCovMatrix()[2] + hit.getCovMatrix()[5]*hit.getCovMatrix()[5] );
+      hitExt->setResolutionRPhi( point_res_rphi );
+      
+      // SJA:FIXME why is this needed? 
+      hitExt->setResolutionZ(0.1);
+      
+      // type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+      hitExt->setType(int(INT_MAX));
+      // det is no longer used set to INT_MAX to try and catch any missuse
+      hitExt->setDet(int(INT_MAX));
+    
+      double pos[3];
+      
+      for (int i=0; i<3; ++i) {
+	pos[i] = hit.getPosition()[i];
+      }
+      
+      double Phi = atan2(pos[1],pos[0]);
+      if (Phi < 0.) Phi = Phi + TWOPI;
+      
+      // get the layer number
+      unsigned int layer = static_cast<unsigned int>(getLayerID(&hit));
+      unsigned int petalIndex = static_cast<unsigned int>(getModuleID(&hit));
+      
+      if ( _petalBasedFTDWithOverlaps == true ) {
+	
+	// as we are dealing with staggered petals we will use 2*nlayers in each directions +/- z
+	// the layers will follow the even odd numbering of the petals 
+	if ( petalIndex % 2 == 0 ) {
+	  layer = 2*layer;
+	}
+	else {
+	  layer = 2*layer + 1;
+	}
+	
+      }
+      
+      if (layer >= _nlayersFTD) {
+	error() << "SiliconTracking => fatal error in FTD : layer is outside allowed range : " << layer << " number of layers = " << _nlayersFTD <<  endmsg;
+	exit(1);
+      }
+      
+      int iPhi = int(Phi/_dPhiFTD);
+      
+      int side = getSideID(&hit);
+      int iSemiSphere = 0;
+    
+      if (side > 0) 
+	iSemiSphere = 1;
+      
+      int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPhi;
+      _sectorsFTD[iCode].push_back( hitExt );
+      
+      debug() << " FTD Pixel Hit added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iSemiSphere "  << iSemiSphere << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+    }
+  }
+  // Reading out FTD SpacePoint Collection
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  const edm4hep::TrackerHitCollection* hitFTDSpacePointCol = nullptr;
+  try {
+    hitFTDSpacePointCol = _inFTDSpacePointColHdl.get();
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << _inFTDSpacePointColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+    success = 0;
+  }
+
+  if(hitFTDSpacePointCol){
+    //LCCollection * hitCollection = evt->getCollection(_FTDSpacePointCollection.c_str());
+    
+    //_colNamesTrackerHits[hitCollection] = _FTDSpacePointCollection;
+    //_colTrackerHits.push_back(hitCollection);
+    
+    int nelem = hitFTDSpacePointCol->size();
+    
+    debug() << "Number of FTD SpacePoints = " << nelem << endmsg;
+    _nTotalFTDHits += nelem;
+    
+    //for (int ielem=0; ielem<nelem; ++ielem) {
+    for(auto hit : *hitFTDSpacePointCol){
+    //edm4hep::TrackerHit* hit =  hitFTDSpacePointCol->at(ielem);
+      
+      TrackerHitExtended * hitExt = new TrackerHitExtended(hit);
+      
+      // SJA:FIXME: fudge for now by a factor of two and ignore covariance
+      double point_res_rphi = 2 * sqrt( hit.getCovMatrix()[0] + hit.getCovMatrix()[2] );
+      
+      hitExt->setResolutionRPhi( point_res_rphi );
+      
+      // SJA:FIXME why is this needed? 
+      hitExt->setResolutionZ(0.1);
+      
+      // type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+      hitExt->setType(int(INT_MAX));
+      // det is no longer used set to INT_MAX to try and catch any missuse
+      hitExt->setDet(int(INT_MAX));
+      
+      double pos[3];
+      
+      for (int i=0; i<3; ++i) {
+        pos[i] = hit.getPosition()[i];
+      }
+      
+      double Phi = atan2(pos[1],pos[0]);
+      if (Phi < 0.) Phi = Phi + TWOPI;
+      
+      // get the layer number
+      unsigned int layer = static_cast<unsigned int>(getLayerID(&hit));
+      unsigned int petalIndex = static_cast<unsigned int>(getModuleID(&hit));
+      
+      if ( _petalBasedFTDWithOverlaps == true ) {
+        
+        // as we are dealing with staggered petals we will use 2*nlayers in each directions +/- z
+        // the layers will follow the even odd numbering of the petals 
+        if ( petalIndex % 2 == 0 ) {
+          layer = 2*layer;
+        }
+        else {
+          layer = 2*layer + 1;
+        }
+        
+      }
+      
+      if (layer >= _nlayersFTD) {
+        error() << "SiliconTracking => fatal error in FTD : layer is outside allowed range : " << layer << " number of layers = " << _nlayersFTD <<  endmsg;
+        exit(1);
+      }
+      
+      int iPhi = int(Phi/_dPhiFTD);
+      
+      int side = getSideID(&hit);
+      int iSemiSphere = 0;
+      
+      if (side > 0) 
+        iSemiSphere = 1;
+      
+      int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPhi;
+      _sectorsFTD[iCode].push_back( hitExt );
+      
+      debug() << " FTD SpacePoint Hit added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iSemiSphere "  << iSemiSphere << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+      
+    }
+  }
+  
+  for (unsigned i=0; i<_sectorsFTD.size(); ++i) {
+    int nhits = _sectorsFTD[i].size();
+    if( nhits != 0 ) debug() << " Number of Hits in FTD Sector " << i << " = " << _sectorsFTD[i].size() << endmsg;
+    if (nhits > _max_hits_per_sector) {
+      for (unsigned ihit=0; ihit<_sectorsFTD[i].size(); ++ihit) {
+        delete _sectorsFTD[i][ihit];
+      } 
+      _sectorsFTD[i].clear();
+      if( nhits != 0 ) error()  << " \n ### Number of Hits in FTD Sector " << i << " = " << nhits << " : Limit is set to " << _max_hits_per_sector << " : This sector will be dropped from track search, and QualityCode set to \"Poor\" " << endmsg;
+      
+      _output_track_col_quality = _output_track_col_quality_POOR;
+      
+    }
+    
+  }
+  debug() << "FTD initialized" << endmsg;
+  return success;
+}
+
+int SiliconTracking::InitialiseVTX() {
+  //std::cout << "fucd================" << std::endl;
+  _nTotalVTXHits = 0;
+  _nTotalSITHits = 0;
+  _sectors.clear();
+  _sectors.resize(_nLayers*_nDivisionsInPhi*_nDivisionsInTheta);
+  //std::cout << "fucd================" << std::endl;
+  int success = 1;
+  // Reading out VTX Hits Collection
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
+  const edm4hep::TrackerHitCollection* hitVTXCol = nullptr;
+  try {
+    hitVTXCol = _inVTXColHdl.get();
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << _inVTXColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+    success = 0;
+  }
+  if(hitVTXCol){
+    //LCCollection * hitCollection = evt->getCollection(_VTXHitCollection.c_str());
+    
+    //_colNamesTrackerHits[hitCollection] = _VTXHitCollection;
+    //_colTrackerHits.push_back(hitCollection);
+    //std::cout << "fucd================1" << std::endl;
+    int nelem = hitVTXCol->size();
+    //std::cout << "fucd================2" << std::endl;
+    debug() << "Number of VTX hits = " << nelem << endmsg;
+    _nTotalVTXHits = nelem;
+    
+    for (int ielem=0; ielem<nelem; ++ielem) {
+    //for(auto hit : *hitVTXCol){ 
+      edm4hep::TrackerHit hit = hitVTXCol->at(ielem);
+      //_allHits.push_back(hit);
+      //gear::Vector3D U(1.0,hit->getU()[1],hit->getU()[0],gear::Vector3D::spherical);
+      //gear::Vector3D V(1.0,hit->getV()[1],hit->getV()[0],gear::Vector3D::spherical);
+      gear::Vector3D U(1.0,hit.getCovMatrix()[1],hit.getCovMatrix()[0],gear::Vector3D::spherical);
+      gear::Vector3D V(1.0,hit.getCovMatrix()[4],hit.getCovMatrix()[3],gear::Vector3D::spherical);
+      gear::Vector3D Z(0.0,0.0,1.0);
+      //debug() << "covMatrix : " << hit->getCovMatrix()[0] << " " << hit->getCovMatrix()[1] << endmsg;
+      const float eps = 1.0e-07;
+      // V must be the global z axis 
+      if( fabs(1.0 - V.dot(Z)) > eps ) {
+        error() << "SiliconTracking: VXD Hit measurment vectors V is not equal to the global Z axis. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+        exit(1);
+      }
+      
+      if( fabs(U.dot(Z)) > eps ) {
+        error() << "SiliconTracking: VXD Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+        exit(1);
+      }
+      //std::cout << "fucd: " << &hit << " " << &_allHits.back() << std::endl;
+      //TrackerHitExtended * hitExt = new TrackerHitExtended( &_allHits.back() );
+      TrackerHitExtended * hitExt = new TrackerHitExtended(hit);
+      std::cout << "Saved TrackerHit pointer in TrackerHitExtended " << ielem << ": " << hitExt->getTrackerHit() << std::endl;
+      //std::cout << (&_allHits.back())->getPosition()[0] << " " << hit.getCovMatrix()[2] << " " << hit.getCovMatrix()[5] << std::endl;
+            
+      // SJA:FIXME: just use planar res for now
+      hitExt->setResolutionRPhi(hit.getCovMatrix()[2]);
+      hitExt->setResolutionZ(hit.getCovMatrix()[5]);
+      
+      // set type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+      hitExt->setType(int(INT_MAX));
+      // det is no longer used set to INT_MAX to try and catch any missuse
+      hitExt->setDet(int(INT_MAX));
+      
+      double pos[3];
+      double radius = 0;
+      
+      for (int i=0; i<3; ++i) {
+        pos[i] = hit.getPosition()[i];
+        radius += pos[i]*pos[i];
+      }
+      
+      radius = sqrt(radius);
+      
+      double cosTheta = pos[2]/radius;
+      double Phi = atan2(pos[1],pos[0]);
+      
+      if (Phi < 0.) Phi = Phi + TWOPI;
+      
+      // get the layer number
+      int layer = getLayerID(&hit);
+      
+      if (layer < 0 || layer >= _nLayers) {
+        error() << "SiliconTracking => fatal error in VTX : layer is outside allowed range : " << layer << endmsg;
+        exit(1);
+      }
+      
+      int iPhi = int(Phi/_dPhi);
+      int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+      int iCode = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta;      
+      _sectors[iCode].push_back( hitExt );
+      
+      debug() << " VXD Hit " <<  hit.id() << " added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iTheta "  << iTheta << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+      
+    }
+  }
+  
+  if (_useSIT > 0 ) {
+    const edm4hep::TrackerHitCollection* hitSITCol = nullptr;
+    try {
+      hitSITCol = _inSITColHdl.get();
+    }
+    catch ( GaudiException &e ) {
+      debug() << "Collection " << _inSITColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+      success = 0;
+    }
+    if(hitSITCol){
+      //LCCollection *hitCollection = evt->getCollection(_SITHitCollection.c_str());
+      
+      //_colNamesTrackerHits[hitCollection] = _SITHitCollection;
+      //_colTrackerHits.push_back(hitCollection);
+      
+      int nelem = hitSITCol->size();
+      
+      debug() << "Number of SIT hits = " << nelem << endmsg;
+      _nTotalSITHits = nelem;
+      
+      //TrackerHit*          trkhit   = 0;
+      //TrackerHitPlane*     trkhit_P = 0;
+      //TrackerHitZCylinder* trkhit_C = 0;
+      
+      double drphi(NAN);
+      double dz(NAN);
+      
+      //for (int ielem=0; ielem<nelem; ++ielem) {
+      for(auto trkhit : *hitSITCol){
+        // hit could be of the following type
+        // 1) TrackerHit, either ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT or just standard TrackerHit
+        // 2) TrackerHitPlane, either 1D or 2D
+        // 3) TrackerHitZCylinder, if coming from a simple cylinder design as in the LOI
+        
+        // Establish which of these it is in the following order of likelyhood
+        //    i)   ILDTrkHitTypeBit::ONE_DIMENSIONAL (TrackerHitPlane) Should Never Happen: SpacePoints Must be Used Instead
+        //    ii)  ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT (TrackerHit)
+        //    iii) TrackerHitPlane (Two dimentional)
+        //    iv)  TrackerHitZCylinder 
+        //    v)   Must be standard TrackerHit
+        
+	//const edm4hep::TrackerHit* trkhit = hitSITCol->at(ielem);
+        
+        int layer = getLayerID(&trkhit);
+        
+        // VXD and SIT are treated as one system so SIT layers start from _nLayersVTX
+        layer = layer + _nLayersVTX;
+        
+        if (layer < 0 || layer >= _nLayers) {
+          error() << "SiliconTracking => fatal error in SIT : layer is outside allowed range : " << layer << endmsg;
+          exit(1);
+        }
+        
+        // first check that we have not been given 1D hits by mistake, as they won't work here
+        if ( UTIL::BitSet32( trkhit.getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] ) {
+          
+          error() << "SiliconTracking: SIT Hit cannot be of type UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL COMPOSITE SPACEPOINTS must be use instead. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+          exit(1);
+          
+        } 
+        // most likely case: COMPOSITE_SPACEPOINT hits formed from stereo strip hits
+        else if ( UTIL::BitSet32( trkhit.getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ) {
+          
+          // SJA:FIXME: fudge for now by a factor of two and ignore covariance
+          drphi =  2 * sqrt(trkhit.getCovMatrix()[0] + trkhit.getCovMatrix()[2]);         
+          dz    =      sqrt(trkhit.getCovMatrix()[5]);         
+          
+        } 
+        // or a PIXEL based SIT, using 2D TrackerHitPlane like the VXD above
+	// by fucd
+        //else if ( ( trkhit_P = dynamic_cast<TrackerHitPlane*>( hitCollection->getElementAt( ielem ) ) ) )  {
+	else if( UTIL::BitSet32( trkhit.getType() )[ 31 ]){
+          // first we need to check if the measurement vectors are aligned with the global coordinates 
+          //gear::Vector3D U(1.0,trkhit_P->getU()[1],trkhit_P->getU()[0],gear::Vector3D::spherical);
+          //gear::Vector3D V(1.0,trkhit_P->getV()[1],trkhit_P->getV()[0],gear::Vector3D::spherical);
+	  gear::Vector3D U(1.0,trkhit.getCovMatrix()[1],trkhit.getCovMatrix()[0],gear::Vector3D::spherical);
+	  gear::Vector3D V(1.0,trkhit.getCovMatrix()[4],trkhit.getCovMatrix()[3],gear::Vector3D::spherical);
+          gear::Vector3D Z(0.0,0.0,1.0);
+          
+          const float eps = 1.0e-07;
+          // V must be the global z axis 
+          if( fabs(1.0 - V.dot(Z)) > eps ) {
+            error() << "SiliconTracking: PIXEL SIT Hit measurment vectors V is not equal to the global Z axis. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+            exit(1);
+          }
+          
+          // U must be normal to the global z axis
+          if( fabs(U.dot(Z)) > eps ) {
+            error() << "SiliconTracking: PIXEL SIT Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+            exit(1);
+          }
+          
+          //drphi = trkhit_P->getdU();
+          //dz    = trkhit_P->getdV();                                                 
+          drphi = trkhit.getCovMatrix()[2];
+          dz    = trkhit.getCovMatrix()[5];
+        }
+	
+        // or a simple cylindrical design, as used in the LOI      
+	/* by fucd
+        else if ( ( trkhit_C = dynamic_cast<TrackerHitZCylinder*>( hitCollection->getElementAt( ielem ) ) ) ) {
+          
+          drphi = trkhit_C->getdRPhi();
+          dz    = trkhit_C->getdZ();
+          
+        } 
+	*/
+        // this would be very unlikely, but who knows ... just an ordinary TrackerHit, which is not a COMPOSITE_SPACEPOINT
+        else {
+          
+          // SJA:FIXME: fudge for now by a factor of two and ignore covariance
+          drphi =  2 * sqrt(trkhit.getCovMatrix()[0] + trkhit.getCovMatrix()[2]);         
+          dz =     sqrt(trkhit.getCovMatrix()[5]);             
+          
+        }
+        // now that the hit type has been established carry on and create a 
+        
+        TrackerHitExtended * hitExt = new TrackerHitExtended(trkhit);
+        
+        // SJA:FIXME: just use planar res for now
+        hitExt->setResolutionRPhi(drphi);
+        hitExt->setResolutionZ(dz);
+        
+        // set type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+        hitExt->setType(int(INT_MAX));
+        // det is no longer used set to INT_MAX to try and catch any missuse
+        hitExt->setDet(int(INT_MAX));
+        
+        double pos[3];
+        double radius = 0;
+        
+        for (int i=0; i<3; ++i) {
+          pos[i] = trkhit.getPosition()[i];
+          radius += pos[i]*pos[i];
+        }
+        
+        radius = sqrt(radius);
+        
+        double cosTheta = pos[2]/radius;
+        double Phi = atan2(pos[1],pos[0]);
+        
+        if (Phi < 0.) Phi = Phi + TWOPI;
+        
+        int iPhi = int(Phi/_dPhi);
+        int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+        int iCode = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta;      
+        _sectors[iCode].push_back( hitExt );
+        
+        debug() << " SIT Hit " <<  trkhit.id() << " added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iTheta "  << iTheta << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+        
+      }
+    }    
+  }
+  
+  
+  for (unsigned i=0; i<_sectors.size(); ++i) {
+    int nhits = _sectors[i].size();
+    if( nhits != 0 ) debug() << " Number of Hits in VXD/SIT Sector " << i << " = " << _sectors[i].size() << endmsg;
+    if (nhits > _max_hits_per_sector) {
+      for (unsigned ihit=0; ihit<_sectors[i].size(); ++ihit) {
+        delete _sectors[i][ihit];
+      }
+      _sectors[i].clear();
+      if( nhits != 0 ) error()  << " \n ### Number of Hits in VXD/SIT Sector " << i << " = " << nhits << " : Limit is set to " << _max_hits_per_sector << " : This sector will be dropped from track search, and QualityCode set to \"Poor\" " << endmsg;
+      
+      _output_track_col_quality = _output_track_col_quality_POOR;
+    }
+  }
+  debug() << "VXD initialized" << endmsg;
+  return success; 
+}
+
+StatusCode  SiliconTracking::finalize(){
+  
+  delete _fastfitter ; _fastfitter = 0;
+  delete _encoder ; _encoder = 0;
+  //delete _trksystem ; _trksystem = 0;
+  //delete _histos ; _histos = 0;
+  info() << "Processed " << _nEvt << " events " << endmsg;
+  return GaudiAlgorithm::finalize();
+}
+
+
+void SiliconTracking::ProcessOneSector(int iPhi, int iTheta) {
+  
+  int counter = 0 ;
+  
+  int iPhi_Up    = iPhi + 1;
+  int iPhi_Low   = iPhi - 1;
+  int iTheta_Up  = iTheta + 1; 
+  int iTheta_Low = iTheta - 1;
+  if (iTheta_Low < 0) iTheta_Low = 0;
+  if (iTheta_Up  >= _nDivisionsInTheta) iTheta_Up = _nDivisionsInTheta-1;
+  
+  int nComb = int( _Combinations.size() / 3 ); // number of triplet combinations
+                                               //  std::cout << iPhi << " " << iTheta << " " << _nEvt << endmsg;
+  int iNC = 0;
+  
+  for (int iComb=0; iComb < nComb; ++iComb) { // loop over triplets
+    
+    int nLR[3];
+    
+    for (int iS=0; iS<3; ++iS) {
+      nLR[iS] = _Combinations[iNC];
+      iNC++;
+    }    
+    
+    //std::cout << iPhi << " " << iTheta << " " << nLR[0] << " " << nLR[1] << " " << nLR[2] << " " << std::endl;
+    
+    // index of theta-phi bin of outer most layer
+    int iCode = nLR[0] + _nLayers*iPhi +  _nLayers*_nDivisionsInPhi*iTheta;
+    
+    //std::cout << "size of vector = " << _sectors.size() << " iCode = " << iCode << std::endl;
+    
+    // get the all the hits in the outer most theta-phi bin 
+    
+    TrackerHitExtendedVec& hitVecOuter =  _sectors[iCode];
+    
+    int nHitsOuter = int(hitVecOuter.size());
+    if (nHitsOuter > 0) {
+      
+      //std::cout << " " << iPhi << " " << iTheta << " " << nLR[0] << " " << nLR[1] << " " << nLR[2] << " size of vector = " << hitVecOuter.size() << std::endl;
+      
+      for (int ipMiddle=iPhi_Low; ipMiddle<iPhi_Up+1;ipMiddle++) { // loop over phi in the Middle
+        
+        for (int itMiddle=iTheta_Low; itMiddle<iTheta_Up+1;itMiddle++) { // loop over theta in the Middle 
+          
+          int iPhiMiddle = ipMiddle;
+          
+          // catch wrap-around
+          if (ipMiddle < 0) iPhiMiddle = _nDivisionsInPhi-1;          
+          if (ipMiddle >= _nDivisionsInPhi) iPhiMiddle = ipMiddle - _nDivisionsInPhi;
+          
+          // index of current theta-phi bin of middle layer
+          iCode = nLR[1] + _nLayers*iPhiMiddle +  _nLayers*_nDivisionsInPhi*itMiddle;
+          
+          // get the all the hits in the current middle theta-phi bin 
+          TrackerHitExtendedVec& hitVecMiddle = _sectors[iCode];
+          
+          int nHitsMiddle = int(hitVecMiddle.size());
+          
+          // determine which inner theta-phi bins to look in
+          
+          int iPhiLowInner = iPhi_Low;
+          int iPhiUpInner = iPhi_Up;
+          int iThetaLowInner = iTheta_Low;
+          int iThetaUpInner = iTheta_Up;        
+          
+          // test to see if this is the core bin of the current search
+          // if so, look into the neigboring bins in the inner layer
+          if (ipMiddle == iPhi && itMiddle==iTheta) { 
+            iPhiLowInner = iPhi_Low;
+            iPhiUpInner  = iPhi_Up;
+            iThetaLowInner = iTheta_Low;
+            iThetaUpInner = iTheta_Up;
+          }
+          else { 
+            int difP = abs(ipMiddle-iPhi); //  number of phi bins from core: can only be 1 or 0 due to hard coded 1 above
+            int difT = abs(itMiddle-iTheta);// number of theta bins from core: can only be 1 or 0 due to hard coded 1 above
+            int minP = min(ipMiddle,iPhi);   // min phi: core bin or current phi bin middle
+            int minT = min(itMiddle,iTheta); // min theta: core bin or current theta bin middle
+            int maxP = max(ipMiddle,iPhi);   // max phi: core bin or current phi bin middle
+            int maxT = max(itMiddle,iTheta); // max theta: core bin or current theta bin middle
+            
+            if (difP==1 && difT==1) { // if the diffence is a single bin in both phi and theta : only look in the bin adjacent to the core bin  
+              iPhiLowInner = minP;
+              iPhiUpInner = maxP;
+              iThetaLowInner = minT;
+              iThetaUpInner = maxT;
+            }
+            if (difP==0) { // must be +/-1 theta : only look in bins adjacent to the middle bin
+              iPhiLowInner = iPhi_Low;
+              iPhiUpInner  = iPhi_Up;
+              iThetaLowInner = minT;
+              iThetaUpInner = maxT;
+            }
+            if (difT==0) { // must be +/-1 phi : only look in bins adjacent to the middle bin
+              iPhiLowInner = minP;
+              iPhiUpInner  = maxP;
+              iThetaLowInner = iTheta_Low;
+              iThetaUpInner = iTheta_Up;            
+            }
+          }               
+          if (nHitsMiddle > 0) { // look into inner bins
+            
+            for (int ipInner=iPhiLowInner; ipInner<iPhiUpInner+1;ipInner++) { // loop over phi in the Inner
+              
+              for (int itInner=iThetaLowInner; itInner<iThetaUpInner+1;itInner++) { // loop over theta in the Inner 
+                
+                int iPhiInner = ipInner;
+                
+                // catch wrap-around
+                if (ipInner < 0) iPhiInner = _nDivisionsInPhi-1;
+                if (ipInner >= _nDivisionsInPhi) iPhiInner = ipInner - _nDivisionsInPhi;
+                
+                iCode = nLR[2] + _nLayers*iPhiInner +  _nLayers*_nDivisionsInPhi*itInner;
+                
+                // get hit for inner bin
+                TrackerHitExtendedVec& hitVecInner = _sectors[iCode];
+                
+                int nHitsInner = int(hitVecInner.size());
+                
+                if (nHitsInner > 0) {
+                  
+                  debug() << " " 
+                  << std::setw(3) << iPhi       << " "   << std::setw(3) << ipMiddle << " "      << std::setw(3) << ipInner << "   " 
+                  << std::setw(3) << iTheta     << " "   << std::setw(3) << itMiddle << " "      << std::setw(3) << itInner << "  " 
+                  << std::setw(3) << nLR[0]     << " "   << std::setw(3) << nLR[1]   << " "      << std::setw(3) << nLR[2]  << "     " 
+                  << std::setw(3) << nHitsOuter << " : " << std::setw(3) << nHitsMiddle << " : " << std::setw(3) << nHitsInner << "  :: " 
+                  << std::setw(3) << nHitsOuter*nHitsMiddle* nHitsInner << endmsg;
+                  
+                  // test all triplets 
+                  
+                  for (int iOuter=0; iOuter<nHitsOuter; ++iOuter) { // loop over hits in the outer sector
+                    TrackerHitExtended * outerHit = hitVecOuter[iOuter];
+                    for (int iMiddle=0;iMiddle<nHitsMiddle;iMiddle++) { // loop over hits in the middle sector
+                      TrackerHitExtended * middleHit = hitVecMiddle[iMiddle];
+                      for (int iInner=0;iInner<nHitsInner;iInner++) { // loop over hits in the inner sector
+                        TrackerHitExtended * innerHit = hitVecInner[iInner];
+                        HelixClass helix;
+			//std::cout <<"fucd++++++++++++++++++++++1" << std::endl;
+                        // test fit to triplet
+                        TrackExtended * trackAR = TestTriplet(outerHit,middleHit,innerHit,helix);
+			//std::cout <<"fucd++++++++++++++++++++++2" << std::endl;
+                        if ( trackAR != NULL ) {
+                          int nHits = BuildTrack(outerHit,middleHit,innerHit,helix,nLR[2],
+                                                 iPhiLowInner,iPhiUpInner,
+                                                 iThetaLowInner,iThetaUpInner,trackAR);
+                          
+                          _tracksWithNHitsContainer.getTracksWithNHitsVec(nHits).push_back(trackAR);
+                          
+                          counter ++ ;
+                        }
+			//std::cout <<"fucd++++++++++++++++++++++3" << std::endl;
+                      } // endloop over hits in the inner sector
+                    } // endloop over hits in the middle sector
+                  } // endloop over hits in the outer sector
+                } // endif nHitsInner > 0
+              } // endloop over theta in the Inner
+            } // endloop over phi in the Inner      
+          } // endif nHitsMiddle > 0
+        } // endloop over theta in the Middle
+      } // endloop over phi in the Middle
+    } // endif nHitsOuter > 0
+  } // endloop over triplets
+    
+  //debug() << " process one sectector theta,phi " << iTheta << ", " << iPhi << "  number of loops : " << counter << endmsg  ;
+}
+
+TrackExtended * SiliconTracking::TestTriplet(TrackerHitExtended * outerHit, 
+                                                       TrackerHitExtended * middleHit,
+                                                       TrackerHitExtended * innerHit,
+                                                       HelixClass & helix) {
+  /*
+   Methods checks if the triplet of hits satisfies helix hypothesis
+   */
+  //std::cout << "fucd================1" << std::endl;
+  // get the tracks already associated with the triplet
+  TrackExtendedVec& trackOuterVec  = outerHit->getTrackExtendedVec();
+  TrackExtendedVec& trackMiddleVec = middleHit->getTrackExtendedVec();
+  TrackExtendedVec& trackInnerVec  = innerHit->getTrackExtendedVec();
+  
+  //std::cout << "fucd================2" << std::endl;
+  // check if all the hits are already assigned to a track 
+  if ( (!trackOuterVec.empty())  && (!trackMiddleVec.empty()) && (!trackInnerVec.empty())) {
+    
+    TrackExtendedVec::const_iterator middleEndIter = trackMiddleVec.end();
+    TrackExtendedVec::const_iterator outerEndIter  = trackOuterVec.end();
+    TrackExtendedVec::const_iterator innerEndIter  = trackInnerVec.end();
+    TrackExtendedVec::const_iterator outerBeginIter  = trackOuterVec.begin();
+    TrackExtendedVec::const_iterator innerBeginIter  = trackInnerVec.begin();
+    
+    // loop over the tracks from the middle hit
+    for (TrackExtendedVec::const_iterator middleIter = trackMiddleVec.begin();
+         middleIter < middleEndIter;
+         ++middleIter) {
+      
+      // loop over the track from the outer hit
+      for (TrackExtendedVec::const_iterator outerIter = outerBeginIter;
+           outerIter < outerEndIter;
+           ++outerIter) {
+        
+        // if track from the outer and middle are not the same progress  
+        if ( *outerIter != *middleIter ) continue;
+        
+        // loop over the tracks from the inner hit
+        for (TrackExtendedVec::const_iterator innerIter = innerBeginIter;
+             innerIter < innerEndIter;
+             ++innerIter) {
+          
+          // no need to check against middle, it is idendical to outer here
+          if ( *outerIter == *innerIter ) {
+            // an existing track already contains all three hits
+            // return a null pointer
+            debug() << " TestTriplet: track " << *outerIter << " already contains all three hits: Do not create new track from these hits " << endmsg ;
+            return 0;            
+          }
+          
+        }// for inner
+      }// for outer    
+    }// for middle
+  }// if all vectors are not empty
+  //std::cout << "fucd================3" << std::endl;
+  
+  //    float dZ = FastTripletCheck(innerHit, middleHit, outerHit);
+  
+  //    if (fabs(dZ) > _minDistCutAttach)
+  //      return trackAR;    
+
+  
+  // increase triplet count
+  ++_ntriplets;
+
+  // get the hit coordinates and errors
+  double xh[3];
+  double yh[3];
+  float  zh[3];
+  double wrh[3];
+  float  wzh[3];
+  float  rh[3];
+  float  ph[3];
+  
+  float par[5];
+  float epar[15];
+  /*fucd
+  for(int i=0;i<_allHits.size();i++){
+    std::cout << &_allHits.at(i) << std::endl;
+  } 
+  */
+  // first hit
+  xh[0] = outerHit->getTrackerHit()->getPosition()[0];
+  yh[0] = outerHit->getTrackerHit()->getPosition()[1];
+  zh[0] = float(outerHit->getTrackerHit()->getPosition()[2]);
+  wrh[0] = double(1.0/(outerHit->getResolutionRPhi()*outerHit->getResolutionRPhi()));
+  wzh[0] = 1.0/(outerHit->getResolutionZ()*outerHit->getResolutionZ());
+  // second hit
+  xh[1] = middleHit->getTrackerHit()->getPosition()[0];
+  yh[1] = middleHit->getTrackerHit()->getPosition()[1];
+  zh[1] = float(middleHit->getTrackerHit()->getPosition()[2]);
+  wrh[1] = double(1.0/(middleHit->getResolutionRPhi()*middleHit->getResolutionRPhi()));
+  wzh[1] = 1.0/(middleHit->getResolutionZ()*middleHit->getResolutionZ());
+  // third hit
+  xh[2] = innerHit->getTrackerHit()->getPosition()[0];
+  yh[2] = innerHit->getTrackerHit()->getPosition()[1];
+  zh[2] = float(innerHit->getTrackerHit()->getPosition()[2]);
+  wrh[2] = double(1.0/(innerHit->getResolutionRPhi()*innerHit->getResolutionRPhi()));
+  wzh[2] = 1.0/(innerHit->getResolutionZ()*innerHit->getResolutionZ());
+  // calculate r and phi for all hits
+  for (int ih=0; ih<3; ih++) {
+    rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih]));
+    ph[ih] = atan2(yh[ih],xh[ih]);
+    if (ph[ih] < 0.) 
+      ph[ih] = TWOPI + ph[ih]; 
+  }
+  
+  int NPT = 3;
+  int iopt = 2;
+  float chi2RPhi;
+  float chi2Z;
+  
+  debug() << " TestTriplet: Use fastHelixFit " << endmsg ;  
+  
+  _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+  par[3] = par[3]*par[0]/fabs(par[0]);
+
+  // get helix parameters
+  float omega = par[0];
+  float tanlambda = par[1];
+  float phi0 = par[2];
+  float d0 = par[3];
+  float z0 = par[4];
+
+  // chi2 is weighted here by a factor for both rphi and z
+  float Chi2 = chi2RPhi*_chi2WRPhiTriplet+chi2Z*_chi2WZTriplet;
+  int ndf = 2*NPT-5;
+
+  
+  // check the truth information for the triplet
+  
+  // define these outside of the ifdef so that we don't need to keep repeating it.
+  //std::vector<TrackerHit*> hit_list;
+  //std::vector<MCParticle*> mcps_imo;
+  //std::vector<MCParticle*> mcp_s;
+  int triplet_code = 0;
+  /*  
+#ifdef MARLINTRK_DIAGNOSTICS_ON
+
+  int nmcps   = 0;
+  int nbadHits = 0;
+  
+  int layer  = 9 ;
+  int size   = 3 ;
+  int marker = 1 ;
+  int ml     = 0 ;
+  //  float helix_max_r = 0;
+  float helix_max_z = 0;
+  int color = 0;
+
+  // use the MCTruth4HitExt to get the MCPs
+  
+  hit_list.push_back(innerHit->getTrackerHit());
+  hit_list.push_back(middleHit->getTrackerHit());
+  hit_list.push_back(outerHit->getTrackerHit());
+
+  EVENT::MCParticle* mcp_i = 0;
+  EVENT::MCParticle* mcp_m = 0;
+  EVENT::MCParticle* mcp_o = 0;
+  
+  for (unsigned ihit = 0; ihit < hit_list.size(); ++ihit) {
+
+    EVENT::TrackerHit* trkhit = hit_list[ihit];
+    std::vector<MCParticle*> mcps;
+
+    MarlinTrk::getMCParticlesForTrackerHit(trkhit, mcps);
+    
+    if (mcps.size() == 1) {
+      mcps_imo.push_back(mcps[0]);
+      ++nmcps;
+    } else {
+      mcps_imo.push_back(0);
+      ++nbadHits;
+    }
+    
+  }
+    
+  mcp_i = mcps_imo[0];
+  mcp_m = mcps_imo[1];
+  mcp_o = mcps_imo[2];
+  
+  debug()
+  << "\n mcp_i = " << mcp_i
+  << "\n mcp_m = " << mcp_m
+  << "\n mcp_o = " << mcp_o
+  << endmsg;
+  
+  if( mcp_i ) {
+    mcp_s.push_back(mcp_i) ;
+  }
+    
+  if( mcp_m && mcp_m != mcp_i ) {
+    mcp_s.push_back(mcp_m);
+  }
+  
+  if( mcp_o && mcp_o != mcp_m && mcp_o != mcp_i ){
+    mcp_s.push_back(mcp_o);
+  }
+
+  nmcps = mcp_s.size();
+
+  if (_UseEventDisplay) {
+    // display this triplet and the MCPs from which it is formed
+    
+    MarlinCED::newEvent(this , _detector_model_for_drawing ) ;
+    
+    //    CEDPickingHandler &pHandler=CEDPickingHandler::getInstance();
+    //
+    //    pHandler.update(_current_event);
+    
+    for (unsigned imcp = 0; imcp < mcp_s.size(); ++imcp) {
+      
+      MCParticle* mcp = mcp_s[imcp];
+      
+      helix_max_z = fabsf(mcp->getEndpoint()[2]);
+      
+      
+      info() << "Draw MCParticle : " << *mcp <<endmsg;
+      
+      MarlinCED::add_layer_description("MCParticle_For_Fit", layer);
+      
+      MarlinCED::drawHelix( _bField , mcp->getCharge(), mcp->getVertex()[0], mcp->getVertex()[1], mcp->getVertex()[2],
+                           mcp->getMomentum()[0], mcp->getMomentum()[1], mcp->getMomentum()[2], layer , size , 0x7af774  ,
+                           0.0,  _helix_max_r ,
+                           helix_max_z, mcp->id() ) ;
+      
+    }
+    
+    const std::string  colName = "Hits_For_Fit";
+    
+    
+    size   = 10 ;
+    layer  = 11 ;
+    //    ml = marker | ( layer << CED_LAYER_SHIFT ) ;
+    
+    //ced_describe_layer( colName.c_str() ,layer);
+    MarlinCED::add_layer_description(colName, layer);
+    
+    
+    color =  0xFFFFFF;
+    
+    for(   std::vector<TrackerHit* >::const_iterator it = hit_list.begin();  it != hit_list.end() ; it++ ) {
+      
+      TrackerHit* trkhit = *it;
+      
+      ced_hit_ID(trkhit->getPosition()[0],
+                 trkhit->getPosition()[1],
+                 trkhit->getPosition()[2],
+                 marker, layer, size , color, trkhit->id() ) ;
+      
+    } // hits
+    
+  }
+  
+  if (_createDiagnosticsHistograms) {
+    
+    // if no bad hits are present triplet_code = nmcps;
+    triplet_code = nmcps + nbadHits * 3  ;
+        
+    _histos->fill1D(DiagnosticsHistograms::htriplets, triplet_code);
+    
+    double pt =  (2.99792458E-4*_bField) / omega ; // for r in mm, p in GeV and Bz in Tesla
+    
+    if (triplet_code == 1) {
+      ++_ntriplets_good;
+      _histos->fill2D(DiagnosticsHistograms::htripletChi2vPt_good, pt, Chi2 );
+      _histos->fill1D(DiagnosticsHistograms::htriplets_chi2_good, Chi2 );
+      _histos->fill1D(DiagnosticsHistograms::htriplets_pt_good, pt );
+    } else {
+
+      _histos->fill2D(DiagnosticsHistograms::htripletChi2vPt_bad, pt, Chi2);
+      _histos->fill1D(DiagnosticsHistograms::htriplets_chi2_bad, Chi2 );
+      _histos->fill1D(DiagnosticsHistograms::htriplets_pt_bad, pt );
+
+      if(triplet_code == 2) {
+        ++_ntriplets_2MCP;
+      } else if (triplet_code == 3) {
+        ++_ntriplets_3MCP;
+      } else if (triplet_code == 4) {
+        ++_ntriplets_1MCP_Bad;
+      } else {
+        ++_ntriplets_bad;
+      }
+    }
+    
+  }
+  
+#endif
+  */  
+  
+  // Check if track satisfies all conditions
+  
+  
+  //   std::cout << "Chi2/ndf = " << Chi2/float(ndf) << " , cut = " << _chi2FitCut << endmsg;
+  //   std::cout << "d0 = " << d0 << " , cut = " << _cutOnD0  << endmsg;
+  //   std::cout << "z0 = " << z0 << " , cut = " << _cutOnZ0  << endmsg;
+  //   std::cout << "omega = " << omega << " , cut = " << _cutOnOmega << endmsg;
+  
+  //  if ( Chi2/float(ndf) > _chi2FitCut || fabs(d0) > _cutOnD0 || fabs(z0) > _cutOnZ0 || fabs(omega)>_cutOnOmega)
+  // return a null pointer
+  //    return 0;
+  
+  bool failed = false;
+
+  int quality_code = triplet_code * 10 ;
+
+  if ( Chi2/float(ndf) > _chi2FitCut ) {
+    debug() << "Chi2/ndf = " << Chi2/float(ndf) << " , cut = " << _chi2FitCut << endmsg;
+    failed = true;
+    quality_code += 1;
+  } else if (fabs(d0) > _cutOnD0 ) {
+    debug() << "d0 = " << d0 << " , cut = " << _cutOnD0  << endmsg;
+    failed = true;
+    quality_code += 2;
+  } else if (fabs(z0) > _cutOnZ0 ) {
+    debug() << "z0 = " << z0 << " , cut = " << _cutOnZ0  << endmsg;
+    failed = true;
+    quality_code += 3;
+  } else if ( fabs(omega)>_cutOnOmega)  {
+    debug() << "omega = " << omega << " , cut = " << _cutOnOmega << endmsg;
+    failed = true;
+    quality_code += 4;
+  } else {
+    debug() << "Success !!!!!!!" << endmsg;
+  }
+  /*
+  if (_createDiagnosticsHistograms) _histos->fill1D(DiagnosticsHistograms::htriplets, quality_code);
+
+    if (_UseEventDisplay) {
+    drawEvent();
+  }
+  */
+  
+  if( failed ) {
+    // return a null pointer
+    return 0;
+  }
+  
+  
+  helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+  
+  TrackExtended * trackAR = new TrackExtended();
+  trackAR->addTrackerHitExtended(outerHit);
+  trackAR->addTrackerHitExtended(middleHit);
+  trackAR->addTrackerHitExtended(innerHit);
+  outerHit->addTrackExtended(trackAR);
+  middleHit->addTrackExtended(trackAR);
+  innerHit->addTrackExtended(trackAR);    
+  trackAR->setD0(d0);
+  trackAR->setZ0(z0);
+  trackAR->setPhi(phi0);
+  trackAR->setTanLambda(tanlambda);
+  trackAR->setOmega(omega);
+  trackAR->setChi2( Chi2 );
+  trackAR->setNDF( ndf );
+  trackAR->setCovMatrix(epar);
+  
+  
+  return trackAR;
+  
+}
+
+int SiliconTracking::BuildTrack(TrackerHitExtended * outerHit, 
+                                          TrackerHitExtended * middleHit,
+                                          TrackerHitExtended * innerHit,
+                                          HelixClass & helix,
+                                          int innerLayer,
+                                          int iPhiLow, int iPhiUp,
+                                          int iThetaLow, int iThetaUp, 
+                                          TrackExtended * trackAR) {
+  /**
+   Method for building up track in the VXD. Method starts from the found triplet and performs
+   sequential attachment of hits in other layers, which have hits within the search window.
+   Only searches inwards.
+   Given that we know we are now jumping over layers due to the doublet nature of the VXD, we 
+   could optimise this to look for the hits in interleaving layers as well. 
+   Currently a fast fit is being done for each additional hit, it could be more efficient to try and use kaltest?
+   
+   */
+  
+  debug() << " BuildTrack starting " << endmsg;
+  
+  for (int layer = innerLayer-1; layer>=0; layer--) { // loop over remaining layers
+    float distMin = 1.0e+20;
+    TrackerHitExtended * assignedhit = NULL;
+    //std::cout << "fucd---------------------1" << std::endl;
+    // loop over phi in the Inner region
+    for (int ipInner=iPhiLow; ipInner<iPhiUp+1;ipInner++) { 
+      
+      // loop over theta in the Inner region 
+      for (int itInner=iThetaLow; itInner<iThetaUp+1;itInner++) { 
+        
+        int iPhiInner = ipInner;
+        
+        // catch wrap-around
+        if (ipInner < 0) iPhiInner = _nDivisionsInPhi-1;
+        if (ipInner >= _nDivisionsInPhi) iPhiInner = ipInner - _nDivisionsInPhi;
+        
+        // get the index of the theta-phi bin to search
+        int iCode = layer + _nLayers*iPhiInner +  _nLayers*_nDivisionsInPhi*itInner;
+        
+        // get the hits from this bin
+        TrackerHitExtendedVec& hitVecInner = _sectors[iCode];
+        
+        int nHitsInner = int(hitVecInner.size());
+        
+        // loop over hits in the Inner sector
+        for (int iInner=0;iInner<nHitsInner;iInner++) { 
+          
+          TrackerHitExtended * currentHit = hitVecInner[iInner];
+          
+          // get the position of the hit to test
+          float pos[3];
+          float distance[3];
+          
+          for (int i=0; i<3; ++i) {
+            pos[i] = float(currentHit->getTrackerHit()->getPosition()[i]);
+          }
+          
+          // get the distance of closest approach and distance s traversed to the POCA 
+          float time = helix.getDistanceToPoint(pos,distance);    
+          
+          // sanity check on s 
+          if (time < 1.0e+10) {
+            
+            // check if this is the closest hit yet
+            if (distance[2] < distMin) { // distance[2] = sqrt( d0*d0 + z0*z0 ) 
+              
+              // if yes store hit and distance 
+              distMin = distance[2];             
+              assignedhit = currentHit;
+            }
+          }
+        } // endloop over hits in the Inner sector
+      } // endloop over theta in the Inner region 
+    } // endloop over phi in the Inner region
+    //std::cout << "fucd---------------------2" << std::endl;
+    // check if closest hit fulfills the min distance cut
+    if (distMin < _minDistCutAttach) {
+      
+      // if yes try to include it in the fit 
+      
+      TrackerHitExtendedVec& hvec = trackAR->getTrackerHitExtendedVec();
+      int  nHits = int(hvec.size());
+      double * xh = new double[nHits+1];
+      double * yh = new double[nHits+1];
+      float * zh = new float[nHits+1];
+      double * wrh = new double[nHits+1];
+      float * wzh = new float[nHits+1];
+      float * rh = new float[nHits+1];
+      float * ph = new float[nHits+1];
+      float par[5];
+      float epar[15];
+      
+      for (int ih=0;ih<nHits;++ih) {
+	edm4hep::TrackerHit * trkHit = hvec[ih]->getTrackerHit();
+        xh[ih] = trkHit->getPosition()[0];
+        yh[ih] = trkHit->getPosition()[1];
+        zh[ih] = float(trkHit->getPosition()[2]);
+        wrh[ih] = double(1.0/(hvec[ih]->getResolutionRPhi()*hvec[ih]->getResolutionRPhi()));
+        wzh[ih] = 1.0/(hvec[ih]->getResolutionZ()*hvec[ih]->getResolutionZ());
+        rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih]));
+        ph[ih] = float(atan2(yh[ih],xh[ih]));
+        if (ph[ih] < 0.) 
+          ph[ih] = TWOPI + ph[ih]; 
+      }      
+      edm4hep::TrackerHit * assignedTrkHit = assignedhit->getTrackerHit();
+      xh[nHits] = assignedTrkHit->getPosition()[0];
+      yh[nHits] = assignedTrkHit->getPosition()[1];
+      zh[nHits] = float(assignedTrkHit->getPosition()[2]);
+      rh[nHits] = float(sqrt(xh[nHits]*xh[nHits]+yh[nHits]*yh[nHits]));
+      ph[nHits] = float(atan2(yh[nHits],xh[nHits]));
+      if (ph[nHits] < 0.) 
+        ph[nHits] = TWOPI + ph[nHits]; 
+      wrh[nHits] = double(1.0/(assignedhit->getResolutionRPhi()*assignedhit->getResolutionRPhi()));
+      wzh[nHits] = 1.0/(assignedhit->getResolutionZ()*assignedhit->getResolutionZ());
+      
+      int NPT = nHits + 1;
+      int iopt = 2;
+      float chi2RPhi;
+      float chi2Z;
+      
+//      std::cout << "######## number of hits to fit with _fastfitter = " << NPT << endmsg; 
+      
+      _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+      par[3] = par[3]*par[0]/fabs(par[0]);
+      
+      
+      delete[] xh;
+      delete[] yh;
+      delete[] zh;
+      delete[] wrh;
+      delete[] wzh;
+      delete[] rh;
+      delete[] ph;
+      
+      bool validCombination = 0;
+      float Chi2 = FLT_MAX;
+      
+      if ((nHits+1) == 4) {
+        Chi2 = chi2RPhi*_chi2WRPhiQuartet+chi2Z*_chi2WZQuartet;
+      }         
+      if ((nHits+1) >= 5) {
+        Chi2 = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+      }
+      int ndf = 2*NPT-5;
+      
+      // check if this is valid combination based on the chi2/ndf
+      validCombination = Chi2/float(ndf) < _chi2FitCut;
+      
+      if ( validCombination ) {
+        // assign hit to track and track to hit, update the track parameters
+        trackAR->addTrackerHitExtended(assignedhit);
+        assignedhit->addTrackExtended(trackAR);
+        float omega = par[0];
+        float tanlambda = par[1];
+        float phi0 = par[2];
+        float d0 = par[3];
+        float z0 = par[4];
+        helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+        trackAR->setD0(d0);
+        trackAR->setZ0(z0);
+        trackAR->setPhi(phi0);
+        trackAR->setTanLambda(tanlambda);
+        trackAR->setOmega(omega);
+        trackAR->setChi2( Chi2 );
+        trackAR->setCovMatrix(epar);
+        trackAR->setNDF( ndf );
+      }
+      
+    }
+  } // endloop over remaining layers
+  //std::cout << "fucd---------------------3" << std::endl;
+  TrackerHitExtendedVec& hvec = trackAR->getTrackerHitExtendedVec();  
+  int nTotalHits = int(hvec.size());
+  
+//  std::cout << "######## number of hits to return = " << nTotalHits << endmsg; 
+  
+  return nTotalHits;
+  
+}
+
+
+void SiliconTracking::Sorting(TrackExtendedVec & trackVec) {
+  /**
+   Sorting of Track Vector in ascending order of chi2/ndf
+   */
+  
+  std::sort(trackVec.begin(), trackVec.end(), compare_TrackExtended() );
+  
+  // also clean up? what does this do here?
+  for (size_t i=0, sizeOfVector=trackVec.size(); i<sizeOfVector; ++i) {
+    
+    TrackerHitExtendedVec& hitVec = trackVec[i]->getTrackerHitExtendedVec();
+    int nHits = int(hitVec.size());
+    
+    for (int ih=0;ih<nHits;ih++) {
+      hitVec[ih]->clearTrackVec();
+    }
+  }
+  
+}
+
+void SiliconTracking::CreateTrack(TrackExtended * trackAR ) {
+  
+  /**
+   Method which creates Track out of TrackExtended objects. Checks for possible
+   track splitting (separate track segments in VXD and FTD).
+   */
+  
+  
+  TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+  int nHits = int(hitVec.size());
+  
+  for (int i=0; i<nHits; ++i) {
+    TrackExtendedVec& trackVec = hitVec[i]->getTrackExtendedVec();
+    if (trackVec.size() != 0) 
+      return ;
+  }
+  
+  // First check if the current track is piece of the split one
+  // look for matching track segment
+  
+  int found = 0;
+  
+  int nTrk = int(_trackImplVec.size());
+  
+  for (int itrk=0; itrk<nTrk; ++itrk) {
+    TrackExtended * trackOld = _trackImplVec[itrk];
+    TrackerHitExtendedVec& hitVecOld = trackOld->getTrackerHitExtendedVec();
+    
+    float phiNew = trackAR->getPhi();
+    float phiOld = trackOld->getPhi();
+    float thetaNew = M_PI_2 - atan(trackAR->getTanLambda());
+    float thetaOld = M_PI_2 - atan(trackOld->getTanLambda());
+    
+    float angle = (cos(phiNew)*cos(phiOld)+sin(phiNew)*sin(phiOld))*sin(thetaNew)*sin(thetaOld)+cos(thetaNew)*cos(thetaOld);
+    angle = acos(angle);
+    
+    if (angle < _angleCutForMerging) {
+      int nHitsOld = int(hitVecOld.size());
+      int nTotHits = nHits + nHitsOld;
+      double * xh = new double[nTotHits];
+      double * yh = new double[nTotHits];
+      float * zh = new float[nTotHits];
+      double * wrh = new double[nTotHits];
+      float * wzh = new float[nTotHits];
+      float * rh = new float[nTotHits];
+      float * ph = new float[nTotHits];
+      float par[5];
+      float epar[15];
+      float refPoint[3] = {0.,0.,0.};
+      for (int ih=0;ih<nHits;++ih) {
+	edm4hep::TrackerHit * trkHit = hitVec[ih]->getTrackerHit();
+        float rR = hitVec[ih]->getResolutionRPhi();
+        float rZ = hitVec[ih]->getResolutionZ();
+        if (int(hitVec[ih]->getTrackExtendedVec().size()) != 0)
+          debug() << "WARNING : HIT POINTS TO TRACK " << endmsg;
+        xh[ih] = trkHit->getPosition()[0];
+        yh[ih] = trkHit->getPosition()[1];
+        zh[ih] = float(trkHit->getPosition()[2]);
+        wrh[ih] = double(1.0/(rR*rR));
+        wzh[ih] = 1.0/(rZ*rZ);
+        rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih]));
+        ph[ih] = float(atan2(yh[ih],xh[ih]));
+      }      
+      for (int ih=0;ih<nHitsOld;++ih) {
+	edm4hep::TrackerHit * trkHit = hitVecOld[ih]->getTrackerHit();
+        xh[ih+nHits] = trkHit->getPosition()[0];
+        yh[ih+nHits] = trkHit->getPosition()[1];
+        zh[ih+nHits] = float(trkHit->getPosition()[2]);
+        float rR = hitVecOld[ih]->getResolutionRPhi();
+        float rZ = hitVecOld[ih]->getResolutionZ();     
+        wrh[ih+nHits] = double(1.0/(rR*rR));
+        wzh[ih+nHits] = 1.0/(rZ*rZ);
+        rh[ih+nHits] = float(sqrt(xh[ih+nHits]*xh[ih+nHits]+yh[ih+nHits]*yh[ih+nHits]));
+        ph[ih+nHits] = float(atan2(yh[ih+nHits],xh[ih+nHits]));
+        
+      }
+      int NPT = nTotHits;
+      int iopt = 2;
+      float chi2RPhi;
+      float chi2Z;
+      int ndf = 2*NPT - 5;
+      
+      _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+      par[3] = par[3]*par[0]/fabs(par[0]);
+      
+      float omega = par[0];
+      float tanlambda = par[1];
+      float phi0 = par[2];
+      float d0 = par[3];
+      float z0 = par[4];
+      
+      float eparmin[15];
+      for (int iparam=0;iparam<15;++iparam)
+        eparmin[iparam] = epar[iparam];      
+      
+      float refPointMin[3];
+      for (int ipp=0;ipp<3;++ipp)
+        refPointMin[ipp] = refPoint[ipp];
+      
+      float chi2Min = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+      chi2Min = chi2Min/float(ndf);
+      
+      float chi2MinRPhi = chi2RPhi;
+      float chi2MinZ = chi2Z;
+      
+      int iBad = -1;
+      if (chi2Min < _chi2FitCut) {
+        found = 1;
+      }
+      else { // SJA:FIXME: UH What is going on here? setting weights to 0 and refitting?
+        float * wzhOld = new float[nTotHits];
+        double * wrhOld = new double[nTotHits];
+        for (int i=0;i<nTotHits;++i) {
+          wzhOld[i] = wzh[i];
+          wrhOld[i] = wrh[i];
+        }
+        for (int i=0; i<nTotHits; ++i) {
+          for (int j=0;j<nTotHits;++j) {
+            if (i == j) {
+              wrh[j] = 0.0;
+              wzh[j] = 0.0;
+            } 
+            else {
+              wrh[j] = wrhOld[j];
+              wzh[j] = wzhOld[j];
+            }
+          }
+          
+          _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+          par[3] = par[3]*par[0]/fabs(par[0]);
+          
+          float chi2Cur = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+          chi2Cur = chi2Cur/float(ndf);
+          
+          if (chi2Cur < chi2Min) {
+            chi2Min = chi2Cur;
+            chi2MinRPhi = chi2RPhi;
+            chi2MinZ = chi2Z;
+            omega = par[0];
+            tanlambda = par[1];
+            phi0 = par[2];
+            d0 = par[3];
+            z0 = par[4];
+            for (int iparam=0;iparam<15;++iparam)
+              eparmin[iparam] = epar[iparam];
+            for (int ipp=0;ipp<3;++ipp)
+              refPointMin[ipp] = refPoint[ipp];
+            iBad = i;
+          }
+        }
+        if (chi2Min < _chi2FitCut) {
+          found = 1;
+        }
+        delete[] wzhOld;
+        delete[] wrhOld;
+      }
+      
+      // Split track is found.
+      // Attach hits belonging to the current track segment to  
+      // the track already created
+      if (found == 1) {
+        trackOld->ClearTrackerHitExtendedVec();
+        for (int i=0;i<nHits;++i) {
+          TrackerHitExtended * trkHit = hitVec[i];
+          trkHit->clearTrackVec();
+          if (i == iBad) {          
+          }
+          else {
+            trackOld->addTrackerHitExtended(trkHit);
+            trkHit->addTrackExtended( trackOld );
+          }
+        }  
+        for (int i=0;i<nHitsOld;++i) {
+          int icur = i+nHits;
+          TrackerHitExtended * trkHit = hitVecOld[i];
+          trkHit->clearTrackVec();
+          if (icur == iBad) {
+          }
+          else {
+            trackOld->addTrackerHitExtended(trkHit);
+            trkHit->addTrackExtended( trackOld );
+          }
+        }
+        trackOld->setOmega(omega);
+        trackOld->setTanLambda(tanlambda);
+        trackOld->setPhi(phi0);
+        trackOld->setD0(d0);
+        trackOld->setZ0(z0);
+        
+        //      std::cout << "Split track found " << d0 << " " << z0 << endmsg;
+        
+        // killeb:  In the original SiliconTracking this was in the NOT simple helix branch.
+        // The rest of the code uses the simple helix branch, where ndf_D is never set.
+        // In fact it has never been initialised or used anywhere. I think this line should not be executed.
+        // ndf = ndf_D;
+        
+        trackOld->setChi2(chi2Min*float(ndf));  
+        trackOld->setNDF(ndf);
+        trackOld->setCovMatrix(eparmin);
+        //      trackOld->setReferencePoint(refPointMin);
+      }
+      
+      delete[] xh;
+      delete[] yh;
+      delete[] zh;
+      delete[] wrh;
+      delete[] wzh;
+      delete[] rh;
+      delete[] ph;
+      
+    }
+    if (found == 1)
+      break;
+  }
+  
+  // Candidate is a unique track
+  // No other segments are found
+  if (found == 0 ) {
+    _trackImplVec.push_back(trackAR);
+    for (int i=0;i<nHits;++i) {
+      TrackerHitExtended * hit = hitVec[i];
+      hit->addTrackExtended( trackAR );
+    }
+  }
+  
+  
+}
+
+void SiliconTracking::AttachRemainingVTXHitsFast() {
+  
+  std::vector<TrackerHitExtendedVec> nonAttachedHits;
+  nonAttachedHits.resize(_nDivisionsInPhi*_nDivisionsInTheta);
+  std::vector<TrackExtendedVec> trackVector;
+  trackVector.resize(_nDivisionsInPhi*_nDivisionsInTheta);
+  int nTracks = int(_trackImplVec.size());
+  
+  for (int iTrk=0;iTrk<nTracks;++iTrk) {
+    TrackExtended * track = _trackImplVec[iTrk];
+    double Phi = double(track->getPhi());
+    if (Phi < 0)
+      Phi = Phi + TWOPI;
+    float tanlambda = track->getTanLambda();
+    double cosTheta = double(tanlambda/sqrt(1+tanlambda*tanlambda));
+    int iPhi = int(Phi/_dPhi);
+    int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+    int iCode = iPhi + _nDivisionsInPhi*iTheta; 
+    trackVector[iCode].push_back( track );
+  }
+  
+  for (int il=0;il<_nLayers;++il) {
+    for (int ip=0;ip<_nDivisionsInPhi;++ip) {
+      for (int it=0;it<_nDivisionsInTheta; ++it) {
+        int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it;      
+        TrackerHitExtendedVec& hitVec = _sectors[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hitExt = hitVec[iH];
+          TrackExtendedVec& trackVec = hitExt->getTrackExtendedVec();
+          if (trackVec.size()==0) {
+	    edm4hep::TrackerHit * hit = hitExt->getTrackerHit();
+            double pos[3];
+            double radius = 0;
+            for (int i=0; i<3; ++i) {
+              pos[i] = hit->getPosition()[i];
+              radius += pos[i]*pos[i];
+            }
+            radius = sqrt(radius);
+            double cosTheta = pos[2]/radius;
+            double Phi = atan2(pos[1],pos[0]);
+            if (Phi < 0.) Phi = Phi + TWOPI;
+            int iPhi = int(Phi/_dPhi);
+            int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+            iCode = iPhi + _nDivisionsInPhi*iTheta;      
+            nonAttachedHits[iCode].push_back( hitExt );
+          }
+        }
+      }
+    }
+  }
+  
+  for (int iT=0; iT<_nDivisionsInTheta; ++iT) {
+    for (int iP=0; iP<_nDivisionsInPhi; ++iP) {
+      int iCode = iP + _nDivisionsInPhi*iT; 
+      int nHits = int(nonAttachedHits[iCode].size());
+      int iT1 = iT - 1;
+      int iT2 = iT + 1; 
+      if (iT == 0) {
+        iT1 = iT;
+        iT2 = iT1 + 1;
+      }
+      if (iT == _nDivisionsInTheta - 1) {
+        iT2 = iT;
+        iT1 = iT2 - 1;
+      }
+      int iPHI[3];
+      iPHI[0] = iP - 1;
+      iPHI[1] = iP;
+      iPHI[2] = iP + 1;
+      if (iP == 0) 
+        iPHI[0] = _nDivisionsInPhi - 1;
+      if (iP == _nDivisionsInPhi - 1 )
+        iPHI[2] = 0;
+      
+      for (int ihit = 0; ihit<nHits; ++ihit) {
+        
+        TrackerHitExtended * hit = nonAttachedHits[iCode][ihit];
+        TrackExtended * trackToAttach = NULL;
+        float minDist = 1.0e+6;
+        
+        for (int iTheta = iT1; iTheta <iT2+1; ++iTheta) {
+          for (int indexP=0;indexP<3;++indexP) {
+            int iPhi = iPHI[indexP];        
+            int iCodeForTrack = iPhi + _nDivisionsInPhi*iTheta;
+            int nTrk = int(trackVector[iCodeForTrack].size());
+            for (int iTrk=0; iTrk<nTrk; ++iTrk) {         
+              TrackExtended * trackAR = trackVector[iCodeForTrack][iTrk];
+              bool consider = true;
+              if (_checkForDelta) {
+                TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+                int NHITS = int(hitVector.size());
+                for (int IHIT=0;IHIT<NHITS;++IHIT) {
+                  
+                  // Here we are trying to find if a hits are too close i.e. closer than _minDistToDelta
+		  edm4hep::TrackerHit* trkhit1 = hit->getTrackerHit();
+		  edm4hep::TrackerHit* trkhit2 = hitVector[IHIT]->getTrackerHit();                  
+                  
+                  if ( trkhit1->getCellID() == trkhit2->getCellID() ){ // i.e. they are in the same sensor
+                    float distance = 0.;
+                    for (int iC=0;iC<3;++iC) {
+                      float posFirst = float(hit->getTrackerHit()->getPosition()[iC]);
+                      float posSecond = float(hitVector[IHIT]->getTrackerHit()->getPosition()[iC]);
+                      float deltaPos = posFirst - posSecond;
+                      distance += deltaPos*deltaPos;
+                    }
+                    distance = sqrt(distance);
+                    if (distance<_minDistToDelta) {
+                      consider = false;
+                      break;
+                    }
+                  }
+                }
+              }
+              if (consider) {   
+                float phi0 = trackAR->getPhi();
+                float d0 = trackAR->getD0();
+                float z0 = trackAR->getZ0();
+                float omega = trackAR->getOmega();
+                float tanlambda = trackAR->getTanLambda();
+                HelixClass helix;
+                helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+                int layer = getLayerID(hit->getTrackerHit());
+                if (layer > _minimalLayerToAttach) {
+                  float pos[3];
+                  for (int i=0; i<3; ++i) 
+                    pos[i] = hit->getTrackerHit()->getPosition()[i];      
+                  float distance[3];
+                  float time = helix.getDistanceToPoint(pos,distance);
+                  if (time < 1.0e+10) {
+                    if (distance[2] < minDist) {
+                      minDist = distance[2];
+                      trackToAttach = trackAR;
+                    }                      
+                  }    
+                }
+              }
+            }
+          }
+        }
+        if (minDist < _minDistCutAttach && trackToAttach != NULL) {
+          int iopt = 2;
+          AttachHitToTrack(trackToAttach,hit,iopt);
+        }      
+      }
+    }
+  }
+}
+
+void SiliconTracking::AttachRemainingVTXHitsSlow() {
+  
+  TrackerHitExtendedVec nonAttachedHits;
+  nonAttachedHits.clear();
+  
+  for (int il=0;il<_nLayers;++il) {
+    for (int ip=0;ip<_nDivisionsInPhi;++ip) {
+      for (int it=0;it<_nDivisionsInTheta; ++it) {
+        int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it;      
+        TrackerHitExtendedVec& hitVec = _sectors[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          TrackExtendedVec& trackVec = hit->getTrackExtendedVec();
+          // if (trackVec.size()==0)
+          // nonAttachedHits.push_back( hit );
+          //-- allow hits that are only used in triplets to be re-attached 
+          unsigned int maxTrackSize = 0;
+          for(unsigned int itrack = 0;itrack < trackVec.size();itrack++){
+            TrackerHitExtendedVec hitVec_tmp= trackVec[itrack]->getTrackerHitExtendedVec();
+            unsigned int isize = hitVec_tmp.size();
+            if(isize>maxTrackSize)maxTrackSize = isize;
+          }     
+          if (maxTrackSize<=3) { 
+            debug() << " Add non attached hit to list: id = " << hit->getTrackerHit()->id() << endmsg;
+            nonAttachedHits.push_back( hit );
+          } 
+          
+          
+        }
+      }
+    }
+  }
+  
+  int nNotAttached = int(nonAttachedHits.size());
+  
+  int nTrk = int(_trackImplVec.size()); 
+  for (int iHit=0; iHit<nNotAttached; ++iHit) {
+    TrackerHitExtended * hit = nonAttachedHits[iHit];
+    debug() << " Try hit: id = " << hit->getTrackerHit()->id() << endmsg;
+    int layer = getLayerID( hit->getTrackerHit() );
+    if (layer > _minimalLayerToAttach) {
+      float pos[3];
+      for (int i=0; i<3; ++i) 
+        pos[i] = hit->getTrackerHit()->getPosition()[i];      
+      float minDist = 1e+10;
+      TrackExtended * trackToAttach = NULL;
+      for (int iTrk=0; iTrk<nTrk; ++iTrk) {
+        TrackExtended * trackAR = _trackImplVec[iTrk];
+        bool consider = true;
+        if (_checkForDelta) {
+          TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+          int NHITS = int(hitVector.size());
+          for (int IHIT=0;IHIT<NHITS;++IHIT) {
+            
+            // Here we are trying to find if a hits are too close i.e. closer than _minDistToDelta
+	    edm4hep::TrackerHit* trkhit1 = hit->getTrackerHit();
+	    edm4hep::TrackerHit* trkhit2 = hitVector[IHIT]->getTrackerHit();                  
+            
+            if ( trkhit1->getCellID() == trkhit2->getCellID() ){ // i.e. they are in the same sensor
+              
+              float distance = 0.;
+              for (int iC=0;iC<3;++iC) {
+                float posFirst = float(hit->getTrackerHit()->getPosition()[iC]);
+                float posSecond = float(hitVector[IHIT]->getTrackerHit()->getPosition()[iC]);
+                float deltaPos = posFirst - posSecond;
+                distance += deltaPos*deltaPos;
+              }
+              distance = sqrt(distance);
+              if (distance<_minDistToDelta) {
+                consider = false;
+                debug() << " hit: id = " << hit->getTrackerHit()->id() << " condsidered delta together with hit " << trkhit2->id() << endmsg;
+                break;
+              }
+            }       
+          }
+        }
+        if (consider) {
+          HelixClass helix;
+          float phi0 = trackAR->getPhi();
+          float d0 = trackAR->getD0();
+          float z0 = trackAR->getZ0();
+          float omega = trackAR->getOmega();
+          float tanlambda = trackAR->getTanLambda();
+          helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+          float distance[3];
+          float time = helix.getDistanceToPoint(pos,distance);
+          if (time < 1.0e+10) {
+            if (distance[2] < minDist) {
+              minDist = distance[2];
+              trackToAttach = trackAR;
+            }
+          }
+        }
+      }
+      if (minDist < _minDistCutAttach && trackToAttach != NULL) {
+        int iopt = 2;
+        debug() << " Hit: id = " << hit->getTrackerHit()->id() << " : try attachement"<< endmsg;
+        AttachHitToTrack(trackToAttach,hit,iopt);
+      } else {
+        debug() << " Hit: id = " << hit->getTrackerHit()->id() << " rejected due to distance cut of " <<_minDistCutAttach<< " min distance = "  << minDist << endmsg;
+      }      
+    }
+  }  
+}
+
+void SiliconTracking::AttachRemainingFTDHitsSlow() {
+  TrackerHitExtendedVec nonAttachedHits;
+  nonAttachedHits.clear();
+  
+  for (int iS=0;iS<2;++iS) {
+    for (unsigned int layer=0;layer<_nlayersFTD;++layer) {
+      for (int ip=0;ip<_nPhiFTD;++ip) {
+        int iCode = iS + 2*layer + 2*_nlayersFTD*ip;      
+        TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          TrackExtendedVec& trackVec = hit->getTrackExtendedVec();
+          if (trackVec.size()==0)
+            nonAttachedHits.push_back( hit );
+        }
+      }
+    }
+  }
+  
+  int nNotAttached = int(nonAttachedHits.size());
+  
+  int nTrk = int(_trackImplVec.size()); 
+  for (int iHit=0; iHit<nNotAttached; ++iHit) {
+    TrackerHitExtended * hit = nonAttachedHits[iHit];
+    float pos[3];
+    for (int i=0; i<3; ++i) 
+      pos[i] = hit->getTrackerHit()->getPosition()[i];      
+    float minDist = 1e+10;
+    TrackExtended * trackToAttach = NULL;
+    for (int iTrk=0; iTrk<nTrk; ++iTrk) {
+      TrackExtended * trackAR = _trackImplVec[iTrk];
+      bool consider = true;
+      TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+      int NHITS = int(hitVector.size());
+      
+      for (int IHIT=0;IHIT<NHITS;++IHIT) {
+        
+        // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works 
+        //        if (hit->getTrackerHit()->getType() == hitVector[IHIT]->getTrackerHit()->getType()) {
+        if (hit->getTrackerHit()->getCellID() == hitVector[IHIT]->getTrackerHit()->getCellID()) {
+          
+          consider = false;
+          break;
+        }
+      }
+      
+      
+      if (consider) {
+        HelixClass helix;
+        float phi0 = trackAR->getPhi();
+        float d0 = trackAR->getD0();
+        float z0 = trackAR->getZ0();
+        float omega = trackAR->getOmega();
+        float tanlambda = trackAR->getTanLambda();
+        if (tanlambda*float(getSideID(hit->getTrackerHit())) > 0) {
+          helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+          float distance[3];
+          float time = helix.getDistanceToPoint(pos,distance);
+          if (time < 1.0e+10) {
+            if (distance[2] < minDist) {
+              minDist = distance[2];
+              trackToAttach = trackAR;
+            }
+          }
+        }
+      }
+    }
+    if (minDist < _minDistCutAttach && trackToAttach != NULL) {
+      int iopt = 2;
+      AttachHitToTrack(trackToAttach,hit,iopt);
+    }      
+  }  
+}
+
+
+void SiliconTracking::AttachRemainingFTDHitsFast() {
+  int nTrk = _trackImplVec.size();
+  
+  for (int iTrk=0; iTrk<nTrk; ++iTrk) {
+    TrackExtended * trackAR = _trackImplVec[iTrk];
+    HelixClass helix;
+    float phi0 = trackAR->getPhi();
+    float d0 = trackAR->getD0();
+    float z0 = trackAR->getZ0();
+    float omega = trackAR->getOmega();
+    float tanlambda = trackAR->getTanLambda();
+    helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+    int iSemiSphere = 0;
+    if (tanlambda > 0) 
+      iSemiSphere = 1;
+    float ref[3];
+    for (int i=0;i<3;++i) 
+      ref[i] = helix.getReferencePoint()[i];
+    // Start loop over FTD layers
+    for (unsigned int layer=0;layer<_nlayersFTD;layer++) {
+      float ZL = _zLayerFTD[layer];
+      if (iSemiSphere == 0)
+        ZL = - ZL;
+      float point[3];
+      helix.getPointInZ(ZL,ref,point);
+      float Phi = atan2(point[1],point[0]);
+      if (Phi < 0) 
+        Phi = Phi + TWOPI;
+      int iPhi = int(Phi/_dPhiFTD);
+      float distMin = 1e+10;
+      TrackerHitExtended * attachedHit = NULL;     
+      for (int iP=iPhi-1;iP<=iPhi+1;++iP) {
+        int iPP = iP;
+        if (iP < 0) 
+          iPP = iP + _nPhiFTD;
+        if (iP >= _nPhiFTD)
+          iPP = iP - _nPhiFTD;  
+        int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPP;
+        int nHits = int(_sectorsFTD[iCode].size());
+        for (int iHit=0;iHit<nHits;++iHit) {
+          TrackerHitExtended * hit = _sectorsFTD[iCode][iHit];
+          bool consider = true;
+          TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+          int NHITS = int(hitVector.size());
+          
+          // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works 
+          for (int IHIT=0;IHIT<NHITS;++IHIT) {
+            //            if (hit->getTrackerHit()->getType() == hitVector[IHIT]->getTrackerHit()->getType()) {
+            if (hit->getTrackerHit()->getCellID() == hitVector[IHIT]->getTrackerHit()->getCellID()) {
+              consider = false;
+              break;
+            }
+          }
+          
+          
+          if (consider) {
+            float pos[3];
+            for (int i=0;i<3;++i) {
+              pos[i] = hit->getTrackerHit()->getPosition()[i];
+            }
+            float distance[3];
+            float time = helix.getDistanceToPoint(pos,distance);
+            if (time < 1.0e+10) {
+              if (distance[2] < distMin) {
+                distMin = distance[2];
+                attachedHit = hit;
+              }
+            }
+          }
+        }
+      }
+      if (distMin < _minDistCutAttach && attachedHit != NULL) {
+        int iopt = 2;
+        AttachHitToTrack(trackAR,attachedHit, iopt);
+      }
+    }
+  }
+}
+
+void SiliconTracking::TrackingInFTD() {
+
+  int nComb = int(_CombinationsFTD.size()) / 3;
+
+  for (int iComb=0;iComb<nComb;++iComb) {
+
+    int nLS[3];
+    nLS[0] = _CombinationsFTD[3*iComb];
+    nLS[1] = _CombinationsFTD[3*iComb+1];
+    nLS[2] = _CombinationsFTD[3*iComb+2];
+
+    for (int iS=0;iS<2;++iS) { // loop over +z and -z
+      
+      //      std::cout << "Combinations : " << iS << " " << nLS[0] << " " << nLS[1] << " " << nLS[2] << endmsg;
+      //      int iC = iS + 2*nLS[0];
+      //      TrackerHitExtendedVec& hitVec = _sectorsFTD[iC];
+      //      int nO = int(hitVec.size());
+      //      iC = iS + 2*nLS[1];
+      //      hitVec = _sectorsFTD[iC];
+      //      int nM = int(hitVec.size());
+      //      iC = iS + 2*nLS[2];
+      //      hitVec = _sectorsFTD[iC];
+      //      int nI = int(hitVec.size());
+      //      std::cout << nO << " " << nM << " " << nI << endmsg;
+
+      for (int ipOuter=0;ipOuter<_nPhiFTD;++ipOuter) { 
+
+        int ipMiddleLow = ipOuter - 1;
+        int ipMiddleUp  = ipOuter + 1;
+        
+        unsigned int iCodeOuter = iS + 2*nLS[0] + 2*_nlayersFTD*ipOuter;
+        
+        if( iCodeOuter >= _sectorsFTD.size()){          
+          error() << "iCodeOuter index out of range: iCodeOuter =   " << iCodeOuter << " _sectorsFTD.size() = " << _sectorsFTD.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg;
+          exit(1);
+        }
+        
+        TrackerHitExtendedVec& hitVecOuter = _sectorsFTD[iCodeOuter];
+        
+        int nOuter = int(hitVecOuter.size());
+
+        for (int iOuter=0;iOuter<nOuter;++iOuter) {
+          
+          TrackerHitExtended * hitOuter = hitVecOuter[iOuter];
+        
+          for (int ipMiddle=ipMiddleLow;ipMiddle<=ipMiddleUp;++ipMiddle) {
+            //for(int ipMiddle=0;ipMiddle<_nPhiFTD;++ipMiddle) {
+            int ipM = ipMiddle;
+            if (ipM < 0) 
+              ipM = ipMiddle + _nPhiFTD;
+            if (ipM >= _nPhiFTD)
+              ipM = ipMiddle - _nPhiFTD;
+            int iCodeMiddle = iS + 2*nLS[1] + 2*_nlayersFTD*ipM;
+          
+            TrackerHitExtendedVec& hitVecMiddle = _sectorsFTD[iCodeMiddle];
+            int ipInnerLow,ipInnerUp;       
+            ipInnerLow = ipMiddle - 1;
+            ipInnerUp =  ipMiddle + 1;
+            
+            int nMiddle = int(hitVecMiddle.size());
+            
+            for (int iMiddle=0;iMiddle<nMiddle;++iMiddle) {
+              TrackerHitExtended * hitMiddle = hitVecMiddle[iMiddle];
+              for (int ipInner=ipInnerLow;ipInner<=ipInnerUp;++ipInner) {
+                //for (int ipInner=0;ipInner<_nPhiFTD;++ipInner) {
+                int ipI = ipInner;
+                if (ipI < 0)
+                  ipI = ipInner + _nPhiFTD;
+                if (ipI >= _nPhiFTD) 
+                  ipI = ipInner - _nPhiFTD;
+                int iCodeInner = iS + 2*nLS[2] + 2*_nlayersFTD*ipI;
+                TrackerHitExtendedVec& hitVecInner = _sectorsFTD[iCodeInner];
+            
+                int nInner = int(hitVecInner.size());
+                
+                for (int iInner=0;iInner<nInner;++iInner) {
+                
+                  TrackerHitExtended * hitInner = hitVecInner[iInner];
+                  HelixClass helix;
+                  //                  std::cout << endmsg;
+                  //                  std::cout << "Outer Hit Type " << hitOuter->getTrackerHit()->getType() << " z = " << hitOuter->getTrackerHit()->getPosition()[2] 
+                  //                  << "\nMiddle Hit Type "<< hitMiddle->getTrackerHit()->getType() << " z = " << hitMiddle->getTrackerHit()->getPosition()[2]  
+                  //                  << "\nInner Hit Type "<< hitInner->getTrackerHit()->getType() << " z = " << hitInner->getTrackerHit()->getPosition()[2]  << endmsg;
+
+                  debug() << " "
+                  << std::setw(3) << ipOuter       << " "   << std::setw(3) << ipMiddle << " "      << std::setw(3) << ipInner << "       "
+                  << std::setw(3) << iS << "     "
+                  << std::setw(3) << nLS[0]     << " "   << std::setw(3) << nLS[1]   << " "      << std::setw(3) << nLS[2]  << "     "
+                  << std::setw(3) << nOuter << " : " << std::setw(3) << nMiddle << " : " << std::setw(3) << nInner << "  :: "
+                  << std::setw(3) << nOuter*nMiddle* nInner << endmsg;
+
+                  
+                  TrackExtended * trackAR = TestTriplet(hitOuter,hitMiddle,hitInner,helix);
+                  if (trackAR != NULL) {
+                    //                    std::cout << "FTD triplet found" << endmsg;
+                    int nHits = BuildTrackFTD(trackAR,nLS,iS);
+                    
+                    _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits ).push_back( trackAR );
+                  }
+                }
+              }
+            }
+          }       
+        }
+      }
+    }
+  }
+}
+
+
+int SiliconTracking::BuildTrackFTD(TrackExtended * trackAR, int * nLR, int iS) {
+  //  std::cout << "BuildTrackFTD: Layers = " << nLR[0] << " " << nLR[1] << " " << nLR[2] << endmsg;
+  
+  // initialise a helix from the track
+  HelixClass helix;
+  const float d0 = trackAR->getD0();
+  const float z0 = trackAR->getZ0();
+  const float phi0 = trackAR->getPhi();
+  const float tanlambda = trackAR->getTanLambda();
+  const float omega = trackAR->getOmega();
+  helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+  float ref[3] = {helix.getReferencePoint()[0],
+    helix.getReferencePoint()[1],
+    helix.getReferencePoint()[2]};
+  
+  for (int iL=0; iL < static_cast<int>(_nlayersFTD); ++iL) {
+    if (iL != nLR[0] && iL != nLR[1] && iL != nLR[2]) {
+      float point[3];
+      float ZL = _zLayerFTD[iL];
+      if (iS == 0) 
+        ZL = - ZL;
+      helix.getPointInZ(ZL,ref,point);
+      //      float Phi = atan2(point[1],point[0]);
+      //      int iPhi = int(Phi/_dPhiFTD);
+      float distMin = 1e+6;
+      TrackerHitExtended * attachedHit = NULL;
+      for (int ip=0;ip<=_nPhiFTD;++ip) {
+        int iP = ip;
+        if (iP < 0)
+          iP = ip + _nPhiFTD;
+        if (iP >= _nPhiFTD)
+          iP = ip - _nPhiFTD;   
+        int iCode = iS + 2*iL + 2*_nlayersFTD*iP;
+        TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+	  edm4hep::TrackerHit * trkHit = hit->getTrackerHit();
+          float pos[3];
+          for (int i=0;i<3;++i)
+            pos[i] = float(trkHit->getPosition()[i]);
+          float distance[3];
+          float time = helix.getDistanceToPoint(pos,distance);
+          if (time < 1.0e+10) {
+            if (distance[2] < distMin) {
+              distMin = distance[2];
+              attachedHit = hit;
+            }
+          }
+        }
+      }
+      //      std::cout << "Layer = " << iL << "  distMin = " << distMin << endmsg;
+      if (distMin < _minDistCutAttach && attachedHit != NULL) {
+        int iopt = 2;
+        AttachHitToTrack( trackAR, attachedHit, iopt);
+      }
+    }
+  }
+  TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+  int nH = int (hitVec.size());
+  return nH;
+}
+
+int SiliconTracking::AttachHitToTrack(TrackExtended * trackAR, TrackerHitExtended * hit, int iopt) {
+  
+  int attached = 0;
+  TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+  int nHits = int(hitVec.size());
+  
+  double * xh = new double[nHits+1];
+  double * yh = new double[nHits+1];
+  float  * zh = new float[nHits+1];
+  double * wrh = new double[nHits+1];
+  float * wzh = new float[nHits+1];
+  float * rh = new float[nHits+1];
+  float * ph = new float[nHits+1];
+  float par[5];
+  float epar[15];
+  
+  for (int i=0; i<nHits; ++i) {
+    edm4hep::TrackerHit * trkHit = hitVec[i]->getTrackerHit();
+    xh[i] = double(trkHit->getPosition()[0]);
+    yh[i] = double(trkHit->getPosition()[1]);
+    zh[i] = float(trkHit->getPosition()[2]);
+    ph[i] = float(atan2(yh[i],xh[i]));
+    rh[i] = float(sqrt(xh[i]*xh[i]+yh[i]*yh[i]));
+    float rR = hitVec[i]->getResolutionRPhi();
+    float rZ = hitVec[i]->getResolutionZ();
+    wrh[i] = double(1.0/(rR*rR));
+    wzh[i] = 1.0/(rZ*rZ);
+  }
+  
+  edm4hep::TrackerHit * trkHit = hit->getTrackerHit();
+  xh[nHits] = double(trkHit->getPosition()[0]);
+  yh[nHits] = double(trkHit->getPosition()[1]);
+  zh[nHits] = float(trkHit->getPosition()[2]);
+  ph[nHits] = float(atan2(yh[nHits],xh[nHits]));
+  rh[nHits] = float(sqrt(xh[nHits]*xh[nHits]+yh[nHits]*yh[nHits]));
+  
+  float rR = hit->getResolutionRPhi();
+  float rZ = hit->getResolutionZ();
+  wrh[nHits] = double(1.0/(rR*rR));
+  wzh[nHits] = 1.0/(rZ*rZ);
+  
+  
+  int NPT = nHits + 1;
+  
+  // SJA:FIXME the newtonian part is giving crazy results for FTD so just use iopt 2 for simply attaching hits 
+  // using SIT and VXD doesn't seem to give any problems, so make it a function parameter and let the caller decide
+  //  int iopt = 3;
+  
+  float chi2RPhi = 0 ;
+  float chi2Z = 0 ;
+  
+  
+  int error = _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+  par[3] = par[3]*par[0]/fabs(par[0]);
+  
+  
+  float omega = par[0];
+  float tanlambda = par[1];
+  float phi0 = par[2];
+  float d0 = par[3];
+  float z0 = par[4];
+  float chi2 = FLT_MAX;
+  int ndf = INT_MAX;
+  
+  if (NPT == 3) {
+    chi2 = chi2RPhi*_chi2WRPhiTriplet+chi2Z*_chi2WZTriplet;
+  }
+  if (NPT == 4) {
+    chi2 = chi2RPhi*_chi2WRPhiQuartet+chi2Z*_chi2WZQuartet;
+  }
+  if (NPT > 4) {
+    chi2 = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+  }
+  ndf = 2*NPT-5;
+  
+  
+  if ( error == 0 && chi2/float(ndf) < _chi2FitCut ) {
+    trackAR->addTrackerHitExtended(hit);
+    hit->addTrackExtended( trackAR );
+    trackAR->setChi2( chi2 );
+    trackAR->setOmega( omega );
+    trackAR->setTanLambda( tanlambda );
+    trackAR->setD0( d0 );
+    trackAR->setZ0( z0 );
+    trackAR->setPhi( phi0 );
+    trackAR->setNDF( ndf );
+    trackAR->setCovMatrix( epar );
+    attached = 1;
+    debug() << "Attachement succeeded chi2/float(ndf) = " << chi2/float(ndf) << "  cut = " <<  _chi2FitCut  << " chi2RPhi = " << chi2RPhi << " chi2Z = " << chi2Z << " error = " << error << endmsg;
+  } else {
+    debug() << "Attachement failed chi2/float(ndf) = " << chi2/float(ndf) << "  cut = " <<  _chi2FitCut  << " chi2RPhi = " << chi2RPhi << " chi2Z = " << chi2Z << " error = " << error << endmsg;
+  }
+  
+  delete[] xh;
+  delete[] yh;
+  delete[] zh;
+  delete[] wrh;
+  delete[] wzh;
+  delete[] rh;
+  delete[] ph;
+  
+  return attached;
+  
+  
+}
+
+void SiliconTracking::FinalRefit(edm4hep::TrackCollection* trk_col) {
+  
+  int nTracks = int(_trackImplVec.size());
+  
+  int nSiSegments = 0;        
+  float eTot = 0.;
+  float pxTot = 0.;
+  float pyTot = 0.;
+  float pzTot = 0.;
+  std::cout << "fucd============" << nTracks << std::endl;
+  for (int iTrk=0;iTrk<nTracks;++iTrk) {
+    
+    TrackExtended * trackAR = _trackImplVec[iTrk];    
+    TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+    
+    int nHits = int(hitVec.size());
+    std::cout << "fucd-------------" << iTrk << ": " << nHits << std::endl;
+    if( nHits >= _minimalHits) {
+      //    int * lh = new int[nHits];
+      std::vector<int> lh;
+      lh.resize(nHits);
+      
+      for (int i=0; i<nHits; ++i) {
+        lh[i]=0;
+      }
+      
+      float d0 = trackAR->getD0();
+      float z0 = trackAR->getZ0();
+      float omega = trackAR->getOmega();
+      float tanlambda = trackAR->getTanLambda();
+      float phi0 = trackAR->getPhi();
+      
+      HelixClass * helix = new HelixClass();
+      helix->Initialize_Canonical(phi0, d0, z0, omega, 
+                                  tanlambda, _bField);
+      
+      
+      // get the point of closest approach to the reference point
+      // here it is implicitly assumed that the reference point is the origin 
+      float Pos[3];
+      Pos[0] = -d0*sin(phi0);
+      Pos[1] = d0*cos(phi0);
+      Pos[2] = z0;
+      
+      std::cout << "fucd------------------1" << std::endl; 
+      // at this point is is possible to have hits from the same layer ...
+      // so a check is made to ensure that the hit with the smallest distance to the 
+      // current helix hypothosis is used, the other hit has lh set to 0 
+      
+      // start loop over the hits to
+      for (int ihit=0;ihit<nHits;++ihit) {
+        
+        lh[ihit] = 1; // only hits which have lh=1 will be used for the fit
+        
+        // get the pointer to the lcio trackerhit for this hit
+	edm4hep::TrackerHit * trkHit = hitVec[ihit]->getTrackerHit();
+        
+        int det = getDetectorID(trkHit);
+        
+        if (det == lcio::ILDDetID::VXD || det == lcio::ILDDetID::FTD || det == lcio::ILDDetID::SIT) { // only accept VXD, FTD or SIT
+          
+          
+          //        int layer = getLayerID(trkHit);
+          //        int moduleIndex = getModuleID(trkHit);
+          
+          // start a double loop over the hits which have already been checked 
+          for (int lhit=0;lhit<ihit;++lhit) {
+            
+            // get the pointer to the lcio trackerhit for the previously checked hit
+	    edm4hep::TrackerHit * trkHitS = hitVec[lhit]->getTrackerHit();
+            
+            
+            //          int layerS = getLayerID(trkHitS);
+            //          int moduleIndexS = getModuleID(trkHitS);
+            
+            // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works 
+            // if they are on the same layer and the previously checked hits has been declared good for fitting
+            //          if ((trkHitS->getType() == trkHit->getType()) && (lh[lhit] == 1)) {
+            // check if the hits have the same layer and petal number
+            //          hitVec[ihit]->
+            //          if ((layer == layerS) && (moduleIndex==moduleIndexS) && (lh[lhit] == 1)) {
+            if ( (trkHit->getCellID() == trkHitS->getCellID()) && (lh[lhit] == 1)) {
+              
+              // get the position of the hits 
+              float xP[3];
+              float xPS[3];
+              for (int iC=0;iC<3;++iC) {
+                xP[iC] = float(trkHit->getPosition()[iC]);
+                xPS[iC] = float(trkHitS->getPosition()[iC]);
+              }
+              
+              // get the intersection of the helix with the either the cylinder or plane containing the hit
+              float Point[6];
+              float PointS[6];
+              
+              if (det == lcio::ILDDetID::FTD) {
+
+                float time = helix->getPointInZ(xP[2],Pos,Point);
+                time = helix->getPointInZ(xPS[2],Pos,PointS);
+
+              } else {
+
+                float RAD = sqrt(xP[0]*xP[0]+xP[1]*xP[1]);
+                float RADS = sqrt(xPS[0]*xPS[0]+xPS[1]*xPS[1]);
+                float time = helix->getPointOnCircle(RAD,Pos,Point);
+                time = helix->getPointOnCircle(RADS,Pos,PointS);
+
+              }
+              
+              float DIST = 0;
+              float DISTS = 0;
+              
+              // get the euclidean distance between the hit and the point of intersection
+              for (int iC=0;iC<3;++iC) {
+                DIST += (Point[iC]-xP[iC])*(Point[iC]-xP[iC]);
+                DISTS += (PointS[iC]-xPS[iC])*(PointS[iC]-xPS[iC]);
+              }
+              if (DIST < DISTS) {
+                lh[lhit] = 0;
+              }
+              else {
+                lh[ihit] = 0;
+              }
+              break;
+            }
+          }
+        }
+      }
+      
+      delete helix;
+      
+      std::vector<TrackerHit*> trkHits;
+      std::vector<TrackerHit*> trkHits_used_inFit;
+      
+      int nFit = 0;
+      for (int i=0; i<nHits; ++i) {
+        // check if the hit has been rejected as being on the same layer and further from the helix lh==0
+        if (lh[i] == 1) {
+	  edm4hep::TrackerHit * trkHit = hitVec[i]->getTrackerHit();
+          nFit++;
+          if(trkHit) { 
+            trkHits.push_back(trkHit);   
+          }
+          else{
+            throw EVENT::Exception( std::string("SiliconTracking::FinalRefit: TrackerHit pointer == NULL ")  ) ;
+          }
+        }
+        else { // reject hit 
+               // SJA:FIXME missuse of type find a better way to signal rejected hits
+          hitVec[i]->setType(int(0));
+        }
+      }
+      
+      if( trkHits.size() < 3 ) {
+        debug() << "SiliconTracking::FinalRefit: Cannot fit less than 3 hits. Number of hits =  " << trkHits.size() << endmsg;
+        continue ; 
+      }
+      std::cout << "fucd------------------2" << std::endl;
+      //TrackImpl* Track = new TrackImpl ;
+      auto track = trk_col->create();
+      //fucd
+      //edm4hep::Track track;// = new edm4hep::Track;
+      std::cout << "fucd------------------3" << std::endl;
+      // setup initial dummy covariance matrix
+      //std::vector<float> covMatrix;
+      //covMatrix.resize(15);
+      std::array<float,15> covMatrix;
+
+      for (unsigned icov = 0; icov<covMatrix.size(); ++icov) {
+        covMatrix[icov] = 0;
+      }
+      
+      covMatrix[0]  = ( _initialTrackError_d0    ); //sigma_d0^2
+      covMatrix[2]  = ( _initialTrackError_phi0  ); //sigma_phi0^2
+      covMatrix[5]  = ( _initialTrackError_omega ); //sigma_omega^2
+      covMatrix[9]  = ( _initialTrackError_z0    ); //sigma_z0^2
+      covMatrix[14] = ( _initialTrackError_tanL  ); //sigma_tanl^2
+      
+      
+      std::vector< std::pair<float, edm4hep::TrackerHit*> > r2_values;
+      r2_values.reserve(trkHits.size());
+      
+      for (std::vector<edm4hep::TrackerHit*>::iterator it=trkHits.begin(); it!=trkHits.end(); ++it) {
+        edm4hep::TrackerHit* h = *it;
+        float r2 = h->getPosition()[0]*h->getPosition()[0]+h->getPosition()[1]*h->getPosition()[1];
+        r2_values.push_back(std::make_pair(r2, *it));
+      }
+      
+      sort(r2_values.begin(),r2_values.end());
+      //std::cout << "fucd------------------3" << std::endl;
+      trkHits.clear();
+      trkHits.reserve(r2_values.size());
+
+      for (std::vector< std::pair<float, edm4hep::TrackerHit*> >::iterator it=r2_values.begin(); it!=r2_values.end(); ++it) {
+        trkHits.push_back(it->second);
+      }
+      //std::cout << "fucd------------------3 " << _trksystem << std::endl;
+      //for (unsigned ihit_indx=0 ; ihit_indx < trkHits.size(); ++ihit_indx) {
+      //  std::cout << "fucd trk hit " << *trkHits[ihit_indx] << " " << trkHits[ihit_indx]->getCovMatrix()[0]
+      //		  << " " << BitSet32(trkHits[ihit_indx]->getType())[ ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] << endmsg;
+      //}
+      /*
+      auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc");
+      if ( !_trackSystemSvc ) {
+	error() << "Failed to find TrackSystemSvc ..." << endmsg;
+	return;
+      }
+      _trksystem =  _trackSystemSvc->getTrackSystem();
+
+      if( _trksystem == 0 ){
+	error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg;
+	return;
+      }
+      debug() << "_trksystem pointer " << _trksystem << endmsg;
+      
+      _trksystem->setOption( IMarlinTrkSystem::CFG::useQMS,        _MSOn ) ;
+      _trksystem->setOption( IMarlinTrkSystem::CFG::usedEdx,       _ElossOn) ;
+      _trksystem->setOption( IMarlinTrkSystem::CFG::useSmoothing,  _SmoothOn) ;
+      _trksystem->init() ;
+      */
+      bool fit_backwards = IMarlinTrack::backward;
+      
+      MarlinTrk::IMarlinTrack* marlinTrk = nullptr;
+      try{
+	marlinTrk = _trksystem->createTrack();
+      }
+      catch(...){
+	error() << "Cannot create MarlinTrack ! " << endmsg;
+	return;
+      }
+      
+      int status = 0;
+      std::cout << "fucd------------------3" << std::endl;
+      try {
+        status = MarlinTrk::createFinalisedLCIOTrack(marlinTrk, trkHits, &track, fit_backwards, covMatrix, _bField, _maxChi2PerHit);
+      } catch (...) {
+        
+        //      delete Track;
+        //      delete marlinTrk;
+        error() << "MarlinTrk::createFinalisedLCIOTrack " << endmsg;
+        throw ;
+        
+      }
+      std::cout << "fucd------------------4" << std::endl;
+      /*
+#ifdef MARLINTRK_DIAGNOSTICS_ON
+      if ( status != IMarlinTrack::success && _runMarlinTrkDiagnostics ) {        
+        void * dcv = _trksystem->getDiagnositicsPointer();
+        DiagnosticsController* dc = static_cast<DiagnosticsController*>(dcv);
+        dc->skip_current_track();
+      }        
+#endif
+      */
+      
+      std::vector<std::pair<edm4hep::TrackerHit* , double> > hits_in_fit ;  
+      std::vector<std::pair<edm4hep::TrackerHit* , double> > outliers ;
+      std::vector<edm4hep::TrackerHit*> all_hits;    
+      all_hits.reserve(300);
+      
+      marlinTrk->getHitsInFit(hits_in_fit);
+      
+      for ( unsigned ihit = 0; ihit < hits_in_fit.size(); ++ihit) {
+        all_hits.push_back(hits_in_fit[ihit].first);
+      }
+      
+      UTIL::BitField64 cellID_encoder( lcio::ILDCellID0::encoder_string ) ; 
+      
+      MarlinTrk::addHitNumbersToTrack(&track, all_hits, true, cellID_encoder);
+      
+      marlinTrk->getOutliers(outliers);
+      
+      for ( unsigned ihit = 0; ihit < outliers.size(); ++ihit) {
+        all_hits.push_back(outliers[ihit].first);
+      }
+      
+      MarlinTrk::addHitNumbersToTrack(&track, all_hits, false, cellID_encoder);
+      
+      delete marlinTrk;
+
+      int nhits_in_vxd = track.getSubDetectorHitNumbers(0);
+      int nhits_in_ftd = track.getSubDetectorHitNumbers(1);
+      int nhits_in_sit = track.getSubDetectorHitNumbers(2);
+      
+      //debug() << " Hit numbers for Track "<< track->id() << ": "
+      debug() << " Hit numbers for Track "<< iTrk <<": "
+	      << " vxd hits = " << nhits_in_vxd
+	      << " ftd hits = " << nhits_in_ftd
+	      << " sit hits = " << nhits_in_sit
+	      << endmsg;
+      
+      //if (nhits_in_vxd > 0) Track->setTypeBit( lcio::ILDDetID::VXD ) ;
+      //if (nhits_in_ftd > 0) Track->setTypeBit( lcio::ILDDetID::FTD ) ;
+      //if (nhits_in_sit > 0) Track->setTypeBit( lcio::ILDDetID::SIT ) ;
+
+      
+      
+      if( status != IMarlinTrack::success ) {       
+        
+        //delete track;
+        debug() << "SiliconTracking::FinalRefit: Track fit failed with error code " << status << " track dropped. Number of hits = "<< trkHits.size() << endmsg;       
+        continue ;
+      }
+      
+      if( track.getNdf() < 0) {       
+        //delete track;
+        debug() << "SiliconTracking::FinalRefit: Track fit returns " << track.getNdf() << " degress of freedom track dropped. Number of hits = "<< trkHits.size() << endmsg;       
+	//delete track;
+        continue ;
+      }
+      
+      //trk_col->addElement(Track);     
+      //fucd
+      //trk_col->push_back(track);
+      for(int i=0;i<track.trackStates_size();i++){
+	// 1 = lcio::EVENT::TrackState::AtIP
+	edm4hep::TrackState trkStateIP = track.getTrackStates(i);
+	if(trkStateIP.location !=1) continue;
+      /*
+      if (trkStateIP == 0) {
+        debug() << "SiliconTracking::FinalRefit: Track fit returns " << track->getNdf() << " degress of freedom track dropped. Number of hits = "<< trkHits.size() << endmsg;       
+        throw EVENT::Exception( std::string("SiliconTracking::FinalRefit: trkStateIP pointer == NULL ")  ) ;
+      }
+      */
+      // note trackAR which is of type TrackExtended, only takes fits set for ref point = 0,0,0
+	trackAR->setOmega(trkStateIP.omega);
+	trackAR->setTanLambda(trkStateIP.tanLambda);
+	trackAR->setPhi(trkStateIP.phi);
+	trackAR->setD0(trkStateIP.D0);
+	trackAR->setZ0(trkStateIP.Z0);
+	
+	float cov[15];
+	
+	for (int i = 0 ; i<15 ; ++i) {
+	  cov[i] = trkStateIP.covMatrix.operator[](i);
+	}
+      
+	trackAR->setCovMatrix(cov);
+	trackAR->setChi2(track.getChi2());
+	trackAR->setNDF(track.getNdf());
+      
+	nSiSegments++;
+      
+	HelixClass helix_final;
+      
+	helix_final.Initialize_Canonical(trkStateIP.phi,trkStateIP.D0,trkStateIP.Z0,trkStateIP.omega,trkStateIP.tanLambda,_bField);
+      
+	float trkPx = helix_final.getMomentum()[0];
+	float trkPy = helix_final.getMomentum()[1];
+	float trkPz = helix_final.getMomentum()[2];
+	float trkP = sqrt(trkPx*trkPx+trkPy*trkPy+trkPz*trkPz);
+	eTot += trkP;
+	pxTot += trkPx;
+	pyTot += trkPy;
+	pzTot += trkPz;
+      }
+    }
+  }
+  
+  debug() << "SiliconTracking -> run " << _nRun
+	  << " event " << _nEvt << endmsg;
+  debug() << "Number of Si tracks = " << nSiSegments << endmsg;
+  debug() << "Total 4-momentum of Si Tracks : E = " << eTot
+	  << " Px = " << pxTot
+	  << " Py = " << pyTot
+	  << " Pz = " << pzTot << endmsg;
+  
+  
+}
+
+
+StatusCode SiliconTracking::setupGearGeom(){
+  auto _gear = service<IGearSvc>("GearSvc");
+  if ( !_gear ) {
+    error() << "Failed to find GearSvc ..." << endmsg;
+    return StatusCode::FAILURE;
+  }
+  gear::GearMgr* gearMgr = _gear->getGearMgr();
+  _bField = gearMgr->getBField().at( gear::Vector3D( 0.,0.,0.)  ).z() ;
+  debug() << "Field " << _bField << endmsg;
+  //-- VXD Parameters--
+  _nLayersVTX = 0 ;
+  const gear::VXDParameters* pVXDDetMain = 0;
+  const gear::VXDLayerLayout* pVXDLayerLayout = 0;
+  
+  try{
+    
+    debug() << " filling VXD parameters from gear::SITParameters " << endmsg ;
+    
+    pVXDDetMain = &gearMgr->getVXDParameters();
+    pVXDLayerLayout = &(pVXDDetMain->getVXDLayerLayout());
+    _nLayersVTX = pVXDLayerLayout->getNLayers();
+  }
+  catch( gear::UnknownParameterException& e){
+    
+    debug() << " ### gear::VXDParameters Not Present in GEAR FILE" << endmsg ;
+    
+  }
+  
+  
+  
+  //-- SIT Parameters--
+  _nLayersSIT = 0 ;
+  const gear::ZPlanarParameters* pSITDetMain = 0;
+  const gear::ZPlanarLayerLayout* pSITLayerLayout = 0;
+  
+  try{
+    
+    debug() << " filling SIT parameters from gear::SITParameters " << endmsg ;
+    
+    pSITDetMain = &gearMgr->getSITParameters();
+    pSITLayerLayout = &(pSITDetMain->getZPlanarLayerLayout());
+    _nLayersSIT = pSITLayerLayout->getNLayers();
+    
+  }
+  catch( gear::UnknownParameterException& e){
+    
+    debug() << " ### gear::SITParameters Not Present in GEAR FILE" << endmsg ;
+    
+  }
+  
+  if( _nLayersSIT == 0 ){
+    // try the old LOI style key value pairs as defined in the SSit03 Mokka drive
+    try{
+      
+      info() << "  SiliconTracking - Simple Cylinder Based SIT using parameters defined by SSit03 Mokka driver " << endmsg ;
+      
+      // SIT
+      
+      const gear::GearParameters& pSIT = gearMgr->getGearParameters("SIT");
+      
+      const std::vector<double>& SIT_r   =  pSIT.getDoubleVals("SITLayerRadius" )  ;
+      const std::vector<double>& SIT_hl  =  pSIT.getDoubleVals("SITSupportLayerHalfLength" )  ;
+      
+      _nLayersSIT = SIT_r.size() ; 
+      
+      if (_nLayersSIT != SIT_r.size() || _nLayersSIT != SIT_hl.size()) {
+        
+        error() << "ILDSITCylinderKalDetector miss-match between DoubleVec and nlayers exit(1) called from file " << __FILE__ << " line " << __LINE__  << endmsg ;
+        exit(1);
+        
+      }
+    }
+    catch( gear::UnknownParameterException& e){
+      
+      debug() << " ### gear::SIT Parameters from as defined in SSit03 Not Present in GEAR FILE" << endmsg ;
+      
+    } 
+    
+  }
+  
+  
+  
+  //-- FTD Parameters--
+  _petalBasedFTDWithOverlaps = false;  
+  _nlayersFTD = 0;
+  
+  try{
+    
+    debug() << " filling FTD parameters from gear::FTDParameters " << endmsg ;
+    
+    const gear::FTDParameters&   pFTD      = gearMgr->getFTDParameters();
+    const gear::FTDLayerLayout&  ftdlayers = pFTD.getFTDLayerLayout() ;
+    
+    _nlayersFTD = ftdlayers.getNLayers() ;
+    
+    for (unsigned int disk=0; disk < _nlayersFTD; ++disk) {
+      
+      _zLayerFTD.push_back( ftdlayers.getSensitiveZposition(disk, 0, 1) ); // front petal even numbered
+      
+      if ( ftdlayers.getNPetals(disk) > 0) {
+        _zLayerFTD.push_back( ftdlayers.getSensitiveZposition(disk, 1, 1) );  // front petal odd numbered
+        _petalBasedFTDWithOverlaps = true;
+      }
+      
+    }
+    
+    // SJA: Here we increase the size of _nlayersFTD as we are treating the 
+    _nlayersFTD =_zLayerFTD.size() ;     
+    
+  }
+  catch( gear::UnknownParameterException& e){
+    
+    debug() << " ### gear::FTDParameters Not Present in GEAR FILE" << endmsg ;
+    
+  } 
+  
+  if( _nlayersFTD == 0 ){
+    
+    // FTD
+    try{
+      
+      info() << "  SiliconTracking - Simple Disc Based FTD using parameters defined by SFtd05 Mokka driver " << endmsg ;
+      
+      const gear::GearParameters& pFTD = gearMgr->getGearParameters("FTD");
+      
+      const std::vector<double>* pFTD_z   = NULL;
+      
+      info() << " For FTD using parameters defined by SFtd05 Mokka driver " << endmsg ;
+      
+      pFTD_z = &pFTD.getDoubleVals("FTDZCoordinate" )  ;
+      
+      _nlayersFTD = pFTD_z->size();
+      
+      for (unsigned int i = 0; i<_nlayersFTD; ++i) {
+        _zLayerFTD.push_back((*pFTD_z)[i]);
+      }
+    }
+    catch( gear::UnknownParameterException& e){
+      
+      debug() << " ### gear::FTD Parameters as defined in SFtd05 Not Present in GEAR FILE" << endmsg ;
+      
+    } 
+  }
+  return StatusCode::SUCCESS;
+}
+
+void SiliconTracking::TracksWithNHitsContainer::clear()
+{
+  for (std::vector< TrackExtendedVec >::iterator trackVecIter = _tracksNHits.begin();
+       trackVecIter < _tracksNHits.end(); trackVecIter++)
+  {
+    for (TrackExtendedVec::iterator trackIter = trackVecIter->begin();
+         trackIter < trackVecIter->end(); trackIter++)
+    {
+      delete *trackIter;
+    }
+    
+    trackVecIter->clear();
+  }
+}
+
diff --git a/Reconstruction/SiliconTracking/src/SiliconTracking.h~ b/Reconstruction/SiliconTracking/src/SiliconTracking.h~
new file mode 100644
index 0000000000000000000000000000000000000000..86190002b98883556b62eccdeb6be4aabc0db257
--- /dev/null
+++ b/Reconstruction/SiliconTracking/src/SiliconTracking.h~
@@ -0,0 +1,426 @@
+#ifndef SiliconTracking_h
+#define SiliconTracking_h
+
+//#include "marlin/Processor.h"
+//#include <marlin/Global.h>
+#include "FWCore/DataHandle.h"
+#include "GaudiAlg/GaudiAlgorithm.h"
+#include "edm4hep/EventHeaderCollection.h"
+#include "edm4hep/MCParticleCollection.h"
+#include "edm4hep/SimTrackerHitCollection.h"
+#include "edm4hep/TrackerHitCollection.h"
+#include "edm4hep/TrackCollection.h"
+//#include "edm4hep/LCRelationCollection.h"
+
+//#include "lcio.h"
+#include <string>
+#include <vector>
+#include <cmath>
+//#include <IMPL/TrackImpl.h>
+#include "ClusterExtended.h"
+#include "TrackExtended.h"
+#include "TrackerHitExtended.h"
+#include "HelixClass.h"
+
+#include "TrackSystemSvc/IMarlinTrack.h"
+
+#include <UTIL/BitField64.h>
+#include <UTIL/ILDConf.h>
+
+using namespace edm4hep ;
+
+namespace gear{
+  class GearMgr ;
+}
+
+namespace MarlinTrk {
+  class HelixFit;
+  class IMarlinTrkSystem ;
+}
+
+namespace UTIL{
+  class LCRelationNavigator ;
+}
+
+
+/** === Silicon Tracking Processor === <br>
+ * Processor performing stand-alone pattern recognition
+ * in the vertex detector (VTX), forward tracking disks and SIT. <br>
+ * The procedure consists of three steps : <br> 
+ * 1) Tracking in VTX and SIT ; <br>
+ * 2) Tracking in FTD ; <br>
+ * 3) Merging compatible track segments reconstructed in VTX and FTD <br>
+ * STEP 1 : TRACKING IN VTX and SIT <br>
+ * Algorithm starts with finding of hit triplets satisfying helix hypothesis <br> 
+ * in three different layers. Two layers of SIT are effectively considered as outermost <br>
+ * layers of the vertex detector. To accelerate procedure, the 4-pi solid angle
+ * is divided in NDivisionsInTheta and NDivisionsInPhi sectors in cosQ and Phi, 
+ * respectively. Triplets are looked for in 2x2 window of adjacent sectors. 
+ * Once triplet is found, attempt is made to associate additional hits to 
+ * track. Combinatin of hits is accepted for further analysis if the Chi2 
+ * of the fit is less than certain predefined threshold. All accepted 
+ * combinations are sorted in ascending order of their Chi2. First track candidate 
+ * in the sorted array is automatically accepted. The hits belonging to this track are 
+ * marked as used, and track candidates sharing these hits are discarded.
+ * The procedure proceeds with increasing index of track candidate in the sorted 
+ * array until all track candidate have been output or discarded. <br>
+ * STEP 2 : TRACKING IN FTD <br>
+ * In the next step tracking in FTD is performed. The strategy of tracking in the FTD 
+ * is the same as used for tracking in the VTX+SIT. <br>
+ * STEP 3 : MERGING TRACK SEGMENTS FOUND IN FTD AND VTX+SIT <br>
+ * In the last step, track segments reconstructed in the FTD and VTX+SIT, belonging to the
+ * same track  are identified and merged into one track. All possible 
+ * pairings are tested for their compatibility.
+ * The number of pairings considered is Ntrk_VTX_SIT*Ntrk_FTD, where Ntrk_VTX_SIT is the number of 
+ * track segments reconstructed in the first step in VTX+SIT (segments containing solely VTX and SIT hits) and
+ * Ntrk_FTD is the number of track segments reconstructed in the second step 
+ * (segments containing solely FTD hits).
+ * Pair of segments is accepted for further examination if the angle between track segments and 
+ * than certain specified threshold.
+ * Pairing satisfying this condition is subjected for 
+ * addtitional test. The fit is performed on unified array of hits belonging to both segments. 
+ * If the chi2 of the fit does not exceed predefined cut value two segments are unified into 
+ * one track. 
+ * <h4>Input collections and prerequisites</h4> 
+ * Processor requires collection of digitized vertex, sit and ftd tracker hits. <br>
+ * If such a collections with the user specified names do not exist 
+ * processor takes no action. <br>
+ * <h4>Output</h4>
+ * Processor produces an LCIO collection of the Tracks. Each track is characterised by 
+ * five parameters : Omega (signed curvuture), Tan(lambda) where
+ * lambda is the dip angle, Phi (azimuthal angle @ point of closest approach), D0 (signed impact parameter),
+ * Z0 (displacement along z axis at the point of closest approach to IP). Covariance matrix for these parameters is also provided.
+ * Only lower left corner of the covariance matrix is stored. The sequence of the covariance matrix elements 
+ * assigned to track is the following: <br>
+ * (Omega,Omega) <br>
+ * (Omega,TanLambda), (TanLambda,TanLambda) <br>
+ * (Omega,Phi), (TanLamda,Phi), (Phi,Phi) <br>
+ * (Omega,D0), (TanLambda,D0), (Phi,D0), (D0,D0) <br>
+ * (Omega,Z0), (TanLambda,Z0), (Phi,Z0), (D0,Z0), (Z0,Z0) <br>
+ * The number of hits in the different subdetectors associated
+ * with each track can be accessed via method Track::getSubdetectorHitNumbers().
+ * This method returns vector of integers : <br>
+ * number of VTX hits in track is the first element in this vector  
+ * (Track::getSubdetectorHitNumbers()[0]) <br>
+ * number of FTD hits in track is the second element in this vector  
+ * (Track::getSubdetectorHitNumbers()[1]) <br>
+ * number of SIT hits in track is the third element in this vector  
+ * (Track::getSubdetectorHitNumbers()[2]) <br>
+ * Output track collection has a name "SiTracks". <br>
+ * @param VTXHitCollectionName name of input VTX TrackerHit collection <br>
+ * (default parameter value : "VTXTrackerHits") <br>
+ * @param FTDHitCollectionName name of input FTD TrackerHit collection <br>
+ * (default parameter value : "FTDTrackerHits") <br>
+ * @param SITHitCollectionName name of input SIT TrackerHit collection <br>
+ * (default parameter value : "SITTrackerHits") <br>
+ * @param SiTrackCollectionName name of the output Silicon track collection <br>
+ * (default parameter value : "SiTracks") <br>
+ * @param LayerCombinations combinations of layers used to search for hit triplets in VTX+SIT <br>
+ * (default parameters : 6 4 3  6 4 2  6 3 2  5 4 3  5 4 2  5 3 2  4 3 2  4 3 1  4 2 1  3 2 1) <br> 
+ * Note that in the VTX+SIT system the first and the second layers of SIT have indicies nLayerVTX and nLayerVTX+1. 
+ * Combination given above means that triplets are looked first in layers 6 4 3, and then 
+ * in 6 4 2;  5 4 3;  6 3 2 etc. NOTE THAT LAYER INDEXING STARTS FROM 0.
+ * LAYER 0 is the innermost layer  <br>
+ * @param LayerCombinationsFTD combinations of layers used to search for hit triplets in FTD <br>
+ * (default parameters 6 5 4  5 4 3  5 4 2  5 4 1  5 3 2  5 3 1  5 2 1  4 3 2  4 3 1  
+ *  4 3 0  4 2 1  4 2 0  4 1 0  3 2 1  3 2 0  3 1 0  2 1 0). 
+ * NOTE THAT TRACKS IN FTD ARE SEARCHED ONLY IN ONE HEMISPHERE. TRACK IS NOT 
+ * ALLOWED TO HAVE HITS BOTH IN BACKWARD AND FORWARD PARTS OF FTD SIMULTANEOUSLY. 
+ * @param NDivisionsInPhi Number of divisions in Phi for tracking in VTX+SIT <br>
+ * (default value is 40) <br>
+ * @param NDivisionsInTheta Number of divisions in cosQ for tracking in VTX+SIT <br>
+ * (default value is 40) <br>
+ * @param NDivisionsInPhiFTD Number of divisions in Phi for tracking in FTD <br>
+ * (default value is 3) <br>
+ * @param Chi2WRphiTriplet weight on chi2 in R-Phi plane for track with 3 hits <br>
+ * (default value is 1) <br>
+ * @param Chi2WZTriplet weight on chi2 in S-Z plane for track with 3 hits <br>
+ * (default value is 0.5) <br>
+ * @param Chi2WRphiQuartet weight on chi2 in R-Phi plane to accept track with 4 hits <br>
+ * (default value is 1) <br>
+ * @param Chi2WZQuartet weight on chi2 in S-Z plane for track with 4 hits <br>
+ * (default value is 0.5) <br>
+ * @param Chi2WRphiSeptet weight on chi2 in R-Phi plane for track with 5 and more hits <br>
+ * (default value is 1) <br>
+ * @param Chi2WZSeptet Cut on chi2 in S-Z plane for track with 5 and more hits <br>
+ * (default value is 0.5) <br>
+ * @param Chi2FitCut Cut on chi2/ndf to accept track candidate <br>
+ * (default value is 100.) <br>
+ * @param AngleCutForMerging cut on the angle between two track segments.  
+ * If the angle is greater than this cut, segments are not allowed to be merged. <br>
+ * (default value is 0.1) <br>
+ * @param MinDistCutAttach cut on the distance (in mm) from hit to the helix. This parameter is used
+ * to decide whether hit can be attached to the track. If the distance is less than 
+ * cut value. The track is refitted with a given hit being added to the list of hits already 
+ * assigned for the track. Additional hit is assigned if chi2 of the new fit has good chi2. <br>
+ * (default value is 2 ) <br>
+ * @param MinLayerToAttach the minimal layer index to attach VTX hits to the found hit triplets <br>
+ * (default value is -1) <br>
+ * @param CutOnZ0 cut on Z0 parameter of track (in mm). If abs(Z0) is greater than the cut value, track is 
+ * discarded (used to suppress fake
+ * track rate in the presence of beam induced background hits) <br>
+ * (default value is 100) <br>
+ * @param CutOnD0 cut on D0 parameter of track (in mm). If abs(D0) is greater than the cut value, track is 
+ * discarded (used to suppress fake
+ * track rate in the presence of beam induced background hits) <br>
+ * (default value is 100) <br>
+ * @param CutOnPt cut on Pt (GeV/c). If Pt is less than this cut, track is discarded (used to suppress fake
+ * track rate in the presence of beam induced background hits) <br>
+ * (default value is 0.1) <br>
+ * @param MinimalHits minimal number of hits in track required <br>
+ * (default value is 3) <br>
+ * @param NHitsChi2 Maximal number of hits for which a track with n hits is aways better than one with n-1 hits.
+ * For tracks with equal or more than NHitsChi2 the track  with the lower \f$\chi^2\f$ is better.
+ * (default value is 5) <br>
+ * @param FastAttachment if this flag is set to 1, less accurate but fast procedure to merge additional hits to tracks is used <br> 
+ * if set to 0, a more accurate, but slower procedure is invoked <br>
+ * (default value is 0) <br>
+ * @param UseSIT When this flag is set to 1, SIT is included in pattern recognition. When this flag is set
+ * to 0, SIT is excluded from the procedure of pattern recognition <br>
+ * (default value is 1) <br>
+ * <br>
+ * @author A. Raspereza (MPI Munich)<br>
+ */
+class SiliconTracking : public GaudiAlgorithm {
+ public:
+  
+  SiliconTracking(const std::string& name, ISvcLocator* svcLoc);
+  
+  virtual StatusCode initialize() ;
+  
+  virtual StatusCode execute() ; 
+  
+  virtual StatusCode finalize() ;
+  
+protected:
+  
+  int _nRun ;
+  int _nEvt ;
+  //EVENT::LCEvent* _current_event;
+  int _nLayers;
+  unsigned int _nLayersVTX;
+  unsigned int _nLayersSIT;
+  int _ntriplets, _ntriplets_good, _ntriplets_2MCP, _ntriplets_3MCP, _ntriplets_1MCP_Bad, _ntriplets_bad;
+  
+  MarlinTrk::HelixFit* _fastfitter;
+  gear::GearMgr* _GEAR;
+  /** pointer to the IMarlinTrkSystem instance 
+   */
+  MarlinTrk::IMarlinTrkSystem* _trksystem ;
+  //bool _runMarlinTrkDiagnostics;
+  //std::string _MarlinTrkDiagnosticsName;
+  typedef std::vector<int> IntVec;
+  
+  Gaudi::Property<IntVec> _Combinations{this, "LayerCombinations", {8,6,5, 8,6,4, 8,6,3, 8,6,2, 8,5,3, 8,5,2, 8,4,3, 8,4,2, 6,5,3, 6,5,2, 6,4,3, 6,4,2, 6,3,1, 6,3,0, 6,2,1, 6,2,0,
+	5,3,1, 5,3,0, 5,2,1, 5,2,0, 4,3,1, 4,3,0, 4,2,1, 4,2,0}};
+  Gaudi::Property<IntVec> _CombinationsFTD{this, "LayerCombinationsFTD", {4,3,2, 4,3,1, 4,3,0, 4,2,1, 4,2,0, 4,1,0, 3,2,1, 3,2,0, 3,1,0, 2,1,0,
+	9,8,7, 9,8,6, 9,8,5, 9,7,6, 9,7,5, 9,6,5, 8,7,6, 8,7,5, 8,6,5, 7,6,5}};
+  Gaudi::Property<int> _nDivisionsInPhi{this, "NDivisionsInPhi", 80};
+  Gaudi::Property<int> _nDivisionsInPhiFTD{this, "NDivisionsInPhiFTD", 30};
+  Gaudi::Property<int> _nDivisionsInTheta{this, "NDivisionsInTheta", 80};
+  Gaudi::Property<float> _chi2WRPhiTriplet{this, "Chi2WRphiTriplet", 1.};
+  Gaudi::Property<float> _chi2WRPhiQuartet{this, "Chi2WRphiQuartet", 1.};
+  Gaudi::Property<float> _chi2WRPhiSeptet{this, "Chi2WRphiSeptet", 1.};
+  Gaudi::Property<float> _chi2WZTriplet{this, "Chi2WZTriplet", 0.5};
+  Gaudi::Property<float> _chi2WZQuartet{this, "Chi2WZQuartet", 0.5};
+  Gaudi::Property<float> _chi2WZSeptet{this, "Chi2WZSeptet", 0.5};
+  Gaudi::Property<float> _chi2FitCut{this, "Chi2FitCut", 120.};
+  Gaudi::Property<float> _angleCutForMerging{this, "AngleCutForMerging", 0.1};
+  Gaudi::Property<float> _minDistCutAttach{this, "MinDistCutAttach", 2.5};
+  Gaudi::Property<float> _minimalLayerToAttach{this, "MinLayerToAttach", -1};
+  Gaudi::Property<float> _cutOnD0{this, "CutOnD0", 100.0};
+  Gaudi::Property<float> _cutOnZ0{this, "CutOnZ0", 100.0};
+  Gaudi::Property<float> _cutOnPt{this, "CutOnPt", 0.05};
+  Gaudi::Property<int> _minimalHits{this, "MinimalHits",3};
+  Gaudi::Property<int> _nHitsChi2{this, "NHitsChi2", 5};
+  Gaudi::Property<int> _max_hits_per_sector{this, "MaxHitsPerSector", 100};
+  Gaudi::Property<int> _attachFast{this, "FastAttachment", 0};
+  Gaudi::Property<bool> _useSIT{this, "UseSIT", true};
+  Gaudi::Property<float> _initialTrackError_d0{this, "InitialTrackErrorD0",1e6};
+  Gaudi::Property<float> _initialTrackError_phi0{this, "InitialTrackErrorPhi0",1e2};
+  Gaudi::Property<float> _initialTrackError_omega{this, "InitialTrackErrorOmega",1e-4};
+  Gaudi::Property<float> _initialTrackError_z0{this, "InitialTrackErrorZ0",1e6};
+  Gaudi::Property<float> _initialTrackError_tanL{this, "InitialTrackErrorTanL",1e2};
+  Gaudi::Property<float> _maxChi2PerHit{this, "MaxChi2PerHit", 1e2};
+  Gaudi::Property<int> _checkForDelta{this, "CheckForDelta", 1};
+  Gaudi::Property<float> _minDistToDelta{this, "MinDistToDelta", 0.25};
+  Gaudi::Property<bool> _MSOn{this, "MultipleScatteringOn", true};
+  Gaudi::Property<bool> _ElossOn{this, "EnergyLossOn", true};
+  Gaudi::Property<bool> _SmoothOn{this, "SmoothOn", true};
+  Gaudi::Property<float> _helix_max_r{this, "HelixMaxR", 2000.};
+  
+  //std::vector<int> _colours;  
+  
+  /** helper function to get collection using try catch block */
+  //LCCollection* GetCollection(  LCEvent * evt, std::string colName ) ;
+  
+  /** helper function to get relations using try catch block */
+  //LCRelationNavigator* GetRelations( LCEvent * evt, std::string RelName ) ;
+  
+  /** input MCParticle collection and threshold used for Drawing
+   */
+  //Gaudi::Property<Float> _MCpThreshold{this, "MCpThreshold", 0.1};
+  //std::string  _colNameMCParticles;
+  
+  /// Compare tracks according to their chi2/ndf
+  struct compare_TrackExtended{
+    // n.b.: a and b should be TrackExtended const *, but the getters are not const :-(
+    bool operator()(TrackExtended *a, TrackExtended *b) const {
+      if ( a == b ) return false;
+      return (a->getChi2()/a->getNDF() < b->getChi2()/b->getNDF() );
+    }
+  };
+  
+  
+  //std::string _VTXHitCollection;
+  //std::string _FTDPixelHitCollection;
+  //std::string _FTDSpacePointCollection;
+  //std::string _SITHitCollection;
+  //std::string _siTrkCollection;
+  
+  //std::vector< LCCollection* > _colTrackerHits;
+  //std::map< LCCollection*, std::string > _colNamesTrackerHits;
+
+  // Input collections
+  DataHandle<edm4hep::EventHeaderCollection> _headerColHdl{"EventHeaderCol", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::MCParticleCollection> _inMCColHdl{"MCParticle", Gaudi::DataHandle::Reader, this};
+  //DataHandle<edm4hep::TrackerHitPlaneCollection> _inVTXColHdl{"VXDCollection", Gaudi::DataHandle::Reader, this};
+  //DataHandle<edm4hep::TrackerHitPlaneCollection> _inFTDPixelColHdl{"FTDPixelCollection", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inVTXColHdl{"VXDTrackerHits", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inFTDPixelColHdl{"FTDPixelTrackerHits", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inFTDSpacePointColHdl{"FTDSpacePoints", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inSITColHdl{"SITTrackerHits", Gaudi::DataHandle::Reader, this};
+  // Output collections
+  DataHandle<edm4hep::TrackCollection> _outColHdl{"SiTracks", Gaudi::DataHandle::Writer, this};
+  //DataHandle<edm4hep::LCRelationCollection> _outRelColHdl{"TrackerHitRelations", Gaudi::DataHandle::Reader, this};
+  
+  std::vector<TrackerHitExtendedVec> _sectors;
+  std::vector<TrackerHitExtendedVec> _sectorsFTD;
+  
+  /**
+   * A helper class to allow good code readability by accessing tracks with N hits.
+   * As the smalest valid track contains three hits, but the first index in a vector is 0,
+   * this class hides the index-3 calculation. As the vector access is inline there should be
+   * no performance penalty.
+   */
+  class TracksWithNHitsContainer {
+  public:
+    /// Empty all the vectors and delete the tracks contained in it.
+    void clear();
+    
+    /// Set the size to allow a maximum of maxHit hits.
+    inline void resize(size_t maxHits) {
+      _tracksNHits.resize(maxHits-2);
+      _maxIndex=(maxHits-3);
+    }
+    
+    // Sort all track vectors according to chi2/nDof
+    //      void sort();
+    
+    /// Returns the  TrackExtendedVec for track with n hits. 
+    /// In case n is larger than the maximal number the vector with the largest n ist returned.
+    /// \attention The smallest valid number is three! For
+    /// performance reasons there is no safety check!
+    inline TrackExtendedVec & getTracksWithNHitsVec( size_t nHits ) {
+      //return _tracksNHits[ std::min(nHits-3, _maxIndex) ];
+      // for debugging: with boundary check
+      return _tracksNHits.at(std::min(nHits-3, _maxIndex));
+    }
+    
+  protected:
+    std::vector< TrackExtendedVec > _tracksNHits;
+    size_t _maxIndex; /// local cache variable to avoid calculation overhead
+  };
+  
+  TracksWithNHitsContainer _tracksWithNHitsContainer;
+  
+  int InitialiseVTX();
+  int InitialiseFTD();
+  void ProcessOneSector(int iSectorPhi, int iSectorTheta);
+  void CleanUp();
+  TrackExtended * TestTriplet(TrackerHitExtended * outerHit, 
+                              TrackerHitExtended * middleHit,
+                              TrackerHitExtended * innerHit,
+                              HelixClass & helix);
+  
+  int BuildTrack(TrackerHitExtended * outerHit, 
+                 TrackerHitExtended * middleHit,
+                 TrackerHitExtended * innerHit,
+                 HelixClass & helix, 
+                 int innerlayer,
+                 int iPhiLow, int iPhiUp,
+                 int iTheta, int iThetaUp,
+                 TrackExtended * trackAR);
+  
+  void Sorting( TrackExtendedVec & trackVec);
+  void CreateTrack(TrackExtended * trackAR );
+  void AttachRemainingVTXHitsSlow();
+  void AttachRemainingFTDHitsSlow();
+  void AttachRemainingVTXHitsFast();
+  void AttachRemainingFTDHitsFast();
+  void TrackingInFTD();
+  int BuildTrackFTD(TrackExtended* trackAR, int* nLR, int iS);
+  int AttachHitToTrack(TrackExtended * trackAR, TrackerHitExtended * hit, int iopt);
+  
+  void FinalRefit(edm4hep::TrackCollection*);//, edm4hep::LCRelationCollection*);
+  
+  float _bField;
+  
+  // two pi is not a constant in cmath. Calculate it, once!
+  static const double TWOPI;
+  
+  double _dPhi;
+  double _dTheta;
+  double _dPhiFTD;
+  
+  float _resolutionRPhiVTX;
+  float _resolutionZVTX;
+  
+  float _resolutionRPhiFTD;
+  float _resolutionZFTD;
+  
+  float _resolutionRPhiSIT;
+  float _resolutionZSIT;
+  
+  float _phiCutForMerging;
+  float _tanlambdaCutForMerging;
+  //float _angleCutForMerging;
+  
+  float _distRPhi;
+  float _distZ;
+  
+  float _cutOnOmega;
+
+  TrackExtendedVec _trackImplVec;
+      
+  int _nTotalVTXHits,_nTotalFTDHits,_nTotalSITHits;
+  
+  //  int _createMap;
+  
+  UTIL::BitField64* _encoder;
+  int getDetectorID(edm4hep::TrackerHit* hit) { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::subdet]; }
+  int getSideID(edm4hep::TrackerHit* hit)     { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::side]; };
+  int getLayerID(edm4hep::TrackerHit* hit)    { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::layer]; };
+  int getModuleID(edm4hep::TrackerHit* hit)   { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::module]; };
+  int getSensorID(edm4hep::TrackerHit* hit)   { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::sensor]; };
+  
+  StatusCode setupGearGeom() ;
+  
+  std::vector<float> _zLayerFTD;
+  
+  unsigned int _nlayersFTD;
+  bool _petalBasedFTDWithOverlaps;
+  int _nPhiFTD; 
+
+  int _output_track_col_quality;
+  static const int _output_track_col_quality_GOOD;
+  static const int _output_track_col_quality_FAIR;
+  static const int _output_track_col_quality_POOR;
+
+  std::vector<edm4hep::TrackerHit> _allHits;
+} ;
+
+#endif
+
+
+
diff --git a/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.cpp b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..156d9afde64c18fd7dfcc23558f0133d653f4027
--- /dev/null
+++ b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.cpp
@@ -0,0 +1,3083 @@
+#include "SiliconTrackingAlg.h"
+#include "GearSvc/IGearSvc.h"
+#include "EventSeeder/IEventSeeder.h"
+#include "TrackSystemSvc/ITrackSystemSvc.h"
+#include "edm4hep/MCParticle.h"
+#include "edm4hep/TrackerHit.h"
+//#include "edm4hep/TrackerHitPlane.h"
+#include "edm4hep/Track.h"
+#include "edm4hep/TrackState.h"
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+#include <climits>
+
+#include <gear/GEAR.h>
+#include <gear/GearMgr.h>
+#include <gear/GearParameters.h>
+#include <gear/VXDLayerLayout.h>
+#include <gear/VXDParameters.h>
+#include "gear/FTDLayerLayout.h"
+#include "gear/FTDParameters.h"
+
+#include <gear/BField.h>
+
+#include <UTIL/BitField64.h>
+#include <UTIL/BitSet32.h>
+#include <UTIL/ILDConf.h>
+
+#include "TrackSystemSvc/MarlinTrkUtils.h"
+#include "TrackSystemSvc/HelixTrack.h"
+#include "TrackSystemSvc/HelixFit.h"
+#include "TrackSystemSvc/IMarlinTrack.h"
+
+//#include "TrackSystemSvc/MarlinTrkDiagnostics.h"
+//#ifdef MARLINTRK_DIAGNOSTICS_ON
+//#include "TrackSystemSvc/DiagnosticsController.h"
+//#endif
+
+//#include "MarlinCED.h"
+
+//#include "marlin/AIDAProcessor.h"
+
+//---- ROOT -----
+#include "TH1F.h"
+#include "TH2F.h"
+
+using namespace edm4hep ;
+//using namespace marlin ;
+using namespace MarlinTrk ;
+
+using std::min;
+using std::max;
+using std::abs;
+
+const int SiliconTrackingAlg::_output_track_col_quality_GOOD = 1;
+const int SiliconTrackingAlg::_output_track_col_quality_FAIR = 2;
+const int SiliconTrackingAlg::_output_track_col_quality_POOR = 3;
+
+const double SiliconTrackingAlg::TWOPI = 2*M_PI;
+
+DECLARE_COMPONENT( SiliconTrackingAlg )
+
+SiliconTrackingAlg::SiliconTrackingAlg(const std::string& name, ISvcLocator* svcLoc)
+: GaudiAlgorithm(name, svcLoc) {
+  
+  //_description = "Pattern recognition in silicon trackers";
+  
+  _fastfitter = new MarlinTrk::HelixFit();
+  
+  _encoder = new UTIL::BitField64(lcio::ILDCellID0::encoder_string);
+  
+  _petalBasedFTDWithOverlaps = false;
+  
+  // zero triplet counters
+  _ntriplets = _ntriplets_good = _ntriplets_2MCP = _ntriplets_3MCP = _ntriplets_1MCP_Bad = _ntriplets_bad = 0;
+
+  // Input Collections
+  // ^^^^^^^^^^^^^^^^^
+  declareProperty("HeaderCol", _headerColHdl);
+  declareProperty("MCParticleCollection", _inMCColHdl, "Handle of the Input MCParticle collection");
+  declareProperty("VTXHitCollection", _inVTXColHdl, "Handle of the Input VTX TrackerHits collection");
+  declareProperty("FTDPixelHitCollection", _inFTDPixelColHdl, "Handle of the Input FTD TrackerHits collection");
+  declareProperty("FTDSpacePointCollection", _inFTDSpacePointColHdl, "Handle of the Input FTD SpacePoints collection");
+  declareProperty("SITHitCollection", _inSITColHdl, "Handle of the Input SIT TrackerHits collection");
+    
+  // Output Collections
+  // ^^^^^^^^^^^^^^^^^^
+  declareProperty("SiTrackCollection", _outColHdl, "Handle of the SiTrack output collection");
+  //declareProperty("TrkHitRelCollection", _outRelColHdl, "Handle of TrackerHit Track relation collection");
+  // Steering parameters
+  // ^^^^^^^^^^^^^^^^^^^
+  
+  _output_track_col_quality = _output_track_col_quality_GOOD;
+  
+}
+
+
+
+StatusCode  SiliconTrackingAlg::initialize() { 
+  
+  _nRun = -1 ;
+  _nEvt = 0 ;
+  //printParameters() ;
+  
+  // set up the geometery needed by KalTest
+  //FIXME: for now do KalTest only - make this a steering parameter to use other fitters
+  auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc");
+  if ( !_trackSystemSvc ) {
+    error() << "Failed to find TrackSystemSvc ..." << endmsg;
+    return StatusCode::FAILURE;
+  }
+  _trksystem =  _trackSystemSvc->getTrackSystem();
+  
+  if( _trksystem == 0 ){
+    error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg;
+    return StatusCode::FAILURE;
+  }
+  
+  _trksystem->setOption( IMarlinTrkSystem::CFG::useQMS,        _MSOn ) ;
+  _trksystem->setOption( IMarlinTrkSystem::CFG::usedEdx,       _ElossOn) ;
+  _trksystem->setOption( IMarlinTrkSystem::CFG::useSmoothing,  _SmoothOn) ;
+  _trksystem->init() ;  
+  std::cout << "fucd ==============" << _trksystem << std::endl;
+#ifdef MARLINTRK_DIAGNOSTICS_ON
+  
+  void * dcv = _trksystem->getDiagnositicsPointer();
+  DiagnosticsController* dc = static_cast<DiagnosticsController*>(dcv);
+  dc->init(_MarlinTrkDiagnosticsName,_MarlinTrkDiagnosticsName, _runMarlinTrkDiagnostics);
+  
+#endif
+  
+  if(setupGearGeom()==StatusCode::FAILURE) return StatusCode::FAILURE;
+  
+  if (_useSIT == 0)
+    _nLayers = _nLayersVTX;
+  else 
+    _nLayers = _nLayersVTX + _nLayersSIT;
+  
+  // initialise the container to have separate vectors for up to _nHitsChi2 hits.
+  _tracksWithNHitsContainer.resize(_nHitsChi2);
+  
+  _dPhi = TWOPI/_nDivisionsInPhi;
+  _dTheta = 2.0/_nDivisionsInTheta;
+  _dPhiFTD = TWOPI/_nPhiFTD;
+  // I leave this for the moment, but 0.3 is c/1e9.
+  // For the cut it does not make too much of a difference
+  double cutOnR = _cutOnPt/(0.3*_bField);
+  cutOnR = 1000.*cutOnR;
+  _cutOnOmega = 1/cutOnR;
+  
+  _output_track_col_quality = 0;
+  
+  return GaudiAlgorithm::initialize();
+}
+
+StatusCode SiliconTrackingAlg::execute(){ 
+  
+  //_current_event = evt;
+  //_allHits.reserve(1000);
+
+  _output_track_col_quality = _output_track_col_quality_GOOD;
+  
+  // zero triplet counters
+  _ntriplets = _ntriplets_good = _ntriplets_2MCP = _ntriplets_3MCP = _ntriplets_1MCP_Bad = _ntriplets_bad = 0;
+  
+  // Clearing the working containers from the previous event
+  // FIXME: partly done at the end of the event, in CleanUp. Make it consistent.
+  //_tracksWithNHitsContainer.clear();
+  //_trackImplVec.clear();
+  
+  //_colTrackerHits.clear();
+  //_colNamesTrackerHits.clear();
+  //auto header = _headerColHdl.get()->at(0);
+  //int evtNo = header.getEventNumber();
+  //int runNo = header.getRunNumber();
+  //debug() << "Processing Run[" << runNo << "]::Event[" << evtNo << "]" << endmsg;
+
+  _trackImplVec.reserve(100);
+  _allHits.reserve(1000);
+
+  int successVTX = InitialiseVTX();
+  int successFTD = 0;
+  //int successFTD = InitialiseFTD();
+  if (successVTX == 1) {
+    
+    debug() << "      phi          theta        layer      nh o :   m :   i  :: o*m*i " << endmsg; 
+    
+    for (int iPhi=0; iPhi<_nDivisionsInPhi; ++iPhi) { 
+      for (int iTheta=0; iTheta<_nDivisionsInTheta;++iTheta) {
+        ProcessOneSector(iPhi,iTheta); // Process one VXD sector     
+      }
+    }
+    
+    debug() << "End of Processing VXD and SIT sectors" << endmsg;
+    
+  }
+  
+  if (successFTD == 1) {
+    debug() << "      phi          side        layer      nh o :   m :   i  :: o*m*i " << endmsg;
+    TrackingInFTD(); // Perform tracking in the FTD
+    debug() << "End of Processing FTD sectors" << endmsg;
+  }
+
+  //if(0){
+  if (successVTX == 1 || successFTD == 1) {
+    //if (successVTX == 1 ) {
+    for (int nHits = _nHitsChi2; nHits >= 3 ;// the three is hard coded, sorry.
+         // It's the minimal number to form a track
+         nHits--) {
+      Sorting( _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits ) );
+      
+    }
+    debug() <<  "End of Sorting " << endmsg;
+        
+    for (int nHits = _nHitsChi2; nHits >= 3 ;// the three is hard coded, sorry.
+         // It's the minimal number to form a track
+         nHits--) {
+      
+      TrackExtendedVec &tracksWithNHits = _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits );
+      for (TrackExtendedVec::iterator trackIter = tracksWithNHits.begin();
+           trackIter < tracksWithNHits.end(); trackIter++) {
+        CreateTrack( *trackIter );
+      }
+      debug() <<  "End of creating "<< nHits << " hits tracks " << endmsg;
+    }
+    
+    if (_attachFast == 0) {
+      if(successVTX) AttachRemainingVTXHitsSlow();
+      if(successFTD) AttachRemainingFTDHitsSlow();
+    }
+    else {
+      if(successVTX) AttachRemainingVTXHitsFast();
+      if(successFTD) AttachRemainingFTDHitsFast();
+    }
+    
+    debug() <<  "End of picking up remaining hits " << endmsg;
+
+    //edm4hep::TrackCollection* trkCol = nullptr; 
+    //edm4hep::LCRelationCollection* relCol = nullptr;
+    auto trkCol = _outColHdl.createAndPut();
+    //auto relCol = _outRelColHdl.createAndPut();
+    //std::cout << "fucd------------------" << std::endl;
+    /*
+    LCCollectionVec * trkCol = new LCCollectionVec(LCIO::TRACK);
+    // if we want to point back to the hits we need to set the flag
+    LCFlagImpl trkFlag(0) ;
+    trkFlag.setBit( LCIO::TRBIT_HITS ) ;
+    trkCol->setFlag( trkFlag.getFlag()  ) ;
+    
+    LCCollectionVec * relCol = NULL;
+    */
+    //FinalRefit(trkCol, relCol);
+    FinalRefit(trkCol);
+    //std::cout << "fucd------------------" << std::endl;
+    // set the quality of the output collection
+    switch (_output_track_col_quality) {
+
+      case _output_track_col_quality_FAIR:
+        //trkCol->parameters().setValue( "QualityCode" , "Fair"  ) ;
+        break;
+
+      case _output_track_col_quality_POOR:
+        //trkCol->parameters().setValue( "QualityCode" , "Poor"  ) ;
+        break;
+        
+      default:
+        //trkCol->parameters().setValue( "QualityCode" , "Good"  ) ;
+        break;
+    }
+    /*
+    if (_UseEventDisplay) {
+      this->drawEvent();
+    }
+    */
+  }
+  
+  // fill event based histogram
+  /*
+  if (_createDiagnosticsHistograms) {
+  
+    // triplet histos
+    _histos->fill1D(DiagnosticsHistograms::hntriplets, _ntriplets);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_good, _ntriplets_good);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_2MCP, _ntriplets_2MCP);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_3MCP, _ntriplets_3MCP);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_1MCP_Bad, _ntriplets_1MCP_Bad);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_bad, _ntriplets_bad);
+  
+  }
+  */
+  /*
+  const edm4hep::MCParticleCollection* mcCol = nullptr;
+  try{
+    mcCol =_inMCColHdl.get();
+  }
+  catch(...){
+  }
+  if(mcCol){
+    int id = 0;
+    for(auto mcP : *mcCol){
+      float pos[3];
+      float mom[3];
+      pos[0] = mcP.vertex()[0];
+      pos[1] = mcP.vertex()[1];
+      pos[2] = mcP.vertex()[2];
+      mom[0] = mcP.momentum()[0];
+      mom[1] = mcP.momentum()[1];
+      mom[2] = mcP.momentum()[2];
+      float           charge = mcP.getCharge();
+      HelixClass helix;
+      helix.Initialize_VP(pos,mom,charge,_bField);
+      float d0 = helix.getD0();
+      float z0 = helix.getZ0();
+      float omega = helix.getOmega();
+      float phi0 = helix.getPhi0();
+      float tanLambda = helix.getTanLambda();
+      std::cout <<"MCParticle: " << evtNo << " " << id << " " << sqrt(mom[0]*mom[0]+mom[1]*mom[1]) << " " << acos(mom[2]/sqrt(mom[0]*mom[0]+mom[1]*mom[1]+mom[2]*mom[2]))
+		<< " " << atan2(mom[1],mom[0])
+		<< " " << d0 << " " << phi0 << " " << omega << " " << z0 << " " << tanLambda << " " << mcP.vertex() << std::endl; 
+      id++;
+    }
+  }
+  
+  const edm4hep::TrackCollection* trkCol = nullptr;
+  try{
+    trkCol = _outColHdl.get();
+  }
+  catch(...){
+  }
+  if(trkCol){
+    int id = 0;
+    for(auto track : *trkCol){
+      int nstate = track->trackStates_size();
+      for(int i=0;i<nstate;i++){
+	edm4hep::TrackState trkState = track->getTrackStates(i);
+	if(trkState.location != 1) continue;
+	HelixClass helix_final;
+        helix_final.Initialize_Canonical(trkState.phi,trkState.D0,trkState.Z0,trkState.omega,trkState.tanLambda,_bField);
+        float trkPx = helix_final.getMomentum()[0];
+        float trkPy = helix_final.getMomentum()[1];
+	float trkPz = helix_final.getMomentum()[2];
+        float trkPt = sqrt(trkPx*trkPx+trkPy*trkPy);
+	std::cout << "Track parameter: " << evtNo << " " << id << " " << trkPt << " " << acos(trkPz/sqrt(trkPt*trkPt+trkPz*trkPz)) << " " << atan2(trkPy,trkPx)
+		  << " " << trkState.D0 << " " << trkState.phi << " " << trkState.omega << " " << trkState.Z0 << " " << trkState.tanLambda
+		  << " " << sqrt(trkState.covMatrix[0]) << " " << sqrt(trkState.covMatrix[2]) << " " << sqrt(trkState.covMatrix[5])
+		  << " " << sqrt(trkState.covMatrix[9]) << " " << sqrt(trkState.covMatrix[14]) << " " << std::endl;
+	id++;
+	break;
+      }
+    }
+  }
+  */
+  CleanUp();
+  debug() << "Event is done " << endmsg;
+  _nEvt++;
+  return StatusCode::SUCCESS;
+}
+
+
+void SiliconTrackingAlg::CleanUp() {
+  
+  _tracksWithNHitsContainer.clear();
+  
+  for (int il=0;il<_nLayers;++il) {
+    for (int ip=0;ip<_nDivisionsInPhi;++ip) {
+      for (int it=0;it<_nDivisionsInTheta; ++it) {
+        unsigned int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it;      
+        
+        if( iCode >= _sectors.size()){          
+          error() << "iCode index out of range: iCode =   " << iCode << " _sectors.size() = " << _sectors.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg;
+          continue;
+        }
+        
+        TrackerHitExtendedVec& hitVec = _sectors[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          delete hit;
+        }
+      }
+    }
+  }
+  
+  for (int iS=0;iS<2;++iS) {
+    for (unsigned int layer=0;layer<_nlayersFTD;++layer) {
+      for (int ip=0;ip<_nPhiFTD;++ip) {
+        unsigned int iCode = iS + 2*layer + 2*_nlayersFTD*ip;
+        
+        if( iCode >= _sectorsFTD.size()){
+          //error() << "iCode index out of range: iCode =   " << iCode << " _sectorsFTD.size() = " << _sectorsFTD.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg;
+          continue;
+        }
+        
+        TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          delete hit;
+        }
+      }
+    }
+  }
+  _trackImplVec.clear();
+  _allHits.clear();
+}
+
+int SiliconTrackingAlg::InitialiseFTD() {
+  
+  int success = 1;
+  
+  _nTotalFTDHits = 0;
+  _sectorsFTD.clear();
+  _sectorsFTD.resize(2*_nlayersFTD*_nPhiFTD);
+  
+  // Reading in FTD Pixel Hits Collection
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  const edm4hep::TrackerHitCollection* hitFTDPixelCol = nullptr;
+  try {
+    hitFTDPixelCol = _inFTDPixelColHdl.get();
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << _inFTDPixelColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+    success = 0;
+  }
+  
+  if(hitFTDPixelCol){
+    //LCCollection * hitCollection = evt->getCollection(_FTDPixelHitCollection.c_str());
+    
+    //_colNamesTrackerHits[hitCollection] = _FTDPixelHitCollection;    
+    // _colTrackerHits.push_back(hitCollection);
+    
+    int nelem = hitFTDPixelCol->size();
+    
+    debug() << "Number of FTD Pixel Hits = " << nelem << endmsg;
+    _nTotalFTDHits = nelem;
+    
+    //for (int ielem=0; ielem<nelem; ++ielem) {
+    for(auto hit : *hitFTDPixelCol){  
+    // edm4hep::TrackerHit* hit = hitFTDPixelCol->at(ielem);
+      
+      TrackerHitExtended * hitExt = new TrackerHitExtended( hit );
+      
+      //gear::Vector3D U(1.0,hit->getU()[1],hit->getU()[0],gear::Vector3D::spherical);
+      //gear::Vector3D V(1.0,hit->getV()[1],hit->getV()[0],gear::Vector3D::spherical);
+      gear::Vector3D U(1.0,hit.getCovMatrix()[1],hit.getCovMatrix()[0],gear::Vector3D::spherical);
+      gear::Vector3D V(1.0,hit.getCovMatrix()[4],hit.getCovMatrix()[3],gear::Vector3D::spherical);
+      gear::Vector3D Z(0.0,0.0,1.0);
+      
+      const float eps = 1.0e-07;
+      // V must be the global z axis 
+      if( fabs(V.dot(Z)) > eps ) {
+	error() << "SiliconTrackingAlg: VXD Hit measurment vectors V is not in the global X-Y plane. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+      exit(1);
+      }
+      
+      if( fabs(U.dot(Z)) > eps ) {
+	error() << "SiliconTrackingAlg: VXD Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+	exit(1);
+      }
+      
+      // SJA:FIXME Here dU and dV are almost certainly dX and dY ... should test ...
+      //double point_res_rphi = sqrt( hit->getdU()*hit->getdU() + hit->getdV()*hit->getdV() );
+      double point_res_rphi = sqrt( hit.getCovMatrix()[2]*hit.getCovMatrix()[2] + hit.getCovMatrix()[5]*hit.getCovMatrix()[5] );
+      hitExt->setResolutionRPhi( point_res_rphi );
+      
+      // SJA:FIXME why is this needed? 
+      hitExt->setResolutionZ(0.1);
+      
+      // type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+      hitExt->setType(int(INT_MAX));
+      // det is no longer used set to INT_MAX to try and catch any missuse
+      hitExt->setDet(int(INT_MAX));
+    
+      double pos[3];
+      
+      for (int i=0; i<3; ++i) {
+	pos[i] = hit.getPosition()[i];
+      }
+      
+      double Phi = atan2(pos[1],pos[0]);
+      if (Phi < 0.) Phi = Phi + TWOPI;
+      
+      // get the layer number
+      unsigned int layer = static_cast<unsigned int>(getLayerID(&hit));
+      unsigned int petalIndex = static_cast<unsigned int>(getModuleID(&hit));
+      
+      if ( _petalBasedFTDWithOverlaps == true ) {
+	
+	// as we are dealing with staggered petals we will use 2*nlayers in each directions +/- z
+	// the layers will follow the even odd numbering of the petals 
+	if ( petalIndex % 2 == 0 ) {
+	  layer = 2*layer;
+	}
+	else {
+	  layer = 2*layer + 1;
+	}
+	
+      }
+      
+      if (layer >= _nlayersFTD) {
+	error() << "SiliconTrackingAlg => fatal error in FTD : layer is outside allowed range : " << layer << " number of layers = " << _nlayersFTD <<  endmsg;
+	exit(1);
+      }
+      
+      int iPhi = int(Phi/_dPhiFTD);
+      
+      int side = getSideID(&hit);
+      int iSemiSphere = 0;
+    
+      if (side > 0) 
+	iSemiSphere = 1;
+      
+      int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPhi;
+      _sectorsFTD[iCode].push_back( hitExt );
+      
+      debug() << " FTD Pixel Hit added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iSemiSphere "  << iSemiSphere << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+    }
+  }
+  // Reading out FTD SpacePoint Collection
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  const edm4hep::TrackerHitCollection* hitFTDSpacePointCol = nullptr;
+  try {
+    hitFTDSpacePointCol = _inFTDSpacePointColHdl.get();
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << _inFTDSpacePointColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+    success = 0;
+  }
+
+  if(hitFTDSpacePointCol){
+    //LCCollection * hitCollection = evt->getCollection(_FTDSpacePointCollection.c_str());
+    
+    //_colNamesTrackerHits[hitCollection] = _FTDSpacePointCollection;
+    //_colTrackerHits.push_back(hitCollection);
+    
+    int nelem = hitFTDSpacePointCol->size();
+    
+    debug() << "Number of FTD SpacePoints = " << nelem << endmsg;
+    _nTotalFTDHits += nelem;
+    
+    //for (int ielem=0; ielem<nelem; ++ielem) {
+    for(auto hit : *hitFTDSpacePointCol){
+    //edm4hep::TrackerHit* hit =  hitFTDSpacePointCol->at(ielem);
+      
+      TrackerHitExtended * hitExt = new TrackerHitExtended(hit);
+      
+      // SJA:FIXME: fudge for now by a factor of two and ignore covariance
+      double point_res_rphi = 2 * sqrt( hit.getCovMatrix()[0] + hit.getCovMatrix()[2] );
+      
+      hitExt->setResolutionRPhi( point_res_rphi );
+      
+      // SJA:FIXME why is this needed? 
+      hitExt->setResolutionZ(0.1);
+      
+      // type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+      hitExt->setType(int(INT_MAX));
+      // det is no longer used set to INT_MAX to try and catch any missuse
+      hitExt->setDet(int(INT_MAX));
+      
+      double pos[3];
+      
+      for (int i=0; i<3; ++i) {
+        pos[i] = hit.getPosition()[i];
+      }
+      
+      double Phi = atan2(pos[1],pos[0]);
+      if (Phi < 0.) Phi = Phi + TWOPI;
+      
+      // get the layer number
+      unsigned int layer = static_cast<unsigned int>(getLayerID(&hit));
+      unsigned int petalIndex = static_cast<unsigned int>(getModuleID(&hit));
+      
+      if ( _petalBasedFTDWithOverlaps == true ) {
+        
+        // as we are dealing with staggered petals we will use 2*nlayers in each directions +/- z
+        // the layers will follow the even odd numbering of the petals 
+        if ( petalIndex % 2 == 0 ) {
+          layer = 2*layer;
+        }
+        else {
+          layer = 2*layer + 1;
+        }
+        
+      }
+      
+      if (layer >= _nlayersFTD) {
+        error() << "SiliconTrackingAlg => fatal error in FTD : layer is outside allowed range : " << layer << " number of layers = " << _nlayersFTD <<  endmsg;
+        exit(1);
+      }
+      
+      int iPhi = int(Phi/_dPhiFTD);
+      
+      int side = getSideID(&hit);
+      int iSemiSphere = 0;
+      
+      if (side > 0) 
+        iSemiSphere = 1;
+      
+      int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPhi;
+      _sectorsFTD[iCode].push_back( hitExt );
+      
+      debug() << " FTD SpacePoint Hit added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iSemiSphere "  << iSemiSphere << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+      
+    }
+  }
+  
+  for (unsigned i=0; i<_sectorsFTD.size(); ++i) {
+    int nhits = _sectorsFTD[i].size();
+    if( nhits != 0 ) debug() << " Number of Hits in FTD Sector " << i << " = " << _sectorsFTD[i].size() << endmsg;
+    if (nhits > _max_hits_per_sector) {
+      for (unsigned ihit=0; ihit<_sectorsFTD[i].size(); ++ihit) {
+        delete _sectorsFTD[i][ihit];
+      } 
+      _sectorsFTD[i].clear();
+      if( nhits != 0 ) error()  << " \n ### Number of Hits in FTD Sector " << i << " = " << nhits << " : Limit is set to " << _max_hits_per_sector << " : This sector will be dropped from track search, and QualityCode set to \"Poor\" " << endmsg;
+      
+      _output_track_col_quality = _output_track_col_quality_POOR;
+      
+    }
+    
+  }
+  debug() << "FTD initialized" << endmsg;
+  return success;
+}
+
+int SiliconTrackingAlg::InitialiseVTX() {
+  //std::cout << "fucd================" << std::endl;
+  _nTotalVTXHits = 0;
+  _nTotalSITHits = 0;
+  _sectors.clear();
+  _sectors.resize(_nLayers*_nDivisionsInPhi*_nDivisionsInTheta);
+  //std::cout << "fucd================" << std::endl;
+  int success = 1;
+  // Reading out VTX Hits Collection
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
+  const edm4hep::TrackerHitCollection* hitVTXCol = nullptr;
+  try {
+    hitVTXCol = _inVTXColHdl.get();
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << _inVTXColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+    success = 0;
+  }
+  if(hitVTXCol){
+    //LCCollection * hitCollection = evt->getCollection(_VTXHitCollection.c_str());
+    
+    //_colNamesTrackerHits[hitCollection] = _VTXHitCollection;
+    //_colTrackerHits.push_back(hitCollection);
+    //std::cout << "fucd================1" << std::endl;
+    int nelem = hitVTXCol->size();
+    //std::cout << "fucd================2" << std::endl;
+    debug() << "Number of VTX hits = " << nelem << endmsg;
+    _nTotalVTXHits = nelem;
+    
+    for (int ielem=0; ielem<nelem; ++ielem) {
+    //for(auto hit : *hitVTXCol){ 
+      edm4hep::TrackerHit hit = hitVTXCol->at(ielem);
+      //_allHits.push_back(hit);
+      //gear::Vector3D U(1.0,hit->getU()[1],hit->getU()[0],gear::Vector3D::spherical);
+      //gear::Vector3D V(1.0,hit->getV()[1],hit->getV()[0],gear::Vector3D::spherical);
+      gear::Vector3D U(1.0,hit.getCovMatrix()[1],hit.getCovMatrix()[0],gear::Vector3D::spherical);
+      gear::Vector3D V(1.0,hit.getCovMatrix()[4],hit.getCovMatrix()[3],gear::Vector3D::spherical);
+      gear::Vector3D Z(0.0,0.0,1.0);
+      //debug() << "covMatrix : " << hit->getCovMatrix()[0] << " " << hit->getCovMatrix()[1] << endmsg;
+      const float eps = 1.0e-07;
+      // V must be the global z axis 
+      if( fabs(1.0 - V.dot(Z)) > eps ) {
+        error() << "SiliconTrackingAlg: VXD Hit measurment vectors V is not equal to the global Z axis. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+        exit(1);
+      }
+      
+      if( fabs(U.dot(Z)) > eps ) {
+        error() << "SiliconTrackingAlg: VXD Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+        exit(1);
+      }
+      //std::cout << "fucd: " << &hit << " " << &_allHits.back() << std::endl;
+      //TrackerHitExtended * hitExt = new TrackerHitExtended( &_allHits.back() );
+      TrackerHitExtended * hitExt = new TrackerHitExtended(hit);
+      std::cout << "Saved TrackerHit pointer in TrackerHitExtended " << ielem << ": " << hitExt->getTrackerHit() << std::endl;
+      //std::cout << (&_allHits.back())->getPosition()[0] << " " << hit.getCovMatrix()[2] << " " << hit.getCovMatrix()[5] << std::endl;
+            
+      // SJA:FIXME: just use planar res for now
+      hitExt->setResolutionRPhi(hit.getCovMatrix()[2]);
+      hitExt->setResolutionZ(hit.getCovMatrix()[5]);
+      
+      // set type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+      hitExt->setType(int(INT_MAX));
+      // det is no longer used set to INT_MAX to try and catch any missuse
+      hitExt->setDet(int(INT_MAX));
+      
+      double pos[3];
+      double radius = 0;
+      
+      for (int i=0; i<3; ++i) {
+        pos[i] = hit.getPosition()[i];
+        radius += pos[i]*pos[i];
+      }
+      
+      radius = sqrt(radius);
+      
+      double cosTheta = pos[2]/radius;
+      double Phi = atan2(pos[1],pos[0]);
+      
+      if (Phi < 0.) Phi = Phi + TWOPI;
+      
+      // get the layer number
+      int layer = getLayerID(&hit);
+      
+      if (layer < 0 || layer >= _nLayers) {
+        error() << "SiliconTrackingAlg => fatal error in VTX : layer is outside allowed range : " << layer << endmsg;
+        exit(1);
+      }
+      
+      int iPhi = int(Phi/_dPhi);
+      int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+      int iCode = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta;      
+      _sectors[iCode].push_back( hitExt );
+      
+      debug() << " VXD Hit " <<  hit.id() << " added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iTheta "  << iTheta << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+      
+    }
+  }
+  
+  if (_useSIT > 0 ) {
+    const edm4hep::TrackerHitCollection* hitSITCol = nullptr;
+    try {
+      hitSITCol = _inSITColHdl.get();
+    }
+    catch ( GaudiException &e ) {
+      debug() << "Collection " << _inSITColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+      success = 0;
+    }
+    if(hitSITCol){
+      //LCCollection *hitCollection = evt->getCollection(_SITHitCollection.c_str());
+      
+      //_colNamesTrackerHits[hitCollection] = _SITHitCollection;
+      //_colTrackerHits.push_back(hitCollection);
+      
+      int nelem = hitSITCol->size();
+      
+      debug() << "Number of SIT hits = " << nelem << endmsg;
+      _nTotalSITHits = nelem;
+      
+      //TrackerHit*          trkhit   = 0;
+      //TrackerHitPlane*     trkhit_P = 0;
+      //TrackerHitZCylinder* trkhit_C = 0;
+      
+      double drphi(NAN);
+      double dz(NAN);
+      
+      //for (int ielem=0; ielem<nelem; ++ielem) {
+      for(auto trkhit : *hitSITCol){
+        // hit could be of the following type
+        // 1) TrackerHit, either ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT or just standard TrackerHit
+        // 2) TrackerHitPlane, either 1D or 2D
+        // 3) TrackerHitZCylinder, if coming from a simple cylinder design as in the LOI
+        
+        // Establish which of these it is in the following order of likelyhood
+        //    i)   ILDTrkHitTypeBit::ONE_DIMENSIONAL (TrackerHitPlane) Should Never Happen: SpacePoints Must be Used Instead
+        //    ii)  ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT (TrackerHit)
+        //    iii) TrackerHitPlane (Two dimentional)
+        //    iv)  TrackerHitZCylinder 
+        //    v)   Must be standard TrackerHit
+        
+	//const edm4hep::TrackerHit* trkhit = hitSITCol->at(ielem);
+        
+        int layer = getLayerID(&trkhit);
+        
+        // VXD and SIT are treated as one system so SIT layers start from _nLayersVTX
+        layer = layer + _nLayersVTX;
+        
+        if (layer < 0 || layer >= _nLayers) {
+          error() << "SiliconTrackingAlg => fatal error in SIT : layer is outside allowed range : " << layer << endmsg;
+          exit(1);
+        }
+        
+        // first check that we have not been given 1D hits by mistake, as they won't work here
+        if ( UTIL::BitSet32( trkhit.getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] ) {
+          
+          error() << "SiliconTrackingAlg: SIT Hit cannot be of type UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL COMPOSITE SPACEPOINTS must be use instead. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+          exit(1);
+          
+        } 
+        // most likely case: COMPOSITE_SPACEPOINT hits formed from stereo strip hits
+        else if ( UTIL::BitSet32( trkhit.getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ) {
+          
+          // SJA:FIXME: fudge for now by a factor of two and ignore covariance
+          drphi =  2 * sqrt(trkhit.getCovMatrix()[0] + trkhit.getCovMatrix()[2]);         
+          dz    =      sqrt(trkhit.getCovMatrix()[5]);         
+          
+        } 
+        // or a PIXEL based SIT, using 2D TrackerHitPlane like the VXD above
+	// by fucd
+        //else if ( ( trkhit_P = dynamic_cast<TrackerHitPlane*>( hitCollection->getElementAt( ielem ) ) ) )  {
+	else if( UTIL::BitSet32( trkhit.getType() )[ 31 ]){
+          // first we need to check if the measurement vectors are aligned with the global coordinates 
+          //gear::Vector3D U(1.0,trkhit_P->getU()[1],trkhit_P->getU()[0],gear::Vector3D::spherical);
+          //gear::Vector3D V(1.0,trkhit_P->getV()[1],trkhit_P->getV()[0],gear::Vector3D::spherical);
+	  gear::Vector3D U(1.0,trkhit.getCovMatrix()[1],trkhit.getCovMatrix()[0],gear::Vector3D::spherical);
+	  gear::Vector3D V(1.0,trkhit.getCovMatrix()[4],trkhit.getCovMatrix()[3],gear::Vector3D::spherical);
+          gear::Vector3D Z(0.0,0.0,1.0);
+          
+          const float eps = 1.0e-07;
+          // V must be the global z axis 
+          if( fabs(1.0 - V.dot(Z)) > eps ) {
+            error() << "SiliconTrackingAlg: PIXEL SIT Hit measurment vectors V is not equal to the global Z axis. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+            exit(1);
+          }
+          
+          // U must be normal to the global z axis
+          if( fabs(U.dot(Z)) > eps ) {
+            error() << "SiliconTrackingAlg: PIXEL SIT Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+            exit(1);
+          }
+          
+          //drphi = trkhit_P->getdU();
+          //dz    = trkhit_P->getdV();                                                 
+          drphi = trkhit.getCovMatrix()[2];
+          dz    = trkhit.getCovMatrix()[5];
+        }
+	
+        // or a simple cylindrical design, as used in the LOI      
+	/* by fucd
+        else if ( ( trkhit_C = dynamic_cast<TrackerHitZCylinder*>( hitCollection->getElementAt( ielem ) ) ) ) {
+          
+          drphi = trkhit_C->getdRPhi();
+          dz    = trkhit_C->getdZ();
+          
+        } 
+	*/
+        // this would be very unlikely, but who knows ... just an ordinary TrackerHit, which is not a COMPOSITE_SPACEPOINT
+        else {
+          
+          // SJA:FIXME: fudge for now by a factor of two and ignore covariance
+          drphi =  2 * sqrt(trkhit.getCovMatrix()[0] + trkhit.getCovMatrix()[2]);         
+          dz =     sqrt(trkhit.getCovMatrix()[5]);             
+          
+        }
+        // now that the hit type has been established carry on and create a 
+        
+        TrackerHitExtended * hitExt = new TrackerHitExtended(trkhit);
+        
+        // SJA:FIXME: just use planar res for now
+        hitExt->setResolutionRPhi(drphi);
+        hitExt->setResolutionZ(dz);
+        
+        // set type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+        hitExt->setType(int(INT_MAX));
+        // det is no longer used set to INT_MAX to try and catch any missuse
+        hitExt->setDet(int(INT_MAX));
+        
+        double pos[3];
+        double radius = 0;
+        
+        for (int i=0; i<3; ++i) {
+          pos[i] = trkhit.getPosition()[i];
+          radius += pos[i]*pos[i];
+        }
+        
+        radius = sqrt(radius);
+        
+        double cosTheta = pos[2]/radius;
+        double Phi = atan2(pos[1],pos[0]);
+        
+        if (Phi < 0.) Phi = Phi + TWOPI;
+        
+        int iPhi = int(Phi/_dPhi);
+        int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+        int iCode = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta;      
+        _sectors[iCode].push_back( hitExt );
+        
+        debug() << " SIT Hit " <<  trkhit.id() << " added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iTheta "  << iTheta << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+        
+      }
+    }    
+  }
+  
+  
+  for (unsigned i=0; i<_sectors.size(); ++i) {
+    int nhits = _sectors[i].size();
+    if( nhits != 0 ) debug() << " Number of Hits in VXD/SIT Sector " << i << " = " << _sectors[i].size() << endmsg;
+    if (nhits > _max_hits_per_sector) {
+      for (unsigned ihit=0; ihit<_sectors[i].size(); ++ihit) {
+        delete _sectors[i][ihit];
+      }
+      _sectors[i].clear();
+      if( nhits != 0 ) error()  << " \n ### Number of Hits in VXD/SIT Sector " << i << " = " << nhits << " : Limit is set to " << _max_hits_per_sector << " : This sector will be dropped from track search, and QualityCode set to \"Poor\" " << endmsg;
+      
+      _output_track_col_quality = _output_track_col_quality_POOR;
+    }
+  }
+  debug() << "VXD initialized" << endmsg;
+  return success; 
+}
+
+StatusCode  SiliconTrackingAlg::finalize(){
+  
+  delete _fastfitter ; _fastfitter = 0;
+  delete _encoder ; _encoder = 0;
+  //delete _trksystem ; _trksystem = 0;
+  //delete _histos ; _histos = 0;
+  info() << "Processed " << _nEvt << " events " << endmsg;
+  return GaudiAlgorithm::finalize();
+}
+
+
+void SiliconTrackingAlg::ProcessOneSector(int iPhi, int iTheta) {
+  
+  int counter = 0 ;
+  
+  int iPhi_Up    = iPhi + 1;
+  int iPhi_Low   = iPhi - 1;
+  int iTheta_Up  = iTheta + 1; 
+  int iTheta_Low = iTheta - 1;
+  if (iTheta_Low < 0) iTheta_Low = 0;
+  if (iTheta_Up  >= _nDivisionsInTheta) iTheta_Up = _nDivisionsInTheta-1;
+  
+  int nComb = int( _Combinations.size() / 3 ); // number of triplet combinations
+                                               //  std::cout << iPhi << " " << iTheta << " " << _nEvt << endmsg;
+  int iNC = 0;
+  
+  for (int iComb=0; iComb < nComb; ++iComb) { // loop over triplets
+    
+    int nLR[3];
+    
+    for (int iS=0; iS<3; ++iS) {
+      nLR[iS] = _Combinations[iNC];
+      iNC++;
+    }    
+    
+    //std::cout << iPhi << " " << iTheta << " " << nLR[0] << " " << nLR[1] << " " << nLR[2] << " " << std::endl;
+    
+    // index of theta-phi bin of outer most layer
+    int iCode = nLR[0] + _nLayers*iPhi +  _nLayers*_nDivisionsInPhi*iTheta;
+    
+    //std::cout << "size of vector = " << _sectors.size() << " iCode = " << iCode << std::endl;
+    
+    // get the all the hits in the outer most theta-phi bin 
+    
+    TrackerHitExtendedVec& hitVecOuter =  _sectors[iCode];
+    
+    int nHitsOuter = int(hitVecOuter.size());
+    if (nHitsOuter > 0) {
+      
+      //std::cout << " " << iPhi << " " << iTheta << " " << nLR[0] << " " << nLR[1] << " " << nLR[2] << " size of vector = " << hitVecOuter.size() << std::endl;
+      
+      for (int ipMiddle=iPhi_Low; ipMiddle<iPhi_Up+1;ipMiddle++) { // loop over phi in the Middle
+        
+        for (int itMiddle=iTheta_Low; itMiddle<iTheta_Up+1;itMiddle++) { // loop over theta in the Middle 
+          
+          int iPhiMiddle = ipMiddle;
+          
+          // catch wrap-around
+          if (ipMiddle < 0) iPhiMiddle = _nDivisionsInPhi-1;          
+          if (ipMiddle >= _nDivisionsInPhi) iPhiMiddle = ipMiddle - _nDivisionsInPhi;
+          
+          // index of current theta-phi bin of middle layer
+          iCode = nLR[1] + _nLayers*iPhiMiddle +  _nLayers*_nDivisionsInPhi*itMiddle;
+          
+          // get the all the hits in the current middle theta-phi bin 
+          TrackerHitExtendedVec& hitVecMiddle = _sectors[iCode];
+          
+          int nHitsMiddle = int(hitVecMiddle.size());
+          
+          // determine which inner theta-phi bins to look in
+          
+          int iPhiLowInner = iPhi_Low;
+          int iPhiUpInner = iPhi_Up;
+          int iThetaLowInner = iTheta_Low;
+          int iThetaUpInner = iTheta_Up;        
+          
+          // test to see if this is the core bin of the current search
+          // if so, look into the neigboring bins in the inner layer
+          if (ipMiddle == iPhi && itMiddle==iTheta) { 
+            iPhiLowInner = iPhi_Low;
+            iPhiUpInner  = iPhi_Up;
+            iThetaLowInner = iTheta_Low;
+            iThetaUpInner = iTheta_Up;
+          }
+          else { 
+            int difP = abs(ipMiddle-iPhi); //  number of phi bins from core: can only be 1 or 0 due to hard coded 1 above
+            int difT = abs(itMiddle-iTheta);// number of theta bins from core: can only be 1 or 0 due to hard coded 1 above
+            int minP = min(ipMiddle,iPhi);   // min phi: core bin or current phi bin middle
+            int minT = min(itMiddle,iTheta); // min theta: core bin or current theta bin middle
+            int maxP = max(ipMiddle,iPhi);   // max phi: core bin or current phi bin middle
+            int maxT = max(itMiddle,iTheta); // max theta: core bin or current theta bin middle
+            
+            if (difP==1 && difT==1) { // if the diffence is a single bin in both phi and theta : only look in the bin adjacent to the core bin  
+              iPhiLowInner = minP;
+              iPhiUpInner = maxP;
+              iThetaLowInner = minT;
+              iThetaUpInner = maxT;
+            }
+            if (difP==0) { // must be +/-1 theta : only look in bins adjacent to the middle bin
+              iPhiLowInner = iPhi_Low;
+              iPhiUpInner  = iPhi_Up;
+              iThetaLowInner = minT;
+              iThetaUpInner = maxT;
+            }
+            if (difT==0) { // must be +/-1 phi : only look in bins adjacent to the middle bin
+              iPhiLowInner = minP;
+              iPhiUpInner  = maxP;
+              iThetaLowInner = iTheta_Low;
+              iThetaUpInner = iTheta_Up;            
+            }
+          }               
+          if (nHitsMiddle > 0) { // look into inner bins
+            
+            for (int ipInner=iPhiLowInner; ipInner<iPhiUpInner+1;ipInner++) { // loop over phi in the Inner
+              
+              for (int itInner=iThetaLowInner; itInner<iThetaUpInner+1;itInner++) { // loop over theta in the Inner 
+                
+                int iPhiInner = ipInner;
+                
+                // catch wrap-around
+                if (ipInner < 0) iPhiInner = _nDivisionsInPhi-1;
+                if (ipInner >= _nDivisionsInPhi) iPhiInner = ipInner - _nDivisionsInPhi;
+                
+                iCode = nLR[2] + _nLayers*iPhiInner +  _nLayers*_nDivisionsInPhi*itInner;
+                
+                // get hit for inner bin
+                TrackerHitExtendedVec& hitVecInner = _sectors[iCode];
+                
+                int nHitsInner = int(hitVecInner.size());
+                
+                if (nHitsInner > 0) {
+                  
+                  debug() << " " 
+                  << std::setw(3) << iPhi       << " "   << std::setw(3) << ipMiddle << " "      << std::setw(3) << ipInner << "   " 
+                  << std::setw(3) << iTheta     << " "   << std::setw(3) << itMiddle << " "      << std::setw(3) << itInner << "  " 
+                  << std::setw(3) << nLR[0]     << " "   << std::setw(3) << nLR[1]   << " "      << std::setw(3) << nLR[2]  << "     " 
+                  << std::setw(3) << nHitsOuter << " : " << std::setw(3) << nHitsMiddle << " : " << std::setw(3) << nHitsInner << "  :: " 
+                  << std::setw(3) << nHitsOuter*nHitsMiddle* nHitsInner << endmsg;
+                  
+                  // test all triplets 
+                  
+                  for (int iOuter=0; iOuter<nHitsOuter; ++iOuter) { // loop over hits in the outer sector
+                    TrackerHitExtended * outerHit = hitVecOuter[iOuter];
+                    for (int iMiddle=0;iMiddle<nHitsMiddle;iMiddle++) { // loop over hits in the middle sector
+                      TrackerHitExtended * middleHit = hitVecMiddle[iMiddle];
+                      for (int iInner=0;iInner<nHitsInner;iInner++) { // loop over hits in the inner sector
+                        TrackerHitExtended * innerHit = hitVecInner[iInner];
+                        HelixClass helix;
+			//std::cout <<"fucd++++++++++++++++++++++1" << std::endl;
+                        // test fit to triplet
+                        TrackExtended * trackAR = TestTriplet(outerHit,middleHit,innerHit,helix);
+			//std::cout <<"fucd++++++++++++++++++++++2" << std::endl;
+                        if ( trackAR != NULL ) {
+                          int nHits = BuildTrack(outerHit,middleHit,innerHit,helix,nLR[2],
+                                                 iPhiLowInner,iPhiUpInner,
+                                                 iThetaLowInner,iThetaUpInner,trackAR);
+                          
+                          _tracksWithNHitsContainer.getTracksWithNHitsVec(nHits).push_back(trackAR);
+                          
+                          counter ++ ;
+                        }
+			//std::cout <<"fucd++++++++++++++++++++++3" << std::endl;
+                      } // endloop over hits in the inner sector
+                    } // endloop over hits in the middle sector
+                  } // endloop over hits in the outer sector
+                } // endif nHitsInner > 0
+              } // endloop over theta in the Inner
+            } // endloop over phi in the Inner      
+          } // endif nHitsMiddle > 0
+        } // endloop over theta in the Middle
+      } // endloop over phi in the Middle
+    } // endif nHitsOuter > 0
+  } // endloop over triplets
+    
+  //debug() << " process one sectector theta,phi " << iTheta << ", " << iPhi << "  number of loops : " << counter << endmsg  ;
+}
+
+TrackExtended * SiliconTrackingAlg::TestTriplet(TrackerHitExtended * outerHit, 
+                                                       TrackerHitExtended * middleHit,
+                                                       TrackerHitExtended * innerHit,
+                                                       HelixClass & helix) {
+  /*
+   Methods checks if the triplet of hits satisfies helix hypothesis
+   */
+  //std::cout << "fucd================1" << std::endl;
+  // get the tracks already associated with the triplet
+  TrackExtendedVec& trackOuterVec  = outerHit->getTrackExtendedVec();
+  TrackExtendedVec& trackMiddleVec = middleHit->getTrackExtendedVec();
+  TrackExtendedVec& trackInnerVec  = innerHit->getTrackExtendedVec();
+  
+  //std::cout << "fucd================2" << std::endl;
+  // check if all the hits are already assigned to a track 
+  if ( (!trackOuterVec.empty())  && (!trackMiddleVec.empty()) && (!trackInnerVec.empty())) {
+    
+    TrackExtendedVec::const_iterator middleEndIter = trackMiddleVec.end();
+    TrackExtendedVec::const_iterator outerEndIter  = trackOuterVec.end();
+    TrackExtendedVec::const_iterator innerEndIter  = trackInnerVec.end();
+    TrackExtendedVec::const_iterator outerBeginIter  = trackOuterVec.begin();
+    TrackExtendedVec::const_iterator innerBeginIter  = trackInnerVec.begin();
+    
+    // loop over the tracks from the middle hit
+    for (TrackExtendedVec::const_iterator middleIter = trackMiddleVec.begin();
+         middleIter < middleEndIter;
+         ++middleIter) {
+      
+      // loop over the track from the outer hit
+      for (TrackExtendedVec::const_iterator outerIter = outerBeginIter;
+           outerIter < outerEndIter;
+           ++outerIter) {
+        
+        // if track from the outer and middle are not the same progress  
+        if ( *outerIter != *middleIter ) continue;
+        
+        // loop over the tracks from the inner hit
+        for (TrackExtendedVec::const_iterator innerIter = innerBeginIter;
+             innerIter < innerEndIter;
+             ++innerIter) {
+          
+          // no need to check against middle, it is idendical to outer here
+          if ( *outerIter == *innerIter ) {
+            // an existing track already contains all three hits
+            // return a null pointer
+            debug() << " TestTriplet: track " << *outerIter << " already contains all three hits: Do not create new track from these hits " << endmsg ;
+            return 0;            
+          }
+          
+        }// for inner
+      }// for outer    
+    }// for middle
+  }// if all vectors are not empty
+  //std::cout << "fucd================3" << std::endl;
+  
+  //    float dZ = FastTripletCheck(innerHit, middleHit, outerHit);
+  
+  //    if (fabs(dZ) > _minDistCutAttach)
+  //      return trackAR;    
+
+  
+  // increase triplet count
+  ++_ntriplets;
+
+  // get the hit coordinates and errors
+  double xh[3];
+  double yh[3];
+  float  zh[3];
+  double wrh[3];
+  float  wzh[3];
+  float  rh[3];
+  float  ph[3];
+  
+  float par[5];
+  float epar[15];
+  /*fucd
+  for(int i=0;i<_allHits.size();i++){
+    std::cout << &_allHits.at(i) << std::endl;
+  } 
+  */
+  // first hit
+  xh[0] = outerHit->getTrackerHit()->getPosition()[0];
+  yh[0] = outerHit->getTrackerHit()->getPosition()[1];
+  zh[0] = float(outerHit->getTrackerHit()->getPosition()[2]);
+  wrh[0] = double(1.0/(outerHit->getResolutionRPhi()*outerHit->getResolutionRPhi()));
+  wzh[0] = 1.0/(outerHit->getResolutionZ()*outerHit->getResolutionZ());
+  // second hit
+  xh[1] = middleHit->getTrackerHit()->getPosition()[0];
+  yh[1] = middleHit->getTrackerHit()->getPosition()[1];
+  zh[1] = float(middleHit->getTrackerHit()->getPosition()[2]);
+  wrh[1] = double(1.0/(middleHit->getResolutionRPhi()*middleHit->getResolutionRPhi()));
+  wzh[1] = 1.0/(middleHit->getResolutionZ()*middleHit->getResolutionZ());
+  // third hit
+  xh[2] = innerHit->getTrackerHit()->getPosition()[0];
+  yh[2] = innerHit->getTrackerHit()->getPosition()[1];
+  zh[2] = float(innerHit->getTrackerHit()->getPosition()[2]);
+  wrh[2] = double(1.0/(innerHit->getResolutionRPhi()*innerHit->getResolutionRPhi()));
+  wzh[2] = 1.0/(innerHit->getResolutionZ()*innerHit->getResolutionZ());
+  // calculate r and phi for all hits
+  for (int ih=0; ih<3; ih++) {
+    rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih]));
+    ph[ih] = atan2(yh[ih],xh[ih]);
+    if (ph[ih] < 0.) 
+      ph[ih] = TWOPI + ph[ih]; 
+  }
+  
+  int NPT = 3;
+  int iopt = 2;
+  float chi2RPhi;
+  float chi2Z;
+  
+  debug() << " TestTriplet: Use fastHelixFit " << endmsg ;  
+  
+  _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+  par[3] = par[3]*par[0]/fabs(par[0]);
+
+  // get helix parameters
+  float omega = par[0];
+  float tanlambda = par[1];
+  float phi0 = par[2];
+  float d0 = par[3];
+  float z0 = par[4];
+
+  // chi2 is weighted here by a factor for both rphi and z
+  float Chi2 = chi2RPhi*_chi2WRPhiTriplet+chi2Z*_chi2WZTriplet;
+  int ndf = 2*NPT-5;
+
+  
+  // check the truth information for the triplet
+  
+  // define these outside of the ifdef so that we don't need to keep repeating it.
+  //std::vector<TrackerHit*> hit_list;
+  //std::vector<MCParticle*> mcps_imo;
+  //std::vector<MCParticle*> mcp_s;
+  int triplet_code = 0;
+  /*  
+#ifdef MARLINTRK_DIAGNOSTICS_ON
+
+  int nmcps   = 0;
+  int nbadHits = 0;
+  
+  int layer  = 9 ;
+  int size   = 3 ;
+  int marker = 1 ;
+  int ml     = 0 ;
+  //  float helix_max_r = 0;
+  float helix_max_z = 0;
+  int color = 0;
+
+  // use the MCTruth4HitExt to get the MCPs
+  
+  hit_list.push_back(innerHit->getTrackerHit());
+  hit_list.push_back(middleHit->getTrackerHit());
+  hit_list.push_back(outerHit->getTrackerHit());
+
+  EVENT::MCParticle* mcp_i = 0;
+  EVENT::MCParticle* mcp_m = 0;
+  EVENT::MCParticle* mcp_o = 0;
+  
+  for (unsigned ihit = 0; ihit < hit_list.size(); ++ihit) {
+
+    EVENT::TrackerHit* trkhit = hit_list[ihit];
+    std::vector<MCParticle*> mcps;
+
+    MarlinTrk::getMCParticlesForTrackerHit(trkhit, mcps);
+    
+    if (mcps.size() == 1) {
+      mcps_imo.push_back(mcps[0]);
+      ++nmcps;
+    } else {
+      mcps_imo.push_back(0);
+      ++nbadHits;
+    }
+    
+  }
+    
+  mcp_i = mcps_imo[0];
+  mcp_m = mcps_imo[1];
+  mcp_o = mcps_imo[2];
+  
+  debug()
+  << "\n mcp_i = " << mcp_i
+  << "\n mcp_m = " << mcp_m
+  << "\n mcp_o = " << mcp_o
+  << endmsg;
+  
+  if( mcp_i ) {
+    mcp_s.push_back(mcp_i) ;
+  }
+    
+  if( mcp_m && mcp_m != mcp_i ) {
+    mcp_s.push_back(mcp_m);
+  }
+  
+  if( mcp_o && mcp_o != mcp_m && mcp_o != mcp_i ){
+    mcp_s.push_back(mcp_o);
+  }
+
+  nmcps = mcp_s.size();
+
+  if (_UseEventDisplay) {
+    // display this triplet and the MCPs from which it is formed
+    
+    MarlinCED::newEvent(this , _detector_model_for_drawing ) ;
+    
+    //    CEDPickingHandler &pHandler=CEDPickingHandler::getInstance();
+    //
+    //    pHandler.update(_current_event);
+    
+    for (unsigned imcp = 0; imcp < mcp_s.size(); ++imcp) {
+      
+      MCParticle* mcp = mcp_s[imcp];
+      
+      helix_max_z = fabsf(mcp->getEndpoint()[2]);
+      
+      
+      info() << "Draw MCParticle : " << *mcp <<endmsg;
+      
+      MarlinCED::add_layer_description("MCParticle_For_Fit", layer);
+      
+      MarlinCED::drawHelix( _bField , mcp->getCharge(), mcp->getVertex()[0], mcp->getVertex()[1], mcp->getVertex()[2],
+                           mcp->getMomentum()[0], mcp->getMomentum()[1], mcp->getMomentum()[2], layer , size , 0x7af774  ,
+                           0.0,  _helix_max_r ,
+                           helix_max_z, mcp->id() ) ;
+      
+    }
+    
+    const std::string  colName = "Hits_For_Fit";
+    
+    
+    size   = 10 ;
+    layer  = 11 ;
+    //    ml = marker | ( layer << CED_LAYER_SHIFT ) ;
+    
+    //ced_describe_layer( colName.c_str() ,layer);
+    MarlinCED::add_layer_description(colName, layer);
+    
+    
+    color =  0xFFFFFF;
+    
+    for(   std::vector<TrackerHit* >::const_iterator it = hit_list.begin();  it != hit_list.end() ; it++ ) {
+      
+      TrackerHit* trkhit = *it;
+      
+      ced_hit_ID(trkhit->getPosition()[0],
+                 trkhit->getPosition()[1],
+                 trkhit->getPosition()[2],
+                 marker, layer, size , color, trkhit->id() ) ;
+      
+    } // hits
+    
+  }
+  
+  if (_createDiagnosticsHistograms) {
+    
+    // if no bad hits are present triplet_code = nmcps;
+    triplet_code = nmcps + nbadHits * 3  ;
+        
+    _histos->fill1D(DiagnosticsHistograms::htriplets, triplet_code);
+    
+    double pt =  (2.99792458E-4*_bField) / omega ; // for r in mm, p in GeV and Bz in Tesla
+    
+    if (triplet_code == 1) {
+      ++_ntriplets_good;
+      _histos->fill2D(DiagnosticsHistograms::htripletChi2vPt_good, pt, Chi2 );
+      _histos->fill1D(DiagnosticsHistograms::htriplets_chi2_good, Chi2 );
+      _histos->fill1D(DiagnosticsHistograms::htriplets_pt_good, pt );
+    } else {
+
+      _histos->fill2D(DiagnosticsHistograms::htripletChi2vPt_bad, pt, Chi2);
+      _histos->fill1D(DiagnosticsHistograms::htriplets_chi2_bad, Chi2 );
+      _histos->fill1D(DiagnosticsHistograms::htriplets_pt_bad, pt );
+
+      if(triplet_code == 2) {
+        ++_ntriplets_2MCP;
+      } else if (triplet_code == 3) {
+        ++_ntriplets_3MCP;
+      } else if (triplet_code == 4) {
+        ++_ntriplets_1MCP_Bad;
+      } else {
+        ++_ntriplets_bad;
+      }
+    }
+    
+  }
+  
+#endif
+  */  
+  
+  // Check if track satisfies all conditions
+  
+  
+  //   std::cout << "Chi2/ndf = " << Chi2/float(ndf) << " , cut = " << _chi2FitCut << endmsg;
+  //   std::cout << "d0 = " << d0 << " , cut = " << _cutOnD0  << endmsg;
+  //   std::cout << "z0 = " << z0 << " , cut = " << _cutOnZ0  << endmsg;
+  //   std::cout << "omega = " << omega << " , cut = " << _cutOnOmega << endmsg;
+  
+  //  if ( Chi2/float(ndf) > _chi2FitCut || fabs(d0) > _cutOnD0 || fabs(z0) > _cutOnZ0 || fabs(omega)>_cutOnOmega)
+  // return a null pointer
+  //    return 0;
+  
+  bool failed = false;
+
+  int quality_code = triplet_code * 10 ;
+
+  if ( Chi2/float(ndf) > _chi2FitCut ) {
+    debug() << "Chi2/ndf = " << Chi2/float(ndf) << " , cut = " << _chi2FitCut << endmsg;
+    failed = true;
+    quality_code += 1;
+  } else if (fabs(d0) > _cutOnD0 ) {
+    debug() << "d0 = " << d0 << " , cut = " << _cutOnD0  << endmsg;
+    failed = true;
+    quality_code += 2;
+  } else if (fabs(z0) > _cutOnZ0 ) {
+    debug() << "z0 = " << z0 << " , cut = " << _cutOnZ0  << endmsg;
+    failed = true;
+    quality_code += 3;
+  } else if ( fabs(omega)>_cutOnOmega)  {
+    debug() << "omega = " << omega << " , cut = " << _cutOnOmega << endmsg;
+    failed = true;
+    quality_code += 4;
+  } else {
+    debug() << "Success !!!!!!!" << endmsg;
+  }
+  /*
+  if (_createDiagnosticsHistograms) _histos->fill1D(DiagnosticsHistograms::htriplets, quality_code);
+
+    if (_UseEventDisplay) {
+    drawEvent();
+  }
+  */
+  
+  if( failed ) {
+    // return a null pointer
+    return 0;
+  }
+  
+  
+  helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+  
+  TrackExtended * trackAR = new TrackExtended();
+  trackAR->addTrackerHitExtended(outerHit);
+  trackAR->addTrackerHitExtended(middleHit);
+  trackAR->addTrackerHitExtended(innerHit);
+  outerHit->addTrackExtended(trackAR);
+  middleHit->addTrackExtended(trackAR);
+  innerHit->addTrackExtended(trackAR);    
+  trackAR->setD0(d0);
+  trackAR->setZ0(z0);
+  trackAR->setPhi(phi0);
+  trackAR->setTanLambda(tanlambda);
+  trackAR->setOmega(omega);
+  trackAR->setChi2( Chi2 );
+  trackAR->setNDF( ndf );
+  trackAR->setCovMatrix(epar);
+  
+  
+  return trackAR;
+  
+}
+
+int SiliconTrackingAlg::BuildTrack(TrackerHitExtended * outerHit, 
+                                          TrackerHitExtended * middleHit,
+                                          TrackerHitExtended * innerHit,
+                                          HelixClass & helix,
+                                          int innerLayer,
+                                          int iPhiLow, int iPhiUp,
+                                          int iThetaLow, int iThetaUp, 
+                                          TrackExtended * trackAR) {
+  /**
+   Method for building up track in the VXD. Method starts from the found triplet and performs
+   sequential attachment of hits in other layers, which have hits within the search window.
+   Only searches inwards.
+   Given that we know we are now jumping over layers due to the doublet nature of the VXD, we 
+   could optimise this to look for the hits in interleaving layers as well. 
+   Currently a fast fit is being done for each additional hit, it could be more efficient to try and use kaltest?
+   
+   */
+  
+  debug() << " BuildTrack starting " << endmsg;
+  
+  for (int layer = innerLayer-1; layer>=0; layer--) { // loop over remaining layers
+    float distMin = 1.0e+20;
+    TrackerHitExtended * assignedhit = NULL;
+    //std::cout << "fucd---------------------1" << std::endl;
+    // loop over phi in the Inner region
+    for (int ipInner=iPhiLow; ipInner<iPhiUp+1;ipInner++) { 
+      
+      // loop over theta in the Inner region 
+      for (int itInner=iThetaLow; itInner<iThetaUp+1;itInner++) { 
+        
+        int iPhiInner = ipInner;
+        
+        // catch wrap-around
+        if (ipInner < 0) iPhiInner = _nDivisionsInPhi-1;
+        if (ipInner >= _nDivisionsInPhi) iPhiInner = ipInner - _nDivisionsInPhi;
+        
+        // get the index of the theta-phi bin to search
+        int iCode = layer + _nLayers*iPhiInner +  _nLayers*_nDivisionsInPhi*itInner;
+        
+        // get the hits from this bin
+        TrackerHitExtendedVec& hitVecInner = _sectors[iCode];
+        
+        int nHitsInner = int(hitVecInner.size());
+        
+        // loop over hits in the Inner sector
+        for (int iInner=0;iInner<nHitsInner;iInner++) { 
+          
+          TrackerHitExtended * currentHit = hitVecInner[iInner];
+          
+          // get the position of the hit to test
+          float pos[3];
+          float distance[3];
+          
+          for (int i=0; i<3; ++i) {
+            pos[i] = float(currentHit->getTrackerHit()->getPosition()[i]);
+          }
+          
+          // get the distance of closest approach and distance s traversed to the POCA 
+          float time = helix.getDistanceToPoint(pos,distance);    
+          
+          // sanity check on s 
+          if (time < 1.0e+10) {
+            
+            // check if this is the closest hit yet
+            if (distance[2] < distMin) { // distance[2] = sqrt( d0*d0 + z0*z0 ) 
+              
+              // if yes store hit and distance 
+              distMin = distance[2];             
+              assignedhit = currentHit;
+            }
+          }
+        } // endloop over hits in the Inner sector
+      } // endloop over theta in the Inner region 
+    } // endloop over phi in the Inner region
+    //std::cout << "fucd---------------------2" << std::endl;
+    // check if closest hit fulfills the min distance cut
+    if (distMin < _minDistCutAttach) {
+      
+      // if yes try to include it in the fit 
+      
+      TrackerHitExtendedVec& hvec = trackAR->getTrackerHitExtendedVec();
+      int  nHits = int(hvec.size());
+      double * xh = new double[nHits+1];
+      double * yh = new double[nHits+1];
+      float * zh = new float[nHits+1];
+      double * wrh = new double[nHits+1];
+      float * wzh = new float[nHits+1];
+      float * rh = new float[nHits+1];
+      float * ph = new float[nHits+1];
+      float par[5];
+      float epar[15];
+      
+      for (int ih=0;ih<nHits;++ih) {
+	edm4hep::TrackerHit * trkHit = hvec[ih]->getTrackerHit();
+        xh[ih] = trkHit->getPosition()[0];
+        yh[ih] = trkHit->getPosition()[1];
+        zh[ih] = float(trkHit->getPosition()[2]);
+        wrh[ih] = double(1.0/(hvec[ih]->getResolutionRPhi()*hvec[ih]->getResolutionRPhi()));
+        wzh[ih] = 1.0/(hvec[ih]->getResolutionZ()*hvec[ih]->getResolutionZ());
+        rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih]));
+        ph[ih] = float(atan2(yh[ih],xh[ih]));
+        if (ph[ih] < 0.) 
+          ph[ih] = TWOPI + ph[ih]; 
+      }      
+      edm4hep::TrackerHit * assignedTrkHit = assignedhit->getTrackerHit();
+      xh[nHits] = assignedTrkHit->getPosition()[0];
+      yh[nHits] = assignedTrkHit->getPosition()[1];
+      zh[nHits] = float(assignedTrkHit->getPosition()[2]);
+      rh[nHits] = float(sqrt(xh[nHits]*xh[nHits]+yh[nHits]*yh[nHits]));
+      ph[nHits] = float(atan2(yh[nHits],xh[nHits]));
+      if (ph[nHits] < 0.) 
+        ph[nHits] = TWOPI + ph[nHits]; 
+      wrh[nHits] = double(1.0/(assignedhit->getResolutionRPhi()*assignedhit->getResolutionRPhi()));
+      wzh[nHits] = 1.0/(assignedhit->getResolutionZ()*assignedhit->getResolutionZ());
+      
+      int NPT = nHits + 1;
+      int iopt = 2;
+      float chi2RPhi;
+      float chi2Z;
+      
+//      std::cout << "######## number of hits to fit with _fastfitter = " << NPT << endmsg; 
+      
+      _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+      par[3] = par[3]*par[0]/fabs(par[0]);
+      
+      
+      delete[] xh;
+      delete[] yh;
+      delete[] zh;
+      delete[] wrh;
+      delete[] wzh;
+      delete[] rh;
+      delete[] ph;
+      
+      bool validCombination = 0;
+      float Chi2 = FLT_MAX;
+      
+      if ((nHits+1) == 4) {
+        Chi2 = chi2RPhi*_chi2WRPhiQuartet+chi2Z*_chi2WZQuartet;
+      }         
+      if ((nHits+1) >= 5) {
+        Chi2 = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+      }
+      int ndf = 2*NPT-5;
+      
+      // check if this is valid combination based on the chi2/ndf
+      validCombination = Chi2/float(ndf) < _chi2FitCut;
+      
+      if ( validCombination ) {
+        // assign hit to track and track to hit, update the track parameters
+        trackAR->addTrackerHitExtended(assignedhit);
+        assignedhit->addTrackExtended(trackAR);
+        float omega = par[0];
+        float tanlambda = par[1];
+        float phi0 = par[2];
+        float d0 = par[3];
+        float z0 = par[4];
+        helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+        trackAR->setD0(d0);
+        trackAR->setZ0(z0);
+        trackAR->setPhi(phi0);
+        trackAR->setTanLambda(tanlambda);
+        trackAR->setOmega(omega);
+        trackAR->setChi2( Chi2 );
+        trackAR->setCovMatrix(epar);
+        trackAR->setNDF( ndf );
+      }
+      
+    }
+  } // endloop over remaining layers
+  //std::cout << "fucd---------------------3" << std::endl;
+  TrackerHitExtendedVec& hvec = trackAR->getTrackerHitExtendedVec();  
+  int nTotalHits = int(hvec.size());
+  
+//  std::cout << "######## number of hits to return = " << nTotalHits << endmsg; 
+  
+  return nTotalHits;
+  
+}
+
+
+void SiliconTrackingAlg::Sorting(TrackExtendedVec & trackVec) {
+  /**
+   Sorting of Track Vector in ascending order of chi2/ndf
+   */
+  
+  std::sort(trackVec.begin(), trackVec.end(), compare_TrackExtended() );
+  
+  // also clean up? what does this do here?
+  for (size_t i=0, sizeOfVector=trackVec.size(); i<sizeOfVector; ++i) {
+    
+    TrackerHitExtendedVec& hitVec = trackVec[i]->getTrackerHitExtendedVec();
+    int nHits = int(hitVec.size());
+    
+    for (int ih=0;ih<nHits;ih++) {
+      hitVec[ih]->clearTrackVec();
+    }
+  }
+  
+}
+
+void SiliconTrackingAlg::CreateTrack(TrackExtended * trackAR ) {
+  
+  /**
+   Method which creates Track out of TrackExtended objects. Checks for possible
+   track splitting (separate track segments in VXD and FTD).
+   */
+  
+  
+  TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+  int nHits = int(hitVec.size());
+  
+  for (int i=0; i<nHits; ++i) {
+    TrackExtendedVec& trackVec = hitVec[i]->getTrackExtendedVec();
+    if (trackVec.size() != 0) 
+      return ;
+  }
+  
+  // First check if the current track is piece of the split one
+  // look for matching track segment
+  
+  int found = 0;
+  
+  int nTrk = int(_trackImplVec.size());
+  
+  for (int itrk=0; itrk<nTrk; ++itrk) {
+    TrackExtended * trackOld = _trackImplVec[itrk];
+    TrackerHitExtendedVec& hitVecOld = trackOld->getTrackerHitExtendedVec();
+    
+    float phiNew = trackAR->getPhi();
+    float phiOld = trackOld->getPhi();
+    float thetaNew = M_PI_2 - atan(trackAR->getTanLambda());
+    float thetaOld = M_PI_2 - atan(trackOld->getTanLambda());
+    
+    float angle = (cos(phiNew)*cos(phiOld)+sin(phiNew)*sin(phiOld))*sin(thetaNew)*sin(thetaOld)+cos(thetaNew)*cos(thetaOld);
+    angle = acos(angle);
+    
+    if (angle < _angleCutForMerging) {
+      int nHitsOld = int(hitVecOld.size());
+      int nTotHits = nHits + nHitsOld;
+      double * xh = new double[nTotHits];
+      double * yh = new double[nTotHits];
+      float * zh = new float[nTotHits];
+      double * wrh = new double[nTotHits];
+      float * wzh = new float[nTotHits];
+      float * rh = new float[nTotHits];
+      float * ph = new float[nTotHits];
+      float par[5];
+      float epar[15];
+      float refPoint[3] = {0.,0.,0.};
+      for (int ih=0;ih<nHits;++ih) {
+	edm4hep::TrackerHit * trkHit = hitVec[ih]->getTrackerHit();
+        float rR = hitVec[ih]->getResolutionRPhi();
+        float rZ = hitVec[ih]->getResolutionZ();
+        if (int(hitVec[ih]->getTrackExtendedVec().size()) != 0)
+          debug() << "WARNING : HIT POINTS TO TRACK " << endmsg;
+        xh[ih] = trkHit->getPosition()[0];
+        yh[ih] = trkHit->getPosition()[1];
+        zh[ih] = float(trkHit->getPosition()[2]);
+        wrh[ih] = double(1.0/(rR*rR));
+        wzh[ih] = 1.0/(rZ*rZ);
+        rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih]));
+        ph[ih] = float(atan2(yh[ih],xh[ih]));
+      }      
+      for (int ih=0;ih<nHitsOld;++ih) {
+	edm4hep::TrackerHit * trkHit = hitVecOld[ih]->getTrackerHit();
+        xh[ih+nHits] = trkHit->getPosition()[0];
+        yh[ih+nHits] = trkHit->getPosition()[1];
+        zh[ih+nHits] = float(trkHit->getPosition()[2]);
+        float rR = hitVecOld[ih]->getResolutionRPhi();
+        float rZ = hitVecOld[ih]->getResolutionZ();     
+        wrh[ih+nHits] = double(1.0/(rR*rR));
+        wzh[ih+nHits] = 1.0/(rZ*rZ);
+        rh[ih+nHits] = float(sqrt(xh[ih+nHits]*xh[ih+nHits]+yh[ih+nHits]*yh[ih+nHits]));
+        ph[ih+nHits] = float(atan2(yh[ih+nHits],xh[ih+nHits]));
+        
+      }
+      int NPT = nTotHits;
+      int iopt = 2;
+      float chi2RPhi;
+      float chi2Z;
+      int ndf = 2*NPT - 5;
+      
+      _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+      par[3] = par[3]*par[0]/fabs(par[0]);
+      
+      float omega = par[0];
+      float tanlambda = par[1];
+      float phi0 = par[2];
+      float d0 = par[3];
+      float z0 = par[4];
+      
+      float eparmin[15];
+      for (int iparam=0;iparam<15;++iparam)
+        eparmin[iparam] = epar[iparam];      
+      
+      float refPointMin[3];
+      for (int ipp=0;ipp<3;++ipp)
+        refPointMin[ipp] = refPoint[ipp];
+      
+      float chi2Min = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+      chi2Min = chi2Min/float(ndf);
+      
+      float chi2MinRPhi = chi2RPhi;
+      float chi2MinZ = chi2Z;
+      
+      int iBad = -1;
+      if (chi2Min < _chi2FitCut) {
+        found = 1;
+      }
+      else { // SJA:FIXME: UH What is going on here? setting weights to 0 and refitting?
+        float * wzhOld = new float[nTotHits];
+        double * wrhOld = new double[nTotHits];
+        for (int i=0;i<nTotHits;++i) {
+          wzhOld[i] = wzh[i];
+          wrhOld[i] = wrh[i];
+        }
+        for (int i=0; i<nTotHits; ++i) {
+          for (int j=0;j<nTotHits;++j) {
+            if (i == j) {
+              wrh[j] = 0.0;
+              wzh[j] = 0.0;
+            } 
+            else {
+              wrh[j] = wrhOld[j];
+              wzh[j] = wzhOld[j];
+            }
+          }
+          
+          _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+          par[3] = par[3]*par[0]/fabs(par[0]);
+          
+          float chi2Cur = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+          chi2Cur = chi2Cur/float(ndf);
+          
+          if (chi2Cur < chi2Min) {
+            chi2Min = chi2Cur;
+            chi2MinRPhi = chi2RPhi;
+            chi2MinZ = chi2Z;
+            omega = par[0];
+            tanlambda = par[1];
+            phi0 = par[2];
+            d0 = par[3];
+            z0 = par[4];
+            for (int iparam=0;iparam<15;++iparam)
+              eparmin[iparam] = epar[iparam];
+            for (int ipp=0;ipp<3;++ipp)
+              refPointMin[ipp] = refPoint[ipp];
+            iBad = i;
+          }
+        }
+        if (chi2Min < _chi2FitCut) {
+          found = 1;
+        }
+        delete[] wzhOld;
+        delete[] wrhOld;
+      }
+      
+      // Split track is found.
+      // Attach hits belonging to the current track segment to  
+      // the track already created
+      if (found == 1) {
+        trackOld->ClearTrackerHitExtendedVec();
+        for (int i=0;i<nHits;++i) {
+          TrackerHitExtended * trkHit = hitVec[i];
+          trkHit->clearTrackVec();
+          if (i == iBad) {          
+          }
+          else {
+            trackOld->addTrackerHitExtended(trkHit);
+            trkHit->addTrackExtended( trackOld );
+          }
+        }  
+        for (int i=0;i<nHitsOld;++i) {
+          int icur = i+nHits;
+          TrackerHitExtended * trkHit = hitVecOld[i];
+          trkHit->clearTrackVec();
+          if (icur == iBad) {
+          }
+          else {
+            trackOld->addTrackerHitExtended(trkHit);
+            trkHit->addTrackExtended( trackOld );
+          }
+        }
+        trackOld->setOmega(omega);
+        trackOld->setTanLambda(tanlambda);
+        trackOld->setPhi(phi0);
+        trackOld->setD0(d0);
+        trackOld->setZ0(z0);
+        
+        //      std::cout << "Split track found " << d0 << " " << z0 << endmsg;
+        
+        // killeb:  In the original SiliconTrackingAlg this was in the NOT simple helix branch.
+        // The rest of the code uses the simple helix branch, where ndf_D is never set.
+        // In fact it has never been initialised or used anywhere. I think this line should not be executed.
+        // ndf = ndf_D;
+        
+        trackOld->setChi2(chi2Min*float(ndf));  
+        trackOld->setNDF(ndf);
+        trackOld->setCovMatrix(eparmin);
+        //      trackOld->setReferencePoint(refPointMin);
+      }
+      
+      delete[] xh;
+      delete[] yh;
+      delete[] zh;
+      delete[] wrh;
+      delete[] wzh;
+      delete[] rh;
+      delete[] ph;
+      
+    }
+    if (found == 1)
+      break;
+  }
+  
+  // Candidate is a unique track
+  // No other segments are found
+  if (found == 0 ) {
+    _trackImplVec.push_back(trackAR);
+    for (int i=0;i<nHits;++i) {
+      TrackerHitExtended * hit = hitVec[i];
+      hit->addTrackExtended( trackAR );
+    }
+  }
+  
+  
+}
+
+void SiliconTrackingAlg::AttachRemainingVTXHitsFast() {
+  
+  std::vector<TrackerHitExtendedVec> nonAttachedHits;
+  nonAttachedHits.resize(_nDivisionsInPhi*_nDivisionsInTheta);
+  std::vector<TrackExtendedVec> trackVector;
+  trackVector.resize(_nDivisionsInPhi*_nDivisionsInTheta);
+  int nTracks = int(_trackImplVec.size());
+  
+  for (int iTrk=0;iTrk<nTracks;++iTrk) {
+    TrackExtended * track = _trackImplVec[iTrk];
+    double Phi = double(track->getPhi());
+    if (Phi < 0)
+      Phi = Phi + TWOPI;
+    float tanlambda = track->getTanLambda();
+    double cosTheta = double(tanlambda/sqrt(1+tanlambda*tanlambda));
+    int iPhi = int(Phi/_dPhi);
+    int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+    int iCode = iPhi + _nDivisionsInPhi*iTheta; 
+    trackVector[iCode].push_back( track );
+  }
+  
+  for (int il=0;il<_nLayers;++il) {
+    for (int ip=0;ip<_nDivisionsInPhi;++ip) {
+      for (int it=0;it<_nDivisionsInTheta; ++it) {
+        int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it;      
+        TrackerHitExtendedVec& hitVec = _sectors[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hitExt = hitVec[iH];
+          TrackExtendedVec& trackVec = hitExt->getTrackExtendedVec();
+          if (trackVec.size()==0) {
+	    edm4hep::TrackerHit * hit = hitExt->getTrackerHit();
+            double pos[3];
+            double radius = 0;
+            for (int i=0; i<3; ++i) {
+              pos[i] = hit->getPosition()[i];
+              radius += pos[i]*pos[i];
+            }
+            radius = sqrt(radius);
+            double cosTheta = pos[2]/radius;
+            double Phi = atan2(pos[1],pos[0]);
+            if (Phi < 0.) Phi = Phi + TWOPI;
+            int iPhi = int(Phi/_dPhi);
+            int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+            iCode = iPhi + _nDivisionsInPhi*iTheta;      
+            nonAttachedHits[iCode].push_back( hitExt );
+          }
+        }
+      }
+    }
+  }
+  
+  for (int iT=0; iT<_nDivisionsInTheta; ++iT) {
+    for (int iP=0; iP<_nDivisionsInPhi; ++iP) {
+      int iCode = iP + _nDivisionsInPhi*iT; 
+      int nHits = int(nonAttachedHits[iCode].size());
+      int iT1 = iT - 1;
+      int iT2 = iT + 1; 
+      if (iT == 0) {
+        iT1 = iT;
+        iT2 = iT1 + 1;
+      }
+      if (iT == _nDivisionsInTheta - 1) {
+        iT2 = iT;
+        iT1 = iT2 - 1;
+      }
+      int iPHI[3];
+      iPHI[0] = iP - 1;
+      iPHI[1] = iP;
+      iPHI[2] = iP + 1;
+      if (iP == 0) 
+        iPHI[0] = _nDivisionsInPhi - 1;
+      if (iP == _nDivisionsInPhi - 1 )
+        iPHI[2] = 0;
+      
+      for (int ihit = 0; ihit<nHits; ++ihit) {
+        
+        TrackerHitExtended * hit = nonAttachedHits[iCode][ihit];
+        TrackExtended * trackToAttach = NULL;
+        float minDist = 1.0e+6;
+        
+        for (int iTheta = iT1; iTheta <iT2+1; ++iTheta) {
+          for (int indexP=0;indexP<3;++indexP) {
+            int iPhi = iPHI[indexP];        
+            int iCodeForTrack = iPhi + _nDivisionsInPhi*iTheta;
+            int nTrk = int(trackVector[iCodeForTrack].size());
+            for (int iTrk=0; iTrk<nTrk; ++iTrk) {         
+              TrackExtended * trackAR = trackVector[iCodeForTrack][iTrk];
+              bool consider = true;
+              if (_checkForDelta) {
+                TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+                int NHITS = int(hitVector.size());
+                for (int IHIT=0;IHIT<NHITS;++IHIT) {
+                  
+                  // Here we are trying to find if a hits are too close i.e. closer than _minDistToDelta
+		  edm4hep::TrackerHit* trkhit1 = hit->getTrackerHit();
+		  edm4hep::TrackerHit* trkhit2 = hitVector[IHIT]->getTrackerHit();                  
+                  
+                  if ( trkhit1->getCellID() == trkhit2->getCellID() ){ // i.e. they are in the same sensor
+                    float distance = 0.;
+                    for (int iC=0;iC<3;++iC) {
+                      float posFirst = float(hit->getTrackerHit()->getPosition()[iC]);
+                      float posSecond = float(hitVector[IHIT]->getTrackerHit()->getPosition()[iC]);
+                      float deltaPos = posFirst - posSecond;
+                      distance += deltaPos*deltaPos;
+                    }
+                    distance = sqrt(distance);
+                    if (distance<_minDistToDelta) {
+                      consider = false;
+                      break;
+                    }
+                  }
+                }
+              }
+              if (consider) {   
+                float phi0 = trackAR->getPhi();
+                float d0 = trackAR->getD0();
+                float z0 = trackAR->getZ0();
+                float omega = trackAR->getOmega();
+                float tanlambda = trackAR->getTanLambda();
+                HelixClass helix;
+                helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+                int layer = getLayerID(hit->getTrackerHit());
+                if (layer > _minimalLayerToAttach) {
+                  float pos[3];
+                  for (int i=0; i<3; ++i) 
+                    pos[i] = hit->getTrackerHit()->getPosition()[i];      
+                  float distance[3];
+                  float time = helix.getDistanceToPoint(pos,distance);
+                  if (time < 1.0e+10) {
+                    if (distance[2] < minDist) {
+                      minDist = distance[2];
+                      trackToAttach = trackAR;
+                    }                      
+                  }    
+                }
+              }
+            }
+          }
+        }
+        if (minDist < _minDistCutAttach && trackToAttach != NULL) {
+          int iopt = 2;
+          AttachHitToTrack(trackToAttach,hit,iopt);
+        }      
+      }
+    }
+  }
+}
+
+void SiliconTrackingAlg::AttachRemainingVTXHitsSlow() {
+  
+  TrackerHitExtendedVec nonAttachedHits;
+  nonAttachedHits.clear();
+  
+  for (int il=0;il<_nLayers;++il) {
+    for (int ip=0;ip<_nDivisionsInPhi;++ip) {
+      for (int it=0;it<_nDivisionsInTheta; ++it) {
+        int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it;      
+        TrackerHitExtendedVec& hitVec = _sectors[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          TrackExtendedVec& trackVec = hit->getTrackExtendedVec();
+          // if (trackVec.size()==0)
+          // nonAttachedHits.push_back( hit );
+          //-- allow hits that are only used in triplets to be re-attached 
+          unsigned int maxTrackSize = 0;
+          for(unsigned int itrack = 0;itrack < trackVec.size();itrack++){
+            TrackerHitExtendedVec hitVec_tmp= trackVec[itrack]->getTrackerHitExtendedVec();
+            unsigned int isize = hitVec_tmp.size();
+            if(isize>maxTrackSize)maxTrackSize = isize;
+          }     
+          if (maxTrackSize<=3) { 
+            debug() << " Add non attached hit to list: id = " << hit->getTrackerHit()->id() << endmsg;
+            nonAttachedHits.push_back( hit );
+          } 
+          
+          
+        }
+      }
+    }
+  }
+  
+  int nNotAttached = int(nonAttachedHits.size());
+  
+  int nTrk = int(_trackImplVec.size()); 
+  for (int iHit=0; iHit<nNotAttached; ++iHit) {
+    TrackerHitExtended * hit = nonAttachedHits[iHit];
+    debug() << " Try hit: id = " << hit->getTrackerHit()->id() << endmsg;
+    int layer = getLayerID( hit->getTrackerHit() );
+    if (layer > _minimalLayerToAttach) {
+      float pos[3];
+      for (int i=0; i<3; ++i) 
+        pos[i] = hit->getTrackerHit()->getPosition()[i];      
+      float minDist = 1e+10;
+      TrackExtended * trackToAttach = NULL;
+      for (int iTrk=0; iTrk<nTrk; ++iTrk) {
+        TrackExtended * trackAR = _trackImplVec[iTrk];
+        bool consider = true;
+        if (_checkForDelta) {
+          TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+          int NHITS = int(hitVector.size());
+          for (int IHIT=0;IHIT<NHITS;++IHIT) {
+            
+            // Here we are trying to find if a hits are too close i.e. closer than _minDistToDelta
+	    edm4hep::TrackerHit* trkhit1 = hit->getTrackerHit();
+	    edm4hep::TrackerHit* trkhit2 = hitVector[IHIT]->getTrackerHit();                  
+            
+            if ( trkhit1->getCellID() == trkhit2->getCellID() ){ // i.e. they are in the same sensor
+              
+              float distance = 0.;
+              for (int iC=0;iC<3;++iC) {
+                float posFirst = float(hit->getTrackerHit()->getPosition()[iC]);
+                float posSecond = float(hitVector[IHIT]->getTrackerHit()->getPosition()[iC]);
+                float deltaPos = posFirst - posSecond;
+                distance += deltaPos*deltaPos;
+              }
+              distance = sqrt(distance);
+              if (distance<_minDistToDelta) {
+                consider = false;
+                debug() << " hit: id = " << hit->getTrackerHit()->id() << " condsidered delta together with hit " << trkhit2->id() << endmsg;
+                break;
+              }
+            }       
+          }
+        }
+        if (consider) {
+          HelixClass helix;
+          float phi0 = trackAR->getPhi();
+          float d0 = trackAR->getD0();
+          float z0 = trackAR->getZ0();
+          float omega = trackAR->getOmega();
+          float tanlambda = trackAR->getTanLambda();
+          helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+          float distance[3];
+          float time = helix.getDistanceToPoint(pos,distance);
+          if (time < 1.0e+10) {
+            if (distance[2] < minDist) {
+              minDist = distance[2];
+              trackToAttach = trackAR;
+            }
+          }
+        }
+      }
+      if (minDist < _minDistCutAttach && trackToAttach != NULL) {
+        int iopt = 2;
+        debug() << " Hit: id = " << hit->getTrackerHit()->id() << " : try attachement"<< endmsg;
+        AttachHitToTrack(trackToAttach,hit,iopt);
+      } else {
+        debug() << " Hit: id = " << hit->getTrackerHit()->id() << " rejected due to distance cut of " <<_minDistCutAttach<< " min distance = "  << minDist << endmsg;
+      }      
+    }
+  }  
+}
+
+void SiliconTrackingAlg::AttachRemainingFTDHitsSlow() {
+  TrackerHitExtendedVec nonAttachedHits;
+  nonAttachedHits.clear();
+  
+  for (int iS=0;iS<2;++iS) {
+    for (unsigned int layer=0;layer<_nlayersFTD;++layer) {
+      for (int ip=0;ip<_nPhiFTD;++ip) {
+        int iCode = iS + 2*layer + 2*_nlayersFTD*ip;      
+        TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          TrackExtendedVec& trackVec = hit->getTrackExtendedVec();
+          if (trackVec.size()==0)
+            nonAttachedHits.push_back( hit );
+        }
+      }
+    }
+  }
+  
+  int nNotAttached = int(nonAttachedHits.size());
+  
+  int nTrk = int(_trackImplVec.size()); 
+  for (int iHit=0; iHit<nNotAttached; ++iHit) {
+    TrackerHitExtended * hit = nonAttachedHits[iHit];
+    float pos[3];
+    for (int i=0; i<3; ++i) 
+      pos[i] = hit->getTrackerHit()->getPosition()[i];      
+    float minDist = 1e+10;
+    TrackExtended * trackToAttach = NULL;
+    for (int iTrk=0; iTrk<nTrk; ++iTrk) {
+      TrackExtended * trackAR = _trackImplVec[iTrk];
+      bool consider = true;
+      TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+      int NHITS = int(hitVector.size());
+      
+      for (int IHIT=0;IHIT<NHITS;++IHIT) {
+        
+        // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works 
+        //        if (hit->getTrackerHit()->getType() == hitVector[IHIT]->getTrackerHit()->getType()) {
+        if (hit->getTrackerHit()->getCellID() == hitVector[IHIT]->getTrackerHit()->getCellID()) {
+          
+          consider = false;
+          break;
+        }
+      }
+      
+      
+      if (consider) {
+        HelixClass helix;
+        float phi0 = trackAR->getPhi();
+        float d0 = trackAR->getD0();
+        float z0 = trackAR->getZ0();
+        float omega = trackAR->getOmega();
+        float tanlambda = trackAR->getTanLambda();
+        if (tanlambda*float(getSideID(hit->getTrackerHit())) > 0) {
+          helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+          float distance[3];
+          float time = helix.getDistanceToPoint(pos,distance);
+          if (time < 1.0e+10) {
+            if (distance[2] < minDist) {
+              minDist = distance[2];
+              trackToAttach = trackAR;
+            }
+          }
+        }
+      }
+    }
+    if (minDist < _minDistCutAttach && trackToAttach != NULL) {
+      int iopt = 2;
+      AttachHitToTrack(trackToAttach,hit,iopt);
+    }      
+  }  
+}
+
+
+void SiliconTrackingAlg::AttachRemainingFTDHitsFast() {
+  int nTrk = _trackImplVec.size();
+  
+  for (int iTrk=0; iTrk<nTrk; ++iTrk) {
+    TrackExtended * trackAR = _trackImplVec[iTrk];
+    HelixClass helix;
+    float phi0 = trackAR->getPhi();
+    float d0 = trackAR->getD0();
+    float z0 = trackAR->getZ0();
+    float omega = trackAR->getOmega();
+    float tanlambda = trackAR->getTanLambda();
+    helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+    int iSemiSphere = 0;
+    if (tanlambda > 0) 
+      iSemiSphere = 1;
+    float ref[3];
+    for (int i=0;i<3;++i) 
+      ref[i] = helix.getReferencePoint()[i];
+    // Start loop over FTD layers
+    for (unsigned int layer=0;layer<_nlayersFTD;layer++) {
+      float ZL = _zLayerFTD[layer];
+      if (iSemiSphere == 0)
+        ZL = - ZL;
+      float point[3];
+      helix.getPointInZ(ZL,ref,point);
+      float Phi = atan2(point[1],point[0]);
+      if (Phi < 0) 
+        Phi = Phi + TWOPI;
+      int iPhi = int(Phi/_dPhiFTD);
+      float distMin = 1e+10;
+      TrackerHitExtended * attachedHit = NULL;     
+      for (int iP=iPhi-1;iP<=iPhi+1;++iP) {
+        int iPP = iP;
+        if (iP < 0) 
+          iPP = iP + _nPhiFTD;
+        if (iP >= _nPhiFTD)
+          iPP = iP - _nPhiFTD;  
+        int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPP;
+        int nHits = int(_sectorsFTD[iCode].size());
+        for (int iHit=0;iHit<nHits;++iHit) {
+          TrackerHitExtended * hit = _sectorsFTD[iCode][iHit];
+          bool consider = true;
+          TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+          int NHITS = int(hitVector.size());
+          
+          // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works 
+          for (int IHIT=0;IHIT<NHITS;++IHIT) {
+            //            if (hit->getTrackerHit()->getType() == hitVector[IHIT]->getTrackerHit()->getType()) {
+            if (hit->getTrackerHit()->getCellID() == hitVector[IHIT]->getTrackerHit()->getCellID()) {
+              consider = false;
+              break;
+            }
+          }
+          
+          
+          if (consider) {
+            float pos[3];
+            for (int i=0;i<3;++i) {
+              pos[i] = hit->getTrackerHit()->getPosition()[i];
+            }
+            float distance[3];
+            float time = helix.getDistanceToPoint(pos,distance);
+            if (time < 1.0e+10) {
+              if (distance[2] < distMin) {
+                distMin = distance[2];
+                attachedHit = hit;
+              }
+            }
+          }
+        }
+      }
+      if (distMin < _minDistCutAttach && attachedHit != NULL) {
+        int iopt = 2;
+        AttachHitToTrack(trackAR,attachedHit, iopt);
+      }
+    }
+  }
+}
+
+void SiliconTrackingAlg::TrackingInFTD() {
+
+  int nComb = int(_CombinationsFTD.size()) / 3;
+
+  for (int iComb=0;iComb<nComb;++iComb) {
+
+    int nLS[3];
+    nLS[0] = _CombinationsFTD[3*iComb];
+    nLS[1] = _CombinationsFTD[3*iComb+1];
+    nLS[2] = _CombinationsFTD[3*iComb+2];
+
+    for (int iS=0;iS<2;++iS) { // loop over +z and -z
+      
+      //      std::cout << "Combinations : " << iS << " " << nLS[0] << " " << nLS[1] << " " << nLS[2] << endmsg;
+      //      int iC = iS + 2*nLS[0];
+      //      TrackerHitExtendedVec& hitVec = _sectorsFTD[iC];
+      //      int nO = int(hitVec.size());
+      //      iC = iS + 2*nLS[1];
+      //      hitVec = _sectorsFTD[iC];
+      //      int nM = int(hitVec.size());
+      //      iC = iS + 2*nLS[2];
+      //      hitVec = _sectorsFTD[iC];
+      //      int nI = int(hitVec.size());
+      //      std::cout << nO << " " << nM << " " << nI << endmsg;
+
+      for (int ipOuter=0;ipOuter<_nPhiFTD;++ipOuter) { 
+
+        int ipMiddleLow = ipOuter - 1;
+        int ipMiddleUp  = ipOuter + 1;
+        
+        unsigned int iCodeOuter = iS + 2*nLS[0] + 2*_nlayersFTD*ipOuter;
+        
+        if( iCodeOuter >= _sectorsFTD.size()){          
+          error() << "iCodeOuter index out of range: iCodeOuter =   " << iCodeOuter << " _sectorsFTD.size() = " << _sectorsFTD.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg;
+          exit(1);
+        }
+        
+        TrackerHitExtendedVec& hitVecOuter = _sectorsFTD[iCodeOuter];
+        
+        int nOuter = int(hitVecOuter.size());
+
+        for (int iOuter=0;iOuter<nOuter;++iOuter) {
+          
+          TrackerHitExtended * hitOuter = hitVecOuter[iOuter];
+        
+          for (int ipMiddle=ipMiddleLow;ipMiddle<=ipMiddleUp;++ipMiddle) {
+            //for(int ipMiddle=0;ipMiddle<_nPhiFTD;++ipMiddle) {
+            int ipM = ipMiddle;
+            if (ipM < 0) 
+              ipM = ipMiddle + _nPhiFTD;
+            if (ipM >= _nPhiFTD)
+              ipM = ipMiddle - _nPhiFTD;
+            int iCodeMiddle = iS + 2*nLS[1] + 2*_nlayersFTD*ipM;
+          
+            TrackerHitExtendedVec& hitVecMiddle = _sectorsFTD[iCodeMiddle];
+            int ipInnerLow,ipInnerUp;       
+            ipInnerLow = ipMiddle - 1;
+            ipInnerUp =  ipMiddle + 1;
+            
+            int nMiddle = int(hitVecMiddle.size());
+            
+            for (int iMiddle=0;iMiddle<nMiddle;++iMiddle) {
+              TrackerHitExtended * hitMiddle = hitVecMiddle[iMiddle];
+              for (int ipInner=ipInnerLow;ipInner<=ipInnerUp;++ipInner) {
+                //for (int ipInner=0;ipInner<_nPhiFTD;++ipInner) {
+                int ipI = ipInner;
+                if (ipI < 0)
+                  ipI = ipInner + _nPhiFTD;
+                if (ipI >= _nPhiFTD) 
+                  ipI = ipInner - _nPhiFTD;
+                int iCodeInner = iS + 2*nLS[2] + 2*_nlayersFTD*ipI;
+                TrackerHitExtendedVec& hitVecInner = _sectorsFTD[iCodeInner];
+            
+                int nInner = int(hitVecInner.size());
+                
+                for (int iInner=0;iInner<nInner;++iInner) {
+                
+                  TrackerHitExtended * hitInner = hitVecInner[iInner];
+                  HelixClass helix;
+                  //                  std::cout << endmsg;
+                  //                  std::cout << "Outer Hit Type " << hitOuter->getTrackerHit()->getType() << " z = " << hitOuter->getTrackerHit()->getPosition()[2] 
+                  //                  << "\nMiddle Hit Type "<< hitMiddle->getTrackerHit()->getType() << " z = " << hitMiddle->getTrackerHit()->getPosition()[2]  
+                  //                  << "\nInner Hit Type "<< hitInner->getTrackerHit()->getType() << " z = " << hitInner->getTrackerHit()->getPosition()[2]  << endmsg;
+
+                  debug() << " "
+                  << std::setw(3) << ipOuter       << " "   << std::setw(3) << ipMiddle << " "      << std::setw(3) << ipInner << "       "
+                  << std::setw(3) << iS << "     "
+                  << std::setw(3) << nLS[0]     << " "   << std::setw(3) << nLS[1]   << " "      << std::setw(3) << nLS[2]  << "     "
+                  << std::setw(3) << nOuter << " : " << std::setw(3) << nMiddle << " : " << std::setw(3) << nInner << "  :: "
+                  << std::setw(3) << nOuter*nMiddle* nInner << endmsg;
+
+                  
+                  TrackExtended * trackAR = TestTriplet(hitOuter,hitMiddle,hitInner,helix);
+                  if (trackAR != NULL) {
+                    //                    std::cout << "FTD triplet found" << endmsg;
+                    int nHits = BuildTrackFTD(trackAR,nLS,iS);
+                    
+                    _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits ).push_back( trackAR );
+                  }
+                }
+              }
+            }
+          }       
+        }
+      }
+    }
+  }
+}
+
+
+int SiliconTrackingAlg::BuildTrackFTD(TrackExtended * trackAR, int * nLR, int iS) {
+  //  std::cout << "BuildTrackFTD: Layers = " << nLR[0] << " " << nLR[1] << " " << nLR[2] << endmsg;
+  
+  // initialise a helix from the track
+  HelixClass helix;
+  const float d0 = trackAR->getD0();
+  const float z0 = trackAR->getZ0();
+  const float phi0 = trackAR->getPhi();
+  const float tanlambda = trackAR->getTanLambda();
+  const float omega = trackAR->getOmega();
+  helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+  float ref[3] = {helix.getReferencePoint()[0],
+    helix.getReferencePoint()[1],
+    helix.getReferencePoint()[2]};
+  
+  for (int iL=0; iL < static_cast<int>(_nlayersFTD); ++iL) {
+    if (iL != nLR[0] && iL != nLR[1] && iL != nLR[2]) {
+      float point[3];
+      float ZL = _zLayerFTD[iL];
+      if (iS == 0) 
+        ZL = - ZL;
+      helix.getPointInZ(ZL,ref,point);
+      //      float Phi = atan2(point[1],point[0]);
+      //      int iPhi = int(Phi/_dPhiFTD);
+      float distMin = 1e+6;
+      TrackerHitExtended * attachedHit = NULL;
+      for (int ip=0;ip<=_nPhiFTD;++ip) {
+        int iP = ip;
+        if (iP < 0)
+          iP = ip + _nPhiFTD;
+        if (iP >= _nPhiFTD)
+          iP = ip - _nPhiFTD;   
+        int iCode = iS + 2*iL + 2*_nlayersFTD*iP;
+        TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+	  edm4hep::TrackerHit * trkHit = hit->getTrackerHit();
+          float pos[3];
+          for (int i=0;i<3;++i)
+            pos[i] = float(trkHit->getPosition()[i]);
+          float distance[3];
+          float time = helix.getDistanceToPoint(pos,distance);
+          if (time < 1.0e+10) {
+            if (distance[2] < distMin) {
+              distMin = distance[2];
+              attachedHit = hit;
+            }
+          }
+        }
+      }
+      //      std::cout << "Layer = " << iL << "  distMin = " << distMin << endmsg;
+      if (distMin < _minDistCutAttach && attachedHit != NULL) {
+        int iopt = 2;
+        AttachHitToTrack( trackAR, attachedHit, iopt);
+      }
+    }
+  }
+  TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+  int nH = int (hitVec.size());
+  return nH;
+}
+
+int SiliconTrackingAlg::AttachHitToTrack(TrackExtended * trackAR, TrackerHitExtended * hit, int iopt) {
+  
+  int attached = 0;
+  TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+  int nHits = int(hitVec.size());
+  
+  double * xh = new double[nHits+1];
+  double * yh = new double[nHits+1];
+  float  * zh = new float[nHits+1];
+  double * wrh = new double[nHits+1];
+  float * wzh = new float[nHits+1];
+  float * rh = new float[nHits+1];
+  float * ph = new float[nHits+1];
+  float par[5];
+  float epar[15];
+  
+  for (int i=0; i<nHits; ++i) {
+    edm4hep::TrackerHit * trkHit = hitVec[i]->getTrackerHit();
+    xh[i] = double(trkHit->getPosition()[0]);
+    yh[i] = double(trkHit->getPosition()[1]);
+    zh[i] = float(trkHit->getPosition()[2]);
+    ph[i] = float(atan2(yh[i],xh[i]));
+    rh[i] = float(sqrt(xh[i]*xh[i]+yh[i]*yh[i]));
+    float rR = hitVec[i]->getResolutionRPhi();
+    float rZ = hitVec[i]->getResolutionZ();
+    wrh[i] = double(1.0/(rR*rR));
+    wzh[i] = 1.0/(rZ*rZ);
+  }
+  
+  edm4hep::TrackerHit * trkHit = hit->getTrackerHit();
+  xh[nHits] = double(trkHit->getPosition()[0]);
+  yh[nHits] = double(trkHit->getPosition()[1]);
+  zh[nHits] = float(trkHit->getPosition()[2]);
+  ph[nHits] = float(atan2(yh[nHits],xh[nHits]));
+  rh[nHits] = float(sqrt(xh[nHits]*xh[nHits]+yh[nHits]*yh[nHits]));
+  
+  float rR = hit->getResolutionRPhi();
+  float rZ = hit->getResolutionZ();
+  wrh[nHits] = double(1.0/(rR*rR));
+  wzh[nHits] = 1.0/(rZ*rZ);
+  
+  
+  int NPT = nHits + 1;
+  
+  // SJA:FIXME the newtonian part is giving crazy results for FTD so just use iopt 2 for simply attaching hits 
+  // using SIT and VXD doesn't seem to give any problems, so make it a function parameter and let the caller decide
+  //  int iopt = 3;
+  
+  float chi2RPhi = 0 ;
+  float chi2Z = 0 ;
+  
+  
+  int error = _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+  par[3] = par[3]*par[0]/fabs(par[0]);
+  
+  
+  float omega = par[0];
+  float tanlambda = par[1];
+  float phi0 = par[2];
+  float d0 = par[3];
+  float z0 = par[4];
+  float chi2 = FLT_MAX;
+  int ndf = INT_MAX;
+  
+  if (NPT == 3) {
+    chi2 = chi2RPhi*_chi2WRPhiTriplet+chi2Z*_chi2WZTriplet;
+  }
+  if (NPT == 4) {
+    chi2 = chi2RPhi*_chi2WRPhiQuartet+chi2Z*_chi2WZQuartet;
+  }
+  if (NPT > 4) {
+    chi2 = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+  }
+  ndf = 2*NPT-5;
+  
+  
+  if ( error == 0 && chi2/float(ndf) < _chi2FitCut ) {
+    trackAR->addTrackerHitExtended(hit);
+    hit->addTrackExtended( trackAR );
+    trackAR->setChi2( chi2 );
+    trackAR->setOmega( omega );
+    trackAR->setTanLambda( tanlambda );
+    trackAR->setD0( d0 );
+    trackAR->setZ0( z0 );
+    trackAR->setPhi( phi0 );
+    trackAR->setNDF( ndf );
+    trackAR->setCovMatrix( epar );
+    attached = 1;
+    debug() << "Attachement succeeded chi2/float(ndf) = " << chi2/float(ndf) << "  cut = " <<  _chi2FitCut  << " chi2RPhi = " << chi2RPhi << " chi2Z = " << chi2Z << " error = " << error << endmsg;
+  } else {
+    debug() << "Attachement failed chi2/float(ndf) = " << chi2/float(ndf) << "  cut = " <<  _chi2FitCut  << " chi2RPhi = " << chi2RPhi << " chi2Z = " << chi2Z << " error = " << error << endmsg;
+  }
+  
+  delete[] xh;
+  delete[] yh;
+  delete[] zh;
+  delete[] wrh;
+  delete[] wzh;
+  delete[] rh;
+  delete[] ph;
+  
+  return attached;
+  
+  
+}
+
+void SiliconTrackingAlg::FinalRefit(edm4hep::TrackCollection* trk_col) {
+  
+  int nTracks = int(_trackImplVec.size());
+  
+  int nSiSegments = 0;        
+  float eTot = 0.;
+  float pxTot = 0.;
+  float pyTot = 0.;
+  float pzTot = 0.;
+  std::cout << "fucd============" << nTracks << std::endl;
+  for (int iTrk=0;iTrk<nTracks;++iTrk) {
+    
+    TrackExtended * trackAR = _trackImplVec[iTrk];    
+    TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+    
+    int nHits = int(hitVec.size());
+    std::cout << "fucd-------------" << iTrk << ": " << nHits << std::endl;
+    if( nHits >= _minimalHits) {
+      //    int * lh = new int[nHits];
+      std::vector<int> lh;
+      lh.resize(nHits);
+      
+      for (int i=0; i<nHits; ++i) {
+        lh[i]=0;
+      }
+      
+      float d0 = trackAR->getD0();
+      float z0 = trackAR->getZ0();
+      float omega = trackAR->getOmega();
+      float tanlambda = trackAR->getTanLambda();
+      float phi0 = trackAR->getPhi();
+      
+      HelixClass * helix = new HelixClass();
+      helix->Initialize_Canonical(phi0, d0, z0, omega, 
+                                  tanlambda, _bField);
+      
+      
+      // get the point of closest approach to the reference point
+      // here it is implicitly assumed that the reference point is the origin 
+      float Pos[3];
+      Pos[0] = -d0*sin(phi0);
+      Pos[1] = d0*cos(phi0);
+      Pos[2] = z0;
+      
+      std::cout << "fucd------------------1" << std::endl; 
+      // at this point is is possible to have hits from the same layer ...
+      // so a check is made to ensure that the hit with the smallest distance to the 
+      // current helix hypothosis is used, the other hit has lh set to 0 
+      
+      // start loop over the hits to
+      for (int ihit=0;ihit<nHits;++ihit) {
+        
+        lh[ihit] = 1; // only hits which have lh=1 will be used for the fit
+        
+        // get the pointer to the lcio trackerhit for this hit
+	edm4hep::TrackerHit * trkHit = hitVec[ihit]->getTrackerHit();
+        
+        int det = getDetectorID(trkHit);
+        
+        if (det == lcio::ILDDetID::VXD || det == lcio::ILDDetID::FTD || det == lcio::ILDDetID::SIT) { // only accept VXD, FTD or SIT
+          
+          
+          //        int layer = getLayerID(trkHit);
+          //        int moduleIndex = getModuleID(trkHit);
+          
+          // start a double loop over the hits which have already been checked 
+          for (int lhit=0;lhit<ihit;++lhit) {
+            
+            // get the pointer to the lcio trackerhit for the previously checked hit
+	    edm4hep::TrackerHit * trkHitS = hitVec[lhit]->getTrackerHit();
+            
+            
+            //          int layerS = getLayerID(trkHitS);
+            //          int moduleIndexS = getModuleID(trkHitS);
+            
+            // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works 
+            // if they are on the same layer and the previously checked hits has been declared good for fitting
+            //          if ((trkHitS->getType() == trkHit->getType()) && (lh[lhit] == 1)) {
+            // check if the hits have the same layer and petal number
+            //          hitVec[ihit]->
+            //          if ((layer == layerS) && (moduleIndex==moduleIndexS) && (lh[lhit] == 1)) {
+            if ( (trkHit->getCellID() == trkHitS->getCellID()) && (lh[lhit] == 1)) {
+              
+              // get the position of the hits 
+              float xP[3];
+              float xPS[3];
+              for (int iC=0;iC<3;++iC) {
+                xP[iC] = float(trkHit->getPosition()[iC]);
+                xPS[iC] = float(trkHitS->getPosition()[iC]);
+              }
+              
+              // get the intersection of the helix with the either the cylinder or plane containing the hit
+              float Point[6];
+              float PointS[6];
+              
+              if (det == lcio::ILDDetID::FTD) {
+
+                float time = helix->getPointInZ(xP[2],Pos,Point);
+                time = helix->getPointInZ(xPS[2],Pos,PointS);
+
+              } else {
+
+                float RAD = sqrt(xP[0]*xP[0]+xP[1]*xP[1]);
+                float RADS = sqrt(xPS[0]*xPS[0]+xPS[1]*xPS[1]);
+                float time = helix->getPointOnCircle(RAD,Pos,Point);
+                time = helix->getPointOnCircle(RADS,Pos,PointS);
+
+              }
+              
+              float DIST = 0;
+              float DISTS = 0;
+              
+              // get the euclidean distance between the hit and the point of intersection
+              for (int iC=0;iC<3;++iC) {
+                DIST += (Point[iC]-xP[iC])*(Point[iC]-xP[iC]);
+                DISTS += (PointS[iC]-xPS[iC])*(PointS[iC]-xPS[iC]);
+              }
+              if (DIST < DISTS) {
+                lh[lhit] = 0;
+              }
+              else {
+                lh[ihit] = 0;
+              }
+              break;
+            }
+          }
+        }
+      }
+      
+      delete helix;
+      
+      std::vector<TrackerHit*> trkHits;
+      std::vector<TrackerHit*> trkHits_used_inFit;
+      
+      int nFit = 0;
+      for (int i=0; i<nHits; ++i) {
+        // check if the hit has been rejected as being on the same layer and further from the helix lh==0
+        if (lh[i] == 1) {
+	  edm4hep::TrackerHit * trkHit = hitVec[i]->getTrackerHit();
+          nFit++;
+          if(trkHit) { 
+            trkHits.push_back(trkHit);   
+          }
+          else{
+            throw EVENT::Exception( std::string("SiliconTrackingAlg::FinalRefit: TrackerHit pointer == NULL ")  ) ;
+          }
+        }
+        else { // reject hit 
+               // SJA:FIXME missuse of type find a better way to signal rejected hits
+          hitVec[i]->setType(int(0));
+        }
+      }
+      
+      if( trkHits.size() < 3 ) {
+        debug() << "SiliconTrackingAlg::FinalRefit: Cannot fit less than 3 hits. Number of hits =  " << trkHits.size() << endmsg;
+        continue ; 
+      }
+      std::cout << "fucd------------------2" << std::endl;
+      //TrackImpl* Track = new TrackImpl ;
+      auto track = trk_col->create();
+      //fucd
+      //edm4hep::Track track;// = new edm4hep::Track;
+      std::cout << "fucd------------------3" << std::endl;
+      // setup initial dummy covariance matrix
+      //std::vector<float> covMatrix;
+      //covMatrix.resize(15);
+      std::array<float,15> covMatrix;
+
+      for (unsigned icov = 0; icov<covMatrix.size(); ++icov) {
+        covMatrix[icov] = 0;
+      }
+      
+      covMatrix[0]  = ( _initialTrackError_d0    ); //sigma_d0^2
+      covMatrix[2]  = ( _initialTrackError_phi0  ); //sigma_phi0^2
+      covMatrix[5]  = ( _initialTrackError_omega ); //sigma_omega^2
+      covMatrix[9]  = ( _initialTrackError_z0    ); //sigma_z0^2
+      covMatrix[14] = ( _initialTrackError_tanL  ); //sigma_tanl^2
+      
+      
+      std::vector< std::pair<float, edm4hep::TrackerHit*> > r2_values;
+      r2_values.reserve(trkHits.size());
+      
+      for (std::vector<edm4hep::TrackerHit*>::iterator it=trkHits.begin(); it!=trkHits.end(); ++it) {
+        edm4hep::TrackerHit* h = *it;
+        float r2 = h->getPosition()[0]*h->getPosition()[0]+h->getPosition()[1]*h->getPosition()[1];
+        r2_values.push_back(std::make_pair(r2, *it));
+      }
+      
+      sort(r2_values.begin(),r2_values.end());
+      //std::cout << "fucd------------------3" << std::endl;
+      trkHits.clear();
+      trkHits.reserve(r2_values.size());
+
+      for (std::vector< std::pair<float, edm4hep::TrackerHit*> >::iterator it=r2_values.begin(); it!=r2_values.end(); ++it) {
+        trkHits.push_back(it->second);
+      }
+      //std::cout << "fucd------------------3 " << _trksystem << std::endl;
+      //for (unsigned ihit_indx=0 ; ihit_indx < trkHits.size(); ++ihit_indx) {
+      //  std::cout << "fucd trk hit " << *trkHits[ihit_indx] << " " << trkHits[ihit_indx]->getCovMatrix()[0]
+      //		  << " " << BitSet32(trkHits[ihit_indx]->getType())[ ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] << endmsg;
+      //}
+      /*
+      auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc");
+      if ( !_trackSystemSvc ) {
+	error() << "Failed to find TrackSystemSvc ..." << endmsg;
+	return;
+      }
+      _trksystem =  _trackSystemSvc->getTrackSystem();
+
+      if( _trksystem == 0 ){
+	error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg;
+	return;
+      }
+      debug() << "_trksystem pointer " << _trksystem << endmsg;
+      
+      _trksystem->setOption( IMarlinTrkSystem::CFG::useQMS,        _MSOn ) ;
+      _trksystem->setOption( IMarlinTrkSystem::CFG::usedEdx,       _ElossOn) ;
+      _trksystem->setOption( IMarlinTrkSystem::CFG::useSmoothing,  _SmoothOn) ;
+      _trksystem->init() ;
+      */
+      bool fit_backwards = IMarlinTrack::backward;
+      
+      MarlinTrk::IMarlinTrack* marlinTrk = nullptr;
+      try{
+	marlinTrk = _trksystem->createTrack();
+      }
+      catch(...){
+	error() << "Cannot create MarlinTrack ! " << endmsg;
+	return;
+      }
+      
+      int status = 0;
+      std::cout << "fucd------------------3" << std::endl;
+      try {
+        status = MarlinTrk::createFinalisedLCIOTrack(marlinTrk, trkHits, &track, fit_backwards, covMatrix, _bField, _maxChi2PerHit);
+      } catch (...) {
+        
+        //      delete Track;
+        //      delete marlinTrk;
+        error() << "MarlinTrk::createFinalisedLCIOTrack " << endmsg;
+        throw ;
+        
+      }
+      std::cout << "fucd------------------4" << std::endl;
+      /*
+#ifdef MARLINTRK_DIAGNOSTICS_ON
+      if ( status != IMarlinTrack::success && _runMarlinTrkDiagnostics ) {        
+        void * dcv = _trksystem->getDiagnositicsPointer();
+        DiagnosticsController* dc = static_cast<DiagnosticsController*>(dcv);
+        dc->skip_current_track();
+      }        
+#endif
+      */
+      
+      std::vector<std::pair<edm4hep::TrackerHit* , double> > hits_in_fit ;  
+      std::vector<std::pair<edm4hep::TrackerHit* , double> > outliers ;
+      std::vector<edm4hep::TrackerHit*> all_hits;    
+      all_hits.reserve(300);
+      
+      marlinTrk->getHitsInFit(hits_in_fit);
+      
+      for ( unsigned ihit = 0; ihit < hits_in_fit.size(); ++ihit) {
+        all_hits.push_back(hits_in_fit[ihit].first);
+      }
+      
+      UTIL::BitField64 cellID_encoder( lcio::ILDCellID0::encoder_string ) ; 
+      
+      MarlinTrk::addHitNumbersToTrack(&track, all_hits, true, cellID_encoder);
+      
+      marlinTrk->getOutliers(outliers);
+      
+      for ( unsigned ihit = 0; ihit < outliers.size(); ++ihit) {
+        all_hits.push_back(outliers[ihit].first);
+      }
+      
+      MarlinTrk::addHitNumbersToTrack(&track, all_hits, false, cellID_encoder);
+      
+      delete marlinTrk;
+
+      int nhits_in_vxd = track.getSubDetectorHitNumbers(0);
+      int nhits_in_ftd = track.getSubDetectorHitNumbers(1);
+      int nhits_in_sit = track.getSubDetectorHitNumbers(2);
+      
+      //debug() << " Hit numbers for Track "<< track->id() << ": "
+      debug() << " Hit numbers for Track "<< iTrk <<": "
+	      << " vxd hits = " << nhits_in_vxd
+	      << " ftd hits = " << nhits_in_ftd
+	      << " sit hits = " << nhits_in_sit
+	      << endmsg;
+      
+      //if (nhits_in_vxd > 0) Track->setTypeBit( lcio::ILDDetID::VXD ) ;
+      //if (nhits_in_ftd > 0) Track->setTypeBit( lcio::ILDDetID::FTD ) ;
+      //if (nhits_in_sit > 0) Track->setTypeBit( lcio::ILDDetID::SIT ) ;
+
+      
+      
+      if( status != IMarlinTrack::success ) {       
+        
+        //delete track;
+        debug() << "SiliconTrackingAlg::FinalRefit: Track fit failed with error code " << status << " track dropped. Number of hits = "<< trkHits.size() << endmsg;       
+        continue ;
+      }
+      
+      if( track.getNdf() < 0) {       
+        //delete track;
+        debug() << "SiliconTrackingAlg::FinalRefit: Track fit returns " << track.getNdf() << " degress of freedom track dropped. Number of hits = "<< trkHits.size() << endmsg;       
+	//delete track;
+        continue ;
+      }
+      
+      //trk_col->addElement(Track);     
+      //fucd
+      //trk_col->push_back(track);
+      for(int i=0;i<track.trackStates_size();i++){
+	// 1 = lcio::EVENT::TrackState::AtIP
+	edm4hep::TrackState trkStateIP = track.getTrackStates(i);
+	if(trkStateIP.location !=1) continue;
+      /*
+      if (trkStateIP == 0) {
+        debug() << "SiliconTrackingAlg::FinalRefit: Track fit returns " << track->getNdf() << " degress of freedom track dropped. Number of hits = "<< trkHits.size() << endmsg;       
+        throw EVENT::Exception( std::string("SiliconTrackingAlg::FinalRefit: trkStateIP pointer == NULL ")  ) ;
+      }
+      */
+      // note trackAR which is of type TrackExtended, only takes fits set for ref point = 0,0,0
+	trackAR->setOmega(trkStateIP.omega);
+	trackAR->setTanLambda(trkStateIP.tanLambda);
+	trackAR->setPhi(trkStateIP.phi);
+	trackAR->setD0(trkStateIP.D0);
+	trackAR->setZ0(trkStateIP.Z0);
+	
+	float cov[15];
+	
+	for (int i = 0 ; i<15 ; ++i) {
+	  cov[i] = trkStateIP.covMatrix.operator[](i);
+	}
+      
+	trackAR->setCovMatrix(cov);
+	trackAR->setChi2(track.getChi2());
+	trackAR->setNDF(track.getNdf());
+      
+	nSiSegments++;
+      
+	HelixClass helix_final;
+      
+	helix_final.Initialize_Canonical(trkStateIP.phi,trkStateIP.D0,trkStateIP.Z0,trkStateIP.omega,trkStateIP.tanLambda,_bField);
+      
+	float trkPx = helix_final.getMomentum()[0];
+	float trkPy = helix_final.getMomentum()[1];
+	float trkPz = helix_final.getMomentum()[2];
+	float trkP = sqrt(trkPx*trkPx+trkPy*trkPy+trkPz*trkPz);
+	eTot += trkP;
+	pxTot += trkPx;
+	pyTot += trkPy;
+	pzTot += trkPz;
+      }
+    }
+  }
+  
+  debug() << "SiliconTrackingAlg -> run " << _nRun
+	  << " event " << _nEvt << endmsg;
+  debug() << "Number of Si tracks = " << nSiSegments << endmsg;
+  debug() << "Total 4-momentum of Si Tracks : E = " << std::setprecision(7) << eTot
+	  << " Px = " << pxTot
+	  << " Py = " << pyTot
+	  << " Pz = " << pzTot << endmsg;
+  
+  
+}
+
+
+StatusCode SiliconTrackingAlg::setupGearGeom(){
+  auto _gear = service<IGearSvc>("GearSvc");
+  if ( !_gear ) {
+    error() << "Failed to find GearSvc ..." << endmsg;
+    return StatusCode::FAILURE;
+  }
+  gear::GearMgr* gearMgr = _gear->getGearMgr();
+  _bField = gearMgr->getBField().at( gear::Vector3D( 0.,0.,0.)  ).z() ;
+  debug() << "Field " << _bField << endmsg;
+  //-- VXD Parameters--
+  _nLayersVTX = 0 ;
+  const gear::VXDParameters* pVXDDetMain = 0;
+  const gear::VXDLayerLayout* pVXDLayerLayout = 0;
+  
+  try{
+    
+    debug() << " filling VXD parameters from gear::SITParameters " << endmsg ;
+    
+    pVXDDetMain = &gearMgr->getVXDParameters();
+    pVXDLayerLayout = &(pVXDDetMain->getVXDLayerLayout());
+    _nLayersVTX = pVXDLayerLayout->getNLayers();
+  }
+  catch( gear::UnknownParameterException& e){
+    
+    debug() << " ### gear::VXDParameters Not Present in GEAR FILE" << endmsg ;
+    
+  }
+  
+  
+  
+  //-- SIT Parameters--
+  _nLayersSIT = 0 ;
+  const gear::ZPlanarParameters* pSITDetMain = 0;
+  const gear::ZPlanarLayerLayout* pSITLayerLayout = 0;
+  
+  try{
+    
+    debug() << " filling SIT parameters from gear::SITParameters " << endmsg ;
+    
+    pSITDetMain = &gearMgr->getSITParameters();
+    pSITLayerLayout = &(pSITDetMain->getZPlanarLayerLayout());
+    _nLayersSIT = pSITLayerLayout->getNLayers();
+    
+  }
+  catch( gear::UnknownParameterException& e){
+    
+    debug() << " ### gear::SITParameters Not Present in GEAR FILE" << endmsg ;
+    
+  }
+  
+  if( _nLayersSIT == 0 ){
+    // try the old LOI style key value pairs as defined in the SSit03 Mokka drive
+    try{
+      
+      info() << "  SiliconTrackingAlg - Simple Cylinder Based SIT using parameters defined by SSit03 Mokka driver " << endmsg ;
+      
+      // SIT
+      
+      const gear::GearParameters& pSIT = gearMgr->getGearParameters("SIT");
+      
+      const std::vector<double>& SIT_r   =  pSIT.getDoubleVals("SITLayerRadius" )  ;
+      const std::vector<double>& SIT_hl  =  pSIT.getDoubleVals("SITSupportLayerHalfLength" )  ;
+      
+      _nLayersSIT = SIT_r.size() ; 
+      
+      if (_nLayersSIT != SIT_r.size() || _nLayersSIT != SIT_hl.size()) {
+        
+        error() << "ILDSITCylinderKalDetector miss-match between DoubleVec and nlayers exit(1) called from file " << __FILE__ << " line " << __LINE__  << endmsg ;
+        exit(1);
+        
+      }
+    }
+    catch( gear::UnknownParameterException& e){
+      
+      debug() << " ### gear::SIT Parameters from as defined in SSit03 Not Present in GEAR FILE" << endmsg ;
+      
+    } 
+    
+  }
+  
+  
+  
+  //-- FTD Parameters--
+  _petalBasedFTDWithOverlaps = false;  
+  _nlayersFTD = 0;
+  
+  try{
+    
+    debug() << " filling FTD parameters from gear::FTDParameters " << endmsg ;
+    
+    const gear::FTDParameters&   pFTD      = gearMgr->getFTDParameters();
+    const gear::FTDLayerLayout&  ftdlayers = pFTD.getFTDLayerLayout() ;
+    
+    _nlayersFTD = ftdlayers.getNLayers() ;
+    
+    for (unsigned int disk=0; disk < _nlayersFTD; ++disk) {
+      
+      _zLayerFTD.push_back( ftdlayers.getSensitiveZposition(disk, 0, 1) ); // front petal even numbered
+      
+      if ( ftdlayers.getNPetals(disk) > 0) {
+        _zLayerFTD.push_back( ftdlayers.getSensitiveZposition(disk, 1, 1) );  // front petal odd numbered
+        _petalBasedFTDWithOverlaps = true;
+      }
+      
+    }
+    
+    // SJA: Here we increase the size of _nlayersFTD as we are treating the 
+    _nlayersFTD =_zLayerFTD.size() ;     
+    
+  }
+  catch( gear::UnknownParameterException& e){
+    
+    debug() << " ### gear::FTDParameters Not Present in GEAR FILE" << endmsg ;
+    
+  } 
+  
+  if( _nlayersFTD == 0 ){
+    
+    // FTD
+    try{
+      
+      info() << "  SiliconTrackingAlg - Simple Disc Based FTD using parameters defined by SFtd05 Mokka driver " << endmsg ;
+      
+      const gear::GearParameters& pFTD = gearMgr->getGearParameters("FTD");
+      
+      const std::vector<double>* pFTD_z   = NULL;
+      
+      info() << " For FTD using parameters defined by SFtd05 Mokka driver " << endmsg ;
+      
+      pFTD_z = &pFTD.getDoubleVals("FTDZCoordinate" )  ;
+      
+      _nlayersFTD = pFTD_z->size();
+      
+      for (unsigned int i = 0; i<_nlayersFTD; ++i) {
+        _zLayerFTD.push_back((*pFTD_z)[i]);
+      }
+    }
+    catch( gear::UnknownParameterException& e){
+      
+      debug() << " ### gear::FTD Parameters as defined in SFtd05 Not Present in GEAR FILE" << endmsg ;
+      
+    } 
+  }
+  return StatusCode::SUCCESS;
+}
+
+void SiliconTrackingAlg::TracksWithNHitsContainer::clear()
+{
+  for (std::vector< TrackExtendedVec >::iterator trackVecIter = _tracksNHits.begin();
+       trackVecIter < _tracksNHits.end(); trackVecIter++)
+  {
+    for (TrackExtendedVec::iterator trackIter = trackVecIter->begin();
+         trackIter < trackVecIter->end(); trackIter++)
+    {
+      delete *trackIter;
+    }
+    
+    trackVecIter->clear();
+  }
+}
+
diff --git a/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.cpp~ b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.cpp~
new file mode 100644
index 0000000000000000000000000000000000000000..5ed4f5593ae61e3124b1869bcad980f362e0ae0b
--- /dev/null
+++ b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.cpp~
@@ -0,0 +1,3088 @@
+#include "SiliconTrackingAlg.h"
+#include "GearSvc/IGearSvc.h"
+#include "EventSeeder/IEventSeeder.h"
+#include "TrackSystemSvc/ITrackSystemSvc.h"
+#include "edm4hep/MCParticle.h"
+#include "edm4hep/TrackerHit.h"
+//#include "edm4hep/TrackerHitPlane.h"
+#include "edm4hep/Track.h"
+#include "edm4hep/TrackState.h"
+
+//#include "DataHelper/ClusterExtended.h"
+//#include "DataHelper/TrackExtended.h"
+//#include "DataHelper/TrackerHitExtended.h"
+//#include "DataHelper/HelixClass.h"
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+#include <climits>
+
+#include <gear/GEAR.h>
+#include <gear/GearMgr.h>
+#include <gear/GearParameters.h>
+#include <gear/VXDLayerLayout.h>
+#include <gear/VXDParameters.h>
+#include "gear/FTDLayerLayout.h"
+#include "gear/FTDParameters.h"
+
+#include <gear/BField.h>
+
+#include <UTIL/BitField64.h>
+#include <UTIL/BitSet32.h>
+#include <UTIL/ILDConf.h>
+
+#include "TrackSystemSvc/MarlinTrkUtils.h"
+#include "TrackSystemSvc/HelixTrack.h"
+#include "TrackSystemSvc/HelixFit.h"
+#include "TrackSystemSvc/IMarlinTrack.h"
+
+//#include "TrackSystemSvc/MarlinTrkDiagnostics.h"
+//#ifdef MARLINTRK_DIAGNOSTICS_ON
+//#include "TrackSystemSvc/DiagnosticsController.h"
+//#endif
+
+//#include "MarlinCED.h"
+
+//#include "marlin/AIDAProcessor.h"
+
+//---- ROOT -----
+#include "TH1F.h"
+#include "TH2F.h"
+
+using namespace edm4hep ;
+//using namespace marlin ;
+using namespace MarlinTrk ;
+
+using std::min;
+using std::max;
+using std::abs;
+
+const int SiliconTrackingAlg::_output_track_col_quality_GOOD = 1;
+const int SiliconTrackingAlg::_output_track_col_quality_FAIR = 2;
+const int SiliconTrackingAlg::_output_track_col_quality_POOR = 3;
+
+const double SiliconTrackingAlg::TWOPI = 2*M_PI;
+
+DECLARE_COMPONENT( SiliconTrackingAlg )
+
+SiliconTrackingAlg::SiliconTrackingAlg(const std::string& name, ISvcLocator* svcLoc)
+: GaudiAlgorithm(name, svcLoc) {
+  
+  //_description = "Pattern recognition in silicon trackers";
+  
+  _fastfitter = new MarlinTrk::HelixFit();
+  
+  _encoder = new UTIL::BitField64(lcio::ILDCellID0::encoder_string);
+  
+  _petalBasedFTDWithOverlaps = false;
+  
+  // zero triplet counters
+  _ntriplets = _ntriplets_good = _ntriplets_2MCP = _ntriplets_3MCP = _ntriplets_1MCP_Bad = _ntriplets_bad = 0;
+
+  // Input Collections
+  // ^^^^^^^^^^^^^^^^^
+  declareProperty("HeaderCol", _headerColHdl);
+  declareProperty("MCParticleCollection", _inMCColHdl, "Handle of the Input MCParticle collection");
+  declareProperty("VTXHitCollection", _inVTXColHdl, "Handle of the Input VTX TrackerHits collection");
+  declareProperty("FTDPixelHitCollection", _inFTDPixelColHdl, "Handle of the Input FTD TrackerHits collection");
+  declareProperty("FTDSpacePointCollection", _inFTDSpacePointColHdl, "Handle of the Input FTD SpacePoints collection");
+  declareProperty("SITHitCollection", _inSITColHdl, "Handle of the Input SIT TrackerHits collection");
+    
+  // Output Collections
+  // ^^^^^^^^^^^^^^^^^^
+  declareProperty("SiTrackCollection", _outColHdl, "Handle of the SiTrack output collection");
+  //declareProperty("TrkHitRelCollection", _outRelColHdl, "Handle of TrackerHit Track relation collection");
+  // Steering parameters
+  // ^^^^^^^^^^^^^^^^^^^
+  
+  _output_track_col_quality = _output_track_col_quality_GOOD;
+  
+}
+
+
+
+StatusCode  SiliconTrackingAlg::initialize() { 
+  
+  _nRun = -1 ;
+  _nEvt = 0 ;
+  //printParameters() ;
+  
+  // set up the geometery needed by KalTest
+  //FIXME: for now do KalTest only - make this a steering parameter to use other fitters
+  auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc");
+  if ( !_trackSystemSvc ) {
+    error() << "Failed to find TrackSystemSvc ..." << endmsg;
+    return StatusCode::FAILURE;
+  }
+  _trksystem =  _trackSystemSvc->getTrackSystem();
+  
+  if( _trksystem == 0 ){
+    error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg;
+    return StatusCode::FAILURE;
+  }
+  
+  _trksystem->setOption( IMarlinTrkSystem::CFG::useQMS,        _MSOn ) ;
+  _trksystem->setOption( IMarlinTrkSystem::CFG::usedEdx,       _ElossOn) ;
+  _trksystem->setOption( IMarlinTrkSystem::CFG::useSmoothing,  _SmoothOn) ;
+  _trksystem->init() ;  
+  std::cout << "fucd ==============" << _trksystem << std::endl;
+#ifdef MARLINTRK_DIAGNOSTICS_ON
+  
+  void * dcv = _trksystem->getDiagnositicsPointer();
+  DiagnosticsController* dc = static_cast<DiagnosticsController*>(dcv);
+  dc->init(_MarlinTrkDiagnosticsName,_MarlinTrkDiagnosticsName, _runMarlinTrkDiagnostics);
+  
+#endif
+  
+  if(setupGearGeom()==StatusCode::FAILURE) return StatusCode::FAILURE;
+  
+  if (_useSIT == 0)
+    _nLayers = _nLayersVTX;
+  else 
+    _nLayers = _nLayersVTX + _nLayersSIT;
+  
+  // initialise the container to have separate vectors for up to _nHitsChi2 hits.
+  _tracksWithNHitsContainer.resize(_nHitsChi2);
+  
+  _dPhi = TWOPI/_nDivisionsInPhi;
+  _dTheta = 2.0/_nDivisionsInTheta;
+  _dPhiFTD = TWOPI/_nPhiFTD;
+  // I leave this for the moment, but 0.3 is c/1e9.
+  // For the cut it does not make too much of a difference
+  double cutOnR = _cutOnPt/(0.3*_bField);
+  cutOnR = 1000.*cutOnR;
+  _cutOnOmega = 1/cutOnR;
+  
+  _output_track_col_quality = 0;
+  
+  return GaudiAlgorithm::initialize();
+}
+
+StatusCode SiliconTrackingAlg::execute(){ 
+  
+  //_current_event = evt;
+  //_allHits.reserve(1000);
+
+  _output_track_col_quality = _output_track_col_quality_GOOD;
+  
+  // zero triplet counters
+  _ntriplets = _ntriplets_good = _ntriplets_2MCP = _ntriplets_3MCP = _ntriplets_1MCP_Bad = _ntriplets_bad = 0;
+  
+  // Clearing the working containers from the previous event
+  // FIXME: partly done at the end of the event, in CleanUp. Make it consistent.
+  //_tracksWithNHitsContainer.clear();
+  //_trackImplVec.clear();
+  
+  //_colTrackerHits.clear();
+  //_colNamesTrackerHits.clear();
+  //auto header = _headerColHdl.get()->at(0);
+  //int evtNo = header.getEventNumber();
+  //int runNo = header.getRunNumber();
+  //debug() << "Processing Run[" << runNo << "]::Event[" << evtNo << "]" << endmsg;
+
+  _trackImplVec.reserve(100);
+  _allHits.reserve(1000);
+
+  int successVTX = InitialiseVTX();
+  int successFTD = 0;
+  //int successFTD = InitialiseFTD();
+  if (successVTX == 1) {
+    
+    debug() << "      phi          theta        layer      nh o :   m :   i  :: o*m*i " << endmsg; 
+    
+    for (int iPhi=0; iPhi<_nDivisionsInPhi; ++iPhi) { 
+      for (int iTheta=0; iTheta<_nDivisionsInTheta;++iTheta) {
+        ProcessOneSector(iPhi,iTheta); // Process one VXD sector     
+      }
+    }
+    
+    debug() << "End of Processing VXD and SIT sectors" << endmsg;
+    
+  }
+  
+  if (successFTD == 1) {
+    debug() << "      phi          side        layer      nh o :   m :   i  :: o*m*i " << endmsg;
+    TrackingInFTD(); // Perform tracking in the FTD
+    debug() << "End of Processing FTD sectors" << endmsg;
+  }
+
+  //if(0){
+  if (successVTX == 1 || successFTD == 1) {
+    //if (successVTX == 1 ) {
+    for (int nHits = _nHitsChi2; nHits >= 3 ;// the three is hard coded, sorry.
+         // It's the minimal number to form a track
+         nHits--) {
+      Sorting( _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits ) );
+      
+    }
+    debug() <<  "End of Sorting " << endmsg;
+        
+    for (int nHits = _nHitsChi2; nHits >= 3 ;// the three is hard coded, sorry.
+         // It's the minimal number to form a track
+         nHits--) {
+      
+      TrackExtendedVec &tracksWithNHits = _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits );
+      for (TrackExtendedVec::iterator trackIter = tracksWithNHits.begin();
+           trackIter < tracksWithNHits.end(); trackIter++) {
+        CreateTrack( *trackIter );
+      }
+      debug() <<  "End of creating "<< nHits << " hits tracks " << endmsg;
+    }
+    
+    if (_attachFast == 0) {
+      if(successVTX) AttachRemainingVTXHitsSlow();
+      if(successFTD) AttachRemainingFTDHitsSlow();
+    }
+    else {
+      if(successVTX) AttachRemainingVTXHitsFast();
+      if(successFTD) AttachRemainingFTDHitsFast();
+    }
+    
+    debug() <<  "End of picking up remaining hits " << endmsg;
+
+    //edm4hep::TrackCollection* trkCol = nullptr; 
+    //edm4hep::LCRelationCollection* relCol = nullptr;
+    auto trkCol = _outColHdl.createAndPut();
+    //auto relCol = _outRelColHdl.createAndPut();
+    //std::cout << "fucd------------------" << std::endl;
+    /*
+    LCCollectionVec * trkCol = new LCCollectionVec(LCIO::TRACK);
+    // if we want to point back to the hits we need to set the flag
+    LCFlagImpl trkFlag(0) ;
+    trkFlag.setBit( LCIO::TRBIT_HITS ) ;
+    trkCol->setFlag( trkFlag.getFlag()  ) ;
+    
+    LCCollectionVec * relCol = NULL;
+    */
+    //FinalRefit(trkCol, relCol);
+    FinalRefit(trkCol);
+    //std::cout << "fucd------------------" << std::endl;
+    // set the quality of the output collection
+    switch (_output_track_col_quality) {
+
+      case _output_track_col_quality_FAIR:
+        //trkCol->parameters().setValue( "QualityCode" , "Fair"  ) ;
+        break;
+
+      case _output_track_col_quality_POOR:
+        //trkCol->parameters().setValue( "QualityCode" , "Poor"  ) ;
+        break;
+        
+      default:
+        //trkCol->parameters().setValue( "QualityCode" , "Good"  ) ;
+        break;
+    }
+    /*
+    if (_UseEventDisplay) {
+      this->drawEvent();
+    }
+    */
+  }
+  
+  // fill event based histogram
+  /*
+  if (_createDiagnosticsHistograms) {
+  
+    // triplet histos
+    _histos->fill1D(DiagnosticsHistograms::hntriplets, _ntriplets);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_good, _ntriplets_good);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_2MCP, _ntriplets_2MCP);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_3MCP, _ntriplets_3MCP);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_1MCP_Bad, _ntriplets_1MCP_Bad);
+    _histos->fill1D(DiagnosticsHistograms::hntriplets_bad, _ntriplets_bad);
+  
+  }
+  */
+  /*
+  const edm4hep::MCParticleCollection* mcCol = nullptr;
+  try{
+    mcCol =_inMCColHdl.get();
+  }
+  catch(...){
+  }
+  if(mcCol){
+    int id = 0;
+    for(auto mcP : *mcCol){
+      float pos[3];
+      float mom[3];
+      pos[0] = mcP.vertex()[0];
+      pos[1] = mcP.vertex()[1];
+      pos[2] = mcP.vertex()[2];
+      mom[0] = mcP.momentum()[0];
+      mom[1] = mcP.momentum()[1];
+      mom[2] = mcP.momentum()[2];
+      float           charge = mcP.getCharge();
+      HelixClass helix;
+      helix.Initialize_VP(pos,mom,charge,_bField);
+      float d0 = helix.getD0();
+      float z0 = helix.getZ0();
+      float omega = helix.getOmega();
+      float phi0 = helix.getPhi0();
+      float tanLambda = helix.getTanLambda();
+      std::cout <<"MCParticle: " << evtNo << " " << id << " " << sqrt(mom[0]*mom[0]+mom[1]*mom[1]) << " " << acos(mom[2]/sqrt(mom[0]*mom[0]+mom[1]*mom[1]+mom[2]*mom[2]))
+		<< " " << atan2(mom[1],mom[0])
+		<< " " << d0 << " " << phi0 << " " << omega << " " << z0 << " " << tanLambda << " " << mcP.vertex() << std::endl; 
+      id++;
+    }
+  }
+  
+  const edm4hep::TrackCollection* trkCol = nullptr;
+  try{
+    trkCol = _outColHdl.get();
+  }
+  catch(...){
+  }
+  if(trkCol){
+    int id = 0;
+    for(auto track : *trkCol){
+      int nstate = track->trackStates_size();
+      for(int i=0;i<nstate;i++){
+	edm4hep::TrackState trkState = track->getTrackStates(i);
+	if(trkState.location != 1) continue;
+	HelixClass helix_final;
+        helix_final.Initialize_Canonical(trkState.phi,trkState.D0,trkState.Z0,trkState.omega,trkState.tanLambda,_bField);
+        float trkPx = helix_final.getMomentum()[0];
+        float trkPy = helix_final.getMomentum()[1];
+	float trkPz = helix_final.getMomentum()[2];
+        float trkPt = sqrt(trkPx*trkPx+trkPy*trkPy);
+	std::cout << "Track parameter: " << evtNo << " " << id << " " << trkPt << " " << acos(trkPz/sqrt(trkPt*trkPt+trkPz*trkPz)) << " " << atan2(trkPy,trkPx)
+		  << " " << trkState.D0 << " " << trkState.phi << " " << trkState.omega << " " << trkState.Z0 << " " << trkState.tanLambda
+		  << " " << sqrt(trkState.covMatrix[0]) << " " << sqrt(trkState.covMatrix[2]) << " " << sqrt(trkState.covMatrix[5])
+		  << " " << sqrt(trkState.covMatrix[9]) << " " << sqrt(trkState.covMatrix[14]) << " " << std::endl;
+	id++;
+	break;
+      }
+    }
+  }
+  */
+  CleanUp();
+  debug() << "Event is done " << endmsg;
+  _nEvt++;
+  return StatusCode::SUCCESS;
+}
+
+
+void SiliconTrackingAlg::CleanUp() {
+  
+  _tracksWithNHitsContainer.clear();
+  
+  for (int il=0;il<_nLayers;++il) {
+    for (int ip=0;ip<_nDivisionsInPhi;++ip) {
+      for (int it=0;it<_nDivisionsInTheta; ++it) {
+        unsigned int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it;      
+        
+        if( iCode >= _sectors.size()){          
+          error() << "iCode index out of range: iCode =   " << iCode << " _sectors.size() = " << _sectors.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg;
+          continue;
+        }
+        
+        TrackerHitExtendedVec& hitVec = _sectors[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          delete hit;
+        }
+      }
+    }
+  }
+  
+  for (int iS=0;iS<2;++iS) {
+    for (unsigned int layer=0;layer<_nlayersFTD;++layer) {
+      for (int ip=0;ip<_nPhiFTD;++ip) {
+        unsigned int iCode = iS + 2*layer + 2*_nlayersFTD*ip;
+        
+        if( iCode >= _sectorsFTD.size()){
+          //error() << "iCode index out of range: iCode =   " << iCode << " _sectorsFTD.size() = " << _sectorsFTD.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg;
+          continue;
+        }
+        
+        TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          delete hit;
+        }
+      }
+    }
+  }
+  _trackImplVec.clear();
+  _allHits.clear();
+}
+
+int SiliconTrackingAlg::InitialiseFTD() {
+  
+  int success = 1;
+  
+  _nTotalFTDHits = 0;
+  _sectorsFTD.clear();
+  _sectorsFTD.resize(2*_nlayersFTD*_nPhiFTD);
+  
+  // Reading in FTD Pixel Hits Collection
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  const edm4hep::TrackerHitCollection* hitFTDPixelCol = nullptr;
+  try {
+    hitFTDPixelCol = _inFTDPixelColHdl.get();
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << _inFTDPixelColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+    success = 0;
+  }
+  
+  if(hitFTDPixelCol){
+    //LCCollection * hitCollection = evt->getCollection(_FTDPixelHitCollection.c_str());
+    
+    //_colNamesTrackerHits[hitCollection] = _FTDPixelHitCollection;    
+    // _colTrackerHits.push_back(hitCollection);
+    
+    int nelem = hitFTDPixelCol->size();
+    
+    debug() << "Number of FTD Pixel Hits = " << nelem << endmsg;
+    _nTotalFTDHits = nelem;
+    
+    //for (int ielem=0; ielem<nelem; ++ielem) {
+    for(auto hit : *hitFTDPixelCol){  
+    // edm4hep::TrackerHit* hit = hitFTDPixelCol->at(ielem);
+      
+      TrackerHitExtended * hitExt = new TrackerHitExtended( hit );
+      
+      //gear::Vector3D U(1.0,hit->getU()[1],hit->getU()[0],gear::Vector3D::spherical);
+      //gear::Vector3D V(1.0,hit->getV()[1],hit->getV()[0],gear::Vector3D::spherical);
+      gear::Vector3D U(1.0,hit.getCovMatrix()[1],hit.getCovMatrix()[0],gear::Vector3D::spherical);
+      gear::Vector3D V(1.0,hit.getCovMatrix()[4],hit.getCovMatrix()[3],gear::Vector3D::spherical);
+      gear::Vector3D Z(0.0,0.0,1.0);
+      
+      const float eps = 1.0e-07;
+      // V must be the global z axis 
+      if( fabs(V.dot(Z)) > eps ) {
+	error() << "SiliconTrackingAlg: VXD Hit measurment vectors V is not in the global X-Y plane. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+      exit(1);
+      }
+      
+      if( fabs(U.dot(Z)) > eps ) {
+	error() << "SiliconTrackingAlg: VXD Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+	exit(1);
+      }
+      
+      // SJA:FIXME Here dU and dV are almost certainly dX and dY ... should test ...
+      //double point_res_rphi = sqrt( hit->getdU()*hit->getdU() + hit->getdV()*hit->getdV() );
+      double point_res_rphi = sqrt( hit.getCovMatrix()[2]*hit.getCovMatrix()[2] + hit.getCovMatrix()[5]*hit.getCovMatrix()[5] );
+      hitExt->setResolutionRPhi( point_res_rphi );
+      
+      // SJA:FIXME why is this needed? 
+      hitExt->setResolutionZ(0.1);
+      
+      // type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+      hitExt->setType(int(INT_MAX));
+      // det is no longer used set to INT_MAX to try and catch any missuse
+      hitExt->setDet(int(INT_MAX));
+    
+      double pos[3];
+      
+      for (int i=0; i<3; ++i) {
+	pos[i] = hit.getPosition()[i];
+      }
+      
+      double Phi = atan2(pos[1],pos[0]);
+      if (Phi < 0.) Phi = Phi + TWOPI;
+      
+      // get the layer number
+      unsigned int layer = static_cast<unsigned int>(getLayerID(&hit));
+      unsigned int petalIndex = static_cast<unsigned int>(getModuleID(&hit));
+      
+      if ( _petalBasedFTDWithOverlaps == true ) {
+	
+	// as we are dealing with staggered petals we will use 2*nlayers in each directions +/- z
+	// the layers will follow the even odd numbering of the petals 
+	if ( petalIndex % 2 == 0 ) {
+	  layer = 2*layer;
+	}
+	else {
+	  layer = 2*layer + 1;
+	}
+	
+      }
+      
+      if (layer >= _nlayersFTD) {
+	error() << "SiliconTrackingAlg => fatal error in FTD : layer is outside allowed range : " << layer << " number of layers = " << _nlayersFTD <<  endmsg;
+	exit(1);
+      }
+      
+      int iPhi = int(Phi/_dPhiFTD);
+      
+      int side = getSideID(&hit);
+      int iSemiSphere = 0;
+    
+      if (side > 0) 
+	iSemiSphere = 1;
+      
+      int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPhi;
+      _sectorsFTD[iCode].push_back( hitExt );
+      
+      debug() << " FTD Pixel Hit added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iSemiSphere "  << iSemiSphere << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+    }
+  }
+  // Reading out FTD SpacePoint Collection
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  const edm4hep::TrackerHitCollection* hitFTDSpacePointCol = nullptr;
+  try {
+    hitFTDSpacePointCol = _inFTDSpacePointColHdl.get();
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << _inFTDSpacePointColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+    success = 0;
+  }
+
+  if(hitFTDSpacePointCol){
+    //LCCollection * hitCollection = evt->getCollection(_FTDSpacePointCollection.c_str());
+    
+    //_colNamesTrackerHits[hitCollection] = _FTDSpacePointCollection;
+    //_colTrackerHits.push_back(hitCollection);
+    
+    int nelem = hitFTDSpacePointCol->size();
+    
+    debug() << "Number of FTD SpacePoints = " << nelem << endmsg;
+    _nTotalFTDHits += nelem;
+    
+    //for (int ielem=0; ielem<nelem; ++ielem) {
+    for(auto hit : *hitFTDSpacePointCol){
+    //edm4hep::TrackerHit* hit =  hitFTDSpacePointCol->at(ielem);
+      
+      TrackerHitExtended * hitExt = new TrackerHitExtended(hit);
+      
+      // SJA:FIXME: fudge for now by a factor of two and ignore covariance
+      double point_res_rphi = 2 * sqrt( hit.getCovMatrix()[0] + hit.getCovMatrix()[2] );
+      
+      hitExt->setResolutionRPhi( point_res_rphi );
+      
+      // SJA:FIXME why is this needed? 
+      hitExt->setResolutionZ(0.1);
+      
+      // type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+      hitExt->setType(int(INT_MAX));
+      // det is no longer used set to INT_MAX to try and catch any missuse
+      hitExt->setDet(int(INT_MAX));
+      
+      double pos[3];
+      
+      for (int i=0; i<3; ++i) {
+        pos[i] = hit.getPosition()[i];
+      }
+      
+      double Phi = atan2(pos[1],pos[0]);
+      if (Phi < 0.) Phi = Phi + TWOPI;
+      
+      // get the layer number
+      unsigned int layer = static_cast<unsigned int>(getLayerID(&hit));
+      unsigned int petalIndex = static_cast<unsigned int>(getModuleID(&hit));
+      
+      if ( _petalBasedFTDWithOverlaps == true ) {
+        
+        // as we are dealing with staggered petals we will use 2*nlayers in each directions +/- z
+        // the layers will follow the even odd numbering of the petals 
+        if ( petalIndex % 2 == 0 ) {
+          layer = 2*layer;
+        }
+        else {
+          layer = 2*layer + 1;
+        }
+        
+      }
+      
+      if (layer >= _nlayersFTD) {
+        error() << "SiliconTrackingAlg => fatal error in FTD : layer is outside allowed range : " << layer << " number of layers = " << _nlayersFTD <<  endmsg;
+        exit(1);
+      }
+      
+      int iPhi = int(Phi/_dPhiFTD);
+      
+      int side = getSideID(&hit);
+      int iSemiSphere = 0;
+      
+      if (side > 0) 
+        iSemiSphere = 1;
+      
+      int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPhi;
+      _sectorsFTD[iCode].push_back( hitExt );
+      
+      debug() << " FTD SpacePoint Hit added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iSemiSphere "  << iSemiSphere << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+      
+    }
+  }
+  
+  for (unsigned i=0; i<_sectorsFTD.size(); ++i) {
+    int nhits = _sectorsFTD[i].size();
+    if( nhits != 0 ) debug() << " Number of Hits in FTD Sector " << i << " = " << _sectorsFTD[i].size() << endmsg;
+    if (nhits > _max_hits_per_sector) {
+      for (unsigned ihit=0; ihit<_sectorsFTD[i].size(); ++ihit) {
+        delete _sectorsFTD[i][ihit];
+      } 
+      _sectorsFTD[i].clear();
+      if( nhits != 0 ) error()  << " \n ### Number of Hits in FTD Sector " << i << " = " << nhits << " : Limit is set to " << _max_hits_per_sector << " : This sector will be dropped from track search, and QualityCode set to \"Poor\" " << endmsg;
+      
+      _output_track_col_quality = _output_track_col_quality_POOR;
+      
+    }
+    
+  }
+  debug() << "FTD initialized" << endmsg;
+  return success;
+}
+
+int SiliconTrackingAlg::InitialiseVTX() {
+  //std::cout << "fucd================" << std::endl;
+  _nTotalVTXHits = 0;
+  _nTotalSITHits = 0;
+  _sectors.clear();
+  _sectors.resize(_nLayers*_nDivisionsInPhi*_nDivisionsInTheta);
+  //std::cout << "fucd================" << std::endl;
+  int success = 1;
+  // Reading out VTX Hits Collection
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
+  const edm4hep::TrackerHitCollection* hitVTXCol = nullptr;
+  try {
+    hitVTXCol = _inVTXColHdl.get();
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << _inVTXColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+    success = 0;
+  }
+  if(hitVTXCol){
+    //LCCollection * hitCollection = evt->getCollection(_VTXHitCollection.c_str());
+    
+    //_colNamesTrackerHits[hitCollection] = _VTXHitCollection;
+    //_colTrackerHits.push_back(hitCollection);
+    //std::cout << "fucd================1" << std::endl;
+    int nelem = hitVTXCol->size();
+    //std::cout << "fucd================2" << std::endl;
+    debug() << "Number of VTX hits = " << nelem << endmsg;
+    _nTotalVTXHits = nelem;
+    
+    for (int ielem=0; ielem<nelem; ++ielem) {
+    //for(auto hit : *hitVTXCol){ 
+      edm4hep::TrackerHit hit = hitVTXCol->at(ielem);
+      //_allHits.push_back(hit);
+      //gear::Vector3D U(1.0,hit->getU()[1],hit->getU()[0],gear::Vector3D::spherical);
+      //gear::Vector3D V(1.0,hit->getV()[1],hit->getV()[0],gear::Vector3D::spherical);
+      gear::Vector3D U(1.0,hit.getCovMatrix()[1],hit.getCovMatrix()[0],gear::Vector3D::spherical);
+      gear::Vector3D V(1.0,hit.getCovMatrix()[4],hit.getCovMatrix()[3],gear::Vector3D::spherical);
+      gear::Vector3D Z(0.0,0.0,1.0);
+      //debug() << "covMatrix : " << hit->getCovMatrix()[0] << " " << hit->getCovMatrix()[1] << endmsg;
+      const float eps = 1.0e-07;
+      // V must be the global z axis 
+      if( fabs(1.0 - V.dot(Z)) > eps ) {
+        error() << "SiliconTrackingAlg: VXD Hit measurment vectors V is not equal to the global Z axis. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+        exit(1);
+      }
+      
+      if( fabs(U.dot(Z)) > eps ) {
+        error() << "SiliconTrackingAlg: VXD Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+        exit(1);
+      }
+      //std::cout << "fucd: " << &hit << " " << &_allHits.back() << std::endl;
+      //TrackerHitExtended * hitExt = new TrackerHitExtended( &_allHits.back() );
+      TrackerHitExtended * hitExt = new TrackerHitExtended(hit);
+      std::cout << "Saved TrackerHit pointer in TrackerHitExtended " << ielem << ": " << hitExt->getTrackerHit() << std::endl;
+      //std::cout << (&_allHits.back())->getPosition()[0] << " " << hit.getCovMatrix()[2] << " " << hit.getCovMatrix()[5] << std::endl;
+            
+      // SJA:FIXME: just use planar res for now
+      hitExt->setResolutionRPhi(hit.getCovMatrix()[2]);
+      hitExt->setResolutionZ(hit.getCovMatrix()[5]);
+      
+      // set type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+      hitExt->setType(int(INT_MAX));
+      // det is no longer used set to INT_MAX to try and catch any missuse
+      hitExt->setDet(int(INT_MAX));
+      
+      double pos[3];
+      double radius = 0;
+      
+      for (int i=0; i<3; ++i) {
+        pos[i] = hit.getPosition()[i];
+        radius += pos[i]*pos[i];
+      }
+      
+      radius = sqrt(radius);
+      
+      double cosTheta = pos[2]/radius;
+      double Phi = atan2(pos[1],pos[0]);
+      
+      if (Phi < 0.) Phi = Phi + TWOPI;
+      
+      // get the layer number
+      int layer = getLayerID(&hit);
+      
+      if (layer < 0 || layer >= _nLayers) {
+        error() << "SiliconTrackingAlg => fatal error in VTX : layer is outside allowed range : " << layer << endmsg;
+        exit(1);
+      }
+      
+      int iPhi = int(Phi/_dPhi);
+      int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+      int iCode = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta;      
+      _sectors[iCode].push_back( hitExt );
+      
+      debug() << " VXD Hit " <<  hit.id() << " added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iTheta "  << iTheta << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+      
+    }
+  }
+  
+  if (_useSIT > 0 ) {
+    const edm4hep::TrackerHitCollection* hitSITCol = nullptr;
+    try {
+      hitSITCol = _inSITColHdl.get();
+    }
+    catch ( GaudiException &e ) {
+      debug() << "Collection " << _inSITColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg;
+      success = 0;
+    }
+    if(hitSITCol){
+      //LCCollection *hitCollection = evt->getCollection(_SITHitCollection.c_str());
+      
+      //_colNamesTrackerHits[hitCollection] = _SITHitCollection;
+      //_colTrackerHits.push_back(hitCollection);
+      
+      int nelem = hitSITCol->size();
+      
+      debug() << "Number of SIT hits = " << nelem << endmsg;
+      _nTotalSITHits = nelem;
+      
+      //TrackerHit*          trkhit   = 0;
+      //TrackerHitPlane*     trkhit_P = 0;
+      //TrackerHitZCylinder* trkhit_C = 0;
+      
+      double drphi(NAN);
+      double dz(NAN);
+      
+      //for (int ielem=0; ielem<nelem; ++ielem) {
+      for(auto trkhit : *hitSITCol){
+        // hit could be of the following type
+        // 1) TrackerHit, either ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT or just standard TrackerHit
+        // 2) TrackerHitPlane, either 1D or 2D
+        // 3) TrackerHitZCylinder, if coming from a simple cylinder design as in the LOI
+        
+        // Establish which of these it is in the following order of likelyhood
+        //    i)   ILDTrkHitTypeBit::ONE_DIMENSIONAL (TrackerHitPlane) Should Never Happen: SpacePoints Must be Used Instead
+        //    ii)  ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT (TrackerHit)
+        //    iii) TrackerHitPlane (Two dimentional)
+        //    iv)  TrackerHitZCylinder 
+        //    v)   Must be standard TrackerHit
+        
+	//const edm4hep::TrackerHit* trkhit = hitSITCol->at(ielem);
+        
+        int layer = getLayerID(&trkhit);
+        
+        // VXD and SIT are treated as one system so SIT layers start from _nLayersVTX
+        layer = layer + _nLayersVTX;
+        
+        if (layer < 0 || layer >= _nLayers) {
+          error() << "SiliconTrackingAlg => fatal error in SIT : layer is outside allowed range : " << layer << endmsg;
+          exit(1);
+        }
+        
+        // first check that we have not been given 1D hits by mistake, as they won't work here
+        if ( UTIL::BitSet32( trkhit.getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] ) {
+          
+          error() << "SiliconTrackingAlg: SIT Hit cannot be of type UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL COMPOSITE SPACEPOINTS must be use instead. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+          exit(1);
+          
+        } 
+        // most likely case: COMPOSITE_SPACEPOINT hits formed from stereo strip hits
+        else if ( UTIL::BitSet32( trkhit.getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ) {
+          
+          // SJA:FIXME: fudge for now by a factor of two and ignore covariance
+          drphi =  2 * sqrt(trkhit.getCovMatrix()[0] + trkhit.getCovMatrix()[2]);         
+          dz    =      sqrt(trkhit.getCovMatrix()[5]);         
+          
+        } 
+        // or a PIXEL based SIT, using 2D TrackerHitPlane like the VXD above
+	// by fucd
+        //else if ( ( trkhit_P = dynamic_cast<TrackerHitPlane*>( hitCollection->getElementAt( ielem ) ) ) )  {
+	else if( UTIL::BitSet32( trkhit.getType() )[ 31 ]){
+          // first we need to check if the measurement vectors are aligned with the global coordinates 
+          //gear::Vector3D U(1.0,trkhit_P->getU()[1],trkhit_P->getU()[0],gear::Vector3D::spherical);
+          //gear::Vector3D V(1.0,trkhit_P->getV()[1],trkhit_P->getV()[0],gear::Vector3D::spherical);
+	  gear::Vector3D U(1.0,trkhit.getCovMatrix()[1],trkhit.getCovMatrix()[0],gear::Vector3D::spherical);
+	  gear::Vector3D V(1.0,trkhit.getCovMatrix()[4],trkhit.getCovMatrix()[3],gear::Vector3D::spherical);
+          gear::Vector3D Z(0.0,0.0,1.0);
+          
+          const float eps = 1.0e-07;
+          // V must be the global z axis 
+          if( fabs(1.0 - V.dot(Z)) > eps ) {
+            error() << "SiliconTrackingAlg: PIXEL SIT Hit measurment vectors V is not equal to the global Z axis. \n\n  exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+            exit(1);
+          }
+          
+          // U must be normal to the global z axis
+          if( fabs(U.dot(Z)) > eps ) {
+            error() << "SiliconTrackingAlg: PIXEL SIT Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg;
+            exit(1);
+          }
+          
+          //drphi = trkhit_P->getdU();
+          //dz    = trkhit_P->getdV();                                                 
+          drphi = trkhit.getCovMatrix()[2];
+          dz    = trkhit.getCovMatrix()[5];
+        }
+	
+        // or a simple cylindrical design, as used in the LOI      
+	/* by fucd
+        else if ( ( trkhit_C = dynamic_cast<TrackerHitZCylinder*>( hitCollection->getElementAt( ielem ) ) ) ) {
+          
+          drphi = trkhit_C->getdRPhi();
+          dz    = trkhit_C->getdZ();
+          
+        } 
+	*/
+        // this would be very unlikely, but who knows ... just an ordinary TrackerHit, which is not a COMPOSITE_SPACEPOINT
+        else {
+          
+          // SJA:FIXME: fudge for now by a factor of two and ignore covariance
+          drphi =  2 * sqrt(trkhit.getCovMatrix()[0] + trkhit.getCovMatrix()[2]);         
+          dz =     sqrt(trkhit.getCovMatrix()[5]);             
+          
+        }
+        // now that the hit type has been established carry on and create a 
+        
+        TrackerHitExtended * hitExt = new TrackerHitExtended(trkhit);
+        
+        // SJA:FIXME: just use planar res for now
+        hitExt->setResolutionRPhi(drphi);
+        hitExt->setResolutionZ(dz);
+        
+        // set type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse
+        hitExt->setType(int(INT_MAX));
+        // det is no longer used set to INT_MAX to try and catch any missuse
+        hitExt->setDet(int(INT_MAX));
+        
+        double pos[3];
+        double radius = 0;
+        
+        for (int i=0; i<3; ++i) {
+          pos[i] = trkhit.getPosition()[i];
+          radius += pos[i]*pos[i];
+        }
+        
+        radius = sqrt(radius);
+        
+        double cosTheta = pos[2]/radius;
+        double Phi = atan2(pos[1],pos[0]);
+        
+        if (Phi < 0.) Phi = Phi + TWOPI;
+        
+        int iPhi = int(Phi/_dPhi);
+        int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+        int iCode = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta;      
+        _sectors[iCode].push_back( hitExt );
+        
+        debug() << " SIT Hit " <<  trkhit.id() << " added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << "  iPhi = " << iPhi <<  " iTheta "  << iTheta << " iCode = " << iCode << "  layer = " << layer << endmsg;  
+        
+      }
+    }    
+  }
+  
+  
+  for (unsigned i=0; i<_sectors.size(); ++i) {
+    int nhits = _sectors[i].size();
+    if( nhits != 0 ) debug() << " Number of Hits in VXD/SIT Sector " << i << " = " << _sectors[i].size() << endmsg;
+    if (nhits > _max_hits_per_sector) {
+      for (unsigned ihit=0; ihit<_sectors[i].size(); ++ihit) {
+        delete _sectors[i][ihit];
+      }
+      _sectors[i].clear();
+      if( nhits != 0 ) error()  << " \n ### Number of Hits in VXD/SIT Sector " << i << " = " << nhits << " : Limit is set to " << _max_hits_per_sector << " : This sector will be dropped from track search, and QualityCode set to \"Poor\" " << endmsg;
+      
+      _output_track_col_quality = _output_track_col_quality_POOR;
+    }
+  }
+  debug() << "VXD initialized" << endmsg;
+  return success; 
+}
+
+StatusCode  SiliconTrackingAlg::finalize(){
+  
+  delete _fastfitter ; _fastfitter = 0;
+  delete _encoder ; _encoder = 0;
+  //delete _trksystem ; _trksystem = 0;
+  //delete _histos ; _histos = 0;
+  info() << "Processed " << _nEvt << " events " << endmsg;
+  return GaudiAlgorithm::finalize();
+}
+
+
+void SiliconTrackingAlg::ProcessOneSector(int iPhi, int iTheta) {
+  
+  int counter = 0 ;
+  
+  int iPhi_Up    = iPhi + 1;
+  int iPhi_Low   = iPhi - 1;
+  int iTheta_Up  = iTheta + 1; 
+  int iTheta_Low = iTheta - 1;
+  if (iTheta_Low < 0) iTheta_Low = 0;
+  if (iTheta_Up  >= _nDivisionsInTheta) iTheta_Up = _nDivisionsInTheta-1;
+  
+  int nComb = int( _Combinations.size() / 3 ); // number of triplet combinations
+                                               //  std::cout << iPhi << " " << iTheta << " " << _nEvt << endmsg;
+  int iNC = 0;
+  
+  for (int iComb=0; iComb < nComb; ++iComb) { // loop over triplets
+    
+    int nLR[3];
+    
+    for (int iS=0; iS<3; ++iS) {
+      nLR[iS] = _Combinations[iNC];
+      iNC++;
+    }    
+    
+    //std::cout << iPhi << " " << iTheta << " " << nLR[0] << " " << nLR[1] << " " << nLR[2] << " " << std::endl;
+    
+    // index of theta-phi bin of outer most layer
+    int iCode = nLR[0] + _nLayers*iPhi +  _nLayers*_nDivisionsInPhi*iTheta;
+    
+    //std::cout << "size of vector = " << _sectors.size() << " iCode = " << iCode << std::endl;
+    
+    // get the all the hits in the outer most theta-phi bin 
+    
+    TrackerHitExtendedVec& hitVecOuter =  _sectors[iCode];
+    
+    int nHitsOuter = int(hitVecOuter.size());
+    if (nHitsOuter > 0) {
+      
+      //std::cout << " " << iPhi << " " << iTheta << " " << nLR[0] << " " << nLR[1] << " " << nLR[2] << " size of vector = " << hitVecOuter.size() << std::endl;
+      
+      for (int ipMiddle=iPhi_Low; ipMiddle<iPhi_Up+1;ipMiddle++) { // loop over phi in the Middle
+        
+        for (int itMiddle=iTheta_Low; itMiddle<iTheta_Up+1;itMiddle++) { // loop over theta in the Middle 
+          
+          int iPhiMiddle = ipMiddle;
+          
+          // catch wrap-around
+          if (ipMiddle < 0) iPhiMiddle = _nDivisionsInPhi-1;          
+          if (ipMiddle >= _nDivisionsInPhi) iPhiMiddle = ipMiddle - _nDivisionsInPhi;
+          
+          // index of current theta-phi bin of middle layer
+          iCode = nLR[1] + _nLayers*iPhiMiddle +  _nLayers*_nDivisionsInPhi*itMiddle;
+          
+          // get the all the hits in the current middle theta-phi bin 
+          TrackerHitExtendedVec& hitVecMiddle = _sectors[iCode];
+          
+          int nHitsMiddle = int(hitVecMiddle.size());
+          
+          // determine which inner theta-phi bins to look in
+          
+          int iPhiLowInner = iPhi_Low;
+          int iPhiUpInner = iPhi_Up;
+          int iThetaLowInner = iTheta_Low;
+          int iThetaUpInner = iTheta_Up;        
+          
+          // test to see if this is the core bin of the current search
+          // if so, look into the neigboring bins in the inner layer
+          if (ipMiddle == iPhi && itMiddle==iTheta) { 
+            iPhiLowInner = iPhi_Low;
+            iPhiUpInner  = iPhi_Up;
+            iThetaLowInner = iTheta_Low;
+            iThetaUpInner = iTheta_Up;
+          }
+          else { 
+            int difP = abs(ipMiddle-iPhi); //  number of phi bins from core: can only be 1 or 0 due to hard coded 1 above
+            int difT = abs(itMiddle-iTheta);// number of theta bins from core: can only be 1 or 0 due to hard coded 1 above
+            int minP = min(ipMiddle,iPhi);   // min phi: core bin or current phi bin middle
+            int minT = min(itMiddle,iTheta); // min theta: core bin or current theta bin middle
+            int maxP = max(ipMiddle,iPhi);   // max phi: core bin or current phi bin middle
+            int maxT = max(itMiddle,iTheta); // max theta: core bin or current theta bin middle
+            
+            if (difP==1 && difT==1) { // if the diffence is a single bin in both phi and theta : only look in the bin adjacent to the core bin  
+              iPhiLowInner = minP;
+              iPhiUpInner = maxP;
+              iThetaLowInner = minT;
+              iThetaUpInner = maxT;
+            }
+            if (difP==0) { // must be +/-1 theta : only look in bins adjacent to the middle bin
+              iPhiLowInner = iPhi_Low;
+              iPhiUpInner  = iPhi_Up;
+              iThetaLowInner = minT;
+              iThetaUpInner = maxT;
+            }
+            if (difT==0) { // must be +/-1 phi : only look in bins adjacent to the middle bin
+              iPhiLowInner = minP;
+              iPhiUpInner  = maxP;
+              iThetaLowInner = iTheta_Low;
+              iThetaUpInner = iTheta_Up;            
+            }
+          }               
+          if (nHitsMiddle > 0) { // look into inner bins
+            
+            for (int ipInner=iPhiLowInner; ipInner<iPhiUpInner+1;ipInner++) { // loop over phi in the Inner
+              
+              for (int itInner=iThetaLowInner; itInner<iThetaUpInner+1;itInner++) { // loop over theta in the Inner 
+                
+                int iPhiInner = ipInner;
+                
+                // catch wrap-around
+                if (ipInner < 0) iPhiInner = _nDivisionsInPhi-1;
+                if (ipInner >= _nDivisionsInPhi) iPhiInner = ipInner - _nDivisionsInPhi;
+                
+                iCode = nLR[2] + _nLayers*iPhiInner +  _nLayers*_nDivisionsInPhi*itInner;
+                
+                // get hit for inner bin
+                TrackerHitExtendedVec& hitVecInner = _sectors[iCode];
+                
+                int nHitsInner = int(hitVecInner.size());
+                
+                if (nHitsInner > 0) {
+                  
+                  debug() << " " 
+                  << std::setw(3) << iPhi       << " "   << std::setw(3) << ipMiddle << " "      << std::setw(3) << ipInner << "   " 
+                  << std::setw(3) << iTheta     << " "   << std::setw(3) << itMiddle << " "      << std::setw(3) << itInner << "  " 
+                  << std::setw(3) << nLR[0]     << " "   << std::setw(3) << nLR[1]   << " "      << std::setw(3) << nLR[2]  << "     " 
+                  << std::setw(3) << nHitsOuter << " : " << std::setw(3) << nHitsMiddle << " : " << std::setw(3) << nHitsInner << "  :: " 
+                  << std::setw(3) << nHitsOuter*nHitsMiddle* nHitsInner << endmsg;
+                  
+                  // test all triplets 
+                  
+                  for (int iOuter=0; iOuter<nHitsOuter; ++iOuter) { // loop over hits in the outer sector
+                    TrackerHitExtended * outerHit = hitVecOuter[iOuter];
+                    for (int iMiddle=0;iMiddle<nHitsMiddle;iMiddle++) { // loop over hits in the middle sector
+                      TrackerHitExtended * middleHit = hitVecMiddle[iMiddle];
+                      for (int iInner=0;iInner<nHitsInner;iInner++) { // loop over hits in the inner sector
+                        TrackerHitExtended * innerHit = hitVecInner[iInner];
+                        HelixClass helix;
+			//std::cout <<"fucd++++++++++++++++++++++1" << std::endl;
+                        // test fit to triplet
+                        TrackExtended * trackAR = TestTriplet(outerHit,middleHit,innerHit,helix);
+			//std::cout <<"fucd++++++++++++++++++++++2" << std::endl;
+                        if ( trackAR != NULL ) {
+                          int nHits = BuildTrack(outerHit,middleHit,innerHit,helix,nLR[2],
+                                                 iPhiLowInner,iPhiUpInner,
+                                                 iThetaLowInner,iThetaUpInner,trackAR);
+                          
+                          _tracksWithNHitsContainer.getTracksWithNHitsVec(nHits).push_back(trackAR);
+                          
+                          counter ++ ;
+                        }
+			//std::cout <<"fucd++++++++++++++++++++++3" << std::endl;
+                      } // endloop over hits in the inner sector
+                    } // endloop over hits in the middle sector
+                  } // endloop over hits in the outer sector
+                } // endif nHitsInner > 0
+              } // endloop over theta in the Inner
+            } // endloop over phi in the Inner      
+          } // endif nHitsMiddle > 0
+        } // endloop over theta in the Middle
+      } // endloop over phi in the Middle
+    } // endif nHitsOuter > 0
+  } // endloop over triplets
+    
+  //debug() << " process one sectector theta,phi " << iTheta << ", " << iPhi << "  number of loops : " << counter << endmsg  ;
+}
+
+TrackExtended * SiliconTrackingAlg::TestTriplet(TrackerHitExtended * outerHit, 
+                                                       TrackerHitExtended * middleHit,
+                                                       TrackerHitExtended * innerHit,
+                                                       HelixClass & helix) {
+  /*
+   Methods checks if the triplet of hits satisfies helix hypothesis
+   */
+  //std::cout << "fucd================1" << std::endl;
+  // get the tracks already associated with the triplet
+  TrackExtendedVec& trackOuterVec  = outerHit->getTrackExtendedVec();
+  TrackExtendedVec& trackMiddleVec = middleHit->getTrackExtendedVec();
+  TrackExtendedVec& trackInnerVec  = innerHit->getTrackExtendedVec();
+  
+  //std::cout << "fucd================2" << std::endl;
+  // check if all the hits are already assigned to a track 
+  if ( (!trackOuterVec.empty())  && (!trackMiddleVec.empty()) && (!trackInnerVec.empty())) {
+    
+    TrackExtendedVec::const_iterator middleEndIter = trackMiddleVec.end();
+    TrackExtendedVec::const_iterator outerEndIter  = trackOuterVec.end();
+    TrackExtendedVec::const_iterator innerEndIter  = trackInnerVec.end();
+    TrackExtendedVec::const_iterator outerBeginIter  = trackOuterVec.begin();
+    TrackExtendedVec::const_iterator innerBeginIter  = trackInnerVec.begin();
+    
+    // loop over the tracks from the middle hit
+    for (TrackExtendedVec::const_iterator middleIter = trackMiddleVec.begin();
+         middleIter < middleEndIter;
+         ++middleIter) {
+      
+      // loop over the track from the outer hit
+      for (TrackExtendedVec::const_iterator outerIter = outerBeginIter;
+           outerIter < outerEndIter;
+           ++outerIter) {
+        
+        // if track from the outer and middle are not the same progress  
+        if ( *outerIter != *middleIter ) continue;
+        
+        // loop over the tracks from the inner hit
+        for (TrackExtendedVec::const_iterator innerIter = innerBeginIter;
+             innerIter < innerEndIter;
+             ++innerIter) {
+          
+          // no need to check against middle, it is idendical to outer here
+          if ( *outerIter == *innerIter ) {
+            // an existing track already contains all three hits
+            // return a null pointer
+            debug() << " TestTriplet: track " << *outerIter << " already contains all three hits: Do not create new track from these hits " << endmsg ;
+            return 0;            
+          }
+          
+        }// for inner
+      }// for outer    
+    }// for middle
+  }// if all vectors are not empty
+  //std::cout << "fucd================3" << std::endl;
+  
+  //    float dZ = FastTripletCheck(innerHit, middleHit, outerHit);
+  
+  //    if (fabs(dZ) > _minDistCutAttach)
+  //      return trackAR;    
+
+  
+  // increase triplet count
+  ++_ntriplets;
+
+  // get the hit coordinates and errors
+  double xh[3];
+  double yh[3];
+  float  zh[3];
+  double wrh[3];
+  float  wzh[3];
+  float  rh[3];
+  float  ph[3];
+  
+  float par[5];
+  float epar[15];
+  /*fucd
+  for(int i=0;i<_allHits.size();i++){
+    std::cout << &_allHits.at(i) << std::endl;
+  } 
+  */
+  // first hit
+  xh[0] = outerHit->getTrackerHit()->getPosition()[0];
+  yh[0] = outerHit->getTrackerHit()->getPosition()[1];
+  zh[0] = float(outerHit->getTrackerHit()->getPosition()[2]);
+  wrh[0] = double(1.0/(outerHit->getResolutionRPhi()*outerHit->getResolutionRPhi()));
+  wzh[0] = 1.0/(outerHit->getResolutionZ()*outerHit->getResolutionZ());
+  // second hit
+  xh[1] = middleHit->getTrackerHit()->getPosition()[0];
+  yh[1] = middleHit->getTrackerHit()->getPosition()[1];
+  zh[1] = float(middleHit->getTrackerHit()->getPosition()[2]);
+  wrh[1] = double(1.0/(middleHit->getResolutionRPhi()*middleHit->getResolutionRPhi()));
+  wzh[1] = 1.0/(middleHit->getResolutionZ()*middleHit->getResolutionZ());
+  // third hit
+  xh[2] = innerHit->getTrackerHit()->getPosition()[0];
+  yh[2] = innerHit->getTrackerHit()->getPosition()[1];
+  zh[2] = float(innerHit->getTrackerHit()->getPosition()[2]);
+  wrh[2] = double(1.0/(innerHit->getResolutionRPhi()*innerHit->getResolutionRPhi()));
+  wzh[2] = 1.0/(innerHit->getResolutionZ()*innerHit->getResolutionZ());
+  // calculate r and phi for all hits
+  for (int ih=0; ih<3; ih++) {
+    rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih]));
+    ph[ih] = atan2(yh[ih],xh[ih]);
+    if (ph[ih] < 0.) 
+      ph[ih] = TWOPI + ph[ih]; 
+  }
+  
+  int NPT = 3;
+  int iopt = 2;
+  float chi2RPhi;
+  float chi2Z;
+  
+  debug() << " TestTriplet: Use fastHelixFit " << endmsg ;  
+  
+  _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+  par[3] = par[3]*par[0]/fabs(par[0]);
+
+  // get helix parameters
+  float omega = par[0];
+  float tanlambda = par[1];
+  float phi0 = par[2];
+  float d0 = par[3];
+  float z0 = par[4];
+
+  // chi2 is weighted here by a factor for both rphi and z
+  float Chi2 = chi2RPhi*_chi2WRPhiTriplet+chi2Z*_chi2WZTriplet;
+  int ndf = 2*NPT-5;
+
+  
+  // check the truth information for the triplet
+  
+  // define these outside of the ifdef so that we don't need to keep repeating it.
+  //std::vector<TrackerHit*> hit_list;
+  //std::vector<MCParticle*> mcps_imo;
+  //std::vector<MCParticle*> mcp_s;
+  int triplet_code = 0;
+  /*  
+#ifdef MARLINTRK_DIAGNOSTICS_ON
+
+  int nmcps   = 0;
+  int nbadHits = 0;
+  
+  int layer  = 9 ;
+  int size   = 3 ;
+  int marker = 1 ;
+  int ml     = 0 ;
+  //  float helix_max_r = 0;
+  float helix_max_z = 0;
+  int color = 0;
+
+  // use the MCTruth4HitExt to get the MCPs
+  
+  hit_list.push_back(innerHit->getTrackerHit());
+  hit_list.push_back(middleHit->getTrackerHit());
+  hit_list.push_back(outerHit->getTrackerHit());
+
+  EVENT::MCParticle* mcp_i = 0;
+  EVENT::MCParticle* mcp_m = 0;
+  EVENT::MCParticle* mcp_o = 0;
+  
+  for (unsigned ihit = 0; ihit < hit_list.size(); ++ihit) {
+
+    EVENT::TrackerHit* trkhit = hit_list[ihit];
+    std::vector<MCParticle*> mcps;
+
+    MarlinTrk::getMCParticlesForTrackerHit(trkhit, mcps);
+    
+    if (mcps.size() == 1) {
+      mcps_imo.push_back(mcps[0]);
+      ++nmcps;
+    } else {
+      mcps_imo.push_back(0);
+      ++nbadHits;
+    }
+    
+  }
+    
+  mcp_i = mcps_imo[0];
+  mcp_m = mcps_imo[1];
+  mcp_o = mcps_imo[2];
+  
+  debug()
+  << "\n mcp_i = " << mcp_i
+  << "\n mcp_m = " << mcp_m
+  << "\n mcp_o = " << mcp_o
+  << endmsg;
+  
+  if( mcp_i ) {
+    mcp_s.push_back(mcp_i) ;
+  }
+    
+  if( mcp_m && mcp_m != mcp_i ) {
+    mcp_s.push_back(mcp_m);
+  }
+  
+  if( mcp_o && mcp_o != mcp_m && mcp_o != mcp_i ){
+    mcp_s.push_back(mcp_o);
+  }
+
+  nmcps = mcp_s.size();
+
+  if (_UseEventDisplay) {
+    // display this triplet and the MCPs from which it is formed
+    
+    MarlinCED::newEvent(this , _detector_model_for_drawing ) ;
+    
+    //    CEDPickingHandler &pHandler=CEDPickingHandler::getInstance();
+    //
+    //    pHandler.update(_current_event);
+    
+    for (unsigned imcp = 0; imcp < mcp_s.size(); ++imcp) {
+      
+      MCParticle* mcp = mcp_s[imcp];
+      
+      helix_max_z = fabsf(mcp->getEndpoint()[2]);
+      
+      
+      info() << "Draw MCParticle : " << *mcp <<endmsg;
+      
+      MarlinCED::add_layer_description("MCParticle_For_Fit", layer);
+      
+      MarlinCED::drawHelix( _bField , mcp->getCharge(), mcp->getVertex()[0], mcp->getVertex()[1], mcp->getVertex()[2],
+                           mcp->getMomentum()[0], mcp->getMomentum()[1], mcp->getMomentum()[2], layer , size , 0x7af774  ,
+                           0.0,  _helix_max_r ,
+                           helix_max_z, mcp->id() ) ;
+      
+    }
+    
+    const std::string  colName = "Hits_For_Fit";
+    
+    
+    size   = 10 ;
+    layer  = 11 ;
+    //    ml = marker | ( layer << CED_LAYER_SHIFT ) ;
+    
+    //ced_describe_layer( colName.c_str() ,layer);
+    MarlinCED::add_layer_description(colName, layer);
+    
+    
+    color =  0xFFFFFF;
+    
+    for(   std::vector<TrackerHit* >::const_iterator it = hit_list.begin();  it != hit_list.end() ; it++ ) {
+      
+      TrackerHit* trkhit = *it;
+      
+      ced_hit_ID(trkhit->getPosition()[0],
+                 trkhit->getPosition()[1],
+                 trkhit->getPosition()[2],
+                 marker, layer, size , color, trkhit->id() ) ;
+      
+    } // hits
+    
+  }
+  
+  if (_createDiagnosticsHistograms) {
+    
+    // if no bad hits are present triplet_code = nmcps;
+    triplet_code = nmcps + nbadHits * 3  ;
+        
+    _histos->fill1D(DiagnosticsHistograms::htriplets, triplet_code);
+    
+    double pt =  (2.99792458E-4*_bField) / omega ; // for r in mm, p in GeV and Bz in Tesla
+    
+    if (triplet_code == 1) {
+      ++_ntriplets_good;
+      _histos->fill2D(DiagnosticsHistograms::htripletChi2vPt_good, pt, Chi2 );
+      _histos->fill1D(DiagnosticsHistograms::htriplets_chi2_good, Chi2 );
+      _histos->fill1D(DiagnosticsHistograms::htriplets_pt_good, pt );
+    } else {
+
+      _histos->fill2D(DiagnosticsHistograms::htripletChi2vPt_bad, pt, Chi2);
+      _histos->fill1D(DiagnosticsHistograms::htriplets_chi2_bad, Chi2 );
+      _histos->fill1D(DiagnosticsHistograms::htriplets_pt_bad, pt );
+
+      if(triplet_code == 2) {
+        ++_ntriplets_2MCP;
+      } else if (triplet_code == 3) {
+        ++_ntriplets_3MCP;
+      } else if (triplet_code == 4) {
+        ++_ntriplets_1MCP_Bad;
+      } else {
+        ++_ntriplets_bad;
+      }
+    }
+    
+  }
+  
+#endif
+  */  
+  
+  // Check if track satisfies all conditions
+  
+  
+  //   std::cout << "Chi2/ndf = " << Chi2/float(ndf) << " , cut = " << _chi2FitCut << endmsg;
+  //   std::cout << "d0 = " << d0 << " , cut = " << _cutOnD0  << endmsg;
+  //   std::cout << "z0 = " << z0 << " , cut = " << _cutOnZ0  << endmsg;
+  //   std::cout << "omega = " << omega << " , cut = " << _cutOnOmega << endmsg;
+  
+  //  if ( Chi2/float(ndf) > _chi2FitCut || fabs(d0) > _cutOnD0 || fabs(z0) > _cutOnZ0 || fabs(omega)>_cutOnOmega)
+  // return a null pointer
+  //    return 0;
+  
+  bool failed = false;
+
+  int quality_code = triplet_code * 10 ;
+
+  if ( Chi2/float(ndf) > _chi2FitCut ) {
+    debug() << "Chi2/ndf = " << Chi2/float(ndf) << " , cut = " << _chi2FitCut << endmsg;
+    failed = true;
+    quality_code += 1;
+  } else if (fabs(d0) > _cutOnD0 ) {
+    debug() << "d0 = " << d0 << " , cut = " << _cutOnD0  << endmsg;
+    failed = true;
+    quality_code += 2;
+  } else if (fabs(z0) > _cutOnZ0 ) {
+    debug() << "z0 = " << z0 << " , cut = " << _cutOnZ0  << endmsg;
+    failed = true;
+    quality_code += 3;
+  } else if ( fabs(omega)>_cutOnOmega)  {
+    debug() << "omega = " << omega << " , cut = " << _cutOnOmega << endmsg;
+    failed = true;
+    quality_code += 4;
+  } else {
+    debug() << "Success !!!!!!!" << endmsg;
+  }
+  /*
+  if (_createDiagnosticsHistograms) _histos->fill1D(DiagnosticsHistograms::htriplets, quality_code);
+
+    if (_UseEventDisplay) {
+    drawEvent();
+  }
+  */
+  
+  if( failed ) {
+    // return a null pointer
+    return 0;
+  }
+  
+  
+  helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+  
+  TrackExtended * trackAR = new TrackExtended();
+  trackAR->addTrackerHitExtended(outerHit);
+  trackAR->addTrackerHitExtended(middleHit);
+  trackAR->addTrackerHitExtended(innerHit);
+  outerHit->addTrackExtended(trackAR);
+  middleHit->addTrackExtended(trackAR);
+  innerHit->addTrackExtended(trackAR);    
+  trackAR->setD0(d0);
+  trackAR->setZ0(z0);
+  trackAR->setPhi(phi0);
+  trackAR->setTanLambda(tanlambda);
+  trackAR->setOmega(omega);
+  trackAR->setChi2( Chi2 );
+  trackAR->setNDF( ndf );
+  trackAR->setCovMatrix(epar);
+  
+  
+  return trackAR;
+  
+}
+
+int SiliconTrackingAlg::BuildTrack(TrackerHitExtended * outerHit, 
+                                          TrackerHitExtended * middleHit,
+                                          TrackerHitExtended * innerHit,
+                                          HelixClass & helix,
+                                          int innerLayer,
+                                          int iPhiLow, int iPhiUp,
+                                          int iThetaLow, int iThetaUp, 
+                                          TrackExtended * trackAR) {
+  /**
+   Method for building up track in the VXD. Method starts from the found triplet and performs
+   sequential attachment of hits in other layers, which have hits within the search window.
+   Only searches inwards.
+   Given that we know we are now jumping over layers due to the doublet nature of the VXD, we 
+   could optimise this to look for the hits in interleaving layers as well. 
+   Currently a fast fit is being done for each additional hit, it could be more efficient to try and use kaltest?
+   
+   */
+  
+  debug() << " BuildTrack starting " << endmsg;
+  
+  for (int layer = innerLayer-1; layer>=0; layer--) { // loop over remaining layers
+    float distMin = 1.0e+20;
+    TrackerHitExtended * assignedhit = NULL;
+    //std::cout << "fucd---------------------1" << std::endl;
+    // loop over phi in the Inner region
+    for (int ipInner=iPhiLow; ipInner<iPhiUp+1;ipInner++) { 
+      
+      // loop over theta in the Inner region 
+      for (int itInner=iThetaLow; itInner<iThetaUp+1;itInner++) { 
+        
+        int iPhiInner = ipInner;
+        
+        // catch wrap-around
+        if (ipInner < 0) iPhiInner = _nDivisionsInPhi-1;
+        if (ipInner >= _nDivisionsInPhi) iPhiInner = ipInner - _nDivisionsInPhi;
+        
+        // get the index of the theta-phi bin to search
+        int iCode = layer + _nLayers*iPhiInner +  _nLayers*_nDivisionsInPhi*itInner;
+        
+        // get the hits from this bin
+        TrackerHitExtendedVec& hitVecInner = _sectors[iCode];
+        
+        int nHitsInner = int(hitVecInner.size());
+        
+        // loop over hits in the Inner sector
+        for (int iInner=0;iInner<nHitsInner;iInner++) { 
+          
+          TrackerHitExtended * currentHit = hitVecInner[iInner];
+          
+          // get the position of the hit to test
+          float pos[3];
+          float distance[3];
+          
+          for (int i=0; i<3; ++i) {
+            pos[i] = float(currentHit->getTrackerHit()->getPosition()[i]);
+          }
+          
+          // get the distance of closest approach and distance s traversed to the POCA 
+          float time = helix.getDistanceToPoint(pos,distance);    
+          
+          // sanity check on s 
+          if (time < 1.0e+10) {
+            
+            // check if this is the closest hit yet
+            if (distance[2] < distMin) { // distance[2] = sqrt( d0*d0 + z0*z0 ) 
+              
+              // if yes store hit and distance 
+              distMin = distance[2];             
+              assignedhit = currentHit;
+            }
+          }
+        } // endloop over hits in the Inner sector
+      } // endloop over theta in the Inner region 
+    } // endloop over phi in the Inner region
+    //std::cout << "fucd---------------------2" << std::endl;
+    // check if closest hit fulfills the min distance cut
+    if (distMin < _minDistCutAttach) {
+      
+      // if yes try to include it in the fit 
+      
+      TrackerHitExtendedVec& hvec = trackAR->getTrackerHitExtendedVec();
+      int  nHits = int(hvec.size());
+      double * xh = new double[nHits+1];
+      double * yh = new double[nHits+1];
+      float * zh = new float[nHits+1];
+      double * wrh = new double[nHits+1];
+      float * wzh = new float[nHits+1];
+      float * rh = new float[nHits+1];
+      float * ph = new float[nHits+1];
+      float par[5];
+      float epar[15];
+      
+      for (int ih=0;ih<nHits;++ih) {
+	edm4hep::TrackerHit * trkHit = hvec[ih]->getTrackerHit();
+        xh[ih] = trkHit->getPosition()[0];
+        yh[ih] = trkHit->getPosition()[1];
+        zh[ih] = float(trkHit->getPosition()[2]);
+        wrh[ih] = double(1.0/(hvec[ih]->getResolutionRPhi()*hvec[ih]->getResolutionRPhi()));
+        wzh[ih] = 1.0/(hvec[ih]->getResolutionZ()*hvec[ih]->getResolutionZ());
+        rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih]));
+        ph[ih] = float(atan2(yh[ih],xh[ih]));
+        if (ph[ih] < 0.) 
+          ph[ih] = TWOPI + ph[ih]; 
+      }      
+      edm4hep::TrackerHit * assignedTrkHit = assignedhit->getTrackerHit();
+      xh[nHits] = assignedTrkHit->getPosition()[0];
+      yh[nHits] = assignedTrkHit->getPosition()[1];
+      zh[nHits] = float(assignedTrkHit->getPosition()[2]);
+      rh[nHits] = float(sqrt(xh[nHits]*xh[nHits]+yh[nHits]*yh[nHits]));
+      ph[nHits] = float(atan2(yh[nHits],xh[nHits]));
+      if (ph[nHits] < 0.) 
+        ph[nHits] = TWOPI + ph[nHits]; 
+      wrh[nHits] = double(1.0/(assignedhit->getResolutionRPhi()*assignedhit->getResolutionRPhi()));
+      wzh[nHits] = 1.0/(assignedhit->getResolutionZ()*assignedhit->getResolutionZ());
+      
+      int NPT = nHits + 1;
+      int iopt = 2;
+      float chi2RPhi;
+      float chi2Z;
+      
+//      std::cout << "######## number of hits to fit with _fastfitter = " << NPT << endmsg; 
+      
+      _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+      par[3] = par[3]*par[0]/fabs(par[0]);
+      
+      
+      delete[] xh;
+      delete[] yh;
+      delete[] zh;
+      delete[] wrh;
+      delete[] wzh;
+      delete[] rh;
+      delete[] ph;
+      
+      bool validCombination = 0;
+      float Chi2 = FLT_MAX;
+      
+      if ((nHits+1) == 4) {
+        Chi2 = chi2RPhi*_chi2WRPhiQuartet+chi2Z*_chi2WZQuartet;
+      }         
+      if ((nHits+1) >= 5) {
+        Chi2 = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+      }
+      int ndf = 2*NPT-5;
+      
+      // check if this is valid combination based on the chi2/ndf
+      validCombination = Chi2/float(ndf) < _chi2FitCut;
+      
+      if ( validCombination ) {
+        // assign hit to track and track to hit, update the track parameters
+        trackAR->addTrackerHitExtended(assignedhit);
+        assignedhit->addTrackExtended(trackAR);
+        float omega = par[0];
+        float tanlambda = par[1];
+        float phi0 = par[2];
+        float d0 = par[3];
+        float z0 = par[4];
+        helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+        trackAR->setD0(d0);
+        trackAR->setZ0(z0);
+        trackAR->setPhi(phi0);
+        trackAR->setTanLambda(tanlambda);
+        trackAR->setOmega(omega);
+        trackAR->setChi2( Chi2 );
+        trackAR->setCovMatrix(epar);
+        trackAR->setNDF( ndf );
+      }
+      
+    }
+  } // endloop over remaining layers
+  //std::cout << "fucd---------------------3" << std::endl;
+  TrackerHitExtendedVec& hvec = trackAR->getTrackerHitExtendedVec();  
+  int nTotalHits = int(hvec.size());
+  
+//  std::cout << "######## number of hits to return = " << nTotalHits << endmsg; 
+  
+  return nTotalHits;
+  
+}
+
+
+void SiliconTrackingAlg::Sorting(TrackExtendedVec & trackVec) {
+  /**
+   Sorting of Track Vector in ascending order of chi2/ndf
+   */
+  
+  std::sort(trackVec.begin(), trackVec.end(), compare_TrackExtended() );
+  
+  // also clean up? what does this do here?
+  for (size_t i=0, sizeOfVector=trackVec.size(); i<sizeOfVector; ++i) {
+    
+    TrackerHitExtendedVec& hitVec = trackVec[i]->getTrackerHitExtendedVec();
+    int nHits = int(hitVec.size());
+    
+    for (int ih=0;ih<nHits;ih++) {
+      hitVec[ih]->clearTrackVec();
+    }
+  }
+  
+}
+
+void SiliconTrackingAlg::CreateTrack(TrackExtended * trackAR ) {
+  
+  /**
+   Method which creates Track out of TrackExtended objects. Checks for possible
+   track splitting (separate track segments in VXD and FTD).
+   */
+  
+  
+  TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+  int nHits = int(hitVec.size());
+  
+  for (int i=0; i<nHits; ++i) {
+    TrackExtendedVec& trackVec = hitVec[i]->getTrackExtendedVec();
+    if (trackVec.size() != 0) 
+      return ;
+  }
+  
+  // First check if the current track is piece of the split one
+  // look for matching track segment
+  
+  int found = 0;
+  
+  int nTrk = int(_trackImplVec.size());
+  
+  for (int itrk=0; itrk<nTrk; ++itrk) {
+    TrackExtended * trackOld = _trackImplVec[itrk];
+    TrackerHitExtendedVec& hitVecOld = trackOld->getTrackerHitExtendedVec();
+    
+    float phiNew = trackAR->getPhi();
+    float phiOld = trackOld->getPhi();
+    float thetaNew = M_PI_2 - atan(trackAR->getTanLambda());
+    float thetaOld = M_PI_2 - atan(trackOld->getTanLambda());
+    
+    float angle = (cos(phiNew)*cos(phiOld)+sin(phiNew)*sin(phiOld))*sin(thetaNew)*sin(thetaOld)+cos(thetaNew)*cos(thetaOld);
+    angle = acos(angle);
+    
+    if (angle < _angleCutForMerging) {
+      int nHitsOld = int(hitVecOld.size());
+      int nTotHits = nHits + nHitsOld;
+      double * xh = new double[nTotHits];
+      double * yh = new double[nTotHits];
+      float * zh = new float[nTotHits];
+      double * wrh = new double[nTotHits];
+      float * wzh = new float[nTotHits];
+      float * rh = new float[nTotHits];
+      float * ph = new float[nTotHits];
+      float par[5];
+      float epar[15];
+      float refPoint[3] = {0.,0.,0.};
+      for (int ih=0;ih<nHits;++ih) {
+	edm4hep::TrackerHit * trkHit = hitVec[ih]->getTrackerHit();
+        float rR = hitVec[ih]->getResolutionRPhi();
+        float rZ = hitVec[ih]->getResolutionZ();
+        if (int(hitVec[ih]->getTrackExtendedVec().size()) != 0)
+          debug() << "WARNING : HIT POINTS TO TRACK " << endmsg;
+        xh[ih] = trkHit->getPosition()[0];
+        yh[ih] = trkHit->getPosition()[1];
+        zh[ih] = float(trkHit->getPosition()[2]);
+        wrh[ih] = double(1.0/(rR*rR));
+        wzh[ih] = 1.0/(rZ*rZ);
+        rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih]));
+        ph[ih] = float(atan2(yh[ih],xh[ih]));
+      }      
+      for (int ih=0;ih<nHitsOld;++ih) {
+	edm4hep::TrackerHit * trkHit = hitVecOld[ih]->getTrackerHit();
+        xh[ih+nHits] = trkHit->getPosition()[0];
+        yh[ih+nHits] = trkHit->getPosition()[1];
+        zh[ih+nHits] = float(trkHit->getPosition()[2]);
+        float rR = hitVecOld[ih]->getResolutionRPhi();
+        float rZ = hitVecOld[ih]->getResolutionZ();     
+        wrh[ih+nHits] = double(1.0/(rR*rR));
+        wzh[ih+nHits] = 1.0/(rZ*rZ);
+        rh[ih+nHits] = float(sqrt(xh[ih+nHits]*xh[ih+nHits]+yh[ih+nHits]*yh[ih+nHits]));
+        ph[ih+nHits] = float(atan2(yh[ih+nHits],xh[ih+nHits]));
+        
+      }
+      int NPT = nTotHits;
+      int iopt = 2;
+      float chi2RPhi;
+      float chi2Z;
+      int ndf = 2*NPT - 5;
+      
+      _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+      par[3] = par[3]*par[0]/fabs(par[0]);
+      
+      float omega = par[0];
+      float tanlambda = par[1];
+      float phi0 = par[2];
+      float d0 = par[3];
+      float z0 = par[4];
+      
+      float eparmin[15];
+      for (int iparam=0;iparam<15;++iparam)
+        eparmin[iparam] = epar[iparam];      
+      
+      float refPointMin[3];
+      for (int ipp=0;ipp<3;++ipp)
+        refPointMin[ipp] = refPoint[ipp];
+      
+      float chi2Min = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+      chi2Min = chi2Min/float(ndf);
+      
+      float chi2MinRPhi = chi2RPhi;
+      float chi2MinZ = chi2Z;
+      
+      int iBad = -1;
+      if (chi2Min < _chi2FitCut) {
+        found = 1;
+      }
+      else { // SJA:FIXME: UH What is going on here? setting weights to 0 and refitting?
+        float * wzhOld = new float[nTotHits];
+        double * wrhOld = new double[nTotHits];
+        for (int i=0;i<nTotHits;++i) {
+          wzhOld[i] = wzh[i];
+          wrhOld[i] = wrh[i];
+        }
+        for (int i=0; i<nTotHits; ++i) {
+          for (int j=0;j<nTotHits;++j) {
+            if (i == j) {
+              wrh[j] = 0.0;
+              wzh[j] = 0.0;
+            } 
+            else {
+              wrh[j] = wrhOld[j];
+              wzh[j] = wzhOld[j];
+            }
+          }
+          
+          _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+          par[3] = par[3]*par[0]/fabs(par[0]);
+          
+          float chi2Cur = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+          chi2Cur = chi2Cur/float(ndf);
+          
+          if (chi2Cur < chi2Min) {
+            chi2Min = chi2Cur;
+            chi2MinRPhi = chi2RPhi;
+            chi2MinZ = chi2Z;
+            omega = par[0];
+            tanlambda = par[1];
+            phi0 = par[2];
+            d0 = par[3];
+            z0 = par[4];
+            for (int iparam=0;iparam<15;++iparam)
+              eparmin[iparam] = epar[iparam];
+            for (int ipp=0;ipp<3;++ipp)
+              refPointMin[ipp] = refPoint[ipp];
+            iBad = i;
+          }
+        }
+        if (chi2Min < _chi2FitCut) {
+          found = 1;
+        }
+        delete[] wzhOld;
+        delete[] wrhOld;
+      }
+      
+      // Split track is found.
+      // Attach hits belonging to the current track segment to  
+      // the track already created
+      if (found == 1) {
+        trackOld->ClearTrackerHitExtendedVec();
+        for (int i=0;i<nHits;++i) {
+          TrackerHitExtended * trkHit = hitVec[i];
+          trkHit->clearTrackVec();
+          if (i == iBad) {          
+          }
+          else {
+            trackOld->addTrackerHitExtended(trkHit);
+            trkHit->addTrackExtended( trackOld );
+          }
+        }  
+        for (int i=0;i<nHitsOld;++i) {
+          int icur = i+nHits;
+          TrackerHitExtended * trkHit = hitVecOld[i];
+          trkHit->clearTrackVec();
+          if (icur == iBad) {
+          }
+          else {
+            trackOld->addTrackerHitExtended(trkHit);
+            trkHit->addTrackExtended( trackOld );
+          }
+        }
+        trackOld->setOmega(omega);
+        trackOld->setTanLambda(tanlambda);
+        trackOld->setPhi(phi0);
+        trackOld->setD0(d0);
+        trackOld->setZ0(z0);
+        
+        //      std::cout << "Split track found " << d0 << " " << z0 << endmsg;
+        
+        // killeb:  In the original SiliconTrackingAlg this was in the NOT simple helix branch.
+        // The rest of the code uses the simple helix branch, where ndf_D is never set.
+        // In fact it has never been initialised or used anywhere. I think this line should not be executed.
+        // ndf = ndf_D;
+        
+        trackOld->setChi2(chi2Min*float(ndf));  
+        trackOld->setNDF(ndf);
+        trackOld->setCovMatrix(eparmin);
+        //      trackOld->setReferencePoint(refPointMin);
+      }
+      
+      delete[] xh;
+      delete[] yh;
+      delete[] zh;
+      delete[] wrh;
+      delete[] wzh;
+      delete[] rh;
+      delete[] ph;
+      
+    }
+    if (found == 1)
+      break;
+  }
+  
+  // Candidate is a unique track
+  // No other segments are found
+  if (found == 0 ) {
+    _trackImplVec.push_back(trackAR);
+    for (int i=0;i<nHits;++i) {
+      TrackerHitExtended * hit = hitVec[i];
+      hit->addTrackExtended( trackAR );
+    }
+  }
+  
+  
+}
+
+void SiliconTrackingAlg::AttachRemainingVTXHitsFast() {
+  
+  std::vector<TrackerHitExtendedVec> nonAttachedHits;
+  nonAttachedHits.resize(_nDivisionsInPhi*_nDivisionsInTheta);
+  std::vector<TrackExtendedVec> trackVector;
+  trackVector.resize(_nDivisionsInPhi*_nDivisionsInTheta);
+  int nTracks = int(_trackImplVec.size());
+  
+  for (int iTrk=0;iTrk<nTracks;++iTrk) {
+    TrackExtended * track = _trackImplVec[iTrk];
+    double Phi = double(track->getPhi());
+    if (Phi < 0)
+      Phi = Phi + TWOPI;
+    float tanlambda = track->getTanLambda();
+    double cosTheta = double(tanlambda/sqrt(1+tanlambda*tanlambda));
+    int iPhi = int(Phi/_dPhi);
+    int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+    int iCode = iPhi + _nDivisionsInPhi*iTheta; 
+    trackVector[iCode].push_back( track );
+  }
+  
+  for (int il=0;il<_nLayers;++il) {
+    for (int ip=0;ip<_nDivisionsInPhi;++ip) {
+      for (int it=0;it<_nDivisionsInTheta; ++it) {
+        int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it;      
+        TrackerHitExtendedVec& hitVec = _sectors[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hitExt = hitVec[iH];
+          TrackExtendedVec& trackVec = hitExt->getTrackExtendedVec();
+          if (trackVec.size()==0) {
+	    edm4hep::TrackerHit * hit = hitExt->getTrackerHit();
+            double pos[3];
+            double radius = 0;
+            for (int i=0; i<3; ++i) {
+              pos[i] = hit->getPosition()[i];
+              radius += pos[i]*pos[i];
+            }
+            radius = sqrt(radius);
+            double cosTheta = pos[2]/radius;
+            double Phi = atan2(pos[1],pos[0]);
+            if (Phi < 0.) Phi = Phi + TWOPI;
+            int iPhi = int(Phi/_dPhi);
+            int iTheta = int ((cosTheta + double(1.0))/_dTheta);
+            iCode = iPhi + _nDivisionsInPhi*iTheta;      
+            nonAttachedHits[iCode].push_back( hitExt );
+          }
+        }
+      }
+    }
+  }
+  
+  for (int iT=0; iT<_nDivisionsInTheta; ++iT) {
+    for (int iP=0; iP<_nDivisionsInPhi; ++iP) {
+      int iCode = iP + _nDivisionsInPhi*iT; 
+      int nHits = int(nonAttachedHits[iCode].size());
+      int iT1 = iT - 1;
+      int iT2 = iT + 1; 
+      if (iT == 0) {
+        iT1 = iT;
+        iT2 = iT1 + 1;
+      }
+      if (iT == _nDivisionsInTheta - 1) {
+        iT2 = iT;
+        iT1 = iT2 - 1;
+      }
+      int iPHI[3];
+      iPHI[0] = iP - 1;
+      iPHI[1] = iP;
+      iPHI[2] = iP + 1;
+      if (iP == 0) 
+        iPHI[0] = _nDivisionsInPhi - 1;
+      if (iP == _nDivisionsInPhi - 1 )
+        iPHI[2] = 0;
+      
+      for (int ihit = 0; ihit<nHits; ++ihit) {
+        
+        TrackerHitExtended * hit = nonAttachedHits[iCode][ihit];
+        TrackExtended * trackToAttach = NULL;
+        float minDist = 1.0e+6;
+        
+        for (int iTheta = iT1; iTheta <iT2+1; ++iTheta) {
+          for (int indexP=0;indexP<3;++indexP) {
+            int iPhi = iPHI[indexP];        
+            int iCodeForTrack = iPhi + _nDivisionsInPhi*iTheta;
+            int nTrk = int(trackVector[iCodeForTrack].size());
+            for (int iTrk=0; iTrk<nTrk; ++iTrk) {         
+              TrackExtended * trackAR = trackVector[iCodeForTrack][iTrk];
+              bool consider = true;
+              if (_checkForDelta) {
+                TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+                int NHITS = int(hitVector.size());
+                for (int IHIT=0;IHIT<NHITS;++IHIT) {
+                  
+                  // Here we are trying to find if a hits are too close i.e. closer than _minDistToDelta
+		  edm4hep::TrackerHit* trkhit1 = hit->getTrackerHit();
+		  edm4hep::TrackerHit* trkhit2 = hitVector[IHIT]->getTrackerHit();                  
+                  
+                  if ( trkhit1->getCellID() == trkhit2->getCellID() ){ // i.e. they are in the same sensor
+                    float distance = 0.;
+                    for (int iC=0;iC<3;++iC) {
+                      float posFirst = float(hit->getTrackerHit()->getPosition()[iC]);
+                      float posSecond = float(hitVector[IHIT]->getTrackerHit()->getPosition()[iC]);
+                      float deltaPos = posFirst - posSecond;
+                      distance += deltaPos*deltaPos;
+                    }
+                    distance = sqrt(distance);
+                    if (distance<_minDistToDelta) {
+                      consider = false;
+                      break;
+                    }
+                  }
+                }
+              }
+              if (consider) {   
+                float phi0 = trackAR->getPhi();
+                float d0 = trackAR->getD0();
+                float z0 = trackAR->getZ0();
+                float omega = trackAR->getOmega();
+                float tanlambda = trackAR->getTanLambda();
+                HelixClass helix;
+                helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+                int layer = getLayerID(hit->getTrackerHit());
+                if (layer > _minimalLayerToAttach) {
+                  float pos[3];
+                  for (int i=0; i<3; ++i) 
+                    pos[i] = hit->getTrackerHit()->getPosition()[i];      
+                  float distance[3];
+                  float time = helix.getDistanceToPoint(pos,distance);
+                  if (time < 1.0e+10) {
+                    if (distance[2] < minDist) {
+                      minDist = distance[2];
+                      trackToAttach = trackAR;
+                    }                      
+                  }    
+                }
+              }
+            }
+          }
+        }
+        if (minDist < _minDistCutAttach && trackToAttach != NULL) {
+          int iopt = 2;
+          AttachHitToTrack(trackToAttach,hit,iopt);
+        }      
+      }
+    }
+  }
+}
+
+void SiliconTrackingAlg::AttachRemainingVTXHitsSlow() {
+  
+  TrackerHitExtendedVec nonAttachedHits;
+  nonAttachedHits.clear();
+  
+  for (int il=0;il<_nLayers;++il) {
+    for (int ip=0;ip<_nDivisionsInPhi;++ip) {
+      for (int it=0;it<_nDivisionsInTheta; ++it) {
+        int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it;      
+        TrackerHitExtendedVec& hitVec = _sectors[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          TrackExtendedVec& trackVec = hit->getTrackExtendedVec();
+          // if (trackVec.size()==0)
+          // nonAttachedHits.push_back( hit );
+          //-- allow hits that are only used in triplets to be re-attached 
+          unsigned int maxTrackSize = 0;
+          for(unsigned int itrack = 0;itrack < trackVec.size();itrack++){
+            TrackerHitExtendedVec hitVec_tmp= trackVec[itrack]->getTrackerHitExtendedVec();
+            unsigned int isize = hitVec_tmp.size();
+            if(isize>maxTrackSize)maxTrackSize = isize;
+          }     
+          if (maxTrackSize<=3) { 
+            debug() << " Add non attached hit to list: id = " << hit->getTrackerHit()->id() << endmsg;
+            nonAttachedHits.push_back( hit );
+          } 
+          
+          
+        }
+      }
+    }
+  }
+  
+  int nNotAttached = int(nonAttachedHits.size());
+  
+  int nTrk = int(_trackImplVec.size()); 
+  for (int iHit=0; iHit<nNotAttached; ++iHit) {
+    TrackerHitExtended * hit = nonAttachedHits[iHit];
+    debug() << " Try hit: id = " << hit->getTrackerHit()->id() << endmsg;
+    int layer = getLayerID( hit->getTrackerHit() );
+    if (layer > _minimalLayerToAttach) {
+      float pos[3];
+      for (int i=0; i<3; ++i) 
+        pos[i] = hit->getTrackerHit()->getPosition()[i];      
+      float minDist = 1e+10;
+      TrackExtended * trackToAttach = NULL;
+      for (int iTrk=0; iTrk<nTrk; ++iTrk) {
+        TrackExtended * trackAR = _trackImplVec[iTrk];
+        bool consider = true;
+        if (_checkForDelta) {
+          TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+          int NHITS = int(hitVector.size());
+          for (int IHIT=0;IHIT<NHITS;++IHIT) {
+            
+            // Here we are trying to find if a hits are too close i.e. closer than _minDistToDelta
+	    edm4hep::TrackerHit* trkhit1 = hit->getTrackerHit();
+	    edm4hep::TrackerHit* trkhit2 = hitVector[IHIT]->getTrackerHit();                  
+            
+            if ( trkhit1->getCellID() == trkhit2->getCellID() ){ // i.e. they are in the same sensor
+              
+              float distance = 0.;
+              for (int iC=0;iC<3;++iC) {
+                float posFirst = float(hit->getTrackerHit()->getPosition()[iC]);
+                float posSecond = float(hitVector[IHIT]->getTrackerHit()->getPosition()[iC]);
+                float deltaPos = posFirst - posSecond;
+                distance += deltaPos*deltaPos;
+              }
+              distance = sqrt(distance);
+              if (distance<_minDistToDelta) {
+                consider = false;
+                debug() << " hit: id = " << hit->getTrackerHit()->id() << " condsidered delta together with hit " << trkhit2->id() << endmsg;
+                break;
+              }
+            }       
+          }
+        }
+        if (consider) {
+          HelixClass helix;
+          float phi0 = trackAR->getPhi();
+          float d0 = trackAR->getD0();
+          float z0 = trackAR->getZ0();
+          float omega = trackAR->getOmega();
+          float tanlambda = trackAR->getTanLambda();
+          helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+          float distance[3];
+          float time = helix.getDistanceToPoint(pos,distance);
+          if (time < 1.0e+10) {
+            if (distance[2] < minDist) {
+              minDist = distance[2];
+              trackToAttach = trackAR;
+            }
+          }
+        }
+      }
+      if (minDist < _minDistCutAttach && trackToAttach != NULL) {
+        int iopt = 2;
+        debug() << " Hit: id = " << hit->getTrackerHit()->id() << " : try attachement"<< endmsg;
+        AttachHitToTrack(trackToAttach,hit,iopt);
+      } else {
+        debug() << " Hit: id = " << hit->getTrackerHit()->id() << " rejected due to distance cut of " <<_minDistCutAttach<< " min distance = "  << minDist << endmsg;
+      }      
+    }
+  }  
+}
+
+void SiliconTrackingAlg::AttachRemainingFTDHitsSlow() {
+  TrackerHitExtendedVec nonAttachedHits;
+  nonAttachedHits.clear();
+  
+  for (int iS=0;iS<2;++iS) {
+    for (unsigned int layer=0;layer<_nlayersFTD;++layer) {
+      for (int ip=0;ip<_nPhiFTD;++ip) {
+        int iCode = iS + 2*layer + 2*_nlayersFTD*ip;      
+        TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+          TrackExtendedVec& trackVec = hit->getTrackExtendedVec();
+          if (trackVec.size()==0)
+            nonAttachedHits.push_back( hit );
+        }
+      }
+    }
+  }
+  
+  int nNotAttached = int(nonAttachedHits.size());
+  
+  int nTrk = int(_trackImplVec.size()); 
+  for (int iHit=0; iHit<nNotAttached; ++iHit) {
+    TrackerHitExtended * hit = nonAttachedHits[iHit];
+    float pos[3];
+    for (int i=0; i<3; ++i) 
+      pos[i] = hit->getTrackerHit()->getPosition()[i];      
+    float minDist = 1e+10;
+    TrackExtended * trackToAttach = NULL;
+    for (int iTrk=0; iTrk<nTrk; ++iTrk) {
+      TrackExtended * trackAR = _trackImplVec[iTrk];
+      bool consider = true;
+      TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+      int NHITS = int(hitVector.size());
+      
+      for (int IHIT=0;IHIT<NHITS;++IHIT) {
+        
+        // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works 
+        //        if (hit->getTrackerHit()->getType() == hitVector[IHIT]->getTrackerHit()->getType()) {
+        if (hit->getTrackerHit()->getCellID() == hitVector[IHIT]->getTrackerHit()->getCellID()) {
+          
+          consider = false;
+          break;
+        }
+      }
+      
+      
+      if (consider) {
+        HelixClass helix;
+        float phi0 = trackAR->getPhi();
+        float d0 = trackAR->getD0();
+        float z0 = trackAR->getZ0();
+        float omega = trackAR->getOmega();
+        float tanlambda = trackAR->getTanLambda();
+        if (tanlambda*float(getSideID(hit->getTrackerHit())) > 0) {
+          helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+          float distance[3];
+          float time = helix.getDistanceToPoint(pos,distance);
+          if (time < 1.0e+10) {
+            if (distance[2] < minDist) {
+              minDist = distance[2];
+              trackToAttach = trackAR;
+            }
+          }
+        }
+      }
+    }
+    if (minDist < _minDistCutAttach && trackToAttach != NULL) {
+      int iopt = 2;
+      AttachHitToTrack(trackToAttach,hit,iopt);
+    }      
+  }  
+}
+
+
+void SiliconTrackingAlg::AttachRemainingFTDHitsFast() {
+  int nTrk = _trackImplVec.size();
+  
+  for (int iTrk=0; iTrk<nTrk; ++iTrk) {
+    TrackExtended * trackAR = _trackImplVec[iTrk];
+    HelixClass helix;
+    float phi0 = trackAR->getPhi();
+    float d0 = trackAR->getD0();
+    float z0 = trackAR->getZ0();
+    float omega = trackAR->getOmega();
+    float tanlambda = trackAR->getTanLambda();
+    helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+    int iSemiSphere = 0;
+    if (tanlambda > 0) 
+      iSemiSphere = 1;
+    float ref[3];
+    for (int i=0;i<3;++i) 
+      ref[i] = helix.getReferencePoint()[i];
+    // Start loop over FTD layers
+    for (unsigned int layer=0;layer<_nlayersFTD;layer++) {
+      float ZL = _zLayerFTD[layer];
+      if (iSemiSphere == 0)
+        ZL = - ZL;
+      float point[3];
+      helix.getPointInZ(ZL,ref,point);
+      float Phi = atan2(point[1],point[0]);
+      if (Phi < 0) 
+        Phi = Phi + TWOPI;
+      int iPhi = int(Phi/_dPhiFTD);
+      float distMin = 1e+10;
+      TrackerHitExtended * attachedHit = NULL;     
+      for (int iP=iPhi-1;iP<=iPhi+1;++iP) {
+        int iPP = iP;
+        if (iP < 0) 
+          iPP = iP + _nPhiFTD;
+        if (iP >= _nPhiFTD)
+          iPP = iP - _nPhiFTD;  
+        int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPP;
+        int nHits = int(_sectorsFTD[iCode].size());
+        for (int iHit=0;iHit<nHits;++iHit) {
+          TrackerHitExtended * hit = _sectorsFTD[iCode][iHit];
+          bool consider = true;
+          TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec();
+          int NHITS = int(hitVector.size());
+          
+          // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works 
+          for (int IHIT=0;IHIT<NHITS;++IHIT) {
+            //            if (hit->getTrackerHit()->getType() == hitVector[IHIT]->getTrackerHit()->getType()) {
+            if (hit->getTrackerHit()->getCellID() == hitVector[IHIT]->getTrackerHit()->getCellID()) {
+              consider = false;
+              break;
+            }
+          }
+          
+          
+          if (consider) {
+            float pos[3];
+            for (int i=0;i<3;++i) {
+              pos[i] = hit->getTrackerHit()->getPosition()[i];
+            }
+            float distance[3];
+            float time = helix.getDistanceToPoint(pos,distance);
+            if (time < 1.0e+10) {
+              if (distance[2] < distMin) {
+                distMin = distance[2];
+                attachedHit = hit;
+              }
+            }
+          }
+        }
+      }
+      if (distMin < _minDistCutAttach && attachedHit != NULL) {
+        int iopt = 2;
+        AttachHitToTrack(trackAR,attachedHit, iopt);
+      }
+    }
+  }
+}
+
+void SiliconTrackingAlg::TrackingInFTD() {
+
+  int nComb = int(_CombinationsFTD.size()) / 3;
+
+  for (int iComb=0;iComb<nComb;++iComb) {
+
+    int nLS[3];
+    nLS[0] = _CombinationsFTD[3*iComb];
+    nLS[1] = _CombinationsFTD[3*iComb+1];
+    nLS[2] = _CombinationsFTD[3*iComb+2];
+
+    for (int iS=0;iS<2;++iS) { // loop over +z and -z
+      
+      //      std::cout << "Combinations : " << iS << " " << nLS[0] << " " << nLS[1] << " " << nLS[2] << endmsg;
+      //      int iC = iS + 2*nLS[0];
+      //      TrackerHitExtendedVec& hitVec = _sectorsFTD[iC];
+      //      int nO = int(hitVec.size());
+      //      iC = iS + 2*nLS[1];
+      //      hitVec = _sectorsFTD[iC];
+      //      int nM = int(hitVec.size());
+      //      iC = iS + 2*nLS[2];
+      //      hitVec = _sectorsFTD[iC];
+      //      int nI = int(hitVec.size());
+      //      std::cout << nO << " " << nM << " " << nI << endmsg;
+
+      for (int ipOuter=0;ipOuter<_nPhiFTD;++ipOuter) { 
+
+        int ipMiddleLow = ipOuter - 1;
+        int ipMiddleUp  = ipOuter + 1;
+        
+        unsigned int iCodeOuter = iS + 2*nLS[0] + 2*_nlayersFTD*ipOuter;
+        
+        if( iCodeOuter >= _sectorsFTD.size()){          
+          error() << "iCodeOuter index out of range: iCodeOuter =   " << iCodeOuter << " _sectorsFTD.size() = " << _sectorsFTD.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg;
+          exit(1);
+        }
+        
+        TrackerHitExtendedVec& hitVecOuter = _sectorsFTD[iCodeOuter];
+        
+        int nOuter = int(hitVecOuter.size());
+
+        for (int iOuter=0;iOuter<nOuter;++iOuter) {
+          
+          TrackerHitExtended * hitOuter = hitVecOuter[iOuter];
+        
+          for (int ipMiddle=ipMiddleLow;ipMiddle<=ipMiddleUp;++ipMiddle) {
+            //for(int ipMiddle=0;ipMiddle<_nPhiFTD;++ipMiddle) {
+            int ipM = ipMiddle;
+            if (ipM < 0) 
+              ipM = ipMiddle + _nPhiFTD;
+            if (ipM >= _nPhiFTD)
+              ipM = ipMiddle - _nPhiFTD;
+            int iCodeMiddle = iS + 2*nLS[1] + 2*_nlayersFTD*ipM;
+          
+            TrackerHitExtendedVec& hitVecMiddle = _sectorsFTD[iCodeMiddle];
+            int ipInnerLow,ipInnerUp;       
+            ipInnerLow = ipMiddle - 1;
+            ipInnerUp =  ipMiddle + 1;
+            
+            int nMiddle = int(hitVecMiddle.size());
+            
+            for (int iMiddle=0;iMiddle<nMiddle;++iMiddle) {
+              TrackerHitExtended * hitMiddle = hitVecMiddle[iMiddle];
+              for (int ipInner=ipInnerLow;ipInner<=ipInnerUp;++ipInner) {
+                //for (int ipInner=0;ipInner<_nPhiFTD;++ipInner) {
+                int ipI = ipInner;
+                if (ipI < 0)
+                  ipI = ipInner + _nPhiFTD;
+                if (ipI >= _nPhiFTD) 
+                  ipI = ipInner - _nPhiFTD;
+                int iCodeInner = iS + 2*nLS[2] + 2*_nlayersFTD*ipI;
+                TrackerHitExtendedVec& hitVecInner = _sectorsFTD[iCodeInner];
+            
+                int nInner = int(hitVecInner.size());
+                
+                for (int iInner=0;iInner<nInner;++iInner) {
+                
+                  TrackerHitExtended * hitInner = hitVecInner[iInner];
+                  HelixClass helix;
+                  //                  std::cout << endmsg;
+                  //                  std::cout << "Outer Hit Type " << hitOuter->getTrackerHit()->getType() << " z = " << hitOuter->getTrackerHit()->getPosition()[2] 
+                  //                  << "\nMiddle Hit Type "<< hitMiddle->getTrackerHit()->getType() << " z = " << hitMiddle->getTrackerHit()->getPosition()[2]  
+                  //                  << "\nInner Hit Type "<< hitInner->getTrackerHit()->getType() << " z = " << hitInner->getTrackerHit()->getPosition()[2]  << endmsg;
+
+                  debug() << " "
+                  << std::setw(3) << ipOuter       << " "   << std::setw(3) << ipMiddle << " "      << std::setw(3) << ipInner << "       "
+                  << std::setw(3) << iS << "     "
+                  << std::setw(3) << nLS[0]     << " "   << std::setw(3) << nLS[1]   << " "      << std::setw(3) << nLS[2]  << "     "
+                  << std::setw(3) << nOuter << " : " << std::setw(3) << nMiddle << " : " << std::setw(3) << nInner << "  :: "
+                  << std::setw(3) << nOuter*nMiddle* nInner << endmsg;
+
+                  
+                  TrackExtended * trackAR = TestTriplet(hitOuter,hitMiddle,hitInner,helix);
+                  if (trackAR != NULL) {
+                    //                    std::cout << "FTD triplet found" << endmsg;
+                    int nHits = BuildTrackFTD(trackAR,nLS,iS);
+                    
+                    _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits ).push_back( trackAR );
+                  }
+                }
+              }
+            }
+          }       
+        }
+      }
+    }
+  }
+}
+
+
+int SiliconTrackingAlg::BuildTrackFTD(TrackExtended * trackAR, int * nLR, int iS) {
+  //  std::cout << "BuildTrackFTD: Layers = " << nLR[0] << " " << nLR[1] << " " << nLR[2] << endmsg;
+  
+  // initialise a helix from the track
+  HelixClass helix;
+  const float d0 = trackAR->getD0();
+  const float z0 = trackAR->getZ0();
+  const float phi0 = trackAR->getPhi();
+  const float tanlambda = trackAR->getTanLambda();
+  const float omega = trackAR->getOmega();
+  helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField);
+  float ref[3] = {helix.getReferencePoint()[0],
+    helix.getReferencePoint()[1],
+    helix.getReferencePoint()[2]};
+  
+  for (int iL=0; iL < static_cast<int>(_nlayersFTD); ++iL) {
+    if (iL != nLR[0] && iL != nLR[1] && iL != nLR[2]) {
+      float point[3];
+      float ZL = _zLayerFTD[iL];
+      if (iS == 0) 
+        ZL = - ZL;
+      helix.getPointInZ(ZL,ref,point);
+      //      float Phi = atan2(point[1],point[0]);
+      //      int iPhi = int(Phi/_dPhiFTD);
+      float distMin = 1e+6;
+      TrackerHitExtended * attachedHit = NULL;
+      for (int ip=0;ip<=_nPhiFTD;++ip) {
+        int iP = ip;
+        if (iP < 0)
+          iP = ip + _nPhiFTD;
+        if (iP >= _nPhiFTD)
+          iP = ip - _nPhiFTD;   
+        int iCode = iS + 2*iL + 2*_nlayersFTD*iP;
+        TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode];
+        int nH = int(hitVec.size());
+        for (int iH=0; iH<nH; ++iH) {
+          TrackerHitExtended * hit = hitVec[iH];
+	  edm4hep::TrackerHit * trkHit = hit->getTrackerHit();
+          float pos[3];
+          for (int i=0;i<3;++i)
+            pos[i] = float(trkHit->getPosition()[i]);
+          float distance[3];
+          float time = helix.getDistanceToPoint(pos,distance);
+          if (time < 1.0e+10) {
+            if (distance[2] < distMin) {
+              distMin = distance[2];
+              attachedHit = hit;
+            }
+          }
+        }
+      }
+      //      std::cout << "Layer = " << iL << "  distMin = " << distMin << endmsg;
+      if (distMin < _minDistCutAttach && attachedHit != NULL) {
+        int iopt = 2;
+        AttachHitToTrack( trackAR, attachedHit, iopt);
+      }
+    }
+  }
+  TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+  int nH = int (hitVec.size());
+  return nH;
+}
+
+int SiliconTrackingAlg::AttachHitToTrack(TrackExtended * trackAR, TrackerHitExtended * hit, int iopt) {
+  
+  int attached = 0;
+  TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+  int nHits = int(hitVec.size());
+  
+  double * xh = new double[nHits+1];
+  double * yh = new double[nHits+1];
+  float  * zh = new float[nHits+1];
+  double * wrh = new double[nHits+1];
+  float * wzh = new float[nHits+1];
+  float * rh = new float[nHits+1];
+  float * ph = new float[nHits+1];
+  float par[5];
+  float epar[15];
+  
+  for (int i=0; i<nHits; ++i) {
+    edm4hep::TrackerHit * trkHit = hitVec[i]->getTrackerHit();
+    xh[i] = double(trkHit->getPosition()[0]);
+    yh[i] = double(trkHit->getPosition()[1]);
+    zh[i] = float(trkHit->getPosition()[2]);
+    ph[i] = float(atan2(yh[i],xh[i]));
+    rh[i] = float(sqrt(xh[i]*xh[i]+yh[i]*yh[i]));
+    float rR = hitVec[i]->getResolutionRPhi();
+    float rZ = hitVec[i]->getResolutionZ();
+    wrh[i] = double(1.0/(rR*rR));
+    wzh[i] = 1.0/(rZ*rZ);
+  }
+  
+  edm4hep::TrackerHit * trkHit = hit->getTrackerHit();
+  xh[nHits] = double(trkHit->getPosition()[0]);
+  yh[nHits] = double(trkHit->getPosition()[1]);
+  zh[nHits] = float(trkHit->getPosition()[2]);
+  ph[nHits] = float(atan2(yh[nHits],xh[nHits]));
+  rh[nHits] = float(sqrt(xh[nHits]*xh[nHits]+yh[nHits]*yh[nHits]));
+  
+  float rR = hit->getResolutionRPhi();
+  float rZ = hit->getResolutionZ();
+  wrh[nHits] = double(1.0/(rR*rR));
+  wzh[nHits] = 1.0/(rZ*rZ);
+  
+  
+  int NPT = nHits + 1;
+  
+  // SJA:FIXME the newtonian part is giving crazy results for FTD so just use iopt 2 for simply attaching hits 
+  // using SIT and VXD doesn't seem to give any problems, so make it a function parameter and let the caller decide
+  //  int iopt = 3;
+  
+  float chi2RPhi = 0 ;
+  float chi2Z = 0 ;
+  
+  
+  int error = _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z);
+  par[3] = par[3]*par[0]/fabs(par[0]);
+  
+  
+  float omega = par[0];
+  float tanlambda = par[1];
+  float phi0 = par[2];
+  float d0 = par[3];
+  float z0 = par[4];
+  float chi2 = FLT_MAX;
+  int ndf = INT_MAX;
+  
+  if (NPT == 3) {
+    chi2 = chi2RPhi*_chi2WRPhiTriplet+chi2Z*_chi2WZTriplet;
+  }
+  if (NPT == 4) {
+    chi2 = chi2RPhi*_chi2WRPhiQuartet+chi2Z*_chi2WZQuartet;
+  }
+  if (NPT > 4) {
+    chi2 = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet;
+  }
+  ndf = 2*NPT-5;
+  
+  
+  if ( error == 0 && chi2/float(ndf) < _chi2FitCut ) {
+    trackAR->addTrackerHitExtended(hit);
+    hit->addTrackExtended( trackAR );
+    trackAR->setChi2( chi2 );
+    trackAR->setOmega( omega );
+    trackAR->setTanLambda( tanlambda );
+    trackAR->setD0( d0 );
+    trackAR->setZ0( z0 );
+    trackAR->setPhi( phi0 );
+    trackAR->setNDF( ndf );
+    trackAR->setCovMatrix( epar );
+    attached = 1;
+    debug() << "Attachement succeeded chi2/float(ndf) = " << chi2/float(ndf) << "  cut = " <<  _chi2FitCut  << " chi2RPhi = " << chi2RPhi << " chi2Z = " << chi2Z << " error = " << error << endmsg;
+  } else {
+    debug() << "Attachement failed chi2/float(ndf) = " << chi2/float(ndf) << "  cut = " <<  _chi2FitCut  << " chi2RPhi = " << chi2RPhi << " chi2Z = " << chi2Z << " error = " << error << endmsg;
+  }
+  
+  delete[] xh;
+  delete[] yh;
+  delete[] zh;
+  delete[] wrh;
+  delete[] wzh;
+  delete[] rh;
+  delete[] ph;
+  
+  return attached;
+  
+  
+}
+
+void SiliconTrackingAlg::FinalRefit(edm4hep::TrackCollection* trk_col) {
+  
+  int nTracks = int(_trackImplVec.size());
+  
+  int nSiSegments = 0;        
+  float eTot = 0.;
+  float pxTot = 0.;
+  float pyTot = 0.;
+  float pzTot = 0.;
+  std::cout << "fucd============" << nTracks << std::endl;
+  for (int iTrk=0;iTrk<nTracks;++iTrk) {
+    
+    TrackExtended * trackAR = _trackImplVec[iTrk];    
+    TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec();
+    
+    int nHits = int(hitVec.size());
+    std::cout << "fucd-------------" << iTrk << ": " << nHits << std::endl;
+    if( nHits >= _minimalHits) {
+      //    int * lh = new int[nHits];
+      std::vector<int> lh;
+      lh.resize(nHits);
+      
+      for (int i=0; i<nHits; ++i) {
+        lh[i]=0;
+      }
+      
+      float d0 = trackAR->getD0();
+      float z0 = trackAR->getZ0();
+      float omega = trackAR->getOmega();
+      float tanlambda = trackAR->getTanLambda();
+      float phi0 = trackAR->getPhi();
+      
+      HelixClass * helix = new HelixClass();
+      helix->Initialize_Canonical(phi0, d0, z0, omega, 
+                                  tanlambda, _bField);
+      
+      
+      // get the point of closest approach to the reference point
+      // here it is implicitly assumed that the reference point is the origin 
+      float Pos[3];
+      Pos[0] = -d0*sin(phi0);
+      Pos[1] = d0*cos(phi0);
+      Pos[2] = z0;
+      
+      std::cout << "fucd------------------1" << std::endl; 
+      // at this point is is possible to have hits from the same layer ...
+      // so a check is made to ensure that the hit with the smallest distance to the 
+      // current helix hypothosis is used, the other hit has lh set to 0 
+      
+      // start loop over the hits to
+      for (int ihit=0;ihit<nHits;++ihit) {
+        
+        lh[ihit] = 1; // only hits which have lh=1 will be used for the fit
+        
+        // get the pointer to the lcio trackerhit for this hit
+	edm4hep::TrackerHit * trkHit = hitVec[ihit]->getTrackerHit();
+        
+        int det = getDetectorID(trkHit);
+        
+        if (det == lcio::ILDDetID::VXD || det == lcio::ILDDetID::FTD || det == lcio::ILDDetID::SIT) { // only accept VXD, FTD or SIT
+          
+          
+          //        int layer = getLayerID(trkHit);
+          //        int moduleIndex = getModuleID(trkHit);
+          
+          // start a double loop over the hits which have already been checked 
+          for (int lhit=0;lhit<ihit;++lhit) {
+            
+            // get the pointer to the lcio trackerhit for the previously checked hit
+	    edm4hep::TrackerHit * trkHitS = hitVec[lhit]->getTrackerHit();
+            
+            
+            //          int layerS = getLayerID(trkHitS);
+            //          int moduleIndexS = getModuleID(trkHitS);
+            
+            // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works 
+            // if they are on the same layer and the previously checked hits has been declared good for fitting
+            //          if ((trkHitS->getType() == trkHit->getType()) && (lh[lhit] == 1)) {
+            // check if the hits have the same layer and petal number
+            //          hitVec[ihit]->
+            //          if ((layer == layerS) && (moduleIndex==moduleIndexS) && (lh[lhit] == 1)) {
+            if ( (trkHit->getCellID() == trkHitS->getCellID()) && (lh[lhit] == 1)) {
+              
+              // get the position of the hits 
+              float xP[3];
+              float xPS[3];
+              for (int iC=0;iC<3;++iC) {
+                xP[iC] = float(trkHit->getPosition()[iC]);
+                xPS[iC] = float(trkHitS->getPosition()[iC]);
+              }
+              
+              // get the intersection of the helix with the either the cylinder or plane containing the hit
+              float Point[6];
+              float PointS[6];
+              
+              if (det == lcio::ILDDetID::FTD) {
+
+                float time = helix->getPointInZ(xP[2],Pos,Point);
+                time = helix->getPointInZ(xPS[2],Pos,PointS);
+
+              } else {
+
+                float RAD = sqrt(xP[0]*xP[0]+xP[1]*xP[1]);
+                float RADS = sqrt(xPS[0]*xPS[0]+xPS[1]*xPS[1]);
+                float time = helix->getPointOnCircle(RAD,Pos,Point);
+                time = helix->getPointOnCircle(RADS,Pos,PointS);
+
+              }
+              
+              float DIST = 0;
+              float DISTS = 0;
+              
+              // get the euclidean distance between the hit and the point of intersection
+              for (int iC=0;iC<3;++iC) {
+                DIST += (Point[iC]-xP[iC])*(Point[iC]-xP[iC]);
+                DISTS += (PointS[iC]-xPS[iC])*(PointS[iC]-xPS[iC]);
+              }
+              if (DIST < DISTS) {
+                lh[lhit] = 0;
+              }
+              else {
+                lh[ihit] = 0;
+              }
+              break;
+            }
+          }
+        }
+      }
+      
+      delete helix;
+      
+      std::vector<TrackerHit*> trkHits;
+      std::vector<TrackerHit*> trkHits_used_inFit;
+      
+      int nFit = 0;
+      for (int i=0; i<nHits; ++i) {
+        // check if the hit has been rejected as being on the same layer and further from the helix lh==0
+        if (lh[i] == 1) {
+	  edm4hep::TrackerHit * trkHit = hitVec[i]->getTrackerHit();
+          nFit++;
+          if(trkHit) { 
+            trkHits.push_back(trkHit);   
+          }
+          else{
+            throw EVENT::Exception( std::string("SiliconTrackingAlg::FinalRefit: TrackerHit pointer == NULL ")  ) ;
+          }
+        }
+        else { // reject hit 
+               // SJA:FIXME missuse of type find a better way to signal rejected hits
+          hitVec[i]->setType(int(0));
+        }
+      }
+      
+      if( trkHits.size() < 3 ) {
+        debug() << "SiliconTrackingAlg::FinalRefit: Cannot fit less than 3 hits. Number of hits =  " << trkHits.size() << endmsg;
+        continue ; 
+      }
+      std::cout << "fucd------------------2" << std::endl;
+      //TrackImpl* Track = new TrackImpl ;
+      auto track = trk_col->create();
+      //fucd
+      //edm4hep::Track track;// = new edm4hep::Track;
+      std::cout << "fucd------------------3" << std::endl;
+      // setup initial dummy covariance matrix
+      //std::vector<float> covMatrix;
+      //covMatrix.resize(15);
+      std::array<float,15> covMatrix;
+
+      for (unsigned icov = 0; icov<covMatrix.size(); ++icov) {
+        covMatrix[icov] = 0;
+      }
+      
+      covMatrix[0]  = ( _initialTrackError_d0    ); //sigma_d0^2
+      covMatrix[2]  = ( _initialTrackError_phi0  ); //sigma_phi0^2
+      covMatrix[5]  = ( _initialTrackError_omega ); //sigma_omega^2
+      covMatrix[9]  = ( _initialTrackError_z0    ); //sigma_z0^2
+      covMatrix[14] = ( _initialTrackError_tanL  ); //sigma_tanl^2
+      
+      
+      std::vector< std::pair<float, edm4hep::TrackerHit*> > r2_values;
+      r2_values.reserve(trkHits.size());
+      
+      for (std::vector<edm4hep::TrackerHit*>::iterator it=trkHits.begin(); it!=trkHits.end(); ++it) {
+        edm4hep::TrackerHit* h = *it;
+        float r2 = h->getPosition()[0]*h->getPosition()[0]+h->getPosition()[1]*h->getPosition()[1];
+        r2_values.push_back(std::make_pair(r2, *it));
+      }
+      
+      sort(r2_values.begin(),r2_values.end());
+      //std::cout << "fucd------------------3" << std::endl;
+      trkHits.clear();
+      trkHits.reserve(r2_values.size());
+
+      for (std::vector< std::pair<float, edm4hep::TrackerHit*> >::iterator it=r2_values.begin(); it!=r2_values.end(); ++it) {
+        trkHits.push_back(it->second);
+      }
+      //std::cout << "fucd------------------3 " << _trksystem << std::endl;
+      //for (unsigned ihit_indx=0 ; ihit_indx < trkHits.size(); ++ihit_indx) {
+      //  std::cout << "fucd trk hit " << *trkHits[ihit_indx] << " " << trkHits[ihit_indx]->getCovMatrix()[0]
+      //		  << " " << BitSet32(trkHits[ihit_indx]->getType())[ ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] << endmsg;
+      //}
+      /*
+      auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc");
+      if ( !_trackSystemSvc ) {
+	error() << "Failed to find TrackSystemSvc ..." << endmsg;
+	return;
+      }
+      _trksystem =  _trackSystemSvc->getTrackSystem();
+
+      if( _trksystem == 0 ){
+	error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg;
+	return;
+      }
+      debug() << "_trksystem pointer " << _trksystem << endmsg;
+      
+      _trksystem->setOption( IMarlinTrkSystem::CFG::useQMS,        _MSOn ) ;
+      _trksystem->setOption( IMarlinTrkSystem::CFG::usedEdx,       _ElossOn) ;
+      _trksystem->setOption( IMarlinTrkSystem::CFG::useSmoothing,  _SmoothOn) ;
+      _trksystem->init() ;
+      */
+      bool fit_backwards = IMarlinTrack::backward;
+      
+      MarlinTrk::IMarlinTrack* marlinTrk = nullptr;
+      try{
+	marlinTrk = _trksystem->createTrack();
+      }
+      catch(...){
+	error() << "Cannot create MarlinTrack ! " << endmsg;
+	return;
+      }
+      
+      int status = 0;
+      std::cout << "fucd------------------3" << std::endl;
+      try {
+        status = MarlinTrk::createFinalisedLCIOTrack(marlinTrk, trkHits, &track, fit_backwards, covMatrix, _bField, _maxChi2PerHit);
+      } catch (...) {
+        
+        //      delete Track;
+        //      delete marlinTrk;
+        error() << "MarlinTrk::createFinalisedLCIOTrack " << endmsg;
+        throw ;
+        
+      }
+      std::cout << "fucd------------------4" << std::endl;
+      /*
+#ifdef MARLINTRK_DIAGNOSTICS_ON
+      if ( status != IMarlinTrack::success && _runMarlinTrkDiagnostics ) {        
+        void * dcv = _trksystem->getDiagnositicsPointer();
+        DiagnosticsController* dc = static_cast<DiagnosticsController*>(dcv);
+        dc->skip_current_track();
+      }        
+#endif
+      */
+      
+      std::vector<std::pair<edm4hep::TrackerHit* , double> > hits_in_fit ;  
+      std::vector<std::pair<edm4hep::TrackerHit* , double> > outliers ;
+      std::vector<edm4hep::TrackerHit*> all_hits;    
+      all_hits.reserve(300);
+      
+      marlinTrk->getHitsInFit(hits_in_fit);
+      
+      for ( unsigned ihit = 0; ihit < hits_in_fit.size(); ++ihit) {
+        all_hits.push_back(hits_in_fit[ihit].first);
+      }
+      
+      UTIL::BitField64 cellID_encoder( lcio::ILDCellID0::encoder_string ) ; 
+      
+      MarlinTrk::addHitNumbersToTrack(&track, all_hits, true, cellID_encoder);
+      
+      marlinTrk->getOutliers(outliers);
+      
+      for ( unsigned ihit = 0; ihit < outliers.size(); ++ihit) {
+        all_hits.push_back(outliers[ihit].first);
+      }
+      
+      MarlinTrk::addHitNumbersToTrack(&track, all_hits, false, cellID_encoder);
+      
+      delete marlinTrk;
+
+      int nhits_in_vxd = track.getSubDetectorHitNumbers(0);
+      int nhits_in_ftd = track.getSubDetectorHitNumbers(1);
+      int nhits_in_sit = track.getSubDetectorHitNumbers(2);
+      
+      //debug() << " Hit numbers for Track "<< track->id() << ": "
+      debug() << " Hit numbers for Track "<< iTrk <<": "
+	      << " vxd hits = " << nhits_in_vxd
+	      << " ftd hits = " << nhits_in_ftd
+	      << " sit hits = " << nhits_in_sit
+	      << endmsg;
+      
+      //if (nhits_in_vxd > 0) Track->setTypeBit( lcio::ILDDetID::VXD ) ;
+      //if (nhits_in_ftd > 0) Track->setTypeBit( lcio::ILDDetID::FTD ) ;
+      //if (nhits_in_sit > 0) Track->setTypeBit( lcio::ILDDetID::SIT ) ;
+
+      
+      
+      if( status != IMarlinTrack::success ) {       
+        
+        //delete track;
+        debug() << "SiliconTrackingAlg::FinalRefit: Track fit failed with error code " << status << " track dropped. Number of hits = "<< trkHits.size() << endmsg;       
+        continue ;
+      }
+      
+      if( track.getNdf() < 0) {       
+        //delete track;
+        debug() << "SiliconTrackingAlg::FinalRefit: Track fit returns " << track.getNdf() << " degress of freedom track dropped. Number of hits = "<< trkHits.size() << endmsg;       
+	//delete track;
+        continue ;
+      }
+      
+      //trk_col->addElement(Track);     
+      //fucd
+      //trk_col->push_back(track);
+      for(int i=0;i<track.trackStates_size();i++){
+	// 1 = lcio::EVENT::TrackState::AtIP
+	edm4hep::TrackState trkStateIP = track.getTrackStates(i);
+	if(trkStateIP.location !=1) continue;
+      /*
+      if (trkStateIP == 0) {
+        debug() << "SiliconTrackingAlg::FinalRefit: Track fit returns " << track->getNdf() << " degress of freedom track dropped. Number of hits = "<< trkHits.size() << endmsg;       
+        throw EVENT::Exception( std::string("SiliconTrackingAlg::FinalRefit: trkStateIP pointer == NULL ")  ) ;
+      }
+      */
+      // note trackAR which is of type TrackExtended, only takes fits set for ref point = 0,0,0
+	trackAR->setOmega(trkStateIP.omega);
+	trackAR->setTanLambda(trkStateIP.tanLambda);
+	trackAR->setPhi(trkStateIP.phi);
+	trackAR->setD0(trkStateIP.D0);
+	trackAR->setZ0(trkStateIP.Z0);
+	
+	float cov[15];
+	
+	for (int i = 0 ; i<15 ; ++i) {
+	  cov[i] = trkStateIP.covMatrix.operator[](i);
+	}
+      
+	trackAR->setCovMatrix(cov);
+	trackAR->setChi2(track.getChi2());
+	trackAR->setNDF(track.getNdf());
+      
+	nSiSegments++;
+      
+	HelixClass helix_final;
+      
+	helix_final.Initialize_Canonical(trkStateIP.phi,trkStateIP.D0,trkStateIP.Z0,trkStateIP.omega,trkStateIP.tanLambda,_bField);
+      
+	float trkPx = helix_final.getMomentum()[0];
+	float trkPy = helix_final.getMomentum()[1];
+	float trkPz = helix_final.getMomentum()[2];
+	float trkP = sqrt(trkPx*trkPx+trkPy*trkPy+trkPz*trkPz);
+	eTot += trkP;
+	pxTot += trkPx;
+	pyTot += trkPy;
+	pzTot += trkPz;
+      }
+    }
+  }
+  
+  debug() << "SiliconTrackingAlg -> run " << _nRun
+	  << " event " << _nEvt << endmsg;
+  debug() << "Number of Si tracks = " << nSiSegments << endmsg;
+  debug() << "Total 4-momentum of Si Tracks : E = " << std::setprecision(7) << eTot
+	  << " Px = " << pxTot
+	  << " Py = " << pyTot
+	  << " Pz = " << pzTot << endmsg;
+  
+  
+}
+
+
+StatusCode SiliconTrackingAlg::setupGearGeom(){
+  auto _gear = service<IGearSvc>("GearSvc");
+  if ( !_gear ) {
+    error() << "Failed to find GearSvc ..." << endmsg;
+    return StatusCode::FAILURE;
+  }
+  gear::GearMgr* gearMgr = _gear->getGearMgr();
+  _bField = gearMgr->getBField().at( gear::Vector3D( 0.,0.,0.)  ).z() ;
+  debug() << "Field " << _bField << endmsg;
+  //-- VXD Parameters--
+  _nLayersVTX = 0 ;
+  const gear::VXDParameters* pVXDDetMain = 0;
+  const gear::VXDLayerLayout* pVXDLayerLayout = 0;
+  
+  try{
+    
+    debug() << " filling VXD parameters from gear::SITParameters " << endmsg ;
+    
+    pVXDDetMain = &gearMgr->getVXDParameters();
+    pVXDLayerLayout = &(pVXDDetMain->getVXDLayerLayout());
+    _nLayersVTX = pVXDLayerLayout->getNLayers();
+  }
+  catch( gear::UnknownParameterException& e){
+    
+    debug() << " ### gear::VXDParameters Not Present in GEAR FILE" << endmsg ;
+    
+  }
+  
+  
+  
+  //-- SIT Parameters--
+  _nLayersSIT = 0 ;
+  const gear::ZPlanarParameters* pSITDetMain = 0;
+  const gear::ZPlanarLayerLayout* pSITLayerLayout = 0;
+  
+  try{
+    
+    debug() << " filling SIT parameters from gear::SITParameters " << endmsg ;
+    
+    pSITDetMain = &gearMgr->getSITParameters();
+    pSITLayerLayout = &(pSITDetMain->getZPlanarLayerLayout());
+    _nLayersSIT = pSITLayerLayout->getNLayers();
+    
+  }
+  catch( gear::UnknownParameterException& e){
+    
+    debug() << " ### gear::SITParameters Not Present in GEAR FILE" << endmsg ;
+    
+  }
+  
+  if( _nLayersSIT == 0 ){
+    // try the old LOI style key value pairs as defined in the SSit03 Mokka drive
+    try{
+      
+      info() << "  SiliconTrackingAlg - Simple Cylinder Based SIT using parameters defined by SSit03 Mokka driver " << endmsg ;
+      
+      // SIT
+      
+      const gear::GearParameters& pSIT = gearMgr->getGearParameters("SIT");
+      
+      const std::vector<double>& SIT_r   =  pSIT.getDoubleVals("SITLayerRadius" )  ;
+      const std::vector<double>& SIT_hl  =  pSIT.getDoubleVals("SITSupportLayerHalfLength" )  ;
+      
+      _nLayersSIT = SIT_r.size() ; 
+      
+      if (_nLayersSIT != SIT_r.size() || _nLayersSIT != SIT_hl.size()) {
+        
+        error() << "ILDSITCylinderKalDetector miss-match between DoubleVec and nlayers exit(1) called from file " << __FILE__ << " line " << __LINE__  << endmsg ;
+        exit(1);
+        
+      }
+    }
+    catch( gear::UnknownParameterException& e){
+      
+      debug() << " ### gear::SIT Parameters from as defined in SSit03 Not Present in GEAR FILE" << endmsg ;
+      
+    } 
+    
+  }
+  
+  
+  
+  //-- FTD Parameters--
+  _petalBasedFTDWithOverlaps = false;  
+  _nlayersFTD = 0;
+  
+  try{
+    
+    debug() << " filling FTD parameters from gear::FTDParameters " << endmsg ;
+    
+    const gear::FTDParameters&   pFTD      = gearMgr->getFTDParameters();
+    const gear::FTDLayerLayout&  ftdlayers = pFTD.getFTDLayerLayout() ;
+    
+    _nlayersFTD = ftdlayers.getNLayers() ;
+    
+    for (unsigned int disk=0; disk < _nlayersFTD; ++disk) {
+      
+      _zLayerFTD.push_back( ftdlayers.getSensitiveZposition(disk, 0, 1) ); // front petal even numbered
+      
+      if ( ftdlayers.getNPetals(disk) > 0) {
+        _zLayerFTD.push_back( ftdlayers.getSensitiveZposition(disk, 1, 1) );  // front petal odd numbered
+        _petalBasedFTDWithOverlaps = true;
+      }
+      
+    }
+    
+    // SJA: Here we increase the size of _nlayersFTD as we are treating the 
+    _nlayersFTD =_zLayerFTD.size() ;     
+    
+  }
+  catch( gear::UnknownParameterException& e){
+    
+    debug() << " ### gear::FTDParameters Not Present in GEAR FILE" << endmsg ;
+    
+  } 
+  
+  if( _nlayersFTD == 0 ){
+    
+    // FTD
+    try{
+      
+      info() << "  SiliconTrackingAlg - Simple Disc Based FTD using parameters defined by SFtd05 Mokka driver " << endmsg ;
+      
+      const gear::GearParameters& pFTD = gearMgr->getGearParameters("FTD");
+      
+      const std::vector<double>* pFTD_z   = NULL;
+      
+      info() << " For FTD using parameters defined by SFtd05 Mokka driver " << endmsg ;
+      
+      pFTD_z = &pFTD.getDoubleVals("FTDZCoordinate" )  ;
+      
+      _nlayersFTD = pFTD_z->size();
+      
+      for (unsigned int i = 0; i<_nlayersFTD; ++i) {
+        _zLayerFTD.push_back((*pFTD_z)[i]);
+      }
+    }
+    catch( gear::UnknownParameterException& e){
+      
+      debug() << " ### gear::FTD Parameters as defined in SFtd05 Not Present in GEAR FILE" << endmsg ;
+      
+    } 
+  }
+  return StatusCode::SUCCESS;
+}
+
+void SiliconTrackingAlg::TracksWithNHitsContainer::clear()
+{
+  for (std::vector< TrackExtendedVec >::iterator trackVecIter = _tracksNHits.begin();
+       trackVecIter < _tracksNHits.end(); trackVecIter++)
+  {
+    for (TrackExtendedVec::iterator trackIter = trackVecIter->begin();
+         trackIter < trackVecIter->end(); trackIter++)
+    {
+      delete *trackIter;
+    }
+    
+    trackVecIter->clear();
+  }
+}
+
diff --git a/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.h b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5cfca0cb76ded4a59ce14347794834427b5277f
--- /dev/null
+++ b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.h
@@ -0,0 +1,429 @@
+#ifndef SiliconTrackingAlg_h
+#define SiliconTrackingAlg_h
+
+//#include "marlin/Processor.h"
+//#include <marlin/Global.h>
+#include "FWCore/DataHandle.h"
+#include "GaudiAlg/GaudiAlgorithm.h"
+#include "edm4hep/EventHeaderCollection.h"
+#include "edm4hep/MCParticleCollection.h"
+#include "edm4hep/SimTrackerHitCollection.h"
+#include "edm4hep/TrackerHitCollection.h"
+#include "edm4hep/TrackCollection.h"
+//#include "edm4hep/LCRelationCollection.h"
+
+//#include "lcio.h"
+#include <string>
+#include <vector>
+#include <cmath>
+//#include <IMPL/TrackImpl.h>
+#include "DataHelper/ClusterExtended.h"
+#include "DataHelper/TrackExtended.h"
+#include "DataHelper/TrackerHitExtended.h"
+#include "DataHelper/HelixClass.h"
+
+#include "TrackSystemSvc/IMarlinTrack.h"
+
+#include <UTIL/BitField64.h>
+#include <UTIL/ILDConf.h>
+
+//using namespace edm4hep ;
+
+namespace gear{
+  class GearMgr ;
+}
+
+namespace MarlinTrk {
+  class HelixFit;
+  class IMarlinTrkSystem ;
+}
+
+namespace UTIL{
+  class LCRelationNavigator ;
+}
+
+class TrackExtended;
+class TrackerHitExtended;
+class HelixClass;
+
+/** === Silicon Tracking Processor === <br>
+ * Processor performing stand-alone pattern recognition
+ * in the vertex detector (VTX), forward tracking disks and SIT. <br>
+ * The procedure consists of three steps : <br> 
+ * 1) Tracking in VTX and SIT ; <br>
+ * 2) Tracking in FTD ; <br>
+ * 3) Merging compatible track segments reconstructed in VTX and FTD <br>
+ * STEP 1 : TRACKING IN VTX and SIT <br>
+ * Algorithm starts with finding of hit triplets satisfying helix hypothesis <br> 
+ * in three different layers. Two layers of SIT are effectively considered as outermost <br>
+ * layers of the vertex detector. To accelerate procedure, the 4-pi solid angle
+ * is divided in NDivisionsInTheta and NDivisionsInPhi sectors in cosQ and Phi, 
+ * respectively. Triplets are looked for in 2x2 window of adjacent sectors. 
+ * Once triplet is found, attempt is made to associate additional hits to 
+ * track. Combinatin of hits is accepted for further analysis if the Chi2 
+ * of the fit is less than certain predefined threshold. All accepted 
+ * combinations are sorted in ascending order of their Chi2. First track candidate 
+ * in the sorted array is automatically accepted. The hits belonging to this track are 
+ * marked as used, and track candidates sharing these hits are discarded.
+ * The procedure proceeds with increasing index of track candidate in the sorted 
+ * array until all track candidate have been output or discarded. <br>
+ * STEP 2 : TRACKING IN FTD <br>
+ * In the next step tracking in FTD is performed. The strategy of tracking in the FTD 
+ * is the same as used for tracking in the VTX+SIT. <br>
+ * STEP 3 : MERGING TRACK SEGMENTS FOUND IN FTD AND VTX+SIT <br>
+ * In the last step, track segments reconstructed in the FTD and VTX+SIT, belonging to the
+ * same track  are identified and merged into one track. All possible 
+ * pairings are tested for their compatibility.
+ * The number of pairings considered is Ntrk_VTX_SIT*Ntrk_FTD, where Ntrk_VTX_SIT is the number of 
+ * track segments reconstructed in the first step in VTX+SIT (segments containing solely VTX and SIT hits) and
+ * Ntrk_FTD is the number of track segments reconstructed in the second step 
+ * (segments containing solely FTD hits).
+ * Pair of segments is accepted for further examination if the angle between track segments and 
+ * than certain specified threshold.
+ * Pairing satisfying this condition is subjected for 
+ * addtitional test. The fit is performed on unified array of hits belonging to both segments. 
+ * If the chi2 of the fit does not exceed predefined cut value two segments are unified into 
+ * one track. 
+ * <h4>Input collections and prerequisites</h4> 
+ * Processor requires collection of digitized vertex, sit and ftd tracker hits. <br>
+ * If such a collections with the user specified names do not exist 
+ * processor takes no action. <br>
+ * <h4>Output</h4>
+ * Processor produces an LCIO collection of the Tracks. Each track is characterised by 
+ * five parameters : Omega (signed curvuture), Tan(lambda) where
+ * lambda is the dip angle, Phi (azimuthal angle @ point of closest approach), D0 (signed impact parameter),
+ * Z0 (displacement along z axis at the point of closest approach to IP). Covariance matrix for these parameters is also provided.
+ * Only lower left corner of the covariance matrix is stored. The sequence of the covariance matrix elements 
+ * assigned to track is the following: <br>
+ * (Omega,Omega) <br>
+ * (Omega,TanLambda), (TanLambda,TanLambda) <br>
+ * (Omega,Phi), (TanLamda,Phi), (Phi,Phi) <br>
+ * (Omega,D0), (TanLambda,D0), (Phi,D0), (D0,D0) <br>
+ * (Omega,Z0), (TanLambda,Z0), (Phi,Z0), (D0,Z0), (Z0,Z0) <br>
+ * The number of hits in the different subdetectors associated
+ * with each track can be accessed via method Track::getSubdetectorHitNumbers().
+ * This method returns vector of integers : <br>
+ * number of VTX hits in track is the first element in this vector  
+ * (Track::getSubdetectorHitNumbers()[0]) <br>
+ * number of FTD hits in track is the second element in this vector  
+ * (Track::getSubdetectorHitNumbers()[1]) <br>
+ * number of SIT hits in track is the third element in this vector  
+ * (Track::getSubdetectorHitNumbers()[2]) <br>
+ * Output track collection has a name "SiTracks". <br>
+ * @param VTXHitCollectionName name of input VTX TrackerHit collection <br>
+ * (default parameter value : "VTXTrackerHits") <br>
+ * @param FTDHitCollectionName name of input FTD TrackerHit collection <br>
+ * (default parameter value : "FTDTrackerHits") <br>
+ * @param SITHitCollectionName name of input SIT TrackerHit collection <br>
+ * (default parameter value : "SITTrackerHits") <br>
+ * @param SiTrackCollectionName name of the output Silicon track collection <br>
+ * (default parameter value : "SiTracks") <br>
+ * @param LayerCombinations combinations of layers used to search for hit triplets in VTX+SIT <br>
+ * (default parameters : 6 4 3  6 4 2  6 3 2  5 4 3  5 4 2  5 3 2  4 3 2  4 3 1  4 2 1  3 2 1) <br> 
+ * Note that in the VTX+SIT system the first and the second layers of SIT have indicies nLayerVTX and nLayerVTX+1. 
+ * Combination given above means that triplets are looked first in layers 6 4 3, and then 
+ * in 6 4 2;  5 4 3;  6 3 2 etc. NOTE THAT LAYER INDEXING STARTS FROM 0.
+ * LAYER 0 is the innermost layer  <br>
+ * @param LayerCombinationsFTD combinations of layers used to search for hit triplets in FTD <br>
+ * (default parameters 6 5 4  5 4 3  5 4 2  5 4 1  5 3 2  5 3 1  5 2 1  4 3 2  4 3 1  
+ *  4 3 0  4 2 1  4 2 0  4 1 0  3 2 1  3 2 0  3 1 0  2 1 0). 
+ * NOTE THAT TRACKS IN FTD ARE SEARCHED ONLY IN ONE HEMISPHERE. TRACK IS NOT 
+ * ALLOWED TO HAVE HITS BOTH IN BACKWARD AND FORWARD PARTS OF FTD SIMULTANEOUSLY. 
+ * @param NDivisionsInPhi Number of divisions in Phi for tracking in VTX+SIT <br>
+ * (default value is 40) <br>
+ * @param NDivisionsInTheta Number of divisions in cosQ for tracking in VTX+SIT <br>
+ * (default value is 40) <br>
+ * @param NDivisionsInPhiFTD Number of divisions in Phi for tracking in FTD <br>
+ * (default value is 3) <br>
+ * @param Chi2WRphiTriplet weight on chi2 in R-Phi plane for track with 3 hits <br>
+ * (default value is 1) <br>
+ * @param Chi2WZTriplet weight on chi2 in S-Z plane for track with 3 hits <br>
+ * (default value is 0.5) <br>
+ * @param Chi2WRphiQuartet weight on chi2 in R-Phi plane to accept track with 4 hits <br>
+ * (default value is 1) <br>
+ * @param Chi2WZQuartet weight on chi2 in S-Z plane for track with 4 hits <br>
+ * (default value is 0.5) <br>
+ * @param Chi2WRphiSeptet weight on chi2 in R-Phi plane for track with 5 and more hits <br>
+ * (default value is 1) <br>
+ * @param Chi2WZSeptet Cut on chi2 in S-Z plane for track with 5 and more hits <br>
+ * (default value is 0.5) <br>
+ * @param Chi2FitCut Cut on chi2/ndf to accept track candidate <br>
+ * (default value is 100.) <br>
+ * @param AngleCutForMerging cut on the angle between two track segments.  
+ * If the angle is greater than this cut, segments are not allowed to be merged. <br>
+ * (default value is 0.1) <br>
+ * @param MinDistCutAttach cut on the distance (in mm) from hit to the helix. This parameter is used
+ * to decide whether hit can be attached to the track. If the distance is less than 
+ * cut value. The track is refitted with a given hit being added to the list of hits already 
+ * assigned for the track. Additional hit is assigned if chi2 of the new fit has good chi2. <br>
+ * (default value is 2 ) <br>
+ * @param MinLayerToAttach the minimal layer index to attach VTX hits to the found hit triplets <br>
+ * (default value is -1) <br>
+ * @param CutOnZ0 cut on Z0 parameter of track (in mm). If abs(Z0) is greater than the cut value, track is 
+ * discarded (used to suppress fake
+ * track rate in the presence of beam induced background hits) <br>
+ * (default value is 100) <br>
+ * @param CutOnD0 cut on D0 parameter of track (in mm). If abs(D0) is greater than the cut value, track is 
+ * discarded (used to suppress fake
+ * track rate in the presence of beam induced background hits) <br>
+ * (default value is 100) <br>
+ * @param CutOnPt cut on Pt (GeV/c). If Pt is less than this cut, track is discarded (used to suppress fake
+ * track rate in the presence of beam induced background hits) <br>
+ * (default value is 0.1) <br>
+ * @param MinimalHits minimal number of hits in track required <br>
+ * (default value is 3) <br>
+ * @param NHitsChi2 Maximal number of hits for which a track with n hits is aways better than one with n-1 hits.
+ * For tracks with equal or more than NHitsChi2 the track  with the lower \f$\chi^2\f$ is better.
+ * (default value is 5) <br>
+ * @param FastAttachment if this flag is set to 1, less accurate but fast procedure to merge additional hits to tracks is used <br> 
+ * if set to 0, a more accurate, but slower procedure is invoked <br>
+ * (default value is 0) <br>
+ * @param UseSIT When this flag is set to 1, SIT is included in pattern recognition. When this flag is set
+ * to 0, SIT is excluded from the procedure of pattern recognition <br>
+ * (default value is 1) <br>
+ * <br>
+ * @author A. Raspereza (MPI Munich)<br>
+ */
+class SiliconTrackingAlg : public GaudiAlgorithm {
+ public:
+  
+  SiliconTrackingAlg(const std::string& name, ISvcLocator* svcLoc);
+  
+  virtual StatusCode initialize() ;
+  
+  virtual StatusCode execute() ; 
+  
+  virtual StatusCode finalize() ;
+  
+protected:
+  
+  int _nRun ;
+  int _nEvt ;
+  //EVENT::LCEvent* _current_event;
+  int _nLayers;
+  unsigned int _nLayersVTX;
+  unsigned int _nLayersSIT;
+  int _ntriplets, _ntriplets_good, _ntriplets_2MCP, _ntriplets_3MCP, _ntriplets_1MCP_Bad, _ntriplets_bad;
+  
+  MarlinTrk::HelixFit* _fastfitter;
+  gear::GearMgr* _GEAR;
+  /** pointer to the IMarlinTrkSystem instance 
+   */
+  MarlinTrk::IMarlinTrkSystem* _trksystem ;
+  //bool _runMarlinTrkDiagnostics;
+  //std::string _MarlinTrkDiagnosticsName;
+  typedef std::vector<int> IntVec;
+  
+  Gaudi::Property<IntVec> _Combinations{this, "LayerCombinations", {8,6,5, 8,6,4, 8,6,3, 8,6,2, 8,5,3, 8,5,2, 8,4,3, 8,4,2, 6,5,3, 6,5,2, 6,4,3, 6,4,2, 6,3,1, 6,3,0, 6,2,1, 6,2,0,
+	5,3,1, 5,3,0, 5,2,1, 5,2,0, 4,3,1, 4,3,0, 4,2,1, 4,2,0}};
+  Gaudi::Property<IntVec> _CombinationsFTD{this, "LayerCombinationsFTD", {4,3,2, 4,3,1, 4,3,0, 4,2,1, 4,2,0, 4,1,0, 3,2,1, 3,2,0, 3,1,0, 2,1,0,
+	9,8,7, 9,8,6, 9,8,5, 9,7,6, 9,7,5, 9,6,5, 8,7,6, 8,7,5, 8,6,5, 7,6,5}};
+  Gaudi::Property<int> _nDivisionsInPhi{this, "NDivisionsInPhi", 80};
+  Gaudi::Property<int> _nDivisionsInPhiFTD{this, "NDivisionsInPhiFTD", 30};
+  Gaudi::Property<int> _nDivisionsInTheta{this, "NDivisionsInTheta", 80};
+  Gaudi::Property<float> _chi2WRPhiTriplet{this, "Chi2WRphiTriplet", 1.};
+  Gaudi::Property<float> _chi2WRPhiQuartet{this, "Chi2WRphiQuartet", 1.};
+  Gaudi::Property<float> _chi2WRPhiSeptet{this, "Chi2WRphiSeptet", 1.};
+  Gaudi::Property<float> _chi2WZTriplet{this, "Chi2WZTriplet", 0.5};
+  Gaudi::Property<float> _chi2WZQuartet{this, "Chi2WZQuartet", 0.5};
+  Gaudi::Property<float> _chi2WZSeptet{this, "Chi2WZSeptet", 0.5};
+  Gaudi::Property<float> _chi2FitCut{this, "Chi2FitCut", 120.};
+  Gaudi::Property<float> _angleCutForMerging{this, "AngleCutForMerging", 0.1};
+  Gaudi::Property<float> _minDistCutAttach{this, "MinDistCutAttach", 2.5};
+  Gaudi::Property<float> _minimalLayerToAttach{this, "MinLayerToAttach", -1};
+  Gaudi::Property<float> _cutOnD0{this, "CutOnD0", 100.0};
+  Gaudi::Property<float> _cutOnZ0{this, "CutOnZ0", 100.0};
+  Gaudi::Property<float> _cutOnPt{this, "CutOnPt", 0.05};
+  Gaudi::Property<int> _minimalHits{this, "MinimalHits",3};
+  Gaudi::Property<int> _nHitsChi2{this, "NHitsChi2", 5};
+  Gaudi::Property<int> _max_hits_per_sector{this, "MaxHitsPerSector", 100};
+  Gaudi::Property<int> _attachFast{this, "FastAttachment", 0};
+  Gaudi::Property<bool> _useSIT{this, "UseSIT", true};
+  Gaudi::Property<float> _initialTrackError_d0{this, "InitialTrackErrorD0",1e6};
+  Gaudi::Property<float> _initialTrackError_phi0{this, "InitialTrackErrorPhi0",1e2};
+  Gaudi::Property<float> _initialTrackError_omega{this, "InitialTrackErrorOmega",1e-4};
+  Gaudi::Property<float> _initialTrackError_z0{this, "InitialTrackErrorZ0",1e6};
+  Gaudi::Property<float> _initialTrackError_tanL{this, "InitialTrackErrorTanL",1e2};
+  Gaudi::Property<float> _maxChi2PerHit{this, "MaxChi2PerHit", 1e2};
+  Gaudi::Property<int> _checkForDelta{this, "CheckForDelta", 1};
+  Gaudi::Property<float> _minDistToDelta{this, "MinDistToDelta", 0.25};
+  Gaudi::Property<bool> _MSOn{this, "MultipleScatteringOn", true};
+  Gaudi::Property<bool> _ElossOn{this, "EnergyLossOn", true};
+  Gaudi::Property<bool> _SmoothOn{this, "SmoothOn", true};
+  Gaudi::Property<float> _helix_max_r{this, "HelixMaxR", 2000.};
+  
+  //std::vector<int> _colours;  
+  
+  /** helper function to get collection using try catch block */
+  //LCCollection* GetCollection(  LCEvent * evt, std::string colName ) ;
+  
+  /** helper function to get relations using try catch block */
+  //LCRelationNavigator* GetRelations( LCEvent * evt, std::string RelName ) ;
+  
+  /** input MCParticle collection and threshold used for Drawing
+   */
+  //Gaudi::Property<Float> _MCpThreshold{this, "MCpThreshold", 0.1};
+  //std::string  _colNameMCParticles;
+  
+  /// Compare tracks according to their chi2/ndf
+  struct compare_TrackExtended{
+    // n.b.: a and b should be TrackExtended const *, but the getters are not const :-(
+    bool operator()(TrackExtended *a, TrackExtended *b) const {
+      if ( a == b ) return false;
+      return (a->getChi2()/a->getNDF() < b->getChi2()/b->getNDF() );
+    }
+  };
+  
+  
+  //std::string _VTXHitCollection;
+  //std::string _FTDPixelHitCollection;
+  //std::string _FTDSpacePointCollection;
+  //std::string _SITHitCollection;
+  //std::string _siTrkCollection;
+  
+  //std::vector< LCCollection* > _colTrackerHits;
+  //std::map< LCCollection*, std::string > _colNamesTrackerHits;
+
+  // Input collections
+  DataHandle<edm4hep::EventHeaderCollection> _headerColHdl{"EventHeaderCol", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::MCParticleCollection> _inMCColHdl{"MCParticle", Gaudi::DataHandle::Reader, this};
+  //DataHandle<edm4hep::TrackerHitPlaneCollection> _inVTXColHdl{"VXDCollection", Gaudi::DataHandle::Reader, this};
+  //DataHandle<edm4hep::TrackerHitPlaneCollection> _inFTDPixelColHdl{"FTDPixelCollection", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inVTXColHdl{"VXDTrackerHits", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inFTDPixelColHdl{"FTDPixelTrackerHits", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inFTDSpacePointColHdl{"FTDSpacePoints", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inSITColHdl{"SITTrackerHits", Gaudi::DataHandle::Reader, this};
+  // Output collections
+  DataHandle<edm4hep::TrackCollection> _outColHdl{"SiTracks", Gaudi::DataHandle::Writer, this};
+  //DataHandle<edm4hep::LCRelationCollection> _outRelColHdl{"TrackerHitRelations", Gaudi::DataHandle::Reader, this};
+  
+  std::vector<TrackerHitExtendedVec> _sectors;
+  std::vector<TrackerHitExtendedVec> _sectorsFTD;
+  
+  /**
+   * A helper class to allow good code readability by accessing tracks with N hits.
+   * As the smalest valid track contains three hits, but the first index in a vector is 0,
+   * this class hides the index-3 calculation. As the vector access is inline there should be
+   * no performance penalty.
+   */
+  class TracksWithNHitsContainer {
+  public:
+    /// Empty all the vectors and delete the tracks contained in it.
+    void clear();
+    
+    /// Set the size to allow a maximum of maxHit hits.
+    inline void resize(size_t maxHits) {
+      _tracksNHits.resize(maxHits-2);
+      _maxIndex=(maxHits-3);
+    }
+    
+    // Sort all track vectors according to chi2/nDof
+    //      void sort();
+    
+    /// Returns the  TrackExtendedVec for track with n hits. 
+    /// In case n is larger than the maximal number the vector with the largest n ist returned.
+    /// \attention The smallest valid number is three! For
+    /// performance reasons there is no safety check!
+    inline TrackExtendedVec & getTracksWithNHitsVec( size_t nHits ) {
+      //return _tracksNHits[ std::min(nHits-3, _maxIndex) ];
+      // for debugging: with boundary check
+      return _tracksNHits.at(std::min(nHits-3, _maxIndex));
+    }
+    
+  protected:
+    std::vector< TrackExtendedVec > _tracksNHits;
+    size_t _maxIndex; /// local cache variable to avoid calculation overhead
+  };
+  
+  TracksWithNHitsContainer _tracksWithNHitsContainer;
+  
+  int InitialiseVTX();
+  int InitialiseFTD();
+  void ProcessOneSector(int iSectorPhi, int iSectorTheta);
+  void CleanUp();
+  TrackExtended * TestTriplet(TrackerHitExtended * outerHit, 
+                              TrackerHitExtended * middleHit,
+                              TrackerHitExtended * innerHit,
+                              HelixClass & helix);
+  
+  int BuildTrack(TrackerHitExtended * outerHit, 
+                 TrackerHitExtended * middleHit,
+                 TrackerHitExtended * innerHit,
+                 HelixClass & helix, 
+                 int innerlayer,
+                 int iPhiLow, int iPhiUp,
+                 int iTheta, int iThetaUp,
+                 TrackExtended * trackAR);
+  
+  void Sorting( TrackExtendedVec & trackVec);
+  void CreateTrack(TrackExtended * trackAR );
+  void AttachRemainingVTXHitsSlow();
+  void AttachRemainingFTDHitsSlow();
+  void AttachRemainingVTXHitsFast();
+  void AttachRemainingFTDHitsFast();
+  void TrackingInFTD();
+  int BuildTrackFTD(TrackExtended* trackAR, int* nLR, int iS);
+  int AttachHitToTrack(TrackExtended * trackAR, TrackerHitExtended * hit, int iopt);
+  
+  void FinalRefit(edm4hep::TrackCollection*);//, edm4hep::LCRelationCollection*);
+  
+  float _bField;
+  
+  // two pi is not a constant in cmath. Calculate it, once!
+  static const double TWOPI;
+  
+  double _dPhi;
+  double _dTheta;
+  double _dPhiFTD;
+  
+  float _resolutionRPhiVTX;
+  float _resolutionZVTX;
+  
+  float _resolutionRPhiFTD;
+  float _resolutionZFTD;
+  
+  float _resolutionRPhiSIT;
+  float _resolutionZSIT;
+  
+  float _phiCutForMerging;
+  float _tanlambdaCutForMerging;
+  //float _angleCutForMerging;
+  
+  float _distRPhi;
+  float _distZ;
+  
+  float _cutOnOmega;
+
+  TrackExtendedVec _trackImplVec;
+      
+  int _nTotalVTXHits,_nTotalFTDHits,_nTotalSITHits;
+  
+  //  int _createMap;
+  
+  UTIL::BitField64* _encoder;
+  int getDetectorID(edm4hep::TrackerHit* hit) { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::subdet]; }
+  int getSideID(edm4hep::TrackerHit* hit)     { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::side]; };
+  int getLayerID(edm4hep::TrackerHit* hit)    { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::layer]; };
+  int getModuleID(edm4hep::TrackerHit* hit)   { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::module]; };
+  int getSensorID(edm4hep::TrackerHit* hit)   { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::sensor]; };
+  
+  StatusCode setupGearGeom() ;
+  
+  std::vector<float> _zLayerFTD;
+  
+  unsigned int _nlayersFTD;
+  bool _petalBasedFTDWithOverlaps;
+  int _nPhiFTD; 
+
+  int _output_track_col_quality;
+  static const int _output_track_col_quality_GOOD;
+  static const int _output_track_col_quality_FAIR;
+  static const int _output_track_col_quality_POOR;
+
+  std::vector<edm4hep::TrackerHit> _allHits;
+} ;
+
+#endif
+
+
+
diff --git a/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.h~ b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.h~
new file mode 100644
index 0000000000000000000000000000000000000000..6418e101980a2436d1c4bd4d63c35c0558b62441
--- /dev/null
+++ b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.h~
@@ -0,0 +1,429 @@
+#ifndef SiliconTrackingAlg_h
+#define SiliconTrackingAlg_h
+
+//#include "marlin/Processor.h"
+//#include <marlin/Global.h>
+#include "FWCore/DataHandle.h"
+#include "GaudiAlg/GaudiAlgorithm.h"
+#include "edm4hep/EventHeaderCollection.h"
+#include "edm4hep/MCParticleCollection.h"
+#include "edm4hep/SimTrackerHitCollection.h"
+#include "edm4hep/TrackerHitCollection.h"
+#include "edm4hep/TrackCollection.h"
+//#include "edm4hep/LCRelationCollection.h"
+
+//#include "lcio.h"
+#include <string>
+#include <vector>
+#include <cmath>
+//#include <IMPL/TrackImpl.h>
+#include "DataHelper/ClusterExtended.h"
+#include "DataHelper/TrackExtended.h"
+#include "DataHelper/TrackerHitExtended.h"
+#include "DataHelper/HelixClass.h"
+
+#include "TrackSystemSvc/IMarlinTrack.h"
+
+#include <UTIL/BitField64.h>
+#include <UTIL/ILDConf.h>
+
+//using namespace edm4hep ;
+
+namespace gear{
+  class GearMgr ;
+}
+
+namespace MarlinTrk {
+  class HelixFit;
+  class IMarlinTrkSystem ;
+}
+
+namespace UTIL{
+  class LCRelationNavigator ;
+}
+
+class TrackExtended;
+class TrackerHitExtended;
+class HelixClass;
+
+/** === Silicon Tracking Processor === <br>
+ * Processor performing stand-alone pattern recognition
+ * in the vertex detector (VTX), forward tracking disks and SIT. <br>
+ * The procedure consists of three steps : <br> 
+ * 1) Tracking in VTX and SIT ; <br>
+ * 2) Tracking in FTD ; <br>
+ * 3) Merging compatible track segments reconstructed in VTX and FTD <br>
+ * STEP 1 : TRACKING IN VTX and SIT <br>
+ * Algorithm starts with finding of hit triplets satisfying helix hypothesis <br> 
+ * in three different layers. Two layers of SIT are effectively considered as outermost <br>
+ * layers of the vertex detector. To accelerate procedure, the 4-pi solid angle
+ * is divided in NDivisionsInTheta and NDivisionsInPhi sectors in cosQ and Phi, 
+ * respectively. Triplets are looked for in 2x2 window of adjacent sectors. 
+ * Once triplet is found, attempt is made to associate additional hits to 
+ * track. Combinatin of hits is accepted for further analysis if the Chi2 
+ * of the fit is less than certain predefined threshold. All accepted 
+ * combinations are sorted in ascending order of their Chi2. First track candidate 
+ * in the sorted array is automatically accepted. The hits belonging to this track are 
+ * marked as used, and track candidates sharing these hits are discarded.
+ * The procedure proceeds with increasing index of track candidate in the sorted 
+ * array until all track candidate have been output or discarded. <br>
+ * STEP 2 : TRACKING IN FTD <br>
+ * In the next step tracking in FTD is performed. The strategy of tracking in the FTD 
+ * is the same as used for tracking in the VTX+SIT. <br>
+ * STEP 3 : MERGING TRACK SEGMENTS FOUND IN FTD AND VTX+SIT <br>
+ * In the last step, track segments reconstructed in the FTD and VTX+SIT, belonging to the
+ * same track  are identified and merged into one track. All possible 
+ * pairings are tested for their compatibility.
+ * The number of pairings considered is Ntrk_VTX_SIT*Ntrk_FTD, where Ntrk_VTX_SIT is the number of 
+ * track segments reconstructed in the first step in VTX+SIT (segments containing solely VTX and SIT hits) and
+ * Ntrk_FTD is the number of track segments reconstructed in the second step 
+ * (segments containing solely FTD hits).
+ * Pair of segments is accepted for further examination if the angle between track segments and 
+ * than certain specified threshold.
+ * Pairing satisfying this condition is subjected for 
+ * addtitional test. The fit is performed on unified array of hits belonging to both segments. 
+ * If the chi2 of the fit does not exceed predefined cut value two segments are unified into 
+ * one track. 
+ * <h4>Input collections and prerequisites</h4> 
+ * Processor requires collection of digitized vertex, sit and ftd tracker hits. <br>
+ * If such a collections with the user specified names do not exist 
+ * processor takes no action. <br>
+ * <h4>Output</h4>
+ * Processor produces an LCIO collection of the Tracks. Each track is characterised by 
+ * five parameters : Omega (signed curvuture), Tan(lambda) where
+ * lambda is the dip angle, Phi (azimuthal angle @ point of closest approach), D0 (signed impact parameter),
+ * Z0 (displacement along z axis at the point of closest approach to IP). Covariance matrix for these parameters is also provided.
+ * Only lower left corner of the covariance matrix is stored. The sequence of the covariance matrix elements 
+ * assigned to track is the following: <br>
+ * (Omega,Omega) <br>
+ * (Omega,TanLambda), (TanLambda,TanLambda) <br>
+ * (Omega,Phi), (TanLamda,Phi), (Phi,Phi) <br>
+ * (Omega,D0), (TanLambda,D0), (Phi,D0), (D0,D0) <br>
+ * (Omega,Z0), (TanLambda,Z0), (Phi,Z0), (D0,Z0), (Z0,Z0) <br>
+ * The number of hits in the different subdetectors associated
+ * with each track can be accessed via method Track::getSubdetectorHitNumbers().
+ * This method returns vector of integers : <br>
+ * number of VTX hits in track is the first element in this vector  
+ * (Track::getSubdetectorHitNumbers()[0]) <br>
+ * number of FTD hits in track is the second element in this vector  
+ * (Track::getSubdetectorHitNumbers()[1]) <br>
+ * number of SIT hits in track is the third element in this vector  
+ * (Track::getSubdetectorHitNumbers()[2]) <br>
+ * Output track collection has a name "SiTracks". <br>
+ * @param VTXHitCollectionName name of input VTX TrackerHit collection <br>
+ * (default parameter value : "VTXTrackerHits") <br>
+ * @param FTDHitCollectionName name of input FTD TrackerHit collection <br>
+ * (default parameter value : "FTDTrackerHits") <br>
+ * @param SITHitCollectionName name of input SIT TrackerHit collection <br>
+ * (default parameter value : "SITTrackerHits") <br>
+ * @param SiTrackCollectionName name of the output Silicon track collection <br>
+ * (default parameter value : "SiTracks") <br>
+ * @param LayerCombinations combinations of layers used to search for hit triplets in VTX+SIT <br>
+ * (default parameters : 6 4 3  6 4 2  6 3 2  5 4 3  5 4 2  5 3 2  4 3 2  4 3 1  4 2 1  3 2 1) <br> 
+ * Note that in the VTX+SIT system the first and the second layers of SIT have indicies nLayerVTX and nLayerVTX+1. 
+ * Combination given above means that triplets are looked first in layers 6 4 3, and then 
+ * in 6 4 2;  5 4 3;  6 3 2 etc. NOTE THAT LAYER INDEXING STARTS FROM 0.
+ * LAYER 0 is the innermost layer  <br>
+ * @param LayerCombinationsFTD combinations of layers used to search for hit triplets in FTD <br>
+ * (default parameters 6 5 4  5 4 3  5 4 2  5 4 1  5 3 2  5 3 1  5 2 1  4 3 2  4 3 1  
+ *  4 3 0  4 2 1  4 2 0  4 1 0  3 2 1  3 2 0  3 1 0  2 1 0). 
+ * NOTE THAT TRACKS IN FTD ARE SEARCHED ONLY IN ONE HEMISPHERE. TRACK IS NOT 
+ * ALLOWED TO HAVE HITS BOTH IN BACKWARD AND FORWARD PARTS OF FTD SIMULTANEOUSLY. 
+ * @param NDivisionsInPhi Number of divisions in Phi for tracking in VTX+SIT <br>
+ * (default value is 40) <br>
+ * @param NDivisionsInTheta Number of divisions in cosQ for tracking in VTX+SIT <br>
+ * (default value is 40) <br>
+ * @param NDivisionsInPhiFTD Number of divisions in Phi for tracking in FTD <br>
+ * (default value is 3) <br>
+ * @param Chi2WRphiTriplet weight on chi2 in R-Phi plane for track with 3 hits <br>
+ * (default value is 1) <br>
+ * @param Chi2WZTriplet weight on chi2 in S-Z plane for track with 3 hits <br>
+ * (default value is 0.5) <br>
+ * @param Chi2WRphiQuartet weight on chi2 in R-Phi plane to accept track with 4 hits <br>
+ * (default value is 1) <br>
+ * @param Chi2WZQuartet weight on chi2 in S-Z plane for track with 4 hits <br>
+ * (default value is 0.5) <br>
+ * @param Chi2WRphiSeptet weight on chi2 in R-Phi plane for track with 5 and more hits <br>
+ * (default value is 1) <br>
+ * @param Chi2WZSeptet Cut on chi2 in S-Z plane for track with 5 and more hits <br>
+ * (default value is 0.5) <br>
+ * @param Chi2FitCut Cut on chi2/ndf to accept track candidate <br>
+ * (default value is 100.) <br>
+ * @param AngleCutForMerging cut on the angle between two track segments.  
+ * If the angle is greater than this cut, segments are not allowed to be merged. <br>
+ * (default value is 0.1) <br>
+ * @param MinDistCutAttach cut on the distance (in mm) from hit to the helix. This parameter is used
+ * to decide whether hit can be attached to the track. If the distance is less than 
+ * cut value. The track is refitted with a given hit being added to the list of hits already 
+ * assigned for the track. Additional hit is assigned if chi2 of the new fit has good chi2. <br>
+ * (default value is 2 ) <br>
+ * @param MinLayerToAttach the minimal layer index to attach VTX hits to the found hit triplets <br>
+ * (default value is -1) <br>
+ * @param CutOnZ0 cut on Z0 parameter of track (in mm). If abs(Z0) is greater than the cut value, track is 
+ * discarded (used to suppress fake
+ * track rate in the presence of beam induced background hits) <br>
+ * (default value is 100) <br>
+ * @param CutOnD0 cut on D0 parameter of track (in mm). If abs(D0) is greater than the cut value, track is 
+ * discarded (used to suppress fake
+ * track rate in the presence of beam induced background hits) <br>
+ * (default value is 100) <br>
+ * @param CutOnPt cut on Pt (GeV/c). If Pt is less than this cut, track is discarded (used to suppress fake
+ * track rate in the presence of beam induced background hits) <br>
+ * (default value is 0.1) <br>
+ * @param MinimalHits minimal number of hits in track required <br>
+ * (default value is 3) <br>
+ * @param NHitsChi2 Maximal number of hits for which a track with n hits is aways better than one with n-1 hits.
+ * For tracks with equal or more than NHitsChi2 the track  with the lower \f$\chi^2\f$ is better.
+ * (default value is 5) <br>
+ * @param FastAttachment if this flag is set to 1, less accurate but fast procedure to merge additional hits to tracks is used <br> 
+ * if set to 0, a more accurate, but slower procedure is invoked <br>
+ * (default value is 0) <br>
+ * @param UseSIT When this flag is set to 1, SIT is included in pattern recognition. When this flag is set
+ * to 0, SIT is excluded from the procedure of pattern recognition <br>
+ * (default value is 1) <br>
+ * <br>
+ * @author A. Raspereza (MPI Munich)<br>
+ */
+class SiliconTrackingAlg : public GaudiAlgorithm {
+ public:
+  
+  SiliconTracking(const std::string& name, ISvcLocator* svcLoc);
+  
+  virtual StatusCode initialize() ;
+  
+  virtual StatusCode execute() ; 
+  
+  virtual StatusCode finalize() ;
+  
+protected:
+  
+  int _nRun ;
+  int _nEvt ;
+  //EVENT::LCEvent* _current_event;
+  int _nLayers;
+  unsigned int _nLayersVTX;
+  unsigned int _nLayersSIT;
+  int _ntriplets, _ntriplets_good, _ntriplets_2MCP, _ntriplets_3MCP, _ntriplets_1MCP_Bad, _ntriplets_bad;
+  
+  MarlinTrk::HelixFit* _fastfitter;
+  gear::GearMgr* _GEAR;
+  /** pointer to the IMarlinTrkSystem instance 
+   */
+  MarlinTrk::IMarlinTrkSystem* _trksystem ;
+  //bool _runMarlinTrkDiagnostics;
+  //std::string _MarlinTrkDiagnosticsName;
+  typedef std::vector<int> IntVec;
+  
+  Gaudi::Property<IntVec> _Combinations{this, "LayerCombinations", {8,6,5, 8,6,4, 8,6,3, 8,6,2, 8,5,3, 8,5,2, 8,4,3, 8,4,2, 6,5,3, 6,5,2, 6,4,3, 6,4,2, 6,3,1, 6,3,0, 6,2,1, 6,2,0,
+	5,3,1, 5,3,0, 5,2,1, 5,2,0, 4,3,1, 4,3,0, 4,2,1, 4,2,0}};
+  Gaudi::Property<IntVec> _CombinationsFTD{this, "LayerCombinationsFTD", {4,3,2, 4,3,1, 4,3,0, 4,2,1, 4,2,0, 4,1,0, 3,2,1, 3,2,0, 3,1,0, 2,1,0,
+	9,8,7, 9,8,6, 9,8,5, 9,7,6, 9,7,5, 9,6,5, 8,7,6, 8,7,5, 8,6,5, 7,6,5}};
+  Gaudi::Property<int> _nDivisionsInPhi{this, "NDivisionsInPhi", 80};
+  Gaudi::Property<int> _nDivisionsInPhiFTD{this, "NDivisionsInPhiFTD", 30};
+  Gaudi::Property<int> _nDivisionsInTheta{this, "NDivisionsInTheta", 80};
+  Gaudi::Property<float> _chi2WRPhiTriplet{this, "Chi2WRphiTriplet", 1.};
+  Gaudi::Property<float> _chi2WRPhiQuartet{this, "Chi2WRphiQuartet", 1.};
+  Gaudi::Property<float> _chi2WRPhiSeptet{this, "Chi2WRphiSeptet", 1.};
+  Gaudi::Property<float> _chi2WZTriplet{this, "Chi2WZTriplet", 0.5};
+  Gaudi::Property<float> _chi2WZQuartet{this, "Chi2WZQuartet", 0.5};
+  Gaudi::Property<float> _chi2WZSeptet{this, "Chi2WZSeptet", 0.5};
+  Gaudi::Property<float> _chi2FitCut{this, "Chi2FitCut", 120.};
+  Gaudi::Property<float> _angleCutForMerging{this, "AngleCutForMerging", 0.1};
+  Gaudi::Property<float> _minDistCutAttach{this, "MinDistCutAttach", 2.5};
+  Gaudi::Property<float> _minimalLayerToAttach{this, "MinLayerToAttach", -1};
+  Gaudi::Property<float> _cutOnD0{this, "CutOnD0", 100.0};
+  Gaudi::Property<float> _cutOnZ0{this, "CutOnZ0", 100.0};
+  Gaudi::Property<float> _cutOnPt{this, "CutOnPt", 0.05};
+  Gaudi::Property<int> _minimalHits{this, "MinimalHits",3};
+  Gaudi::Property<int> _nHitsChi2{this, "NHitsChi2", 5};
+  Gaudi::Property<int> _max_hits_per_sector{this, "MaxHitsPerSector", 100};
+  Gaudi::Property<int> _attachFast{this, "FastAttachment", 0};
+  Gaudi::Property<bool> _useSIT{this, "UseSIT", true};
+  Gaudi::Property<float> _initialTrackError_d0{this, "InitialTrackErrorD0",1e6};
+  Gaudi::Property<float> _initialTrackError_phi0{this, "InitialTrackErrorPhi0",1e2};
+  Gaudi::Property<float> _initialTrackError_omega{this, "InitialTrackErrorOmega",1e-4};
+  Gaudi::Property<float> _initialTrackError_z0{this, "InitialTrackErrorZ0",1e6};
+  Gaudi::Property<float> _initialTrackError_tanL{this, "InitialTrackErrorTanL",1e2};
+  Gaudi::Property<float> _maxChi2PerHit{this, "MaxChi2PerHit", 1e2};
+  Gaudi::Property<int> _checkForDelta{this, "CheckForDelta", 1};
+  Gaudi::Property<float> _minDistToDelta{this, "MinDistToDelta", 0.25};
+  Gaudi::Property<bool> _MSOn{this, "MultipleScatteringOn", true};
+  Gaudi::Property<bool> _ElossOn{this, "EnergyLossOn", true};
+  Gaudi::Property<bool> _SmoothOn{this, "SmoothOn", true};
+  Gaudi::Property<float> _helix_max_r{this, "HelixMaxR", 2000.};
+  
+  //std::vector<int> _colours;  
+  
+  /** helper function to get collection using try catch block */
+  //LCCollection* GetCollection(  LCEvent * evt, std::string colName ) ;
+  
+  /** helper function to get relations using try catch block */
+  //LCRelationNavigator* GetRelations( LCEvent * evt, std::string RelName ) ;
+  
+  /** input MCParticle collection and threshold used for Drawing
+   */
+  //Gaudi::Property<Float> _MCpThreshold{this, "MCpThreshold", 0.1};
+  //std::string  _colNameMCParticles;
+  
+  /// Compare tracks according to their chi2/ndf
+  struct compare_TrackExtended{
+    // n.b.: a and b should be TrackExtended const *, but the getters are not const :-(
+    bool operator()(TrackExtended *a, TrackExtended *b) const {
+      if ( a == b ) return false;
+      return (a->getChi2()/a->getNDF() < b->getChi2()/b->getNDF() );
+    }
+  };
+  
+  
+  //std::string _VTXHitCollection;
+  //std::string _FTDPixelHitCollection;
+  //std::string _FTDSpacePointCollection;
+  //std::string _SITHitCollection;
+  //std::string _siTrkCollection;
+  
+  //std::vector< LCCollection* > _colTrackerHits;
+  //std::map< LCCollection*, std::string > _colNamesTrackerHits;
+
+  // Input collections
+  DataHandle<edm4hep::EventHeaderCollection> _headerColHdl{"EventHeaderCol", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::MCParticleCollection> _inMCColHdl{"MCParticle", Gaudi::DataHandle::Reader, this};
+  //DataHandle<edm4hep::TrackerHitPlaneCollection> _inVTXColHdl{"VXDCollection", Gaudi::DataHandle::Reader, this};
+  //DataHandle<edm4hep::TrackerHitPlaneCollection> _inFTDPixelColHdl{"FTDPixelCollection", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inVTXColHdl{"VXDTrackerHits", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inFTDPixelColHdl{"FTDPixelTrackerHits", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inFTDSpacePointColHdl{"FTDSpacePoints", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::TrackerHitCollection> _inSITColHdl{"SITTrackerHits", Gaudi::DataHandle::Reader, this};
+  // Output collections
+  DataHandle<edm4hep::TrackCollection> _outColHdl{"SiTracks", Gaudi::DataHandle::Writer, this};
+  //DataHandle<edm4hep::LCRelationCollection> _outRelColHdl{"TrackerHitRelations", Gaudi::DataHandle::Reader, this};
+  
+  std::vector<TrackerHitExtendedVec> _sectors;
+  std::vector<TrackerHitExtendedVec> _sectorsFTD;
+  
+  /**
+   * A helper class to allow good code readability by accessing tracks with N hits.
+   * As the smalest valid track contains three hits, but the first index in a vector is 0,
+   * this class hides the index-3 calculation. As the vector access is inline there should be
+   * no performance penalty.
+   */
+  class TracksWithNHitsContainer {
+  public:
+    /// Empty all the vectors and delete the tracks contained in it.
+    void clear();
+    
+    /// Set the size to allow a maximum of maxHit hits.
+    inline void resize(size_t maxHits) {
+      _tracksNHits.resize(maxHits-2);
+      _maxIndex=(maxHits-3);
+    }
+    
+    // Sort all track vectors according to chi2/nDof
+    //      void sort();
+    
+    /// Returns the  TrackExtendedVec for track with n hits. 
+    /// In case n is larger than the maximal number the vector with the largest n ist returned.
+    /// \attention The smallest valid number is three! For
+    /// performance reasons there is no safety check!
+    inline TrackExtendedVec & getTracksWithNHitsVec( size_t nHits ) {
+      //return _tracksNHits[ std::min(nHits-3, _maxIndex) ];
+      // for debugging: with boundary check
+      return _tracksNHits.at(std::min(nHits-3, _maxIndex));
+    }
+    
+  protected:
+    std::vector< TrackExtendedVec > _tracksNHits;
+    size_t _maxIndex; /// local cache variable to avoid calculation overhead
+  };
+  
+  TracksWithNHitsContainer _tracksWithNHitsContainer;
+  
+  int InitialiseVTX();
+  int InitialiseFTD();
+  void ProcessOneSector(int iSectorPhi, int iSectorTheta);
+  void CleanUp();
+  TrackExtended * TestTriplet(TrackerHitExtended * outerHit, 
+                              TrackerHitExtended * middleHit,
+                              TrackerHitExtended * innerHit,
+                              HelixClass & helix);
+  
+  int BuildTrack(TrackerHitExtended * outerHit, 
+                 TrackerHitExtended * middleHit,
+                 TrackerHitExtended * innerHit,
+                 HelixClass & helix, 
+                 int innerlayer,
+                 int iPhiLow, int iPhiUp,
+                 int iTheta, int iThetaUp,
+                 TrackExtended * trackAR);
+  
+  void Sorting( TrackExtendedVec & trackVec);
+  void CreateTrack(TrackExtended * trackAR );
+  void AttachRemainingVTXHitsSlow();
+  void AttachRemainingFTDHitsSlow();
+  void AttachRemainingVTXHitsFast();
+  void AttachRemainingFTDHitsFast();
+  void TrackingInFTD();
+  int BuildTrackFTD(TrackExtended* trackAR, int* nLR, int iS);
+  int AttachHitToTrack(TrackExtended * trackAR, TrackerHitExtended * hit, int iopt);
+  
+  void FinalRefit(edm4hep::TrackCollection*);//, edm4hep::LCRelationCollection*);
+  
+  float _bField;
+  
+  // two pi is not a constant in cmath. Calculate it, once!
+  static const double TWOPI;
+  
+  double _dPhi;
+  double _dTheta;
+  double _dPhiFTD;
+  
+  float _resolutionRPhiVTX;
+  float _resolutionZVTX;
+  
+  float _resolutionRPhiFTD;
+  float _resolutionZFTD;
+  
+  float _resolutionRPhiSIT;
+  float _resolutionZSIT;
+  
+  float _phiCutForMerging;
+  float _tanlambdaCutForMerging;
+  //float _angleCutForMerging;
+  
+  float _distRPhi;
+  float _distZ;
+  
+  float _cutOnOmega;
+
+  TrackExtendedVec _trackImplVec;
+      
+  int _nTotalVTXHits,_nTotalFTDHits,_nTotalSITHits;
+  
+  //  int _createMap;
+  
+  UTIL::BitField64* _encoder;
+  int getDetectorID(edm4hep::TrackerHit* hit) { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::subdet]; }
+  int getSideID(edm4hep::TrackerHit* hit)     { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::side]; };
+  int getLayerID(edm4hep::TrackerHit* hit)    { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::layer]; };
+  int getModuleID(edm4hep::TrackerHit* hit)   { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::module]; };
+  int getSensorID(edm4hep::TrackerHit* hit)   { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::sensor]; };
+  
+  StatusCode setupGearGeom() ;
+  
+  std::vector<float> _zLayerFTD;
+  
+  unsigned int _nlayersFTD;
+  bool _petalBasedFTDWithOverlaps;
+  int _nPhiFTD; 
+
+  int _output_track_col_quality;
+  static const int _output_track_col_quality_GOOD;
+  static const int _output_track_col_quality_FAIR;
+  static const int _output_track_col_quality_POOR;
+
+  std::vector<edm4hep::TrackerHit> _allHits;
+} ;
+
+#endif
+
+
+
diff --git a/Utilities/DataHelper/CMakeLists.txt~ b/Utilities/DataHelper/CMakeLists.txt~
deleted file mode 100644
index ccbc04fc3b35548799ec0b72116c0c43b7dc1ec1..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/CMakeLists.txt~
+++ /dev/null
@@ -1,26 +0,0 @@
-gaudi_subdir(DataHelper v0r0)
-
-#find_package(CLHEP REQUIRED)
-#find_package(GEAR REQUIRED)
-#find_package(GSL REQUIRED )
-#find_package(LCIO REQUIRED )
-#find_package(podio REQUIRED )
-#find_package(K4FWCore REQUIRED)
-find_package(EDM4HEP REQUIRED)
-
-gaudi_depends_on_subdirs()
-
-set(DataHelper_srcs src/*.cc)
-
-gaudi_install_headers(DataHelper)
-
-#gaudi_add_library(DataHelperLib ${DataHelperLib_srcs}
-#    PUBLIC_HEADERS DataHelper
-#    LINK_LIBRARIES EDM4HEP::edm4hep EDM4HEP::edm4hepDict
-#)
-
-# Modules
-gaudi_add_module(DataHelper ${DataHelper_srcs}
-    INCLUDE_DIRS K4FWCore GaudiKernel GaudiAlgLib CLHEP gear ${GSL_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS}
-    LINK_LIBRARIES K4FWCore GaudiKernel GaudiAlgLib CLHEP $ENV{GEAR}/lib/libgearsurf.so ${GSL_LIBRARIES} ${LCIO_LIBRARIES} EDM4HEP::edm4hep EDM4HEP::edm4hepDict
-)
diff --git a/Utilities/DataHelper/src/CaloHitExtended.cc~ b/Utilities/DataHelper/src/CaloHitExtended.cc~
deleted file mode 100644
index 3adab51d1e2e032a1e61294379faea57bfe631a7..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/CaloHitExtended.cc~
+++ /dev/null
@@ -1,128 +0,0 @@
-#include "CaloHitExtended.h"
-#include <math.h>
-
-CaloHitExtended::CaloHitExtended(const edm4hep::CalorimeterHit& calhit, int type)
-  :_calohit(calhit){
-  _type    = type;
-  _index   = 0;
-  _calohitTo = NULL;
-  _calohitFrom = NULL;
-}
-
-CaloHitExtended::~CaloHitExtended(){    
-}
-
-CalorimeterHit* CaloHitExtended::getCalorimeterHit() {    
-    return &_calohit;
-}
-
-CaloHitExtended* CaloHitExtended::getCaloHitTo() {
-    return _calohitTo;
-}
-
-CaloHitExtended* CaloHitExtended::getCaloHitFrom() {
-    return _calohitFrom;
-}
-
-ClusterExtended* CaloHitExtended::getClusterExtended() {
-    return _clusterAR;    
-}
-
-int CaloHitExtended::getIndex() {
-    return _index;
-
-}
-
-int CaloHitExtended::getType() {
-    return _type;
-
-}
-const float* CaloHitExtended::getDirVec() {
-    return _dirVec;
-}
-
-float  CaloHitExtended::getYresTo() {
-    return _yresTo;
-}
-
-float  CaloHitExtended::getYresFrom() {
-    return _yresFrom;
-}
-
-
-
-float  CaloHitExtended::getGenericDistance() {
-    return _genericDistance;
-}
-
-//void CaloHitExtended::setCalorimeterHit(CalorimeterHit* calhit) {
-//    _calohit = calhit;
-//}
-
-void CaloHitExtended::setCaloHitTo(CaloHitExtended* calhitto) {
-    _calohitTo = calhitto; 
-}
-
-void CaloHitExtended::setCaloHitFrom(CaloHitExtended* calhitfrom) {
-    _calohitFrom = calhitfrom; 
-}
-
-void CaloHitExtended::setClusterExtended(ClusterExtended* cluster) {
-    _clusterAR = cluster;
-}
-
-void CaloHitExtended::setIndex(int index) {
-    _index = index;
-}
-
-void CaloHitExtended::setType(int type) {
-    _type = type;
-}
-
-void CaloHitExtended::setDirVec(float* dirVec) {    
-    float modulus(0.);
-    for (int i(0); i < 3; ++i) {
-	modulus += dirVec[i]*dirVec[i];
-    }
-
-    modulus = sqrt(modulus);
-
-    if (modulus <= 0.) {
-	_dirVec[0] = 0.;
-	_dirVec[1] = 0.;
-	_dirVec[2] = 1.;
-    }
-    else {
-	_dirVec[0] = dirVec[0] / modulus;
-	_dirVec[1] = dirVec[1] / modulus;
-	_dirVec[2] = dirVec[2] / modulus;
-    }
-}
-
-void CaloHitExtended::setYresTo(float yresto) {
-    _yresTo = yresto;
-}
-
-void CaloHitExtended::setYresFrom(float yresfrom) {
-    _yresFrom = yresfrom;
-}
-
-void CaloHitExtended::setGenericDistance(float genericDistance) {
-    _genericDistance = genericDistance;
-}
-
-void CaloHitExtended::setDistanceToCalo(float caloDistance) {
-  _caloDistance = caloDistance;
-}
-
-float CaloHitExtended::getDistanceToCalo() {
-  return _caloDistance;
-}
-
-void CaloHitExtended::setDistanceToNearestHit(float distanceToNearest) {
-  _distanceToNearestHit = distanceToNearest;
-}
-
-float CaloHitExtended::getDistanceToNearestHit() {
-  return _distanceToNearestHit;
-}
diff --git a/Utilities/DataHelper/src/CaloHitExtended.h~ b/Utilities/DataHelper/src/CaloHitExtended.h~
deleted file mode 100644
index 65781a9da8ef764072422e57be4b458117aea6c3..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/CaloHitExtended.h~
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef CaloHitExtended_H
-#define CaloHitExtended_H 1
-
-//#include "lcio.h"
-//#include "EVENT/LCIO.h"
-#include "edm4hep/CalorimeterHit.h"
-#include "ClusterExtended.h"
-
-using namespace edm4hep ;
-
-class ClusterExtended;
-
-/**
- * Class extending native LCIO class CalorimeterHit. <br>
- * Class CaloHitExtended is used in TrackwiseClustering <br>
- * and Wolf processors. <br>
- * @author A. Raspereza (DESY)<br>
- * @version $Id: CaloHitExtended.h,v 1.4 2006-02-22 14:53:27 owendt Exp $<br>
- */
-class CaloHitExtended {
-
-    public:
-
-    CaloHitExtended(CalorimeterHit* calhit, int type);
-    
-    ~CaloHitExtended();
-
-    CalorimeterHit * getCalorimeterHit();
-    CaloHitExtended * getCaloHitTo();
-    CaloHitExtended * getCaloHitFrom();
-    ClusterExtended * getClusterExtended();
-    int    getIndex();
-    int    getType();
-    const float* getDirVec();
-    float  getYresTo();
-    float  getYresFrom();
-    float  getGenericDistance();
-
-    void setCalorimeterHit(CalorimeterHit* calhit);
-    void setCaloHitTo(CaloHitExtended* calhitto);
-    void setCaloHitFrom(CaloHitExtended* calohitfrom);
-    void setClusterExtended(ClusterExtended* cluster);
-    void setIndex(int index);
-    void setType(int type);
-    void setDirVec(float* dirVec);
-    void setYresTo(float yresto);
-    void setYresFrom(float yresfrom);
-    void setGenericDistance(float genericDistance);
-    void setDistanceToCalo(float distanceToCalo);
-    float getDistanceToCalo();
-    void setDistanceToNearestHit(float distanceToNearest);
-    float getDistanceToNearestHit();
-      
-
-    private:
-    
-    CalorimeterHit * _calohit;
-    CaloHitExtended * _calohitTo;
-    CaloHitExtended * _calohitFrom;
-    ClusterExtended * _clusterAR;
-    int _index;
-    int _type;
-    float _dirVec[3];
-    float _yresTo;
-    float _yresFrom;
-    float _genericDistance;
-    float _caloDistance;
-    float _distanceToNearestHit;
-
-};
-
-#endif
diff --git a/Utilities/DataHelper/src/ClusterExtended.cc~ b/Utilities/DataHelper/src/ClusterExtended.cc~
deleted file mode 100644
index a5f99aebdda6b0d18f4f85aeff8ed1a03bf92ac0..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/ClusterExtended.cc~
+++ /dev/null
@@ -1,232 +0,0 @@
-#include "CaloHitExtended.h"
-#include "TrackExtended.h"
-#include "ClusterExtended.h"
-#include <math.h>
-
-ClusterExtended::ClusterExtended() {
-    _hitVector.clear();
-    _trackVector.clear();
-
-    _direction[0] = 0.;
-    _direction[1] = 0.;
-    _direction[2] = 0.;
-
-    _startingPoint[0] = 0.;
-    _startingPoint[1] = 0.;
-    _startingPoint[2] = 0.;	
-
-}
-
-ClusterExtended::ClusterExtended( Cluster * cluster ) {
-    _hitVector.clear();
-    _trackVector.clear();
-
-    _direction[0] = 0.;
-    _direction[1] = 0.;
-    _direction[2] = 0.;
-
-    _startingPoint[0] = 0.;
-    _startingPoint[1] = 0.;
-    _startingPoint[2] = 0.;	
-
-    _cluster = cluster;
-
-}
-
-
-
-
-ClusterExtended::ClusterExtended(CaloHitExtended * calohit) {
-
-    _hitVector.clear();
-    _hitVector.push_back(calohit);
-    _trackVector.clear();
-
-    float rad(0);
-
-    _startingPoint[0] = calohit->getCalorimeterHit()->getPosition().x;
-    _startingPoint[1] = calohit->getCalorimeterHit()->getPosition().y;
-    _startingPoint[2] = calohit->getCalorimeterHit()->getPosition().z;
-    
-    for (int i(0); i < 3; ++i) {
-	rad += _startingPoint[i]*_startingPoint[i];
-    }
-
-    rad = sqrt(rad);
-
-    _direction[0] = _startingPoint[0]/rad;
-    _direction[1] = _startingPoint[1]/rad;
-    _direction[2] = _startingPoint[2]/rad;
-    
-}
-
-ClusterExtended::ClusterExtended(TrackExtended * track) {
-    _hitVector.clear();
-    _trackVector.clear();
-    _trackVector.push_back(track);
-    for (int i(0); i < 3; ++i) {
-	_startingPoint[i] = track->getSeedPosition()[i];
-	_direction[i] = track->getSeedDirection()[i];
-    }
-}
-
-
-ClusterExtended::~ClusterExtended() {
-   _hitVector.clear(); 
-   _trackVector.clear();
-}
-
-CaloHitExtendedVec& ClusterExtended::getCaloHitExtendedVec() {
-    return _hitVector;
-}
-
-TrackExtendedVec& ClusterExtended::getTrackExtendedVec() {
-    return _trackVector;
-}
-
-const float* ClusterExtended::getStartingPoint() {
-    return _startingPoint;
-}
-
-const float* ClusterExtended::getDirection() {
-    return _direction;
-}
-
-void ClusterExtended::setStartingPoint(float* sPoint) {
-    _startingPoint[0] = sPoint[0];
-    _startingPoint[1] = sPoint[1];
-    _startingPoint[2] = sPoint[2];
-    
-}
-
-void ClusterExtended::setDirection(float* direct) {
-    _direction[0] = direct[0];
-    _direction[1] = direct[1];
-    _direction[2] = direct[2];
-}
-
-void ClusterExtended::addCaloHitExtended(CaloHitExtended* calohit) {
-    _hitVector.push_back(calohit);
-}
-
-void ClusterExtended::addTrackExtended(TrackExtended * track) {
-    _trackVector.push_back(track);
-}
-
-void ClusterExtended::Clear() {
-    _hitVector.clear();
-    _trackVector.clear();
-
-}
-
-void ClusterExtended::setType( int type ) {
-  _type = type;
-}
-
-int ClusterExtended::getType() {
-  return _type;
-}
-
-void ClusterExtended::setCluster(Cluster * cluster) {
-  _cluster = cluster;
-}
-
-Cluster * ClusterExtended::getCluster() {
-  return _cluster;
-}
-
-void ClusterExtended::setAxis(float * axis) {
-  _axis[0] = axis[0];
-  _axis[1] = axis[1];
-  _axis[2] = axis[2];
-}
-float * ClusterExtended::getAxis() {
-  return _axis;
-}
-
-void ClusterExtended::setEccentricity( float eccentricity) {
-  _eccentricity = eccentricity;
-}
-float ClusterExtended::getEccentricity() {
-  return _eccentricity;
-}
-
-void ClusterExtended::setHelix(HelixClass helix) {
-  _helix = helix;
-  int nHits = int(_hitVector.size());
-  float timeMax = -1.0e+20;
-  float timeMin = 1.0e+20;
-  for (int ihit=0;ihit<nHits;++ihit) {
-    float pos[3];
-    for (int i=0;i<3;++i)
-      pos[i]=_hitVector[ihit]->getCalorimeterHit()->getPosition()[i];
-      
-    float distance[3];
-    float time = _helix.getDistanceToPoint(pos,distance);
-    if (time > timeMax) {
-      timeMax = time;
-      _upEdge[0] = pos[0];
-      _upEdge[1] = pos[1];
-      _upEdge[2] = pos[2];
-    }
-    if (time < timeMin) {
-      timeMin = time;
-      _lowEdge[0] = pos[0];
-      _lowEdge[1] = pos[1];
-      _lowEdge[2] = pos[2];
-    }
-      
-  }
-
-}
-HelixClass & ClusterExtended::getHelix() {
-  return _helix;
-}
-
-void ClusterExtended::setHelixChi2R(float helixChi2) {
-  _helixChi2R = helixChi2;
-}
-float ClusterExtended::getHelixChi2R() {
-  return _helixChi2R;
-}
-
-void ClusterExtended::setHelixChi2Z(float helixChi2) {
-  _helixChi2Z = helixChi2;
-}
-float ClusterExtended::getHelixChi2Z() {
-  return _helixChi2Z;
-}
-
-
-
-void ClusterExtended::setPosition(float * position) {
-  _position[0] = position[0];
-  _position[1] = position[1];
-  _position[2] = position[2];
-
-}
-
-float * ClusterExtended::getPosition() {
-  return _position;
-}
-
-void ClusterExtended::setUpEdge(float * upEdge) {
-  _upEdge[0] = upEdge[0];
-  _upEdge[1] = upEdge[1];
-  _upEdge[2] = upEdge[2];
-}
-
-void ClusterExtended::setLowEdge(float * lowEdge) {
-  _lowEdge[0] = lowEdge[0]; 
-  _lowEdge[1] = lowEdge[1]; 
-  _lowEdge[2] = lowEdge[2]; 
-}
-
-float * ClusterExtended::getUpEdge() {
-  return _upEdge;
-}
-
-float * ClusterExtended::getLowEdge() {
-  return _lowEdge;
-}
-
diff --git a/Utilities/DataHelper/src/ClusterExtended.h~ b/Utilities/DataHelper/src/ClusterExtended.h~
deleted file mode 100644
index 4a1802408875a859b16673659ca4f71545590eb4..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/ClusterExtended.h~
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef ClusterExtended_H
-#define ClusterExtended_H 1
-
-#include "CaloHitExtended.h"
-#include "TrackExtended.h"
-#include "plcio/Cluster.h"
-#include "HelixClass.h"
-
-using namespace plcio;
-
-//class TrackExtended;
-//typedef std::vector<TrackExtended*> TrackExtendedVec;
-
-//class CaloHitExtended;
-//typedef std::vector<CaloHitExtended*> CaloHitExtendedVec;
-
-//class ClusterExtended;
-//typedef std::vector<ClusterExtended*> ClusterExtendedVec;
-
-/**
- * Class extending native LCIO class Cluster. <br>
- * Class ClusterExtended is used in TrackwiseClustering <br>
- * and Wolf processors. <br>
- * @author A. Raspereza (DESY)<br>
- * @version $Id: ClusterExtended.h,v 1.4 2006-02-22 14:41:41 owendt Exp $<br>
- */
-
-class ClusterExtended {
-
- public:
-
-    ClusterExtended();
-    ClusterExtended( Cluster * cluster );
-    ClusterExtended(CaloHitExtended * calohit);
-    ClusterExtended(TrackExtended * track);
-
-    ~ClusterExtended();
-    
-    CaloHitExtendedVec & getCaloHitExtendedVec();
-    TrackExtendedVec & getTrackExtendedVec();
-    const float* getStartingPoint();
-    const float* getDirection();
-    void setStartingPoint(float* sPoint);
-    void setDirection(float* direct);
-    void addCaloHitExtended(CaloHitExtended * calohit);
-    void addTrackExtended(TrackExtended * track);
-    void setType( int type );
-    int getType();
-
-    void Clear();
-
-    void setCluster(Cluster * cluster);
-    Cluster * getCluster();
-
-    void setAxis(float * axis);
-    float * getAxis();
-
-    void setEccentricity( float eccentricity);
-    float getEccentricity();
-
-    void setHelix(HelixClass helix);
-    HelixClass & getHelix();
-
-    void setHelixChi2R(float helixChi2);
-    float getHelixChi2R();
-
-    void setHelixChi2Z(float helixChi2);
-    float getHelixChi2Z();
-
-    void setPosition(float * position);
-    float * getPosition();
-
-    void setLowEdge(float * lowEdge);
-    float * getLowEdge();
-    void setUpEdge(float * upEdge);
-    float * getUpEdge();
-
-
- private:
-
-    TrackExtendedVec _trackVector;
-    CaloHitExtendedVec _hitVector;
-    float _startingPoint[3];
-    float _direction[3];
-
-    int _type;
-    Cluster * _cluster;
-
-    float _axis[3];
-    float _position[3];
-    float _eccentricity;
-
-    HelixClass _helix;
-    float _helixChi2R;
-    float _helixChi2Z;
-    
-    float _lowEdge[3];
-    float _upEdge[3];
-
-
-};
-
-typedef std::vector<ClusterExtended*> ClusterExtendedVec;
-
-#endif
diff --git a/Utilities/DataHelper/src/GroupTracks.cc~ b/Utilities/DataHelper/src/GroupTracks.cc~
deleted file mode 100644
index fdbda40da169b1481030cb6f9f0ef5a5baaeb9ba..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/GroupTracks.cc~
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "TrackExtended.h"
-#include "GroupTracks.h"
-
-GroupTracks::GroupTracks() {
-  _trackARVec.clear();
-  _edges[0] = 0.0;
-  _edges[1] = 0.0;
-}
-
-GroupTracks::GroupTracks( TrackExtended * track ) {
-  _trackARVec.clear();
-  _trackARVec.push_back( track );
-  _edges[0] = 0.0;
-  _edges[1] = 0.0;
-}
-
-GroupTracks::~GroupTracks() {}
-
-void GroupTracks::addTrackExtended( TrackExtended * track ) {  
-  _trackARVec.push_back( track );
-}
-
-void GroupTracks::ClearTrackExtendedVec() {
-  _trackARVec.clear();
-}
-
-TrackExtendedVec & GroupTracks::getTrackExtendedVec() {
-  return _trackARVec;
-}
-
-void GroupTracks::setEdges(float * edges) {
-
-  _edges[0] = edges[0];
-  _edges[1] = edges[1];  
-
-}
-
-float * GroupTracks::getEdges() {
-  return _edges;
-}
diff --git a/Utilities/DataHelper/src/GroupTracks.h~ b/Utilities/DataHelper/src/GroupTracks.h~
deleted file mode 100644
index 681117bb199bb70ed0bd13b37ce8518f1dd6e643..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/GroupTracks.h~
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef GROUPTRACKS_H
-#define GROUPTRACKS_H 1
-
-#include "TrackExtended.h"
-#include "ClusterExtended.h"
-#include <vector>
-
-//fg : forwar declaration needed because of circular include ....
-class TrackExtended;
-typedef std::vector<TrackExtended*> TrackExtendedVec;
-//fg : forward ....
-
-/**
- * Class GroupTracks is needed to group track segments <br>
- * with close helix parameters. Needed for Tracking. <br>
- *  * @author A. Raspereza (DESY)<br>
- * @version $Id: GroupTracks.h,v 1.4 2007-09-05 09:39:49 rasp Exp $<br>
- */
-class GroupTracks;
-
-typedef std::vector<GroupTracks*>  GroupTracksVec;
-
-class GroupTracks {
-
- public:
-  GroupTracks();
-  GroupTracks(TrackExtended * track );
-  ~GroupTracks();
-
-  void addTrackExtended( TrackExtended * track );
-  void ClearTrackExtendedVec();
-  TrackExtendedVec & getTrackExtendedVec();
-  void setEdges(float * edges);
-  float * getEdges();
-
- private:
-
-  TrackExtendedVec _trackARVec;
-
-  float _edges[2];
-
-};
-
-#endif
diff --git a/Utilities/DataHelper/src/HelixClass.cc~ b/Utilities/DataHelper/src/HelixClass.cc~
deleted file mode 100644
index d16ac9559ad83d565812f5acfbcd6531aa0b0511..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/HelixClass.cc~
+++ /dev/null
@@ -1,768 +0,0 @@
-#include "HelixClass.h"
-#include <math.h>
-#include <stdlib.h>
-#include <iostream>
-//#include "ced_cli.h"
-
-HelixClass::HelixClass() {
-    _const_2pi = 2.0*M_PI;
-    _const_pi2 = 0.5*M_PI;
-    _FCT = 2.99792458E-4;
-}
-
-HelixClass::~HelixClass() {}
-
-void HelixClass::Initialize_VP(float * pos, float * mom, float q, float B) {
-    _referencePoint[0] = pos[0];
-    _referencePoint[1] = pos[1];
-    _referencePoint[2] = pos[2];
-    _momentum[0] = mom[0];
-    _momentum[1] = mom[1];
-    _momentum[2] = mom[2];
-    _charge = q;
-    _bField = B;
-    _pxy = sqrt(mom[0]*mom[0]+mom[1]*mom[1]);
-    _radius = _pxy / (_FCT*B);
-    _omega = q/_radius;
-    _tanLambda = mom[2]/_pxy;
-    _phiMomRefPoint = atan2(mom[1],mom[0]);
-    _xCentre = pos[0] + _radius*cos(_phiMomRefPoint-_const_pi2*q);
-    _yCentre = pos[1] + _radius*sin(_phiMomRefPoint-_const_pi2*q);
-    _phiRefPoint = atan2(pos[1]-_yCentre,pos[0]-_xCentre);
-    _phiAtPCA = atan2(-_yCentre,-_xCentre);
-    _phi0 = -_const_pi2*q + _phiAtPCA;
-    while (_phi0<0) _phi0+=_const_2pi;
-    while (_phi0>=_const_2pi) _phi0-=_const_2pi;
-    _xAtPCA = _xCentre + _radius*cos(_phiAtPCA);
-    _yAtPCA = _yCentre + _radius*sin(_phiAtPCA);
-    //    _d0 = -_xAtPCA*sin(_phi0) + _yAtPCA*cos(_phi0);
-    double pxy = double(_pxy);
-    double radius = pxy/double(_FCT*B);
-    double xCentre = double(pos[0]) + radius*double(cos(_phiMomRefPoint-_const_pi2*q));
-    double yCentre = double(pos[1]) + radius*double(sin(_phiMomRefPoint-_const_pi2*q));
-    
-    double d0;
-
-    if (q>0) {
-      d0 = double(q)*radius - double(sqrt(xCentre*xCentre+yCentre*yCentre));
-    }
-    else {
-      d0 = double(q)*radius + double(sqrt(xCentre*xCentre+yCentre*yCentre));
-    }
-
-    _d0 = float(d0);
-
-//     if (fabs(_d0)>0.001 ) {
-//       std::cout << "New helix : " << std::endl;
-//       std::cout << " Position : " << pos[0] 
-// 		<< " " << pos[1]
-// 		<< " " << pos[2] << std::endl;
-//       std::cout << " Radius = " << _radius << std::endl;
-//       std::cout << " RC = " << sqrt(_xCentre*_xCentre+_yCentre*_yCentre) << std::endl;  
-//       std::cout << " D0 = " << _d0 << std::endl;
-//     }
-
-    _pxAtPCA = _pxy*cos(_phi0);
-    _pyAtPCA = _pxy*sin(_phi0);
-    float deltaPhi = _phiRefPoint - _phiAtPCA;    
-    float xCircles = -pos[2]*q/(_radius*_tanLambda) - deltaPhi;
-    xCircles = xCircles/_const_2pi;
-    int nCircles;
-    int n1,n2;
-
-    if (xCircles >= 0.) {
-	n1 = int(xCircles);
-	n2 = n1 + 1;
-    }
-    else {
-	n1 = int(xCircles) - 1;
-	n2 = n1 + 1;
-    }
-    
-    if (fabs(n1-xCircles) < fabs(n2-xCircles)) {
-	nCircles = n1;
-    }
-    else {
-	nCircles = n2;
-    }
-    _z0 = pos[2] + _radius*_tanLambda*q*(deltaPhi + _const_2pi*nCircles);
-
-}
-
-void HelixClass::Initialize_Canonical(float phi0, float d0, float z0, 
-				      float omega, float tanLambda, float B) {
-    _omega = omega;
-    _d0 = d0;
-    _phi0 = phi0;
-    _z0 = z0;
-    _tanLambda = tanLambda;
-    _charge = omega/fabs(omega);
-    _radius = 1./fabs(omega);
-    _xAtPCA = -_d0*sin(_phi0);
-    _yAtPCA = _d0*cos(_phi0);    
-    _referencePoint[0] = _xAtPCA;
-    _referencePoint[1] = _yAtPCA;
-    _referencePoint[2] = _z0;
-    _pxy = _FCT*B*_radius;
-    _momentum[0] = _pxy*cos(_phi0);
-    _momentum[1] = _pxy*sin(_phi0);
-    _momentum[2] = _tanLambda * _pxy;    
-    _pxAtPCA = _momentum[0];
-    _pyAtPCA = _momentum[1];
-    _phiMomRefPoint = atan2(_momentum[1],_momentum[0]);
-    _xCentre = _referencePoint[0] + 
-      _radius*cos(_phi0-_const_pi2*_charge);
-    _yCentre = _referencePoint[1] + 
-      _radius*sin(_phi0-_const_pi2*_charge);
-    _phiAtPCA = atan2(-_yCentre,-_xCentre);
-    _phiRefPoint =  _phiAtPCA ;
-    _bField = B;
-}
-
-
-void HelixClass::Initialize_BZ(float xCentre, float yCentre, float radius, 
-			       float bZ, float phi0, float B, float signPz,
-			       float zBegin) {
-
-  _radius = radius;
-  _pxy = _FCT*B*_radius;
-  _charge = -(bZ*signPz)/fabs(bZ*signPz);
-  _momentum[2] = -_charge*_pxy/(bZ*_radius);
-  _xCentre = xCentre;
-  _yCentre = yCentre;
-  _omega = _charge/radius;
-  _phiAtPCA = atan2(-_yCentre,-_xCentre);
-  _phi0 = -_const_pi2*_charge + _phiAtPCA;
-  while (_phi0<0) _phi0+=_const_2pi;
-  while (_phi0>=_const_2pi) _phi0-=_const_2pi;
-  _xAtPCA = _xCentre + _radius*cos(_phiAtPCA);
-  _yAtPCA = _yCentre + _radius*sin(_phiAtPCA);
-  _d0 = -_xAtPCA*sin(_phi0) + _yAtPCA*cos(_phi0);
-  _pxAtPCA = _pxy*cos(_phi0);
-  _pyAtPCA = _pxy*sin(_phi0);
-  _referencePoint[2] = zBegin;
-  _referencePoint[0] = xCentre + radius*cos(bZ*zBegin+phi0);
-  _referencePoint[1] = yCentre + radius*sin(bZ*zBegin+phi0);
-  _phiRefPoint = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre);
-  _phiMomRefPoint =  -_const_pi2*_charge + _phiRefPoint;
-  _tanLambda = _momentum[2]/_pxy;
-  _momentum[0] = _pxy*cos(_phiMomRefPoint);
-  _momentum[1] = _pxy*sin(_phiMomRefPoint);
-  
-  float deltaPhi = _phiRefPoint - _phiAtPCA;    
-  float xCircles = bZ*_referencePoint[2] - deltaPhi;
-  xCircles = xCircles/_const_2pi;
-  int nCircles;
-  int n1,n2;
-
-  if (xCircles >= 0.) {
-    n1 = int(xCircles);
-    n2 = n1 + 1;
-  }
-  else {
-    n1 = int(xCircles) - 1;
-    n2 = n1 + 1;
-  }
-  
-  if (fabs(n1-xCircles) < fabs(n2-xCircles)) {
-    nCircles = n1;
-  }
-  else {
-    nCircles = n2;
-  }  
-  _z0 = _referencePoint[2] - (deltaPhi + _const_2pi*nCircles)/bZ;  
-  _bField = B;
-
-}
-
-const float * HelixClass::getMomentum() {
-    return _momentum;
-}
-const float * HelixClass::getReferencePoint() {
-    return _referencePoint;
-}
-float HelixClass::getPhi0() {
-  if (_phi0<0.0)
-    _phi0 += 2*M_PI;
-  return _phi0;
-}
-float HelixClass::getD0() {
-    return _d0;
-}
-float HelixClass::getZ0() {
-    return _z0;
-}
-float HelixClass::getOmega() {
-    return _omega;
-}
-float HelixClass::getTanLambda() {
-    return _tanLambda;
-}
-float HelixClass::getPXY() {
-    return _pxy;
-}
-float HelixClass::getXC() {
-  return _xCentre;
-}
-
-float HelixClass::getYC() {
-  return _yCentre;
-}
-
-float HelixClass::getRadius() {
-  return _radius;
-}
-
-float HelixClass::getBz() {
-  return _bZ;
-}
-
-float HelixClass::getPhiZ() {
-  return _phiZ;
-}
-
-float HelixClass::getCharge() {
-    return _charge;
-}
-
-float HelixClass::getPointInXY(float x0, float y0, float ax, float ay, 
-			      float * ref , float * point) {
-
-  float time;
-
-  float AA = sqrt(ax*ax+ay*ay);
-
-
-  if (AA <= 0) {
-    time = -1.0e+20; 
-    return time;
-  }
-
-
-  float BB = ax*(x0-_xCentre) + ay*(y0-_yCentre);
-  BB = BB / AA;
-
-  float CC = (x0-_xCentre)*(x0-_xCentre) 
-    + (y0-_yCentre)*(y0-_yCentre) - _radius*_radius;
-
-  CC = CC / AA;
-
-  float DET = BB*BB - CC;
-  float tt1 = 0.;
-  float tt2 = 0.;
-  float xx1,xx2,yy1,yy2; 
-
-
-  if (DET < 0 ) {
-    time = 1.0e+10;
-    point[0]=0.0;
-    point[1]=0.0;
-    point[2]=0.0;
-    return time;
-  }
-  
-  
-  tt1 = - BB + sqrt(DET);
-  tt2 = - BB - sqrt(DET);
-
-  xx1 = x0 + tt1*ax;
-  yy1 = y0 + tt1*ay;
-  xx2 = x0 + tt2*ax;
-  yy2 = y0 + tt2*ay;
-  
-  float phi1 = atan2(yy1-_yCentre,xx1-_xCentre);
-  float phi2 = atan2(yy2-_yCentre,xx2-_xCentre);
-  float phi0 = atan2(ref[1]-_yCentre,ref[0]-_xCentre);
-
-  float dphi1 = phi1 - phi0;
-  float dphi2 = phi2 - phi0;
-
-  if (dphi1 < 0 && _charge < 0) {
-    dphi1 = dphi1 + _const_2pi;
-  }
-  else if (dphi1 > 0 && _charge > 0) { 
-    dphi1 = dphi1 - _const_2pi;
-  }
-
-  if (dphi2 < 0 && _charge < 0) {
-    dphi2 = dphi2 + _const_2pi;
-  }
-  else if (dphi2 > 0 && _charge > 0) { 
-    dphi2 = dphi2 - _const_2pi;
-  }
-
-  // Times
-  tt1 = -_charge*dphi1*_radius/_pxy;
-  tt2 = -_charge*dphi2*_radius/_pxy;
-
-  if (tt1 < 0. )
-    std::cout << "WARNING " << tt1 << std::endl;
-  if (tt2 < 0. )
-    std::cout << "WARNING " << tt2 << std::endl;
-  
-
-  if (tt1 < tt2) {
-    point[0] = xx1;
-    point[1] = yy1;
-    time = tt1;
-  }
-  else {
-    point[0] = xx2;
-    point[1] = yy2;
-    time = tt2;
-  }
-
-  point[2] = ref[2]+time*_momentum[2];
-
-  
-
-  return time;
-
-}
-
-
-float HelixClass::getPointOnCircle(float Radius, float * ref, float * point) {
-
-  float distCenterToIP = sqrt(_xCentre*_xCentre + _yCentre*_yCentre);
-
-  point[0] = 0.0;
-  point[1] = 0.0;
-  point[2] = 0.0;
-
-  if ((distCenterToIP+_radius)<Radius) {
-    float xx = -1.0e+20;
-    return xx;
-  }
-
-  if ((_radius+Radius)<distCenterToIP) {
-    float xx = -1.0e+20;
-    return xx;
-  }
-
-  float phiCentre = atan2(_yCentre,_xCentre);
-  float phiStar   = Radius*Radius + distCenterToIP*distCenterToIP 
-                                    - _radius*_radius;
-
-  phiStar = 0.5*phiStar/fmax(1.0e-20,Radius*distCenterToIP);
-  
-  if (phiStar > 1.0) 
-    phiStar = 0.9999999;
-  
-  if (phiStar < -1.0)
-    phiStar = -0.9999999;
-  
-  phiStar = acos(phiStar);
-
-  float tt1,tt2,time;
-
-  float xx1 = Radius*cos(phiCentre+phiStar);
-  float yy1 = Radius*sin(phiCentre+phiStar);
-
-  float xx2 = Radius*cos(phiCentre-phiStar);
-  float yy2 = Radius*sin(phiCentre-phiStar);
-
-
-  float phi1 = atan2(yy1-_yCentre,xx1-_xCentre);
-  float phi2 = atan2(yy2-_yCentre,xx2-_xCentre);
-  float phi0 = atan2(ref[1]-_yCentre,ref[0]-_xCentre);
-
-  float dphi1 = phi1 - phi0;
-  float dphi2 = phi2 - phi0;
-
-  if (dphi1 < 0 && _charge < 0) {
-    dphi1 = dphi1 + _const_2pi;
-  }
-  else if (dphi1 > 0 && _charge > 0) { 
-    dphi1 = dphi1 - _const_2pi;
-  }
-
-  if (dphi2 < 0 && _charge < 0) {
-    dphi2 = dphi2 + _const_2pi;
-  }
-  else if (dphi2 > 0 && _charge > 0) { 
-    dphi2 = dphi2 - _const_2pi;
-  }
-
-  // Times
-  tt1 = -_charge*dphi1*_radius/_pxy;
-  tt2 = -_charge*dphi2*_radius/_pxy;
-
-  if (tt1 < 0. )
-    std::cout << "WARNING " << tt1 << std::endl;
-  if (tt2 < 0. )
-    std::cout << "WARNING " << tt2 << std::endl;
-  
-
-  float time2;
-  if (tt1 < tt2) {
-    point[0] = xx1;
-    point[1] = yy1;
-    point[3] = xx2;
-    point[4] = yy2;
-    time = tt1;
-    time2 = tt2;
-  }
-  else {
-    point[0] = xx2;
-    point[1] = yy2;
-    point[3] = xx1;
-    point[4] = yy1;
-    time = tt2;
-    time2 = tt1;
-  }
-
-  point[2] = ref[2]+time*_momentum[2];
-  point[5] = ref[2]+time2*_momentum[2];
-  
-
-  return time;
-
-}
-
-
-float HelixClass::getPointInZ(float zLine, float * ref, float * point) {
-
-  float time = zLine - ref[2];
-
-  if (_momentum[2] == 0.) {
-    time = -1.0e+20;
-    point[0] = 0.;
-    point[1] = 0.;
-    point[2] = 0.;
-    return time;
-  }
-
-  time = time/_momentum[2];
-
-  float phi0 = atan2(ref[1] - _yCentre , ref[0] - _xCentre);
-  float phi = phi0 - _charge*_pxy*time/_radius;
-  float xx = _xCentre + _radius*cos(phi);
-  float yy = _yCentre + _radius*sin(phi);
-
-  point[0] = xx;
-  point[1] = yy;
-  point[2] = zLine;
-
-  return time;
-
-
-}
-
-float HelixClass::getDistanceToPoint(float * xPoint, float * Distance) {
-
-  float zOnHelix;
-  float phi = atan2(xPoint[1]-_yCentre,xPoint[0]-_xCentre);
-  float phi0 = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre);
-  //calculate distance to XYprojected centre of Helix, comparing this with distance to radius around centre gives DistXY
-  float DistXY = (_xCentre-xPoint[0])*(_xCentre-xPoint[0]) + (_yCentre-xPoint[1])*(_yCentre-xPoint[1]);
-  DistXY = sqrt(DistXY);
-  DistXY = fabs(DistXY - _radius);
-  
-  int nCircles = 0;
-
-  if (fabs(_tanLambda*_radius)>1.0e-20) {
-    float xCircles = phi0 - phi -_charge*(xPoint[2]-_referencePoint[2])/(_tanLambda*_radius);
-    xCircles = xCircles/_const_2pi;
-    int n1,n2;
-
-    if (xCircles >= 0.) {
-	n1 = int(xCircles);
-	n2 = n1 + 1;
-    }
-    else {
-	n1 = int(xCircles) - 1;
-	n2 = n1 + 1;
-    }
-    
-    if (fabs(n1-xCircles) < fabs(n2-xCircles)) {
-	nCircles = n1;
-    }
-    else {
-	nCircles = n2;
-    }
-
-  }
-  
-  float DPhi = _const_2pi*((float)nCircles) + phi - phi0;
-
-  zOnHelix = _referencePoint[2] - _charge*_radius*_tanLambda*DPhi;
-
-  float DistZ = fabs(zOnHelix - xPoint[2]);
-  float Time;
-
-  if (fabs(_momentum[2]) > 1.0e-20) {
-    Time = (zOnHelix - _referencePoint[2])/_momentum[2];
-  }
-  else {
-    Time = _charge*_radius*DPhi/_pxy;
-  }
-
-  Distance[0] = DistXY;
-  Distance[1] = DistZ;
-  Distance[2] = sqrt(DistXY*DistXY+DistZ*DistZ);
-
-  return Time;
-
-
-}
-
-//When we are not interested in the exact distance, we can check if we are
-//already far enough away in XY, before we start calculating in Z as the
-//distance will only increase
-float HelixClass::getDistanceToPoint(const std::vector<float>& xPoint, float distCut) {
-  //calculate distance to XYprojected centre of Helix, comparing this with distance to radius around centre gives DistXY
-  float tempx = xPoint[0]-_xCentre;
-  float tempy = xPoint[1]-_yCentre;
-  float tempsq = sqrt(tempx*tempx + tempy*tempy);
-  float tempdf = tempsq - _radius;
-  float DistXY = fabs( tempdf );
-  //If this is bigger than distCut, we dont have to know how much bigger this is
-  if( DistXY > distCut) {
-    return DistXY;
-  }
-
-  int nCircles = 0;
-  float phi = atan2(tempy,tempx);
-  float phi0 = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre);
-  float phidiff = phi0-phi;
-  float  tempz = xPoint[2] - _referencePoint[2];//Yes referencePoint
-  float tanradius = _tanLambda*_radius;
-  if (fabs(tanradius)>1.0e-20) {
-    float xCircles = (phidiff -_charge*tempz/tanradius)/_const_2pi;
-    int n1,n2;
-    if (xCircles >= 0.) {
-	n1 = int(xCircles);
-	n2 = n1 + 1;
-    }
-    else {
-	n1 = int(xCircles) - 1;
-	n2 = n1 + 1;
-    }
-    if (fabs(n1-xCircles) < fabs(n2-xCircles)) {
-	nCircles = n1;
-    }
-    else {
-	nCircles = n2;
-    }
-  }
-  float DistZ = - tempz - _charge*tanradius*(_const_2pi*((float)nCircles) - phidiff);
-  return sqrt(DistXY*DistXY+DistZ*DistZ);
-}//getDistanceToPoint(vector,float)
-
-float HelixClass::getDistanceToPoint(const float* xPoint, float distCut) {
-  std::vector<float> xPosition(xPoint, xPoint + 3 );//We are expecting three coordinates, must be +3, last element is excluded!
-  return getDistanceToPoint(xPosition, distCut);
-}//getDistanceToPoint(float*,float)
-
-
-
-void HelixClass::setHelixEdges(float * xStart, float * xEnd) {
-  for (int i=0; i<3; ++i) {
-    _xStart[i] = xStart[i];
-    _xEnd[i] = xEnd[i];
-  }
-
-}
-
-float HelixClass::getDistanceToHelix(HelixClass * helix, float * pos, float * mom) {
-
-  float x01 = getXC();
-  float y01 = getYC();
-  
-  float x02 = helix->getXC();
-  float y02 = helix->getYC();
-  
-  float rad1 = getRadius();
-  float rad2 = helix->getRadius();
-
-  float distance = sqrt((x01-x02)*(x01-x02)+(y01-y02)*(y01-y02));
-
-  bool singlePoint = true;
-
-  float phi1 = 0;
-  float phi2 = 0;
-
-  if (rad1+rad2<distance) {
-    phi1 = atan2(y02-y01,x02-x01);
-    phi2 = atan2(y01-y02,x01-x02);
-  }
-  else if (distance+rad2<rad1) {
-    phi1 = atan2(y02-y01,x02-x01);
-    phi2 = phi1;
-  }
-  else if (distance+rad1<rad2) {
-    phi1 = atan2(y01-y02,x01-x02);
-    phi2 = phi1;
-  }
-  else {
-    singlePoint = false;
-    float cosAlpha = 0.5*(distance*distance+rad2*rad2-rad1*rad1)/(distance*rad2);
-    float alpha = acos(cosAlpha);
-    float phi0 = atan2(y01-y02,x01-x02);
-    phi1 = phi0 + alpha;
-    phi2 = phi0 - alpha;
-  }
-  
-
-  float ref1[3];
-  float ref2[3];
-  for (int i=0;i<3;++i) {
-    ref1[i]=_referencePoint[i];
-    ref2[i]=helix->getReferencePoint()[i];
-  }
-  
-  float pos1[3];
-  float pos2[3];
-  float mom1[3];
-  float mom2[3];
-
-
-  if (singlePoint ) {
-
-    float xSect1 = x01 + rad1*cos(phi1);
-    float ySect1 = y01 + rad1*sin(phi1);
-    float xSect2 = x02 + rad2*cos(phi2);
-    float ySect2 = y02 + rad2*sin(phi2);
-    float R1 = sqrt(xSect1*xSect1+ySect1*ySect1);
-    float R2 = sqrt(xSect2*xSect2+ySect2*ySect2);
-
-    getPointOnCircle(R1,ref1,pos1);
-    helix->getPointOnCircle(R2,ref2,pos2);
-    
-  }
-  else {    
-
-    float xSect1 = x02 + rad2*cos(phi1);
-    float ySect1 = y02 + rad2*sin(phi1);
-    float xSect2 = x02 + rad2*cos(phi2);
-    float ySect2 = y02 + rad2*sin(phi2);
-
-//     std::cout << "(xSect1,ySect1)=(" << xSect1 << "," << ySect1 << ")" << std::endl;
-//     std::cout << "(xSect2,ySect2)=(" << xSect2 << "," << ySect2 << ")" << std::endl;
-
-    float temp21[3];
-    float temp22[3];
-
-    float phiI2  = atan2(ref2[1]-y02,ref2[0]-x02); 
-    float phiF21 = atan2(ySect1-y02,xSect1-x02);
-    float phiF22 = atan2(ySect2-y02,xSect2-x02);
-    float deltaPhi21 = phiF21 - phiI2;
-    float deltaPhi22 = phiF22 - phiI2;
-    float charge2 = helix->getCharge();
-    float pxy2 = helix->getPXY();
-    float pz2   = helix->getMomentum()[2];
-    if (deltaPhi21 < 0 && charge2 < 0) {
-      deltaPhi21 += _const_2pi;
-    }
-    else if (deltaPhi21 > 0 && charge2 > 0) { 
-      deltaPhi21 -= _const_2pi;
-    }
-
-    if (deltaPhi22 < 0 && charge2 < 0) {
-      deltaPhi22 += _const_2pi;
-    }
-    else if (deltaPhi22 > 0 && charge2 > 0) { 
-      deltaPhi22 -= _const_2pi;
-    }
-
-    float time21 = -charge2*deltaPhi21*rad2/pxy2;
-    float time22 = -charge2*deltaPhi22*rad2/pxy2;
-
-    float Z21 = ref2[2] + time21*pz2;
-    float Z22 = ref2[2] + time22*pz2;
-
-    temp21[0] = xSect1; temp21[1] = ySect1; temp21[2] = Z21;
-    temp22[0] = xSect2; temp22[1] = ySect2; temp22[2] = Z22;
-    
-
-//     std::cout << "temp21 = " << temp21[0] << " " << temp21[1] << " " << temp21[2] << std::endl;
-//     std::cout << "temp22 = " << temp22[0] << " " << temp22[1] << " " << temp22[2] << std::endl;
-
-
-    float temp11[3];
-    float temp12[3];
-
-    float phiI1  = atan2(ref1[1]-y01,ref1[0]-x01); 
-    float phiF11 = atan2(ySect1-y01,xSect1-x01);
-    float phiF12 = atan2(ySect2-y01,xSect2-x01);
-    float deltaPhi11 = phiF11 - phiI1;
-    float deltaPhi12 = phiF12 - phiI1;
-    float charge1 = _charge;
-    float pxy1 = _pxy;
-    float pz1   = _momentum[2];
-    if (deltaPhi11 < 0 && charge1 < 0) {
-      deltaPhi11 += _const_2pi;
-    }
-    else if (deltaPhi11 > 0 && charge1 > 0) { 
-      deltaPhi11 -= _const_2pi;
-    }
-
-    if (deltaPhi12 < 0 && charge1 < 0) {
-      deltaPhi12 += _const_2pi;
-    }
-    else if (deltaPhi12 > 0 && charge1 > 0) { 
-      deltaPhi12 -= _const_2pi;
-    }
-
-    float time11 = -charge1*deltaPhi11*rad1/pxy1;
-    float time12 = -charge1*deltaPhi12*rad1/pxy1;
-
-    float Z11 = ref1[2] + time11*pz1;
-    float Z12 = ref1[2] + time12*pz1;
-
-    temp11[0] = xSect1; temp11[1] = ySect1; temp11[2] = Z11;
-    temp12[0] = xSect2; temp12[1] = ySect2; temp12[2] = Z12;
-    
-//     std::cout << "temp11 = " << temp11[0] << " " << temp11[1] << " " << temp11[2] << std::endl;
-//     std::cout << "temp12 = " << temp12[0] << " " << temp12[1] << " " << temp12[2] << std::endl;
-
-    float Dist1 = 0;
-    float Dist2 = 0;
-
-    for (int j=0;j<3;++j) {
-      Dist1 += (temp11[j]-temp21[j])*(temp11[j]-temp21[j]);
-      Dist2 += (temp12[j]-temp22[j])*(temp12[j]-temp22[j]);
-    }
-
-    if (Dist1<Dist2) {
-      for (int l=0;l<3;++l) {
-	pos1[l] = temp11[l];
-	pos2[l] = temp21[l];
-      }
-    }
-    else {
-       for (int l=0;l<3;++l) {
-	pos1[l] = temp12[l];
-	pos2[l] = temp22[l];
-      }
-    }
-
-  }
-
-  getExtrapolatedMomentum(pos1,mom1);
-  helix->getExtrapolatedMomentum(pos2,mom2);
-
-  float helixDistance = 0;
-
-  for (int i=0;i<3;++i) {
-    helixDistance += (pos1[i] - pos2[i])*(pos1[i] - pos2[i]);
-    pos[i] = 0.5*(pos1[i]+pos2[i]);
-    mom[i] = mom1[i]+mom2[i];
-  }
-  helixDistance = sqrt(helixDistance);
-
-  return helixDistance;
-
-}
-
-void HelixClass::getExtrapolatedMomentum(float * pos, float * momentum) {
-
-  float phi = atan2(pos[1]-_yCentre,pos[0]-_xCentre);
-  if (phi <0.) phi += _const_2pi;
-  phi = phi - _phiAtPCA + _phi0;
-  momentum[0] = _pxy*cos(phi);
-  momentum[1] = _pxy*sin(phi);
-  momentum[2] = _momentum[2];
-
-
-}
diff --git a/Utilities/DataHelper/src/LineClass.cc~ b/Utilities/DataHelper/src/LineClass.cc~
deleted file mode 100644
index e23db1fa3f46982b8fff4a5ecb27a0264896f97d..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/LineClass.cc~
+++ /dev/null
@@ -1,73 +0,0 @@
-#include "LineClass.h"
-#include <math.h> 
-
-/*
- * Constructor
- */
-
-LineClass::LineClass(float x0,
-		     float y0,
-		     float z0,
-		     float ax,
-		     float ay,
-		     float az) {
-  _x0[0] = x0;
-  _x0[1] = y0;
-  _x0[2] = z0;
-  _ax[0] = ax;
-  _ax[1] = ay;
-  _ax[2] = az;
-}
-
-LineClass::LineClass(float *x0,
-		     float *ax) {
-
-  for (int i=0; i<3; ++i) {
-    _x0[i] = x0[i];
-    _ax[i] = ax[i];
-  }
-}
-
-float * LineClass::getReferencePoint() {
-  return _x0;
-}
-
-float * LineClass::getDirectionalVector() {
-  return _ax;
-}
-
-void LineClass::setReferencePoint(float *x0) {
-  for (int i=0; i<3; ++i)
-    _x0[i] = x0[i];
-}
- 
-void LineClass::setDirectionalVector(float *ax) {
-  for (int i=0; i<3; ++i)
-    _ax[i] = ax[i];
- 
-}
-
-float LineClass::getDistanceToPoint(float * xpoint, float * pos) {
-  
-  float dif[3];
-  float prod = 0;
-  float den = 0;
-  for (int i=0; i<3; ++i) {
-    dif[i] = xpoint[i] - _x0[i];
-    prod += _ax[i]*dif[i];
-    den += _ax[i]*_ax[i];
-  }
-  float time = prod/fmax(1e-10,den);
-
-  float dist = 0.0;
-  for (int i=0; i<3; ++i) {
-    pos[i] = _x0[i] + _ax[i]*time;
-    dist += (xpoint[i]-pos[i])*(xpoint[i]-pos[i]);
-  }
-  dist = sqrt(dist);
-
-  return dist;
-
-
-
-}
diff --git a/Utilities/DataHelper/src/TrackExtended.cc~ b/Utilities/DataHelper/src/TrackExtended.cc~
deleted file mode 100644
index 773937055c850be0249ad5b0d732f8e88462b251..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/TrackExtended.cc~
+++ /dev/null
@@ -1,229 +0,0 @@
-#include "ClusterExtended.h"
-#include "TrackerHitExtended.h"
-#include "TrackExtended.h"
-#include <math.h>
-
-TrackExtended::TrackExtended( ) {
-    _track = NULL;
-    _superCluster = NULL;
-    _trackerHitVector.clear();
-    _clusterVec.clear();
-    _group = NULL;
-}
-
-TrackExtended::TrackExtended( Track * track) {
-    _track = track;
-    _superCluster = NULL;
-    _trackerHitVector.clear();
-    _clusterVec.clear();
-    _group = NULL;
-    
-}
-
-TrackExtended::TrackExtended( TrackerHitExtended * trackerhit) {
-    _trackerHitVector.clear();
-    _trackerHitVector.push_back(trackerhit);
-    _track = NULL;
-    _superCluster = NULL;
-    _clusterVec.clear();
-    _group = NULL;
-}
-
-
-TrackExtended::~TrackExtended() {}
-
-Track * TrackExtended::getTrack() {
-    return _track;
-}
-
-const float * TrackExtended::getSeedPosition() {
-    return _seedPosition;
-}
-
-const float * TrackExtended::getSeedDirection() {
-    return _seedDirection;
-}
-
-ClusterExtendedVec & TrackExtended::getClusterVec() {
-    return _clusterVec;
-}
-
-ClusterExtended * TrackExtended::getSuperCluster() {
-    return _superCluster;
-}
-
-TrackerHitExtendedVec & TrackExtended::getTrackerHitExtendedVec() {
-    return _trackerHitVector;
-}
-
-void TrackExtended::addCluster(ClusterExtended * cluster) {
-    _clusterVec.push_back(cluster);
-}
-
-void TrackExtended::setSuperCluster(ClusterExtended * superCluster) {
-    _superCluster = superCluster;
-}
-
-void TrackExtended::setSeedDirection( float * seedDirection ) {
-    _seedDirection[0] = seedDirection[0];
-    _seedDirection[1] = seedDirection[1];
-    _seedDirection[2] = seedDirection[2];
-}
-
-void TrackExtended::setSeedPosition( float * seedPosition) {
-    _seedPosition[0] = seedPosition[0];
-    _seedPosition[1] = seedPosition[1];
-    _seedPosition[2] = seedPosition[2];
-}
-
-void TrackExtended::addTrackerHitExtended( TrackerHitExtended * trackerhit) {
-  _trackerHitVector.push_back(trackerhit);
-
-}
-
-void TrackExtended::ClearTrackerHitExtendedVec() {
-  _trackerHitVector.clear();
-}
-
-void TrackExtended::setX0( float x0 ) {
-  _x0 = x0;
-}
-
-void TrackExtended::setD0( float d0 ) {
-  _d0 = d0;
-}
-
-void TrackExtended::setZ0( float z0 ) {
-  _z0 = z0;
-}
-
-void TrackExtended::setY0( float y0 ) {
-  _y0 = y0;
-}
-
-void TrackExtended::setR0( float r0 ) {
-  _r0 = r0;
-}
-
-void TrackExtended::setBz( float bz ) {
-  _bz = bz;
-}
-
-void TrackExtended::setPhi0( float phi0 ) {
-  _phi0 = phi0;
-}
-
-void TrackExtended::setPhi( float phi ) {
-  _phi = phi;
-}
-
-void TrackExtended::setOmega( float omega ) {
-  _omega = omega;
-}
-
-void TrackExtended::setTanLambda( float tanLambda ) {
-  _tanLambda = tanLambda;
-}
-void TrackExtended::setNDF( int ndf) {
-  _ndf = ndf;
-}
-
-
-float TrackExtended::getX0() {
-  return _x0;
-}
-
-float TrackExtended::getY0() {
-  return _y0;
-}
-
-float TrackExtended::getR0() {
-  return _r0;
-}
-
-float TrackExtended::getBz() {
-  return _bz;
-}
-
-float TrackExtended::getD0() {
-  return _d0;
-}
-
-float TrackExtended::getZ0() {
-  return _z0;
-}
-
-float TrackExtended::getPhi0() {
-  return _phi0;
-}
-
-float TrackExtended::getPhi() {
-  return _phi;
-}
-
-float TrackExtended::getOmega() {
-  return _omega;
-}
-
-float TrackExtended::getTanLambda() {
-  return _tanLambda;
-}
-
-int TrackExtended::getNDF() {
-  return _ndf;
-}
-
-void TrackExtended::setStart(float * xStart) {
-  _xStart[0] = xStart[0];
-  _xStart[1] = xStart[1];
-  _xStart[2] = xStart[2];
-}
-
-void TrackExtended::setEnd(float * xEnd) {
-  _xEnd[0] = xEnd[0];
-  _xEnd[1] = xEnd[1];
-  _xEnd[2] = xEnd[2];
-}
-
-float * TrackExtended::getStart() {
-  return _xStart;
-}
-
-float * TrackExtended::getEnd() {
-  return _xEnd;
-}
-
-void TrackExtended::setGroupTracks( GroupTracks * group ) {
-  _group = group;
-}
-
-GroupTracks * TrackExtended::getGroupTracks() {
-  return _group;
-}
-
-float TrackExtended::getChi2() {
-  return _chi2;
-}
-
-void TrackExtended::setChi2(float chi2) {
-  _chi2 = chi2;
-}
-
-void TrackExtended::setCovMatrix(float * cov) {
-  for (int i=0; i<15; ++i)
-    _cov[i] = cov[i];
-}
-
-float * TrackExtended::getCovMatrix() {
-  return _cov;
-}
-
-// void TrackExtended::setType(int type) {
-//   _type = type
-
-// }
-
-// int TrackExtended::getType() {
-//   return _type;
-
-// }
diff --git a/Utilities/DataHelper/src/TrackExtended.h~ b/Utilities/DataHelper/src/TrackExtended.h~
deleted file mode 100644
index e6cbd4a03eb21bb267221a97dd853d49ef86c1c9..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/TrackExtended.h~
+++ /dev/null
@@ -1,130 +0,0 @@
-#ifndef TRACKAR_H 
-#define TRACKAR_H 1
-
-//#include "lcio.h"
-//#include "EVENT/LCIO.h"
-#include "plcio/Track.h"
-#include <vector>
-//#include "ClusterExtended.h"
-//#include "TrackerHitExtended.h"
-#include "GroupTracks.h"
-
-using namespace plcio;
-
-class ClusterExtended;
-//class GroupTracks;
-class TrackerHitExtended;
-typedef std::vector<TrackerHitExtended*> TrackerHitExtendedVec;
-typedef std::vector<ClusterExtended*> ClusterExtendedVec;
-
-/**
- * Class extending native LCIO class Track. <br>
- * Class TrackExtended is used in TrackwiseClustering <br>
- * and Wolf processors. <br>
- * @author A. Raspereza (DESY)<br>
- * @version $Id: TrackExtended.h,v 1.8 2007-09-05 09:39:49 rasp Exp $<br>
- */
-
-class TrackExtended {
-
- public:
-
-
-    TrackExtended( );
-    TrackExtended( TrackerHitExtended * trackerhit );
-    TrackExtended( plcio::Track * track );
-    ~TrackExtended();
-    
-    plcio::Track * getTrack();
-    const float * getSeedDirection();
-    const float * getSeedPosition();
-    ClusterExtendedVec & getClusterVec();
-    ClusterExtended * getSuperCluster();
-    TrackerHitExtendedVec & getTrackerHitExtendedVec();
-    void addCluster(ClusterExtended * cluster);
-    void setSuperCluster(ClusterExtended * superCluster);
-    void setSeedDirection( float * seedDirection );
-    void setSeedPosition( float * seedPosition);
-    void addTrackerHitExtended( TrackerHitExtended * trackerhit);
-    void ClearTrackerHitExtendedVec();
-
-    void setX0(float x0);
-    void setY0(float y0);
-    void setR0(float r0);
-    void setD0(float d0);
-    void setZ0(float z0);
-    void setBz(float bz);
-    void setPhi0(float phi0);
-    void setPhi(float phi);
-    void setOmega(float omega);
-    void setTanLambda(float tanLambda);
-    
-
-    void setStart(float * xStart);
-    void setEnd(float * xEnd);
-
-
-    float getX0();
-    float getY0();
-    float getD0();
-    float getZ0();
-    float getOmega();
-    float getTanLambda();
-    float getPhi();
-    float getR0();
-    float getBz();
-    float getPhi0();
-    
-    float * getStart();
-    float * getEnd();
-
-    void setGroupTracks( GroupTracks * group );
-    GroupTracks * getGroupTracks();
-
-    float getChi2();
-    void setChi2(float chi2);
-
-    int getNDF();
-    void setNDF(int ndf);
-
-    float * getCovMatrix();
-    void setCovMatrix( float * cov);
-
- private:
-
-    ClusterExtended *_superCluster;
-    ClusterExtendedVec _clusterVec;
-    GroupTracks * _group;
-    Track * _track;
-    float _seedDirection[3];
-    float _seedPosition[3];
-    TrackerHitExtendedVec _trackerHitVector;    
-
-    float _x0;
-    float _y0;
-    float _r0;
-    float _bz;
-    float _phi0;
-
-    float _xStart[3];
-    float _xEnd[3];
-
-    float _d0; // d0 in canonical parameterisation
-    float _z0; // z0 in canonical parameterisation
-    float _omega; // omega in canonical parameterisation
-    float _tanLambda; // tanlambda in canonical parameterisation
-    float _phi; // phi in canonical parameterisation 
-
-    float _chi2; // chi2 of the fit
-
-    float _cov[15]; // covariance matrix
-    
-    int _ndf; // NDF
-
-    int _type; // Track type;
-    
-};
-
-typedef std::vector<TrackExtended*> TrackExtendedVec;
-
-#endif
diff --git a/Utilities/DataHelper/src/TrackerHitExtended.cc~ b/Utilities/DataHelper/src/TrackerHitExtended.cc~
deleted file mode 100644
index 551b1923c5ca4df818c95cbad6abe394195145a9..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/TrackerHitExtended.cc~
+++ /dev/null
@@ -1,133 +0,0 @@
-#include "TrackExtended.h"
-#include "TrackerHitExtended.h"
-
-TrackerHitExtended::TrackerHitExtended(const edm4hep::TrackerHit& trackerhit):
-  _trackerHit(trackerhit){
-  _trackAR = NULL;
-  _trackVecAR.clear();
-  _usedInFit = false;
-}
-
-TrackerHitExtended::~TrackerHitExtended() {
-
-}
-
-void TrackerHitExtended::setTrackExtended(TrackExtended * trackAR) {
-    _trackAR = trackAR;
-    _trackVecAR.clear();
-    _trackVecAR.push_back(trackAR);
-      
-} 
-
-void TrackerHitExtended::addTrackExtended(TrackExtended * trackAR) {
-  _trackVecAR.push_back(trackAR);
-}
-
-TrackExtendedVec & TrackerHitExtended::getTrackExtendedVec() {
-  return _trackVecAR;
-}
-
-
-void TrackerHitExtended::setTrackerHitTo(TrackerHitExtended * hitTo) {
-    _hitTo = hitTo;
-}
-
-void TrackerHitExtended::setTrackerHitFrom(TrackerHitExtended * hitFrom) {
-    _hitFrom = hitFrom;
-
-} 
-
-void TrackerHitExtended::setGenericDistance(float genericDistance) {
-    _genericDistance = genericDistance; 
-}
-
-//void TrackerHitExtended::setTrackerHit(edm4hep::TrackerHit * hit) {
-//    _trackerHit = hit;
-//}
-
-void TrackerHitExtended::setYresTo(float yresTo) {
-    _yresTo = yresTo;
-}
-
-void TrackerHitExtended::setYresFrom(float yresFrom) {
-    _yresFrom = yresFrom;
-}
-
-void TrackerHitExtended::setDirVec(float * dirVec) {
-    _dirVec[0] = dirVec[0];
-    _dirVec[1] = dirVec[1];
-    _dirVec[2] = dirVec[2];
-}
-
-void TrackerHitExtended::setType(int ityp) {
-    _type = ityp;
-}
-
-void TrackerHitExtended::setDet(int idet) {
-    _idet = idet;
-}
-
-edm4hep::TrackerHit * TrackerHitExtended::getTrackerHit() {
-    return &_trackerHit;
-}
-
-TrackExtended * TrackerHitExtended::getTrackExtended() {
-    return _trackAR;
-}
-
-TrackerHitExtended * TrackerHitExtended::getTrackerHitFrom() {
-    return _hitFrom;
-}
-TrackerHitExtended * TrackerHitExtended::getTrackerHitTo() {
-    return _hitTo;
-}
-float TrackerHitExtended::getGenericDistance() {
-    return _genericDistance;
-}
-float TrackerHitExtended::getYresTo() {
-    return _yresTo;
-}
-float TrackerHitExtended::getYresFrom() {
-    return _yresFrom;
-}
-
-float * TrackerHitExtended::getDirVec() {
-    return _dirVec;
-}
-
-void TrackerHitExtended::clearTrackVec() {
-  _trackVecAR.clear();
-}
-
-float TrackerHitExtended::getResolutionRPhi() {
-  return _rphiReso;
-}
-
-float TrackerHitExtended::getResolutionZ() {
-  return _zReso;
-}
-
-void TrackerHitExtended::setResolutionRPhi(float rphiReso) {
-  _rphiReso = rphiReso;
-}
-
-void TrackerHitExtended::setResolutionZ(float zReso) {
-  _zReso = zReso;
-}
-
-int TrackerHitExtended::getType() {
-    return _type;
-}
-
-int TrackerHitExtended::getDet() {
-    return _idet;
-}
-
-void TrackerHitExtended::setUsedInFit(bool usedInFit) {
-    _usedInFit = usedInFit;
-}
-
-bool TrackerHitExtended::getUsedInFit() {
-    return _usedInFit;
-}
-
diff --git a/Utilities/DataHelper/src/TrackerHitExtended.h~ b/Utilities/DataHelper/src/TrackerHitExtended.h~
deleted file mode 100644
index e2a85261afe5b9e119755766ea9bdb915e914f5e..0000000000000000000000000000000000000000
--- a/Utilities/DataHelper/src/TrackerHitExtended.h~
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef TRACKERHITAR_H
-#define TRACKERHITAR_H 1
-
-//#include "lcio.h"
-//#include "EVENT/LCIO.h"
-#include "edm4hep/TrackerHit.h"
-//#include "TrackExtended.h"
-#include <vector>
-
-
-//using namespace edm4hep;
-
-class TrackExtended;
-typedef std::vector<TrackExtended*> TrackExtendedVec;
-
-/**
- * Class extending native LCIO class TrackerHit. <br>
- * Class TrackerHitExtended is used in TrackwiseClustering <br>
- * and Wolf processors. <br>
- * @author A. Raspereza (DESY)<br>
- * @version $Id: TrackerHitExtended.h,v 1.7 2007-09-05 09:39:49 rasp Exp $<br>
- */
-class TrackerHitExtended {
-  
- public:
-  
-  TrackerHitExtended(const edm4hep::TrackerHit& trackerhit);
-  ~TrackerHitExtended();
-  void setTrackExtended(TrackExtended * trackAR);
-    void addTrackExtended(TrackExtended * trackAR);
-    void setTrackerHitTo(TrackerHitExtended * hitTo);
-    void setTrackerHitFrom(TrackerHitExtended * hitFrom);
-    void setGenericDistance(float genericDistance);
-    void setTrackerHit(edm4hep::TrackerHit hit);
-    void setYresTo(float yresTo);
-    void setYresFrom(float yresFrom);
-    void setDirVec(float * dirVec);
-    void clearTrackVec();
-    void setResolutionRPhi(float rphiReso);
-    void setResolutionZ(float zReso);
-    void setType(int type);
-    void setDet(int idet);
-    void setUsedInFit(bool usedInFit);
-
-    edm4hep::TrackerHit* getTrackerHit();
-    TrackExtended * getTrackExtended();
-    TrackExtendedVec & getTrackExtendedVec();
-    TrackerHitExtended * getTrackerHitFrom();
-    TrackerHitExtended * getTrackerHitTo();
-    float getGenericDistance();
-    float getYresTo();
-    float getYresFrom();
-    float * getDirVec();
-    float getResolutionRPhi();
-    float getResolutionZ();
-    int getType();
-    int getDet();
-    bool getUsedInFit();
-
- private:
-
-    edm4hep::TrackerHit _trackerHit;
-    TrackExtended * _trackAR;
-    TrackerHitExtended * _hitTo;
-    TrackerHitExtended * _hitFrom;
-    TrackExtendedVec _trackVecAR;
-
-    float _rphiReso;
-    float _zReso;
-    float _yresTo;
-    float _yresFrom;
-    float _genericDistance;
-    float _dirVec[3];
-
-    int _type;
-    int _idet;
-
-    bool _usedInFit;
-	
-};
-
-typedef std::vector<TrackerHitExtended*> TrackerHitExtendedVec; 
-
-#endif