diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/TrigFastTrackFinder/TrigFastTrackFinder.h b/Trigger/TrigAlgorithms/TrigFastTrackFinder/TrigFastTrackFinder/TrigFastTrackFinder.h
new file mode 100644
index 0000000000000000000000000000000000000000..b6684686b299a770e9d287196543bc70038b4bde
--- /dev/null
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/TrigFastTrackFinder/TrigFastTrackFinder.h
@@ -0,0 +1,284 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// filename: TrigFastTrackFinder.h
+// 
+// Description: a part of L2+EF HLT ID tracking
+// 
+// date: 16/04/2013
+// 
+// -------------------------------
+// ATLAS Collaboration
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef __TRIG_FAST_TRACK_FINDER_H__
+#define __TRIG_FAST_TRACK_FINDER_H__
+
+#include<string>
+#include<vector>
+#include<map>
+//#include<algorithm>
+
+#include "GaudiKernel/ToolHandle.h"
+#include "TrigInterfaces/FexAlgo.h"
+
+#include "TrkEventPrimitives/ParticleHypothesis.h"
+
+#include "TrigInDetEvent/TrigInDetTrackCollection.h"
+#include "TrigInDetPattRecoEvent/TrigInDetPattRecoEvent/TrigInDetRoad.h"
+#include "TrigInDetPattRecoTools/TrigCombinatorialSettings.h"
+
+class IFTK_DataProviderTool;
+class ITrigL2LayerNumberTool;
+class ITrigL2LayerSetPredictorTool;
+class ITrigSpacePointConversionTool;
+class ITrigInDetRoadMakerTool;
+class ITrigL2SpacePointTruthTool;
+class ITrigInDetTrackFitter;
+class IRegSelSvc;
+class TrigRoiDescriptor;
+class Identifier;
+namespace InDet { 
+  class SiSpacePointsSeed;
+  class ISiTrackMaker; 
+}
+
+namespace MagField {	
+  class IMagFieldSvc;
+}
+
+namespace Trk {
+  class ITrackSummaryTool;
+}
+
+class TrigL2LayerSetLUT;
+class TrigSpacePointStorage;
+class TrigInDetDoublet;
+class TrigInDetTriplet;
+class TrigInDetTripletCluster;
+class TrigCombinatorialTrackFinding;
+class IBeamCondSvc;
+//class EventID;
+class PixelID;
+class SCT_ID;
+class AtlasDetectorID;
+
+class TrigFastTrackFinder : public HLT::FexAlgo {
+
+ public:
+  
+  TrigFastTrackFinder(const std::string& name, ISvcLocator* pSvcLocator);
+  ~TrigFastTrackFinder();
+  HLT::ErrorCode hltInitialize();
+  HLT::ErrorCode hltFinalize();
+  HLT::ErrorCode hltBeginRun();
+
+  HLT::ErrorCode hltExecute(const HLT::TriggerElement* inputTE,
+			    HLT::TriggerElement* outputTE);
+
+  bool isInRoad(const TrigSiSpacePointBase*, const TrigInDetRoad*);
+
+  void convertToTrigInDetTrack(const TrackCollection& offlineTracks, TrigInDetTrackCollection& trigInDetTracks);
+  double trackQuality(const Trk::Track* Tr);
+  void filterSharedTracks(std::vector<std::tuple<bool, double, Trk::Track*>>& QT);
+  void createOfflineSeeds(const std::vector<std::shared_ptr<TrigInDetTriplet>>& input, std::vector<InDet::SiSpacePointsSeed>& output);
+
+protected: 
+
+  void updateClusterMap(long int, const Trk::Track*, std::map<Identifier, std::vector<long int> >&);
+  void extractClusterIds(const Trk::SpacePoint*, std::vector<Identifier>&);
+  bool usedByAnyTrack(const std::vector<Identifier>&, std::map<Identifier, std::vector<long int> >&);
+
+  int findBarCodeInData(int, const std::vector<TrigSiSpacePointBase>&);
+  void showBarCodeInData(int, const std::vector<TrigSiSpacePointBase>&);
+  int findBarCodeInTriplets(int, const std::vector<std::shared_ptr<TrigInDetTriplet>>&);
+  int findBarCodeInDoublets(int, const std::vector<TrigInDetDoublet*>&);
+  void assignTripletBarCodes(const std::vector<std::shared_ptr<TrigInDetTriplet>>&, std::vector<int>&);
+  void assignTripletBarCodes(const std::vector<TrigInDetTriplet*>&, std::vector<int>&);
+  
+ private:
+
+  // AlgTools and Services
+
+  ToolHandle<ITrigL2LayerNumberTool> m_numberingTool;
+  ToolHandle<ITrigL2LayerSetPredictorTool> m_predictorTool;
+  ToolHandle<ITrigSpacePointConversionTool> m_spacePointTool;
+  ToolHandle<ITrigInDetRoadMakerTool> m_roadMakerTool;
+  ToolHandle<ITrigL2SpacePointTruthTool> m_TrigL2SpacePointTruthTool;
+  ToolHandle<InDet::ISiTrackMaker> m_trackMaker;   // Track maker 
+  ToolHandle<ITrigInDetTrackFitter> m_trigInDetTrackFitter;   // Track maker 
+  ToolHandle< Trk::ITrackSummaryTool > m_trackSummaryTool;
+
+  // ToolHandle<IFTK_DataProviderTool> m_ftkReader;
+ 
+  ServiceHandle<IRegSelSvc>     m_regionSelector;      //!< region selector service
+
+  ServiceHandle<MagField::IMagFieldSvc> m_MagFieldSvc;
+
+  double m_shift_x, m_shift_y;
+
+  // Control flags
+
+  bool m_useNewSeeding;//to activate roadless seed generator
+
+  bool m_ftkMode;
+  bool m_useBeamSpot; 
+  bool m_vertexSeededMode;
+
+  HLT::ErrorCode makeTripletClusters(const TrigSpacePointStorage& spacePointStorage, 
+                                     TrigCombinatorialTrackFinding& combinatorial, 
+                                     std::vector<TrigInDetTripletCluster*>& tripletClusters,  
+                                     const TrigL2LayerSetLUT* pLUT,
+                                     std::map<int,int>& nGoodDoublets,
+                                     const std::vector<TrigSiSpacePointBase>& convertedSpacePoints);
+
+  // Cuts and settings
+  TrigCombinatorialSettings m_tcs;
+
+  int  m_minHits;
+
+  int                     m_nSeeds;       //!< Number seeds 
+  int                     m_nTracksNew;      //!< Number found tracks 
+  int                     m_nfreeCut;     // Min number free clusters 
+
+  int                     m_nUsedLayers;
+
+  bool m_retrieveBarCodes;
+
+  float m_tripletMinPtFrac;
+  float m_pTmin;
+
+  bool m_checkSeedRedundancy;
+
+  // Roads
+
+  std::vector<TrigInDetRoad> m_roads;
+
+  // Names of IDCs with input data 
+  //
+  //
+  // Vertex (from beamspot)
+  Amg::Vector3D m_vertex;
+
+ 
+  // Reconstructed tracks 
+
+  TrigInDetTrackCollection* m_recoTracks;
+
+  IBeamCondSvc* m_iBeamCondSvc;
+  
+  // Data members for monitoring
+
+  int m_ntracks;
+  int m_nPixSPsInRoI;  // Total number of (filtered) pixel SPs in the RoI
+  int m_nSCTSPsInRoI;  // Total number of (filtered) SCT SPs in the RoI
+  int m_currentStage;  // The last stage reached during the processing of a given RoI
+
+  int m_roi_nSPs;
+
+  double m_roiPhi, m_roiEta;  
+  double m_roiPhiWidth, m_roiEtaWidth;  
+  double m_timePattReco;
+
+  int m_nZvertices; 
+  std::vector<float> m_zVertices; 
+
+  std::vector<double> m_a0beam;
+  std::vector<double> m_trkdPhi0, m_trkdEta;
+  //std::vector<double> m_sp_x, m_sp_y, m_sp_z, m_sp_r;//Spacepoint coordinates
+
+  std::vector<double> m_pixResPhiBarrel;
+  std::vector<double> m_pixResEtaBarrel;
+  std::vector<double> m_pixPullPhiBarrel;
+  std::vector<double> m_pixPullEtaBarrel;
+  std::vector<double> m_sctResBarrel;
+  std::vector<double> m_sctPullBarrel;
+  std::vector<double> m_pixResPhiEC;
+  std::vector<double> m_pixResEtaEC;
+  std::vector<double> m_pixPullPhiEC;
+  std::vector<double> m_pixPullEtaEC;
+  std::vector<double> m_sctResEC;
+  std::vector<double> m_sctPullEC;
+
+  // Monitoring member functions 
+
+  static inline double monPt(const TrigInDetTrack *t){return t->param()->pT(); }
+  static inline double monA0(const TrigInDetTrack *t){return t->param()->a0(); }
+  static inline double monZ0(const TrigInDetTrack *t){return t->param()->z0(); }
+  static inline double monPhi0(const TrigInDetTrack *t){return t->param()->phi0();}
+  static inline double monEta(const TrigInDetTrack *t){return t->param()->eta(); }
+  static inline double monNHit_Si(const TrigInDetTrack *t){return (t->NPixelSpacePoints()+t->NSCT_SpacePoints());}
+  static inline double monChi2(const TrigInDetTrack *t){return (t->chi2()>9e7)?-9.9:t->chi2();}
+
+  void fill_a0();
+
+  void calculateRecoEfficiency(const std::vector<TrigSiSpacePointBase>&,
+			       const std::map<int,int>&,
+			       const std::map<int,int>&,
+			       const std::map<int,int>&);
+
+
+  //Setup functions
+  void clearMembers();
+  void getBeamSpot();
+  void getMagField();
+  HLT::ErrorCode getRoI(const HLT::TriggerElement* inputTE, const IRoiDescriptor*& roi);
+
+  // Timers 
+
+  TrigTimer* m_SpacePointConversionTimer;
+  TrigTimer* m_PatternRecoTimer; 
+  TrigTimer* m_SpacePointSortingTimer;
+  TrigTimer* m_DoubletFindingTimer; 
+  TrigTimer* m_TripletFindingTimer; 
+  TrigTimer* m_TripletClusterTimer; 
+  TrigTimer* m_TripletMakingTimer; 
+  TrigTimer* m_CombTrackingTimer; 
+  TrigTimer* m_TrackFitterTimer; 
+
+  // Other member functions
+
+  StatusCode storeSpacePoints(const std::vector<TrigSiSpacePointBase>& convertedSpacePoints, TrigSpacePointStorage& spacePointStorage);
+
+  // Internal bookkeeping
+
+  std::string m_instanceName, m_attachedFeatureName1, m_attachedFeatureName2, 
+    m_outputCollectionSuffix;
+
+  unsigned int m_l1Id;
+  unsigned int m_countTotalEvents;
+  unsigned int m_countTotalRoI;
+  unsigned int m_countRoIwithEnoughHits;
+  unsigned int m_countRoIwithTracks;
+
+  //efficiency calculations
+  std::vector<int> m_vSignalBarCodes;
+
+  int m_nSignalPresent;
+  int m_nSignalDetected;
+  int m_nSignalTracked;
+  int m_nGoodDoublets;
+  int m_nSignalClones;
+  const PixelID* m_pixelId;
+  const SCT_ID* m_sctId;
+  const AtlasDetectorID* m_idHelper;
+  StoreGateSvc*  m_detectorStore;
+
+  //Merge clone triplet clusters?
+  bool m_doCloneMerge;
+  bool m_doCloneRemove;
+  int m_numSeedsToTry;
+  int m_minSignalSPs;
+
+	bool m_roiForIDWarning=false;
+
+  Trk::ParticleHypothesis m_particleHypothesis = Trk::pion;//particle hypothesis to attach to each track - usually pion, can be set to other values
+
+  std::map<Identifier, std::vector<long int> > m_siClusterMap;
+
+};
+
+#endif
diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/cmt/requirements b/Trigger/TrigAlgorithms/TrigFastTrackFinder/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..d81a33ff86bde5a5f4621b64dc9e72eae42718cd
--- /dev/null
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/cmt/requirements
@@ -0,0 +1,53 @@
+package TrigFastTrackFinder
+
+# =====================================================================
+
+public
+
+# General
+use AtlasPolicy			AtlasPolicy-*
+use GaudiInterface		GaudiInterface-*     External
+
+# Trigger
+use TrigInterfaces              TrigInterfaces-*	 Trigger/TrigSteer
+use TrigInDetEvent		TrigInDetEvent-*	 Trigger/TrigEvent
+use TrigSteeringEvent           TrigSteeringEvent-*      Trigger/TrigEvent
+use TrigInDetPattRecoEvent	TrigInDetPattRecoEvent-*   Trigger/TrigEvent
+use TrigInDetPattRecoTools      TrigInDetPattRecoTools-*   Trigger/TrigTools
+
+use TrkEventPrimitives   TrkEventPrimitives-*   Tracking/TrkEvent
+
+# =====================================================================
+
+apply_pattern declare_python_modules files="*.py"
+
+apply_pattern component_library
+
+library TrigFastTrackFinder  *.cxx components/*.cxx 
+
+private
+
+# Tracking
+
+use     AtlasTBB                        AtlasTBB-*                      External
+use 	TrkRIO_OnTrack			TrkRIO_OnTrack-*		Tracking/TrkEvent 
+use     InDetRIO_OnTrack                InDetRIO_OnTrack-*              InnerDetector/InDetRecEvent 
+use	TrkParameters			TrkParameters-*			Tracking/TrkEvent 
+use     EventPrimitives                 EventPrimitives-*               Event
+use TrkToolInterfaces           TrkToolInterfaces-*           Tracking/TrkTools
+
+use	InDetRecToolInterfaces		InDetRecToolInterfaces-* 	InnerDetector/InDetRecTools 
+use	IRegionSelector			IRegionSelector-*		DetectorDescription
+use     InDetIdentifier                 InDetIdentifier-*               InnerDetector/InDetDetDescr
+
+use TrigInDetToolInterfaces     TrigInDetToolInterfaces-*  Trigger/TrigTools
+use TrkTrack		        TrkTrack-* 		   Tracking/TrkEvent
+use TrigTimeAlgs		TrigTimeAlgs-*		   Trigger/TrigTools
+use StoreGate			StoreGate-*		   Control
+use InDetBeamSpotService        InDetBeamSpotService-*     InnerDetector/InDetConditions
+
+use AthenaBaseComps              AthenaBaseComps-*	   Control
+use InDetPrepRawData     	 InDetPrepRawData-*	   InnerDetector/InDetRecEvent 
+use SiSpacePointsSeed            SiSpacePointsSeed-*       InnerDetector/InDetRecEvent 
+use TrigInDetRecoTools           TrigInDetRecoTools-*      Trigger/TrigTools
+use MagFieldInterfaces           MagFieldInterfaces-*      MagneticField 
diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/python/TrigFastTrackFinder_Config.py b/Trigger/TrigAlgorithms/TrigFastTrackFinder/python/TrigFastTrackFinder_Config.py
new file mode 100755
index 0000000000000000000000000000000000000000..15538166e9deb9e8bb91a078379754762c0799e4
--- /dev/null
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/python/TrigFastTrackFinder_Config.py
@@ -0,0 +1,539 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from TrigFastTrackFinder.TrigFastTrackFinderConf import TrigFastTrackFinder
+
+from TrigOnlineSpacePointTool.TrigOnlineSpacePointToolConf import TrigL2LayerNumberTool
+from TrigTimeMonitor.TrigTimeHistToolConfig import TrigTimeHistToolConfig
+
+from AthenaCommon.AppMgr import ToolSvc
+import math
+
+numberingTool = TrigL2LayerNumberTool()
+ToolSvc += numberingTool
+
+
+from TrigMonitorBase.TrigGenericMonitoringToolConfig import defineHistogram, TrigGenericMonitoringToolConfig
+
+from AthenaCommon.SystemOfUnits import *
+
+class CommonSettings() :
+    def __init__(self):
+        self.allowedInstanceNames = ['Muon', 'eGamma', 'muonIso', 'Tau', 'TauCore', 'TauIso',
+                                     'Jet', 'Bphysics', 'FullScan', 'BeamSpot', 'Tile', 'FullScan_ZF_Only']
+        self.db = {}
+   
+    def __getitem__(self, (quantity, slice)):
+        v = None
+        try:
+            q = self.db[quantity]
+            try:
+                v = q[slice]
+            except:
+                print 'Settings has no instance %s ' % slice
+        except:
+            print 'Settings has no setting %s ' % quantity
+        return v
+
+    def __setitem__(self, (quantity, slice), value):
+        try:
+            q = self.db[quantity]
+            try:
+                q[slice] = value
+            except:
+                print 'Settings has no instance %s ' % slice
+        except:
+            print 'Settings has no setting %s ' % quantity
+
+class ConfigurationFactory() :
+    def __init__(self):
+        self.settings = CommonSettings()
+       
+        width = {}
+        usezvtool = {}
+        nclustersmin = {}
+        nholesmax = {}
+        nholesgapmax = {}
+        seedsfilterlevel = {}
+        freeclusterscut = {}
+        tripletminptfrac = {}
+        tripletcutroieta = {}
+        tripletcutroiphi = {}
+        tripletdofilter = {} 
+        usenewseeding   = {}
+        tripletrzmax = {}
+        tripletchi2max = {}
+        tripletphiscale = {}
+        tripletnbest = {}
+        uselikelihood = {}
+        tripletminllr = {}
+        tripletmintriplets = {}
+        tripletsmaxlayers = {}
+        tripletsdomaxlayers = {}
+        tripletcloneremovethr = {}
+        doclonemerge = {}
+        docloneremove = {}
+        doredundantseeds = {}
+        numseedstotry = {}
+        clusterprefit = {}
+        layeronedepth = {}
+        layertwodepth = {}
+        ptmin = {}
+        dospacepointphifiltering = {}
+
+        for i in self.settings.allowedInstanceNames :
+            width[i] = 10.0
+            usezvtool[i] = True
+            nclustersmin[i] = 7
+            nholesmax[i] = 2
+            nholesgapmax[i] = 2
+            seedsfilterlevel[i] = 0
+            freeclusterscut[i] = 5
+            tripletminptfrac[i] = 1.0
+            tripletcutroieta[i] = False
+            tripletcutroiphi[i] = False
+            tripletdofilter[i] = True
+            usenewseeding[i]   = True
+            tripletrzmax[i] = 8.0
+            tripletchi2max[i] = 25.0
+            tripletphiscale[i] = 0.0006
+            tripletnbest[i] = 2
+            uselikelihood[i] = False
+            tripletminllr[i] = -200.0
+            tripletmintriplets[i] = 2
+            tripletsmaxlayers[i] = 5
+            tripletsdomaxlayers[i] = False
+            tripletcloneremovethr[i] = 0.6
+            doclonemerge[i] = False
+            docloneremove[i] = False
+            doredundantseeds[i] = False
+            numseedstotry[i] = 2
+            clusterprefit[i] = False
+            layeronedepth[i] = 2
+            layertwodepth[i] = 2
+            ptmin[i] = 1.0*GeV
+            dospacepointphifiltering[i] = True
+       
+        # customize setting here: for example width['Tau'] = 20.
+        tripletdofilter['eGamma'] = True
+        #tripletphiscale['eGamma'] =  0.005 # to account for brem
+        clusterprefit['eGamma'] = True
+        numseedstotry['eGamma'] = 1
+        doredundantseeds['eGamma'] = True
+        tripletcutroieta['eGamma'] = True
+        tripletcutroiphi['eGamma'] = True
+
+        tripletdofilter['Muon'] = True
+        clusterprefit['Muon'] = True
+        numseedstotry['Muon'] = 1
+        doredundantseeds['Muon'] = True
+        tripletcutroieta['Muon'] = True
+        tripletcutroiphi['Muon'] = True
+        
+        tripletchi2max['Tau'] = 12.0
+        clusterprefit['Tau'] = False
+        tripletnbest['Tau'] = 2
+        numseedstotry['Tau'] = 1
+        doredundantseeds['Tau'] = False
+        tripletdofilter['Tau'] = True
+        tripletcutroieta['Tau'] = True
+        tripletcutroiphi['Tau'] = True
+
+        clusterprefit['Jet'] = False
+        tripletnbest['Jet'] = 2
+        numseedstotry['Jet'] = 1
+        doredundantseeds['Jet'] = False
+        tripletcutroieta['Jet'] = True
+        tripletcutroiphi['Jet'] = True
+
+
+        # extend settings database
+        self.settings.db['RoadWidth']=width
+        self.settings.db['useZvertexTool'] = usezvtool
+        self.settings.db['nClustersMin'] = nclustersmin
+        self.settings.db['nHolesMax'] = nholesmax
+        self.settings.db['nHolesGapMax'] = nholesgapmax
+        self.settings.db['SeedsFilterLevel'] = seedsfilterlevel
+        self.settings.db['FreeClustersCut'] = freeclusterscut
+        self.settings.db['Triplet_DoFilter'] = tripletdofilter
+        self.settings.db['Triplet_MinPtFrac'] = tripletminptfrac
+        self.settings.db['Triplet_CutRoiEta'] = tripletcutroieta
+        self.settings.db['Triplet_CutRoiPhi'] = tripletcutroiphi
+        self.settings.db['UseNewSeeding'] = usenewseeding
+        self.settings.db['Triplet_RZMax'] = tripletrzmax
+        self.settings.db['Triplet_Chi2Max'] = tripletchi2max
+        self.settings.db['Triplet_FilterPhiScale'] = tripletphiscale
+        self.settings.db['Triplet_NBest'] = tripletnbest
+        self.settings.db['UseLikelihood'] = uselikelihood
+        self.settings.db['Triplet_MinLLR'] = tripletminllr
+        self.settings.db['Triplet_MinTriplets'] = tripletmintriplets
+        self.settings.db['Triplet_MaxLayers'] = tripletsmaxlayers
+        self.settings.db['Triplet_DoMaxLayers'] = tripletsdomaxlayers
+        self.settings.db['Triplet_CloneRemoveThreshold'] = tripletcloneremovethr
+        self.settings.db['doCloneMerge'] = doclonemerge
+        self.settings.db['doCloneRemove'] = docloneremove
+        self.settings.db['doSeedRedundancyCheck'] = doredundantseeds
+        self.settings.db['numSeedsToTry'] = numseedstotry
+        self.settings.db['Triplet_ClusterPrefit'] = clusterprefit
+        self.settings.db['layerOneDepth'] = layeronedepth
+        self.settings.db['layerTwoDepth'] = layertwodepth
+        self.settings.db['pTmin'] = ptmin
+        self.settings.db['doSpacePointPhiFiltering'] = dospacepointphifiltering 
+        
+    def configureInstance(self, ftfInstance, instName) :
+        if instName in self.settings.allowedInstanceNames :
+            from AthenaCommon.DetFlags import DetFlags
+            from AthenaCommon.AppMgr import ToolSvc
+            from InDetTrigRecExample.InDetTrigFlags import InDetTrigFlags
+
+            ## SCT and Pixel detector elements road builder
+            from InDetTrigRecExample.InDetTrigConfigRecLoadTools import InDetTrigPixelConditionsSummarySvc, InDetTrigSCTConditionsSummarySvc
+            from InDetTrigRecExample.InDetTrigConfigRecLoadTools import InDetTrigSiDetElementsRoadMaker
+            InDetTrigSiDetElementsRoadMaker_FTF = InDetTrigSiDetElementsRoadMaker.clone('InDetTrigSiDetElementsRoadMaker_FTF')
+            InDetTrigSiDetElementsRoadMaker_FTF.RoadWidth = self.settings[('RoadWidth',instName)]
+            ToolSvc += InDetTrigSiDetElementsRoadMaker_FTF
+
+            if DetFlags.haveRIO.pixel_on():
+                from PixelConditionsServices.PixelConditionsServicesConf import PixelConditionsSummarySvc
+                from InDetTrigRecExample.InDetTrigConditionsAccess import PixelConditionsSetup
+                InDetTrigPixelConditionsSummarySvc = PixelConditionsSummarySvc(PixelConditionsSetup.instanceName('PixelConditionsSummarySvc'))
+            else:
+                InDetTrigPixelConditionsSummarySvc = None
+           
+            if DetFlags.haveRIO.SCT_on():
+                from SCT_ConditionsServices.SCT_ConditionsServicesConf import SCT_ConditionsSummarySvc
+                from InDetTrigRecExample.InDetTrigConditionsAccess import SCT_ConditionsSetup
+                InDetTrigSCTConditionsSummarySvc = SCT_ConditionsSummarySvc(SCT_ConditionsSetup.instanceName('InDetSCT_ConditionsSummarySvc'))
+            else:
+                InDetTrigSCTConditionsSummarySvc = None
+
+            from TrigOnlineSpacePointTool.TrigOnlineSpacePointToolConf import TrigSpacePointConversionTool
+            spTool = TrigSpacePointConversionTool()
+            spTool.DoPhiFiltering = self.settings[('doSpacePointPhiFiltering',instName)]
+            ToolSvc += spTool
+            ftfInstance.SpacePointProviderTool=spTool
+
+           
+            from SiCombinatorialTrackFinderTool_xk.SiCombinatorialTrackFinderTool_xkConf import InDet__SiCombinatorialTrackFinder_xk
+            from InDetTrigRecExample.InDetTrigConfigRecLoadTools import InDetTrigPrdAssociationTool, InDetTrigPatternPropagator
+            from InDetTrigRecExample.InDetTrigConfigRecLoadTools import InDetTrigPatternUpdator, InDetTrigRotCreator
+            
+            CombinatorialTrackFinder_FTF = InDet__SiCombinatorialTrackFinder_xk(name = 'InDetTrigSiComTrackFinder_FTF_'+instName,
+                                                                                PropagatorTool = InDetTrigPatternPropagator,
+                                                                                UpdatorTool    = InDetTrigPatternUpdator,
+                                                                                RIOonTrackTool   = InDetTrigRotCreator,
+                                                                                AssosiationTool  = InDetTrigPrdAssociationTool,
+                                                                                usePixel         = DetFlags.haveRIO.pixel_on(),
+                                                                                useSCT           = DetFlags.haveRIO.SCT_on(),
+                                                                                PixelClusterContainer = 'PixelTrigClusters',
+                                                                                SCT_ClusterContainer = 'SCT_TrigClusters',
+                                                                                PixelSummarySvc = InDetTrigPixelConditionsSummarySvc,
+                                                                                SctSummarySvc = InDetTrigSCTConditionsSummarySvc)
+            ToolSvc += CombinatorialTrackFinder_FTF
+
+            from SiTrackMakerTool_xk.SiTrackMakerTool_xkConf import InDet__SiTrackMaker_xk
+
+            from InDetTrigRecExample.ConfiguredNewTrackingTrigCuts import EFIDTrackingCuts
+            TrackMaker_FTF = InDet__SiTrackMaker_xk(name = 'InDetTrigSiTrackMaker_FTF_'+instName,
+                                                    RoadTool       = InDetTrigSiDetElementsRoadMaker_FTF,
+                                                    CombinatorialTrackFinder = CombinatorialTrackFinder_FTF,
+                                                    pTmin          = self.settings[('pTmin',instName)],
+                                                    nClustersMin   = EFIDTrackingCuts.minClusters(),
+                                                    nHolesMax      = EFIDTrackingCuts.nHolesMax(),
+                                                    nHolesGapMax   = EFIDTrackingCuts.nHolesGapMax(),
+                                                    SeedsFilterLevel = self.settings[('SeedsFilterLevel',instName)],
+                                                    Xi2max         = EFIDTrackingCuts.Xi2max(),
+                                                    Xi2maxNoAdd    = EFIDTrackingCuts.Xi2maxNoAdd(),
+                                                    nWeightedClustersMin= EFIDTrackingCuts.nWeightedClustersMin(),
+                                                    Xi2maxMultiTracks         = EFIDTrackingCuts.Xi2max(),
+                                                    UseAssociationTool       = False)
+
+            ToolSvc += TrackMaker_FTF
+            ftfInstance.offlineTrackMaker = TrackMaker_FTF
+            #print TrackMaker_FTF
+
+            from TrigInDetRecoTools.TrigInDetRecoToolsConf import TrigInDetRoadMakerTool
+            roadMakingTool = TrigInDetRoadMakerTool(name = 'TrigInDetRoadMakerTool_FTF_' + instName,
+                                                    EtaBin = False, EtaBinWidth = 5.0, 
+                                                    LayerOneDepth=self.settings[('layerOneDepth',instName)],
+                                                    LayerTwoDepth=self.settings[('layerTwoDepth',instName)]) 
+
+
+            print roadMakingTool
+            ToolSvc += roadMakingTool
+            ftfInstance.RoadMakerTool = roadMakingTool
+            ftfInstance.FreeClustersCut = self.settings[('FreeClustersCut',instName)]
+            ftfInstance.Triplet_DoFilter = self.settings[('Triplet_DoFilter',instName)]
+            ftfInstance.Triplet_MinPtFrac = self.settings[('Triplet_MinPtFrac',instName)]
+            ftfInstance.Triplet_CutRoiEta = self.settings[('Triplet_CutRoiEta',instName)]
+            ftfInstance.Triplet_CutRoiPhi = self.settings[('Triplet_CutRoiPhi',instName)]
+            ftfInstance.UseNewSeeding     = self.settings[('UseNewSeeding',instName)]
+            ftfInstance.Triplet_RZMax = self.settings[('Triplet_RZMax',instName)]
+            ftfInstance.Triplet_Chi2Max = self.settings[('Triplet_Chi2Max',instName)]
+            ftfInstance.Triplet_FilterPhiScale = self.settings[('Triplet_FilterPhiScale',instName)]
+            ftfInstance.Triplet_NBest = self.settings[('Triplet_NBest',instName)]
+            ftfInstance.Triplet_UseLikelihood = self.settings[('UseLikelihood',instName)]
+            ftfInstance.Triplet_MinLLR = self.settings[('Triplet_MinLLR',instName)]
+            ftfInstance.Triplet_MinTriplets = self.settings[('Triplet_MinTriplets',instName)]
+            ftfInstance.Triplet_MaxLayers = self.settings[('Triplet_MaxLayers',instName)]
+            ftfInstance.Triplet_DoMaxLayers = self.settings[('Triplet_DoMaxLayers',instName)]
+            ftfInstance.Triplet_CloneRemoveThreshold = self.settings[('Triplet_CloneRemoveThreshold',instName)]
+            ftfInstance.doCloneMerge = self.settings[('doCloneMerge',instName)]
+            ftfInstance.doCloneRemove = self.settings[('doCloneRemove',instName)]
+            ftfInstance.doSeedRedundancyCheck = self.settings[('doSeedRedundancyCheck',instName)]
+            ftfInstance.numSeedsToTry = self.settings[('numSeedsToTry',instName)]
+            ftfInstance.Triplet_ClusterPrefit = self.settings[('Triplet_ClusterPrefit',instName)]
+            ftfInstance.pTmin = self.settings[('pTmin',instName)]
+        else :
+            print "Instance "+instName+" of TrigFastTrackFinder is not supported!"
+            ftfInstance.offlineTrackMaker = None
+   
+
+#Monitoring
+class TrigFastTrackFinder_CommonMonitoring(TrigGenericMonitoringToolConfig):
+    def __init__ (self, name="TrigFastTrackFinder_OnlineMonitoring"):
+        super(TrigFastTrackFinder_CommonMonitoring, self).__init__(name)
+    def addSPHistograms(self):
+        self.Histograms += [ defineHistogram('roi_nSPsPIX',
+                                             type='TH1F',
+                                             title="Number of Pixel SPs",
+                                             xbins = 500, xmin=-0.5, xmax=4999.5)]
+        self.Histograms += [ defineHistogram('roi_nSPsSCT',
+                                             type='TH1F',
+                                             title="Number of SCT SPs",
+                                             xbins = 500, xmin=-0.5, xmax=4999.5)]
+        self.Histograms += [ defineHistogram('roi_eta',
+                                             type='TH1F',
+                                             title="Eta of the input RoI",
+                                             xbins = 100, xmin=-5, xmax=5)]
+        self.Histograms += [ defineHistogram('roi_phi',
+                                             type='TH1F',
+                                             title="Phi of the input RoI",
+                                             xbins = 100, xmin=-3.2, xmax=3.2)]
+        self.Histograms += [ defineHistogram('roi_phiWidth',
+                                             type='TH1F',
+                                             title="Phi width of the input RoI",
+                                             xbins = 100, xmin=0, xmax=6.4)]
+        self.Histograms += [ defineHistogram('roi_etaWidth',
+                                             type='TH1F',
+                                             title="Eta width of the input RoI",
+                                             xbins = 100, xmin=0, xmax=5)]
+    def addDataErrorHistograms(self):
+        self.Histograms += [ defineHistogram('roi_lastStageExecuted',
+                                             type='TH1F',
+                                             title="Last Step Successfully Executed",
+                                             xbins = 8 , xmin=-0.5, xmax=7.5,
+                             labels='Start : GetRoI : GetSPs : MissingLayers : ZFinder : Groups : TrackFit' ) ]
+   
+    def addTrackHistograms(self):
+        self.Histograms += [ defineHistogram('trk_nSiHits',
+                                             type='TH1F',
+                                             title="Total number of Silicon Hits per Track",
+                                             xbins = 20, xmin=-0.5, xmax=19.5)]
+        self.Histograms += [ defineHistogram('trk_nPIXHits',
+                                             type='TH1F',
+                                             title="Number of Pixel Hits per Track",
+                                             xbins = 10, xmin=-0.5, xmax=9.5)]
+        self.Histograms += [ defineHistogram('trk_nSCTHits',
+                                             type='TH1F',
+                                             title="Number of SCT Hits per Track",
+                                             xbins = 10, xmin=-0.5, xmax=9.5)]
+        self.Histograms += [ defineHistogram('trk_chi2dof',
+                                             type='TH1F',
+                                             title="ChiSqd / nDoF",
+                                             xbins = 100, xmin=0.0, xmax=5)]
+        self.Histograms += [ defineHistogram('trk_pt',
+                                             type='TH1F',
+                                             title="pt",
+                                             xbins = 400, xmin=-1e6, xmax=1e6)]
+        self.Histograms += [ defineHistogram('trk_phi0',
+                                             type='TH1F',
+                                             title="phi",
+                                             xbins = 100, xmin=-3.2, xmax=3.2)]
+        self.Histograms += [ defineHistogram('trk_eta',
+                                             type='TH1F',
+                                             title="eta",
+                                             xbins = 100, xmin=-5, xmax=5)]
+        self.Histograms += [ defineHistogram('trk_dPhi0',
+                                             type='TH1F',
+                                             title="dphi",
+                                             xbins = 160, xmin=-0.8, xmax=0.8)]
+        self.Histograms += [ defineHistogram('trk_dEta',
+                                             type='TH1F',
+                                             title="deta",
+                                             xbins = 160, xmin=-0.8, xmax=0.8)]
+
+        #self.Histograms += [ defineHistogram('sp_x , sp_y',
+        #                                     type='TH2F',
+        #                                     title="Spacepoints-on-track xy",
+        #                                     xbins = 200 ,  xmin=-600.0, xmax=600.0, 
+        #                                     ybins = 200 ,  ymin=-600.0, ymax=600.0)]
+
+        #self.Histograms += [ defineHistogram('sp_z , sp_r',
+        #                                     type='TH2F',
+        #                                     title="Spacepoints-on-track rz",
+        #                                     xbins = 400 ,  xmin=-2800.0, xmax=2800.0, 
+        #                                     ybins = 100 ,  ymin=0.0, ymax=600.0)]
+    #Extra timing histograms for validation only
+    def addTimingHistograms(self,nbin,min,max):
+        self.Histograms += [ defineHistogram('roi_nSPs , time_PattRecoOnly',
+                                             type='TH2F',
+                                             title="PattReco time vs nSPs",
+                                             xbins = 200 ,  xmin=0.0, xmax=3000.0, 
+                                             ybins = 100 ,  ymin=0.0, ymax=200.0)]
+        self.Histograms += [ defineHistogram('roi_nTracks , time_PattRecoOnly',
+                                             type='TH2F',
+                                             title="PattReco time vs nTracks",
+                                             xbins = 50 ,  xmin=0.0, xmax=200.0, 
+                                             ybins = 100 ,  ymin=0.0, ymax=200.0)]
+        self.Histograms += [ defineHistogram('time_PattRecoOnly',
+                                             type='TH1F',
+                                             title="Pure PattReco time",
+                                             xbins = nbin , xmin=0.0, xmax=200.0)]
+    
+   
+
+class TrigFastTrackFinder_OnlineMonitoring(TrigFastTrackFinder_CommonMonitoring):
+    def __init__ (self, name="TrigFastTrackFinder_OnlineMonitoring"):
+        super(TrigFastTrackFinder_OnlineMonitoring, self).__init__(name)
+        self.defineTarget("Online")
+        self.addSPHistograms()
+        self.addDataErrorHistograms()
+        self.addTrackHistograms()
+        self.Histograms += [ defineHistogram('trk_a0',
+                                             type='TH1F',
+                                             title="a0",
+                                             xbins = 200, xmin=-10, xmax=10)]
+        self.Histograms += [ defineHistogram('trk_a0beam',
+                                             type='TH1F',
+                                             title="a0beam",
+                                             xbins = 200, xmin=-10, xmax=10)]
+        self.Histograms += [ defineHistogram('trk_z0',
+                                             type='TH1F',
+                                             title="z0",
+                                             xbins = 200, xmin=-400, xmax=400)]
+        self.Histograms += [ defineHistogram('roi_nTracks',
+                                             type='TH1F',
+                                             title="Number of Tracks",
+                                             xbins = 100, xmin=-0.5, xmax=99.5)]
+
+
+class TrigFastTrackFinder_ValidationMonitoring(TrigFastTrackFinder_CommonMonitoring):
+    def __init__ (self, name="TrigFastTrackFinder_ValidationMonitoring"):
+        super(TrigFastTrackFinder_ValidationMonitoring, self).__init__(name)
+        self.defineTarget("Validation")
+        self.addSPHistograms()
+        self.addTimingHistograms(150,0.,150.)
+        self.addDataErrorHistograms()
+        self.addTrackHistograms()
+        self.Histograms += [ defineHistogram('trk_a0',
+                                             type='TH1F',
+                                             title="a0",
+                                             xbins = 200, xmin=-10, xmax=10)]
+        self.Histograms += [ defineHistogram('trk_a0beam',
+                                             type='TH1F',
+                                             title="a0beam",
+                                             xbins = 200, xmin=-10, xmax=10)]
+        self.Histograms += [ defineHistogram('trk_z0',
+                                             type='TH1F',
+                                             title="z0",
+                                             xbins = 200, xmin=-400, xmax=400)]
+        self.Histograms += [ defineHistogram('roi_nTracks',
+                                             type='TH1F',
+                                             title="Number of Tracks",
+                                             xbins = 200, xmin=-0.5, xmax=199.5)]
+
+
+#Cosmic Monitoring
+class TrigFastTrackFinder_Cosmic_Monitoring(TrigFastTrackFinder_CommonMonitoring):
+    def __init__ (self, name="TrigFastTrackFinder_Cosmic_Monitoring"):
+        super(TrigFastTrackFinder_Cosmic_Monitoring, self).__init__(name)
+        self.defineTarget("Cosmic")
+        self.addSPHistograms()
+        self.addDataErrorHistograms()
+        self.addTrackHistograms()
+        self.Histograms += [ defineHistogram('trk_a0',
+                                             type='TH1F',
+                                             title="a0",
+                                             xbins = 100, xmin=-300, xmax=300)]
+        self.Histograms += [ defineHistogram('trk_a0beam',
+                                             type='TH1F',
+                                             title="a0beam",
+                                             xbins = 100, xmin=-300, xmax=300)]
+        self.Histograms += [ defineHistogram('trk_z0',
+                                             type='TH1F',
+                                             title="z0",
+                                             xbins = 100, xmin=-800, xmax=800)]
+        self.Histograms += [ defineHistogram('roi_nTracks',
+                                             type='TH1F',
+                                             title="Number of Tracks",
+                                             xbins = 100, xmin=-0.5, xmax=99.5)]
+
+
+
+
+class TrigFastTrackFinderBase(TrigFastTrackFinder):
+    __slots__ = []
+    def __init__(self, instName, seqName, etaHalfWidth = 0.1, phiHalfWidth = 0.1, doRefit = True):
+        TrigFastTrackFinder.__init__(self,instName)
+        self.LayerNumberTool=numberingTool
+        self.doRefit       = doRefit
+        #self.doRefit       = False
+        #print instName
+        #print seqName
+       
+        self.phiHalfWidth = phiHalfWidth
+        self.etaHalfWidth = etaHalfWidth
+        self.MinHits = 5
+        
+        self.retrieveBarCodes = False
+        #self.SignalBarCodes = [10001] #single particles
+        self.SignalBarCodes = [11 ,12] #z->mumu
+       
+        self.OutputCollectionSuffix=instName.replace("TrigFastTrackFinder_","")
+        from AthenaCommon.AppMgr import ToolSvc
+
+        timeHist = TrigTimeHistToolConfig("Time")
+        timeHist.TimerHistLimits = [0,2000]
+        self.AthenaMonTools = [ TrigFastTrackFinder_ValidationMonitoring("TrigFastTrackFinder_ValidationMonitoring"),
+                                TrigFastTrackFinder_OnlineMonitoring("TrigFastTrackFinder_OnlineMonitoring"),
+                                timeHist ]
+
+        from TrigInDetConf.TrigInDetRecCommonTools import InDetTrigFastTrackSummaryTool
+        self.TrackSummaryTool = InDetTrigFastTrackSummaryTool
+
+        cfg = ConfigurationFactory()
+        cfg.configureInstance(self,seqName)
+        print self
+
+
+class TrigFastTrackFinder_Muon(TrigFastTrackFinderBase):
+  def __init__(self, name = "TrigFastTrackFinder_Muon"):
+    TrigFastTrackFinderBase.__init__(self, "TrigFastTrackFinder_Muon","Muon")
+
+class TrigFastTrackFinder_FullScan(TrigFastTrackFinderBase):
+  def __init__(self, name = "TrigFastTrackFinder_FullScan"):
+    TrigFastTrackFinderBase.__init__(self,"TrigFastTrackFinder_FullScan","FullScan")
+
+class TrigFastTrackFinder_eGamma(TrigFastTrackFinderBase):
+  def __init__(self, name = "TrigFastTrackFinder_eGamma"):
+    TrigFastTrackFinderBase.__init__(self, "TrigFastTrackFinder_eGamma","eGamma")
+
+class TrigFastTrackFinder_eGamma_L2(TrigFastTrackFinderBase):
+  def __init__(self, name = "TrigFastTrackFinder_eGamma_L2"):
+    TrigFastTrackFinderBase.__init__(self, "TrigFastTrackFinder_eGamma_L2","eGamma")
+
+class TrigFastTrackFinder_Tau(TrigFastTrackFinderBase):
+  def __init__(self, name = "TrigFastTrackFinder_Tau"):
+    TrigFastTrackFinderBase.__init__(self, "TrigFastTrackFinder_Tau","Tau")
+
+class TrigFastTrackFinder_TauCore(TrigFastTrackFinderBase):
+  def __init__(self, name = "TrigFastTrackFinder_TauCore"):
+    TrigFastTrackFinderBase.__init__(self, "TrigFastTrackFinder_TauCore","TauCore")
+
+class TrigFastTrackFinder_TauIso(TrigFastTrackFinderBase):
+  def __init__(self, name = "TrigFastTrackFinder_TauIso"):
+    TrigFastTrackFinderBase.__init__(self, "TrigFastTrackFinder_TauIso","Tau")
+
+class TrigFastTrackFinder_Jet(TrigFastTrackFinderBase):
+  def __init__(self, name = "TrigFastTrackFinder_Jet"):
+    TrigFastTrackFinderBase.__init__(self, "TrigFastTrackFinder_Jet","Jet")
diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.cxx b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7209e81dffbc56162bc30c482eec1f71c2083d94
--- /dev/null
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.cxx
@@ -0,0 +1,1496 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/////////////////////////////////////////////////////////////////////////////////
+// TrigFastTrackFinder.cxx
+// -------------------------------
+// ATLAS Collaboration
+//
+// package created 16/04/2013 by Dmitry Emeliyanov (see ChangeLog for more details)
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include <cmath>
+#include <iostream>
+#include <algorithm>
+#include <array>
+
+#include <tbb/parallel_for.h>
+#include "TrigSteeringEvent/TrigRoiDescriptor.h"
+#include "TrigSteeringEvent/PhiHelper.h"
+
+#include "GaudiKernel/PropertyMgr.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/IssueSeverity.h"
+#include "StoreGate/StoreGateSvc.h"
+
+#include "TrigTimeAlgs/TrigTimerSvc.h"
+
+#include "TrigInDetEvent/TrigVertex.h"
+#include "TrigInDetEvent/TrigVertexCollection.h"
+#include "TrigInDetEvent/TrigInDetTrack.h"
+#include "TrigInDetEvent/TrigInDetTrackCollection.h"
+#include "TrigInDetEvent/TrigInDetTrackFitPar.h"
+
+#include "TrkTrack/TrackCollection.h"
+#include "TrkTrack/Track.h"
+#include "TrkRIO_OnTrack/RIO_OnTrack.h"
+#include "InDetPrepRawData/SCT_Cluster.h"
+#include "InDetPrepRawData/PixelCluster.h"
+#include "InDetRIO_OnTrack/SiClusterOnTrack.h" 
+
+#include "TrkParameters/TrackParameters.h" 
+#include "EventPrimitives/EventPrimitivesHelpers.h"
+#include "EventPrimitives/SymmetricMatrixHelpers.h"
+#include "TrkTrack/Track.h" 
+#include "TrkTrack/TrackInfo.h" 
+
+#include "TrkToolInterfaces/ITrackSummaryTool.h"
+
+#include "IRegionSelector/IRegSelSvc.h"
+
+#include "TrigInDetEvent/TrigSiSpacePointBase.h"
+
+#include "InDetBeamSpotService/IBeamCondSvc.h"
+
+#include "InDetIdentifier/SCT_ID.h"
+#include "InDetIdentifier/PixelID.h" 
+
+#include "TrigInDetPattRecoEvent/TrigSpacePointStorage.h"
+#include "TrigInDetPattRecoEvent/TrigL2SpacePointStorage.h"
+#include "TrigInDetPattRecoEvent/TrigL2SpacePointStorageFiller.h"
+#include "TrigInDetPattRecoEvent/TrigL2TimeoutException.h"
+#include "TrigInDetPattRecoEvent/TrigInDetTracklet.h"
+
+#include "InDetRecToolInterfaces/ISiTrackMaker.h" 
+#include "TrigInDetPattRecoTools/TrigCombinatorialSettings.h"
+#include "TrigInDetPattRecoTools/TrigCombinatorialTrackFinding.h"
+#include "TrigInDetPattRecoTools/TrigTrackSeedGenerator.h"
+
+#include "TrigInDetToolInterfaces/ITrigL2LayerNumberTool.h"
+#include "TrigInDetToolInterfaces/ITrigSpacePointConversionTool.h"
+#include "TrigInDetToolInterfaces/ITrigInDetRoadMakerTool.h"
+#include "TrigInDetToolInterfaces/ITrigL2SpacePointTruthTool.h"
+#include "TrigInDetRecoTools/ITrigL2LayerSetPredictorTool.h"
+
+#include "TrigInDetToolInterfaces/ITrigInDetTrackFitter.h"
+
+#include "SiSpacePointsSeed/SiSpacePointsSeed.h"
+#include "TrigFastTrackFinder/TrigFastTrackFinder.h"
+#include "AthenaBaseComps/AthMsgStreamMacros.h"
+
+#include "MagFieldInterfaces/IMagFieldSvc.h"
+
+template <class SRC>
+inline const DataVector<TrigInDetTrack>** dvec_cast(SRC** ptr) { 
+  return (const DataVector<TrigInDetTrack>**)(ptr); 
+} 
+
+TrigFastTrackFinder::TrigFastTrackFinder(const std::string& name, ISvcLocator* pSvcLocator) : 
+
+  HLT::FexAlgo(name, pSvcLocator), 
+  m_numberingTool("TrigL2LayerNumberTool"), 
+  m_predictorTool("TrigL2LayerSetPredictorTool"),
+  m_spacePointTool("TrigSpacePointConversionTool"),
+  m_roadMakerTool("TrigInDetRoadMakerTool",this),
+  m_TrigL2SpacePointTruthTool("TrigL2SpacePointTruthTool"),
+  m_trackMaker("InDet::SiTrackMaker_xk/InDetTrigSiTrackMaker"),
+  m_trigInDetTrackFitter("TrigInDetTrackFitter"),
+  m_trackSummaryTool("Trk::ITrackSummaryTool/ITrackSummaryTool"),
+  m_regionSelector("RegSelSvc", name),
+  m_MagFieldSvc("AtlasFieldSvc",this->name()),
+  m_shift_x(0.0),
+  m_shift_y(0.0),
+  m_ftkMode(false),
+  m_useBeamSpot(true),
+  m_nfreeCut(5), 
+  m_ntracks(0),
+  m_nPixSPsInRoI(0),
+  m_nSCTSPsInRoI(0),
+  m_currentStage(-1),
+  m_attachedFeatureName1(""),
+  m_attachedFeatureName2("")
+{
+
+  //settings for the combinatorial track seeding
+
+  declareProperty("UseNewSeeding",            m_useNewSeeding      = true);
+
+
+  /** Doublet finding properties. */
+
+  declareProperty("Doublet_D0Max",            m_tcs.m_doubletD0Max         = 5.0);
+  declareProperty("Doublet_DphiOverDrMax",    m_tcs.m_doubletDphiOverDrMax = 0.001);
+  declareProperty("Doublet_Z0Max",            m_tcs.m_doubletZ0Max         = 230.0);
+
+  /** Triplet finding properties. */
+
+  declareProperty("Triplet_CutRoiEta",        m_tcs.m_tripletCutRoiEta  = false);
+  declareProperty("Triplet_CutRoiPhi",        m_tcs.m_tripletCutRoiPhi  = false);
+  declareProperty("Triplet_RZMax",            m_tcs.m_tripletRZMax      = 5.0);
+  declareProperty("Triplet_RZMaxPixel",       m_tcs.m_tripletRZMaxPixel = 1.0);
+  declareProperty("Triplet_RPhiMax",          m_tcs.m_tripletRPhiMax    = 0.0035);
+  declareProperty("Triplet_D0Max",            m_tcs.m_tripletD0Max      = 4.0);
+  declareProperty("Triplet_Chi2Max",          m_tcs.m_tripletChi2Max    = 100.0);
+  declareProperty("Triplet_DoFilter",         m_tcs.m_tripletFilter     = true);
+  declareProperty("Triplet_FilterPhiScale",   m_tcs.m_tripletFilterPhiScale = 0.0006);
+  declareProperty("Triplet_FilterEtaScale",   m_tcs.m_tripletFilterEtaScale = 0.0022);
+  declareProperty("Triplet_FilterDRMax",      m_tcs.m_tripletFilterDRMax    = 9.0);
+  declareProperty("Triplet_NBest",            m_tcs.m_tripletNBest      = 2);//retain only N  best triplets per cluster
+  declareProperty("Triplet_UseLikelihood",    m_tcs.m_useLikelihood      = false);
+  declareProperty("Triplet_MinLLR",           m_tcs.m_tripletMinLLR      = -20.0);
+  declareProperty("Triplet_CloneRemoveThreshold",   m_tcs.m_tripletCloneRemoveThreshold= 0.6);
+  declareProperty("Triplet_MaxLayers",        m_tcs.m_tripletMaxLayers = 100);
+  declareProperty("Triplet_DoMaxLayers",      m_tcs.m_tripletDoMaxLayers = false);
+  declareProperty("Triplet_MinTriplets",      m_tcs.m_minTriplets        = 1);
+  declareProperty("Triplet_ClusterPrefit",    m_tcs.m_prefitTripletClusters = false);
+
+  m_tcs.m_magFieldZ = 2.0;//switched to configured value in getMagField()
+
+  declareProperty( "VertexSeededMode",    m_vertexSeededMode = false);
+
+  declareProperty("Triplet_MinPtFrac",        m_tripletMinPtFrac = 0.3);
+  declareProperty("pTmin",                    m_pTmin = 1000.0);
+
+  declareProperty("doSeedRedundancyCheck",            m_checkSeedRedundancy = false);
+
+  declareProperty( "MinHits",               m_minHits = 5 );
+
+  declareProperty( "OutputCollectionSuffix",m_outputCollectionSuffix = "");
+ 
+  declareProperty( "UseBeamSpot",           m_useBeamSpot = true);
+  declareProperty( "FreeClustersCut"   ,m_nfreeCut      );
+  declareProperty( "SpacePointProviderTool", m_spacePointTool  );
+  declareProperty( "LayerNumberTool", m_numberingTool  );
+
+  declareProperty( "RoadMakerTool", m_roadMakerTool );
+
+  declareProperty( "offlineTrackMaker", m_trackMaker);
+  declareProperty( "TrigInDetTrackFitter",   m_trigInDetTrackFitter );
+
+  declareProperty("doCloneMerge",   m_doCloneMerge = false);
+  declareProperty("doCloneRemove",  m_doCloneRemove = true);
+
+  declareProperty("numSeedsToTry", m_numSeedsToTry = 1);
+
+  declareProperty("TrackSummaryTool", m_trackSummaryTool);
+  declareProperty( "TrigL2SpacePointTruthTool", m_TrigL2SpacePointTruthTool);
+  declareProperty( "retrieveBarCodes", m_retrieveBarCodes = false);
+  declareProperty( "SignalBarCodes", m_vSignalBarCodes);
+  declareProperty( "MinSignalSPs", m_minSignalSPs = 3);
+
+  m_countTotalEvents=0;
+  m_countTotalRoI=0;
+  m_countRoIwithEnoughHits=0;
+  m_countRoIwithTracks=0;
+  m_l1Id=99999999;
+  
+  m_recoTracks=nullptr;
+
+  // declare monitoring histograms
+
+  declareMonitoredCollection("trk_pt",         *dvec_cast(&m_recoTracks), &monPt);
+  declareMonitoredCollection("trk_a0",         *dvec_cast(&m_recoTracks), &monA0);
+  declareMonitoredCollection("trk_z0",         *dvec_cast(&m_recoTracks), &monZ0);
+  declareMonitoredCollection("trk_phi0",       *dvec_cast(&m_recoTracks), &monPhi0);
+  declareMonitoredCollection("trk_eta",        *dvec_cast(&m_recoTracks), &monEta);
+  declareMonitoredCollection("trk_chi2dof",    *dvec_cast(&m_recoTracks), &monChi2);
+  declareMonitoredCollection("trk_nSiHits",    *dvec_cast(&m_recoTracks), &monNHit_Si);
+  declareMonitoredCollection("trk_nPIXHits",   *dvec_cast(&m_recoTracks), &TrigInDetTrack::NPixelSpacePoints);
+  declareMonitoredCollection("trk_nSCTHits",   *dvec_cast(&m_recoTracks), &TrigInDetTrack::NSCT_SpacePoints);
+  declareMonitoredStdContainer("trk_a0beam",m_a0beam);
+  declareMonitoredStdContainer("trk_dPhi0",m_trkdPhi0);
+  declareMonitoredStdContainer("trk_dEta" ,m_trkdEta);
+
+  declareMonitoredVariable("roi_nTracks",m_ntracks);
+  declareMonitoredVariable("roi_nSPsPIX",m_nPixSPsInRoI);
+  declareMonitoredVariable("roi_nSPsSCT",m_nSCTSPsInRoI);
+  declareMonitoredVariable("roi_lastStageExecuted",m_currentStage);
+  declareMonitoredVariable("roi_eta", m_roiEta);
+  declareMonitoredVariable("roi_etaWidth", m_roiEtaWidth);
+  declareMonitoredVariable("roi_phi", m_roiPhi);
+  declareMonitoredVariable("roi_phiWidth", m_roiPhiWidth);
+  declareMonitoredVariable("roi_nSPs", m_roi_nSPs);
+  declareMonitoredVariable("time_PattRecoOnly",m_timePattReco);
+
+  // Z-vertexing 
+  declareMonitoredVariable("roi_nZvertices",m_nZvertices);
+  declareMonitoredStdContainer("roi_zVertices",m_zVertices);
+  ////Spacepoints
+  //declareMonitoredStdContainer("sp_x" ,m_sp_x);
+  //declareMonitoredStdContainer("sp_y" ,m_sp_y);
+  //declareMonitoredStdContainer("sp_z" ,m_sp_z);
+  //declareMonitoredStdContainer("sp_r" ,m_sp_r);
+}
+
+//--------------------------------------------------------------------------
+
+TrigFastTrackFinder::~TrigFastTrackFinder() {}
+
+//-----------------------------------------------------------------------
+
+HLT::ErrorCode TrigFastTrackFinder::hltInitialize() {
+
+  ATH_MSG_DEBUG("TrigFastTrackFinder::initialize() "  << PACKAGE_VERSION);
+
+  if ( timerSvc() ) {
+    m_SpacePointConversionTimer = addTimer("SpacePointConversion"); 
+    m_PatternRecoTimer          = addTimer("PattReco","PattReco_nSP");
+    m_SpacePointSortingTimer    = addTimer("SpacePointSorting"); 
+    m_DoubletFindingTimer       = addTimer("DoubletFinding");
+    m_TripletFindingTimer       = addTimer("TripletFinding");
+    m_TripletMakingTimer        = addTimer("Triplets","Triplets_nSP");
+    m_TripletClusterTimer       = addTimer("TripletClusters");
+    m_CombTrackingTimer         = addTimer("CmbTrack","CmbTrack_nTr");
+    m_TrackFitterTimer          = addTimer("TrackFitter","TrackFitter_nTracks");
+  }
+
+  if(m_ftkMode) {
+    // retrieve the FTK data reader here
+  }
+
+  StatusCode sc= m_trackSummaryTool.retrieve();
+  if(sc.isFailure()) {
+    ATH_MSG_ERROR("unable to locate track summary tool");
+    return HLT::BAD_JOB_SETUP;
+  }
+
+  ATH_MSG_DEBUG(" TrigFastTrackFinder : MinHits set to " << m_minHits);
+
+  sc = service("DetectorStore", m_detectorStore);
+  if(sc.isFailure()) {
+    ATH_MSG_ERROR("unable to locate Detector Store");
+    return HLT::BAD_JOB_SETUP;
+  }
+  
+  if (m_useBeamSpot) {
+    StatusCode scBS = service("BeamCondSvc", m_iBeamCondSvc);
+    if (scBS.isFailure() || m_iBeamCondSvc == 0) {
+      m_iBeamCondSvc = 0;
+      ATH_MSG_WARNING("Could not retrieve Beam Conditions Service. ");
+    }
+  }
+
+  sc=m_numberingTool.retrieve(); 
+  if(sc.isFailure()) { 
+    ATH_MSG_ERROR("Could not retrieve "<<m_numberingTool); 
+    return HLT::BAD_JOB_SETUP;
+   } 
+
+  sc=m_predictorTool.retrieve(); 
+  if(sc.isFailure()) { 
+    ATH_MSG_ERROR("Could not retrieve "<<m_predictorTool); 
+    return HLT::BAD_JOB_SETUP;
+   } 
+
+  sc = m_spacePointTool.retrieve();
+  if(sc.isFailure()) { 
+    ATH_MSG_ERROR("Could not retrieve "<<m_spacePointTool); 
+    return HLT::BAD_JOB_SETUP;
+  }
+
+  sc = m_regionSelector.retrieve();
+  if ( sc.isFailure() ) {
+    ATH_MSG_ERROR("Unable to retrieve RegionSelector tool " << m_regionSelector.type());
+    return HLT::BAD_JOB_SETUP;
+  }
+
+  sc = m_roadMakerTool.retrieve();
+  if(sc.isFailure()) {
+    ATH_MSG_ERROR("Could not retrieve "<<m_roadMakerTool); 
+    return HLT::BAD_JOB_SETUP;
+  }
+
+  sc = m_MagFieldSvc.retrieve();
+  if(sc.isFailure()) 
+    {
+      ATH_MSG_ERROR("Unable to retrieve Athena MagFieldService");
+      return HLT::BAD_JOB_SETUP;
+    }
+  
+  sc = m_trackMaker.retrieve();
+  if(sc.isFailure()) {
+    ATH_MSG_ERROR("Could not retrieve "<<m_trackMaker); 
+    return HLT::BAD_JOB_SETUP;
+  }
+  sc = m_trigInDetTrackFitter.retrieve();
+  if(sc.isFailure()) {
+    ATH_MSG_ERROR("Could not retrieve "<<m_trigInDetTrackFitter); 
+    return HLT::BAD_JOB_SETUP;
+  }
+
+  //Get ID helper
+  if (m_detectorStore->retrieve(m_idHelper, "AtlasID").isFailure()) {
+    ATH_MSG_ERROR("Could not get AtlasDetectorID helper AtlasID");
+    return HLT::BAD_JOB_SETUP;
+  }
+  
+  if (m_detectorStore->retrieve(m_pixelId, "PixelID").isFailure()) {
+    ATH_MSG_ERROR("Could not get Pixel ID helper");
+    return HLT::BAD_JOB_SETUP;
+  }
+  
+  if (m_detectorStore->retrieve(m_sctId, "SCT_ID").isFailure()) { 
+    ATH_MSG_ERROR("Could not get Pixel ID helper");
+    return StatusCode::FAILURE;
+  }
+  
+  if ( m_outputCollectionSuffix != "" ) {
+    m_attachedFeatureName1 = string("TrigFastTrackFinder_TrigInDetTrack_") + m_outputCollectionSuffix;
+    m_attachedFeatureName2 = string("TrigFastTrackFinder_") + m_outputCollectionSuffix;
+  }
+  else {
+    m_attachedFeatureName1 = string("TrigFastTrackFinder_TrigInDetTrack_");
+    m_attachedFeatureName2 = string("TrigFastTrackFinder_");
+  }
+
+  if (m_retrieveBarCodes) {
+    m_nSignalPresent=0;
+    m_nSignalDetected=0;
+    m_nSignalTracked=0;
+    m_nGoodDoublets=0;
+    m_nSignalClones=0;
+    sc = m_TrigL2SpacePointTruthTool.retrieve();
+    if ( sc.isFailure() ) {
+      ATH_MSG_FATAL("Unable to locate SpacePoint-to-Truth associator tool " << m_TrigL2SpacePointTruthTool);
+      return HLT::BAD_JOB_SETUP;
+    }
+  }
+  
+  ATH_MSG_DEBUG(" Feature set 1 recorded with Key " << m_attachedFeatureName1);
+  ATH_MSG_DEBUG(" Feature set 2 recorded with Key " << m_attachedFeatureName2);
+  ATH_MSG_DEBUG(" Initialized successfully"); 
+  return HLT::OK;  
+}
+
+
+//-------------------------------------------------------------------------
+
+HLT::ErrorCode TrigFastTrackFinder::hltBeginRun()
+{
+  ATH_MSG_DEBUG("At BeginRun of " << name());
+
+  // Road making - only needs to be done during hltInitialize()
+  // Needs to follow regionSelector call, since roads should only be within regionSelector regions
+  
+  if (!m_roads.empty()) {
+    ATH_MSG_DEBUG("REGTEST / calling TrigInDetRoadMaker again, m_roads.size() " << m_roads.size());
+    m_roads.clear();
+  }
+  StatusCode sc = m_roadMakerTool->makeRoads(m_roads, nullptr);
+  if(sc.isFailure()) { 
+    ATH_MSG_ERROR("Could not make roads!"<<m_roadMakerTool); 
+    return HLT::BAD_JOB_SETUP;
+  }
+
+  sc = m_predictorTool->createLUT();
+  if(sc.isFailure()) { 
+    ATH_MSG_ERROR("Could not create LayerSetLUT "<<m_predictorTool); 
+    return HLT::BAD_JOB_SETUP;
+  }
+
+  //getting magic numbers from the layer numbering tool
+
+  m_tcs.m_maxBarrelPix    = m_numberingTool->offsetBarrelSCT();
+  m_tcs.m_minEndcapPix    = m_numberingTool->offsetEndcapPixels(); 
+  m_tcs.m_maxEndcapPix    = m_numberingTool->offsetEndcapSCT();
+  m_tcs.m_maxSiliconLayer = m_numberingTool->maxSiliconLayerNum();
+
+  return HLT::OK;
+}
+
+StatusCode TrigFastTrackFinder::storeSpacePoints(const std::vector<TrigSiSpacePointBase>& convertedSpacePoints, TrigSpacePointStorage& spacePointStorage) {
+  ATH_MSG_DEBUG("Storing spacepoints");
+  std::vector< std::vector<const TrigSiSpacePointBase*> > tempSpacePointLayerVector;
+  tempSpacePointLayerVector.resize(m_numberingTool->maxSiliconLayerNum());
+  for (auto spacePointIter = convertedSpacePoints.begin(); spacePointIter != convertedSpacePoints.end(); ++spacePointIter) {
+    tempSpacePointLayerVector[spacePointIter->layer()].push_back(&(*spacePointIter));
+  }
+  TrigL2SpacePointStorageFiller spacePointStorageFiller;
+  spacePointStorageFiller.fillSpacePointStorage(spacePointStorage, tempSpacePointLayerVector, m_roads, TrigInDetRoad::firstRoadLayer);
+  spacePointStorageFiller.fillSpacePointStorage(spacePointStorage, tempSpacePointLayerVector, m_roads, TrigInDetRoad::secondRoadLayer);
+  spacePointStorageFiller.fillSpacePointStorage(spacePointStorage, tempSpacePointLayerVector, m_roads, TrigInDetRoad::thirdRoadLayer);
+  return StatusCode::SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------
+
+HLT::ErrorCode TrigFastTrackFinder::hltExecute(const HLT::TriggerElement* inputTE,
+					       HLT::TriggerElement* outputTE) {
+
+  StatusCode sc(StatusCode::SUCCESS);
+
+  ATH_MSG_VERBOSE("TrigFastTrackFinder::execHLTAlgorithm()");
+
+  clearMembers();
+
+  // Retrieve vertexing information if needed
+
+  const TrigVertexCollection* vertexCollection = nullptr;
+
+  if(m_vertexSeededMode) {
+    //HLT::ErrorCode status = getFeature(inputTE, vertexCollection,"");
+    //
+    //NOTE the inputTE vs outputTE difference - the feature is assumed to come from the same step in the sequence
+    HLT::ErrorCode status = getFeature(outputTE, vertexCollection);
+    if(status != HLT::OK) return status;
+    if(vertexCollection==nullptr) return HLT::ERROR;
+  }
+
+ 
+  // 2. Retrieve beam spot and magnetic field information 
+  //
+
+  m_shift_x=0.0;
+  m_shift_y=0.0;
+  if(m_useBeamSpot && m_iBeamCondSvc) {
+    getBeamSpot();
+  }
+  else {
+    m_vertex = Amg::Vector3D(0.0,0.0,0.0);
+  }
+  
+  getMagField();
+
+  m_currentStage = 1;
+  
+  std::vector<TrigSiSpacePointBase> convertedSpacePoints;
+  convertedSpacePoints.reserve(5000);
+  
+  if ( timerSvc() ) m_SpacePointConversionTimer->start();
+  
+  // 4. RoI preparation/update 
+  const IRoiDescriptor* internalRoI;
+  HLT::ErrorCode ec = getRoI(inputTE, internalRoI);
+  if (ec!=HLT::OK) {
+    return ec;
+  }
+  
+  m_countTotalRoI++;
+  m_tcs.roiDescriptor = internalRoI;
+  
+  sc = m_spacePointTool->getSpacePoints( *internalRoI, convertedSpacePoints, m_nPixSPsInRoI, m_nSCTSPsInRoI);
+  ////Record spacepoint x and y
+  //for(std::vector<TrigSiSpacePointBase>::const_iterator spIt = convertedSpacePoints.begin(); spIt != convertedSpacePoints.end(); ++spIt) {
+  //  m_sp_x.push_back((*spIt).original_x());
+  //  m_sp_y.push_back((*spIt).original_y());
+  //  m_sp_z.push_back((*spIt).z());
+  //  m_sp_r.push_back((*spIt).r());
+  //}
+
+  if(sc.isFailure()) { 
+    ATH_MSG_WARNING("REGTEST / Failed to retrieve offline spacepoints ");
+    return HLT::TOOL_FAILURE;
+  }
+
+  if ( timerSvc() ) m_SpacePointConversionTimer->stop();
+
+  m_roi_nSPs = convertedSpacePoints.size();    
+  ATH_MSG_VERBOSE(m_roi_nSPs <<" spacepoints found");
+  
+  if( m_roi_nSPs >= m_minHits ) {
+    ATH_MSG_DEBUG("REGTEST / Found " << m_roi_nSPs << " space points.");
+    m_countRoIwithEnoughHits++;
+  }
+  else {
+    ATH_MSG_DEBUG("No tracks found - too few hits in ROI to run " << m_roi_nSPs);
+    HLT::ErrorCode code = attachFeature(outputTE, new TrackCollection, m_attachedFeatureName2);
+    if (code != HLT::OK) {
+      return code;
+    }
+    code = attachFeature(outputTE, new TrigInDetTrackCollection, m_attachedFeatureName1);
+    return code;
+  }
+  
+  /*    
+	int lCounts[20];	 
+	for(int k=0;k<20;k++) lCounts[k]=0;
+	for(auto sp : convertedSpacePoints) {
+	lCounts[sp.layer()]++;
+	}	 
+	for(int k=0;k<20;k++) {
+	std::cout<<"L #"<<k<<" NSP="<<lCounts[k]<<std::endl;
+	}
+  */
+  
+  if (m_retrieveBarCodes) {
+    std::vector<int> vBar;
+    m_TrigL2SpacePointTruthTool->getBarCodes(convertedSpacePoints,vBar);
+    
+    //for(auto barCode : vBar) std::cout<<"SP bar code = "<<barCode<<std::endl;
+  } 
+ 
+  m_tcs.m_tripletPtMin = m_tripletMinPtFrac*m_pTmin;
+  ATH_MSG_VERBOSE("m_tcs.m_tripletPtMin: " << m_tcs.m_tripletPtMin);
+  ATH_MSG_VERBOSE("m_pTmin: " << m_pTmin);
+
+  if ( timerSvc() ) m_PatternRecoTimer->start();
+
+  TrackCollection* offlineTracks = new TrackCollection;
+  std::vector<std::tuple<bool, double,Trk::Track*>> qualityTracks; //bool used for later filtering
+
+  std::map<int, int> nGoodDoublets;
+  if (m_retrieveBarCodes) {
+    for(auto barCode : m_vSignalBarCodes) {
+      nGoodDoublets.insert(std::pair<int, int>(barCode,0));
+    }
+  }
+
+  std::map<int, int> nGoodRejected;
+  std::map<int, int> nGoodAccepted;
+  std::map<int, int> nGoodTotal;
+  if(m_retrieveBarCodes) {
+    for(auto barCode : m_vSignalBarCodes) {
+      nGoodRejected.insert(std::pair<int,int>(barCode,0));
+      nGoodAccepted.insert(std::pair<int,int>(barCode,0));
+      nGoodTotal.insert(std::pair<int,int>(barCode,0));
+    }
+  }
+
+  int iSeed=0;
+
+  if(!m_useNewSeeding) {
+    
+    TrigCombinatorialTrackFinding combinatorial(m_tcs);//inject settings here
+    combinatorial.setSpacePointsUnused(convertedSpacePoints);
+   
+    if ( timerSvc() ) m_SpacePointSortingTimer->start();
+
+    // 6. spacepoint sorting 
+    
+    TrigSpacePointStorage spacePointStorage;
+
+    sc = storeSpacePoints(convertedSpacePoints, spacePointStorage);
+    
+    if ( timerSvc() ) m_SpacePointSortingTimer->stop();
+
+    if(sc.isFailure()) {
+      ATH_MSG_ERROR("Failed spacepoint sorting !");
+      delete offlineTracks;
+      return HLT::TOOL_FAILURE;
+    }
+  
+    m_currentStage = 2;
+
+    // 7. combinatorial triplet making
+  
+    if ( timerSvc() ) m_TripletMakingTimer->start();
+
+    const TrigL2LayerSetLUT* pLUT = NULL;
+
+    if(m_tcs.m_useLikelihood) {
+      pLUT = m_predictorTool->getLUT();
+      if(pLUT==NULL) {
+	ATH_MSG_DEBUG("LayerSetLUT is NULL !");
+      }
+    }
+    
+    if ( timerSvc() ) {
+      m_DoubletFindingTimer->start();
+      m_DoubletFindingTimer->pause();
+      m_TripletFindingTimer->start();
+      m_TripletFindingTimer->pause();
+    }
+    std::vector<TrigInDetTripletCluster*> tripletClusters;
+    tripletClusters.clear();
+    ec = makeTripletClusters(spacePointStorage, combinatorial, tripletClusters, pLUT, nGoodDoublets, convertedSpacePoints);
+    if (ec!=HLT::OK) {
+      return ec;
+    }
+  
+    if ( timerSvc() ) m_DoubletFindingTimer->stop();
+    if ( timerSvc() ) m_TripletFindingTimer->stop();
+  
+    ATH_MSG_DEBUG("number of triplet clusters found: " << tripletClusters.size());
+  
+    if ( timerSvc() ) m_TripletClusterTimer->start();
+    if (m_doCloneRemove) {
+      combinatorial.processClusters(tripletClusters);
+    }
+    if (m_doCloneMerge) {
+      std::vector<TrigInDetTripletCluster*> resolvedClusters;
+      combinatorial.mergeClones(tripletClusters, resolvedClusters);
+      for(auto trc : tripletClusters) delete trc;
+      tripletClusters.clear();
+      std::copy(resolvedClusters.begin(), resolvedClusters.end(), std::back_inserter(tripletClusters));
+    }
+
+    if ( timerSvc() ) m_TripletClusterTimer->stop();
+
+    ATH_MSG_DEBUG("number of triplet clusters after clone removal: " << tripletClusters.size());
+
+    if ( timerSvc() ) {
+      m_TripletMakingTimer->stop();
+      m_TripletMakingTimer->propVal(m_roi_nSPs);
+    }
+
+    m_currentStage = 3;
+
+    if ( timerSvc() ) m_CombTrackingTimer->start();
+
+    // 8. Combinatorial tracking
+    
+    bool PIX = true;
+    bool SCT = true;
+    
+    m_trackMaker->newTrigEvent(PIX,SCT);
+    
+    qualityTracks.reserve(3*tripletClusters.size());
+
+    m_nSeeds  = 0;
+    
+    long int trackIndex=0;
+    if(m_checkSeedRedundancy) m_siClusterMap.clear();
+
+    for(auto cluster : tripletClusters) {
+      std::vector<std::shared_ptr<TrigInDetTriplet>> triplets;
+      combinatorial.collectBestTriplets(cluster, triplets);
+      std::vector<InDet::SiSpacePointsSeed> vSeeds;
+      createOfflineSeeds(triplets, vSeeds);
+      if(vSeeds.empty()) continue;
+      bool trackFound=false;
+      for(auto seed : vSeeds) {
+	++m_nSeeds;
+	const std::list<Trk::Track*>& T = m_trackMaker->getTracks(seed.spacePoints());
+	for(std::list<Trk::Track*>::const_iterator t=T.begin(); t!=T.end(); ++t) {
+	  if((*t)) {
+	    if(m_checkSeedRedundancy) {
+	      //update clusterMap 
+	      updateClusterMap(trackIndex++, (*t), m_siClusterMap);
+	    }
+	    qualityTracks.push_back(std::make_tuple(true,-trackQuality((*t)),(*t)));
+	  }
+	}  
+	iSeed++;
+	ATH_MSG_VERBOSE("Found "<<T.size()<<" tracks using triplet");
+	if(!T.empty()) {
+	  trackFound = true;
+	  if(iSeed>=m_numSeedsToTry) break;
+	}
+      }
+      
+      if(m_retrieveBarCodes) {
+	bool goodTriplet=false;
+	int foundBarCode=-1;
+	std::vector<int> vTBarCodes(triplets.size(),-1);
+	assignTripletBarCodes(triplets, vTBarCodes);
+	for(auto barCode : m_vSignalBarCodes) {
+	  for(auto tbc : vTBarCodes) {
+	    if (tbc==barCode) {
+	      foundBarCode=barCode;
+	      goodTriplet=true;break;
+	    }
+	  }
+	  if(goodTriplet) break;
+	}
+
+	if(goodTriplet) {
+	  (*nGoodTotal.find(foundBarCode)).second++;
+	  if(trackFound) (*nGoodAccepted.find(foundBarCode)).second++;
+	  else (*nGoodRejected.find(foundBarCode)).second++;
+	}
+      }
+    }
+    m_trackMaker->endEvent();
+    for(auto cluster : tripletClusters) delete cluster;
+  }
+  else {//alternatively use the new seed generator
+
+    if ( timerSvc() ) m_TripletMakingTimer->start();
+  
+    TRIG_TRACK_SEED_GENERATOR seedGen(m_tcs);
+    seedGen.loadSpacePoints(convertedSpacePoints);
+    seedGen.createSeeds();
+    std::vector<TrigInDetTriplet*> triplets;
+    seedGen.getSeeds(triplets);
+
+    ATH_MSG_DEBUG("number of triplets: " << triplets.size());
+
+    if ( timerSvc() ) {
+      m_TripletMakingTimer->stop();
+      m_TripletMakingTimer->propVal(m_roi_nSPs);
+    }
+
+    if ( timerSvc() ) m_CombTrackingTimer->start();
+
+    // 8. Combinatorial tracking
+  
+    bool PIX = true;
+    bool SCT = true;
+
+    m_trackMaker->newTrigEvent(PIX,SCT);
+
+    std::vector<int> vTBarCodes(triplets.size(),-1);
+
+    if(m_retrieveBarCodes) {
+      assignTripletBarCodes(triplets, vTBarCodes);
+    }
+
+    qualityTracks.reserve(triplets.size());
+
+    m_nSeeds  = 0;
+    iSeed=0;
+
+    long int trackIndex=0;
+
+    if(m_checkSeedRedundancy) m_siClusterMap.clear();
+
+    for(unsigned int tripletIdx=0;tripletIdx!=triplets.size();tripletIdx++) {
+
+      TrigInDetTriplet* seed = triplets[tripletIdx];
+    
+      const Trk::SpacePoint* osp1 = seed->s1().offlineSpacePoint();
+      const Trk::SpacePoint* osp2 = seed->s2().offlineSpacePoint();
+      const Trk::SpacePoint* osp3 = seed->s3().offlineSpacePoint();
+
+      if(m_checkSeedRedundancy) {
+	//check if clusters do not belong to any track
+	std::vector<Identifier> clusterIds;
+	extractClusterIds(osp1, clusterIds);
+	extractClusterIds(osp2, clusterIds);
+	extractClusterIds(osp3, clusterIds);
+	if(usedByAnyTrack(clusterIds, m_siClusterMap)) {
+	  continue;
+	}
+      }
+    
+      InDet::SiSpacePointsSeed offlineSeed(osp1, osp2, osp3, (double)seed->z0());
+  
+      bool trackFound=false;
+    
+      ++m_nSeeds;
+
+      const std::list<Trk::Track*>& T = m_trackMaker->getTracks(offlineSeed.spacePoints());
+      for(std::list<Trk::Track*>::const_iterator t=T.begin(); t!=T.end(); ++t) {
+	if((*t)) {
+	  if(m_checkSeedRedundancy) {
+	    //update clusterMap 
+	    updateClusterMap(trackIndex++, (*t), m_siClusterMap);
+	  }
+	  qualityTracks.push_back(std::make_tuple(true,-trackQuality((*t)),(*t)));
+	}
+      }  
+      iSeed++;
+      ATH_MSG_VERBOSE("Found "<<T.size()<<" tracks using triplet");
+      if(!T.empty()) {
+	trackFound = true;
+      }
+    
+      if(m_retrieveBarCodes) {
+	bool goodTriplet=false;
+	int foundBarCode=-1;
+	
+	for(auto barCode : m_vSignalBarCodes) {
+          if (vTBarCodes[tripletIdx] == barCode) {
+            foundBarCode=barCode;
+            goodTriplet=true;break;
+          }
+	}
+	
+	if(goodTriplet) {
+	  (*nGoodTotal.find(foundBarCode)).second++;
+	  if(trackFound) (*nGoodAccepted.find(foundBarCode)).second++;
+	  else (*nGoodRejected.find(foundBarCode)).second++;
+	}
+      }
+    }
+
+    m_trackMaker->endEvent();
+    for(auto seed : triplets) delete seed;
+  }
+
+  //clone removal
+  filterSharedTracks(qualityTracks);
+
+  offlineTracks->reserve(qualityTracks.size());
+  for(const auto& q : qualityTracks) {
+    if (std::get<0>(q)==true) {
+      offlineTracks->push_back(std::get<2>(q));
+    }
+    else {
+      delete std::get<2>(q);
+    }
+  }
+  qualityTracks.clear();
+  //qualityTracks.erase(std::remove_if(qualityTracks.begin(), qualityTracks.end(), 
+  //                     [](const std::tuple<bool, double, Trk::Track*>& el) {return std::get<0>(el)==false;}),
+  //                        qualityTracks.end());
+  m_nTracksNew=offlineTracks->size();
+  ATH_MSG_DEBUG("After clone removal "<<m_nTracksNew<<" tracks left");
+  
+
+  if ( timerSvc() ) {
+    m_CombTrackingTimer->stop();
+    m_CombTrackingTimer->propVal(iSeed);
+    m_PatternRecoTimer->propVal( offlineTracks->size() );
+    m_PatternRecoTimer->stop();
+    m_timePattReco = m_PatternRecoTimer->elapsed();
+  }
+
+
+
+  if (m_retrieveBarCodes) {
+    //reco. efficiency analysis
+    calculateRecoEfficiency(convertedSpacePoints, nGoodDoublets, nGoodTotal, nGoodAccepted);
+  }
+
+  if ( timerSvc() ) m_TrackFitterTimer->start();
+
+  TrackCollection* fittedTracks = offlineTracks;
+
+
+  if (offlineTracks->size() > 0) {
+    fittedTracks = m_trigInDetTrackFitter->fit(*offlineTracks, m_particleHypothesis);
+    delete offlineTracks;
+  }
+  if( fittedTracks->empty() ) {
+    ATH_MSG_DEBUG("REGTEST / No tracks fitted");
+  }
+
+  for (auto fittedTrack = fittedTracks->begin(); fittedTrack!=fittedTracks->end(); ++fittedTrack) {
+    (*fittedTrack)->info().setPatternRecognitionInfo(Trk::TrackInfo::FastTrackFinderSeed);
+    ATH_MSG_VERBOSE("Updating fitted track: " << **fittedTrack);
+    m_trackSummaryTool->updateTrack(**fittedTrack);
+    ATH_MSG_VERBOSE("Updated track: " << **fittedTrack);
+  }
+
+  if ( timerSvc() ) { 
+    m_TrackFitterTimer->propVal(fittedTracks->size() );
+    m_TrackFitterTimer->stop();
+  }
+
+  //9. Offline to online track conversion
+
+  m_recoTracks = new TrigInDetTrackCollection;
+  if (fittedTracks!=nullptr) {
+    convertToTrigInDetTrack(*fittedTracks, *m_recoTracks);
+  }
+     
+  if( m_recoTracks->empty() ) {
+    ATH_MSG_DEBUG("REGTEST / No tracks reconstructed");
+  }
+  
+  //monitor Z-vertexing
+  
+  m_nZvertices=m_zVertices.size();
+  
+  //monitor number of tracks
+  m_ntracks=m_recoTracks->size();	
+  ATH_MSG_DEBUG("REGTEST / Found " << m_recoTracks->size() << " tracks");
+  if( !m_recoTracks->empty() )
+    m_countRoIwithTracks++;
+  
+  ///////////// fill vectors of quantities to be monitored
+  // a0 wrt beam spot
+  fill_a0();
+        
+  m_currentStage = 4;
+
+  if ( msgLvl() <= MSG::DEBUG) { 
+    ATH_MSG_DEBUG("REGTEST / Reconstructed " << m_recoTracks->size() << " tracks ");
+    
+    TrigInDetTrackCollection::iterator track = m_recoTracks->begin();
+    TrigInDetTrackCollection::iterator lastTrack = m_recoTracks->end();
+    
+    for(; track !=lastTrack; ++track)	{
+      
+      ATH_MSG_DEBUG("REGTEST / track nstraw/ntr/phi0/pt/eta/d0/z0/chi2: " <<
+	(*track)->NStrawHits() << " / "  << 
+	(*track)->NTRHits() << " / "  << 
+	(*track)->param()->phi0() << " / "  << 
+	(*track)->param()->pT() << " / " << 
+	(*track)->param()->eta() << " / " << 
+	(*track)->param()->a0() << " / " <<
+	(*track)->param()->z0() << " / " <<
+	(*track)->chi2());
+    }
+  }
+  HLT::ErrorCode code1 = attachFeature(outputTE, m_recoTracks, m_attachedFeatureName1);
+
+  if ( code1 != HLT::OK ) {
+    ATH_MSG_ERROR("REGTEST/ Write into outputTE failed");
+    delete m_recoTracks;
+    m_recoTracks=nullptr;
+    delete fittedTracks;
+    return code1;
+  }
+  HLT::ErrorCode code2;
+  if (fittedTracks!=nullptr) {
+    code2 = attachFeature(outputTE, fittedTracks, m_attachedFeatureName2);
+  }
+  else {
+    code2 = attachFeature(outputTE, new TrackCollection, m_attachedFeatureName2);
+  }
+  
+  if ( code2 != HLT::OK ) {
+    ATH_MSG_ERROR("REGTEST/ Write into outputTE failed");
+    if (fittedTracks!=nullptr) {
+      delete fittedTracks;
+    }
+    return code2;
+  }
+  
+  return HLT::OK;
+}
+
+void TrigFastTrackFinder::createOfflineSeeds(const std::vector<std::shared_ptr<TrigInDetTriplet>>& input, std::vector<InDet::SiSpacePointsSeed>& output) {
+  
+  output.reserve(input.size());
+  for (const auto triplet : input) {
+    const Trk::SpacePoint* osp1 = triplet->s1().offlineSpacePoint();
+    const Trk::SpacePoint* osp2 = triplet->s2().offlineSpacePoint();
+    const Trk::SpacePoint* osp3 = triplet->s3().offlineSpacePoint();
+
+    if(m_checkSeedRedundancy) {
+      //check if clusters do not belong to any track
+      std::vector<Identifier> clusterIds;
+      extractClusterIds(osp1, clusterIds);
+      extractClusterIds(osp2, clusterIds);
+      extractClusterIds(osp3, clusterIds);
+      if(usedByAnyTrack(clusterIds, m_siClusterMap)) continue;
+    }
+
+    output.push_back(InDet::SiSpacePointsSeed(osp1, osp2, osp3, (double)triplet->z0()));
+  }
+}
+
+double TrigFastTrackFinder::trackQuality(const Trk::Track* Tr) {
+ 
+  DataVector<const Trk::TrackStateOnSurface>::const_iterator  
+    m  = Tr->trackStateOnSurfaces()->begin(), 
+    me = Tr->trackStateOnSurfaces()->end  ();
+  
+  double quality = 0. ;
+  double W       = 17.;
+
+  for(; m!=me; ++m) {
+    const Trk::FitQualityOnSurface* fq =  (*m)->fitQualityOnSurface();
+    if(!fq) continue;
+    
+    double x2 = fq->chiSquared();
+    double q;
+    if(fq->numberDoF() == 2) q = (1.2*(W-x2*.5)); 
+    else                     q =      (W-x2    );
+    if(q < 0.) q = 0.; quality+=q;
+  }
+  return quality;
+}
+
+void TrigFastTrackFinder::filterSharedTracks(std::vector<std::tuple<bool, double,Trk::Track*>>& QT) {
+
+  std::set<const Trk::PrepRawData*> clusters;
+    
+  const Trk::PrepRawData* prd[100];
+  
+  std::sort(QT.begin(), QT.end(),
+      [](const std::tuple<bool, double, Trk::Track*>& lhs, const std::tuple<bool, double, Trk::Track*>& rhs) {
+        return std::get<1>(lhs) < std::get<1>(rhs); } );
+
+  for (auto& q : QT) {
+    DataVector<const Trk::MeasurementBase>::const_iterator 
+      m  = std::get<2>(q)->measurementsOnTrack()->begin(), 
+      me = std::get<2>(q)->measurementsOnTrack()->end  ();
+    
+    int nf = 0, nc = 0; 
+    for(; m!=me; ++m ) {
+
+      const Trk::PrepRawData* pr = ((const Trk::RIO_OnTrack*)(*m))->prepRawData();
+      if(pr) {
+        ++nc;
+        if(clusters.find(pr)==clusters.end()) {prd[nf++]=pr; if(nf==100) break;}
+      }
+    }
+    if((nf >= m_nfreeCut) || (nf == nc) ) {
+      for(int n=0; n!=nf; ++n) clusters.insert(prd[n]);
+    }
+    else  {
+      std::get<0>(q) = false;
+    }
+  }
+}
+
+void TrigFastTrackFinder::convertToTrigInDetTrack(const TrackCollection& offlineTracks, TrigInDetTrackCollection& trigInDetTracks) {
+
+  trigInDetTracks.reserve(offlineTracks.size());
+  for (auto offlineTrack : offlineTracks) {
+    const Trk::TrackParameters* trackPars = offlineTrack->perigeeParameters();
+    if(trackPars==nullptr) {
+      return;
+    }
+
+    if(trackPars->covariance()==nullptr) {
+      return;
+    }
+    
+    float d0 = trackPars->parameters()[Trk::d0]; 
+    float z0 = trackPars->parameters()[Trk::z0]; 
+    float phi0 = trackPars->parameters()[Trk::phi0]; 
+    float theta = trackPars->parameters()[Trk::theta]; 
+    TrigCombinatorialTrackFinding::correct_phi(phi0);
+    float eta = -log(tan(0.5*theta)); 
+    
+    float qOverP = trackPars->parameters()[Trk::qOverP]; 
+    float pT=sin(theta)/qOverP;
+
+    //Calculate	covariance matrix in TID track parameter convention
+    const AmgSymMatrix(5) cov_off = *(trackPars->covariance());
+    float A = -0.5*((1.0+tan(0.5*theta)*tan(0.5*theta))/(tan(0.5*theta))); //deta_by_dtheta
+    float B = cos(theta)/qOverP; //dpT_by_dtheta
+    float C = -sin(theta)/(qOverP*qOverP); //dpT_by_dqOverP
+
+    //std::vector<double>* cov = new std::vector<double>(15, 0);
+    std::vector<double>* cov = new std::vector<double>
+      {cov_off(0,0), cov_off(2,0), cov_off(1,0), A*cov_off(3,0), B*cov_off(3,0) + C*cov_off(4,0),
+       cov_off(2,2), cov_off(2,1), A*cov_off(3,2), B*cov_off(3,2) + C*cov_off(4,2),
+       cov_off(1,1), A*cov_off(3,1), B*cov_off(3,1) + C*cov_off(4,1),
+       A*A*cov_off(3,3), A*(B*cov_off(3,3) + C*cov_off(4,3)),
+       B*(B*cov_off(3,3) + 2*C*cov_off(4,3)) + C*C*cov_off(4,4)};
+
+    if(msgLvl() <= MSG::VERBOSE) {
+      ATH_MSG_DEBUG(cov_off);
+      for (unsigned int i = 0; i < cov->size(); ++i) {
+	msg() << MSG::DEBUG << std::fixed << std::setprecision(10) << "cov_TrigInDetTrack[" << i << "]: " << cov->at(i) << endreq; 
+      }
+    }
+
+    float ed0   = sqrt(cov->at(0));
+    float	ephi0 = sqrt(cov->at(5));
+    float	ez0   = sqrt(cov->at(9));
+    float	eeta  = sqrt(cov->at(12));
+    float	epT   = sqrt(cov->at(14));
+    
+    //const TrigInDetTrackFitPar* tidtfp = new TrigInDetTrackFitPar(d0,phi0,z0,eta,pT,nullptr); 
+    const TrigInDetTrackFitPar* tidtfp = new TrigInDetTrackFitPar(d0, phi0, z0, eta, pT, ed0, ephi0, ez0, eeta, epT,cov);
+    std::vector<const TrigSiSpacePoint*>* pvsp = new std::vector<const TrigSiSpacePoint*>;
+    TrigInDetTrack* pTrack = new TrigInDetTrack(pvsp,tidtfp);
+
+    //calculate chi2 and ndofs
+
+    const Trk::FitQuality* fq = offlineTrack->fitQuality();
+    if (fq) {
+      ATH_MSG_VERBOSE("Fitted chi2: " << fq->chiSquared());
+      ATH_MSG_VERBOSE("Fitted ndof: " << fq->numberDoF());
+      if(fq->numberDoF()!=0) {
+	pTrack->chi2(fq->chiSquared()/fq->numberDoF());
+      }
+      else pTrack->chi2(1e8);
+    }
+    else {
+      pTrack->chi2(1e8);
+    }
+    
+    int nPix=0, nSct=0;
+
+    for(auto tSOS = offlineTrack->trackStateOnSurfaces()->begin();  
+	tSOS!=offlineTrack->trackStateOnSurfaces()->end(); ++tSOS) { 
+      if ((*tSOS)->type(Trk::TrackStateOnSurface::Perigee) == false) {
+	const Trk::FitQualityOnSurface* fq =  (*tSOS)->fitQualityOnSurface(); 
+	if(!fq) continue; 
+	int nd = fq->numberDoF(); 
+	if(nd==2) nPix++;
+	if(nd==1) nSct++;
+      }
+    }
+    pTrack->NPixelSpacePoints(nPix); 
+    pTrack->NSCT_SpacePoints(nSct/2); 
+
+    long hitPattern=0x0;
+    for (auto tMOT = offlineTrack->measurementsOnTrack()->begin();
+	 tMOT != offlineTrack->measurementsOnTrack()->end(); ++tMOT) {
+      Identifier id = (*tMOT)->associatedSurface().associatedDetectorElement()->identify();
+      IdentifierHash hash = (*tMOT)->associatedSurface().associatedDetectorElement()->identifyHash();
+
+      if(m_idHelper->is_sct(id)) {
+	Identifier wafer_id = m_sctId->wafer_id(hash);
+	int layId = m_sctId->layer_disk(wafer_id);
+	long layer=0;
+	if (m_sctId->is_barrel(wafer_id)){
+	  layer = layId+m_tcs.m_maxBarrelPix;
+	} else {
+	  layer = layId+m_tcs.m_maxEndcapPix;
+	}
+	long mask = 1 << layer;
+	hitPattern |= mask;
+      }
+      else if(m_idHelper->is_pixel(id)) {
+	Identifier wafer_id = m_pixelId->wafer_id(hash);
+	int layId = m_pixelId->layer_disk(wafer_id);
+	long layer=0;
+	if (m_pixelId->is_barrel(wafer_id)){
+	  layer = layId;
+	} else {
+	  layer = layId+m_tcs.m_minEndcapPix;
+	}
+	long mask = 1 << layer;
+	hitPattern |= mask;
+      }
+      else {
+	ATH_MSG_WARNING("cannot determine detector type, hash="<<hash);
+      }
+    }
+    pTrack->HitPattern(hitPattern);
+	
+
+    //TODO: algoId for FastTrackFinder
+    pTrack->algorithmId(TrigInDetTrack::NULLID);
+    trigInDetTracks.push_back(pTrack);
+  }
+}
+
+//---------------------------------------------------------------------------
+
+HLT::ErrorCode TrigFastTrackFinder::hltFinalize()
+{
+
+  ATH_MSG_INFO("=========================================================");
+  ATH_MSG_INFO("TrigFastTrackFinder::finalize() - TrigFastTrackFinder Statistics: ");
+  ATH_MSG_INFO("Events processed: " <<  m_countTotalEvents);
+  ATH_MSG_INFO("RoI processed: " <<  m_countTotalRoI);
+  ATH_MSG_INFO("RoI with enough SPs : " <<  m_countRoIwithEnoughHits);
+  ATH_MSG_INFO("RoI with Track(s)  Total/goodZvertex/badZvertex: " << m_countRoIwithTracks);
+  if (m_retrieveBarCodes) {
+    ATH_MSG_INFO("Number of signal tracks present " << m_nSignalPresent);
+    ATH_MSG_INFO("Number of signal seeds  found   " << m_nSignalDetected);
+    ATH_MSG_INFO("Number of signal tracks found   " << m_nSignalTracked);
+    if(m_nSignalPresent!=0) {
+      ATH_MSG_INFO("Doublet making efficiency      " << (100.0*m_nGoodDoublets/m_nSignalPresent) <<" % ");
+      ATH_MSG_INFO("Track seeding  efficiency      " << (100.0*m_nSignalDetected/m_nSignalPresent) <<" % ");
+      ATH_MSG_INFO("Track seeding  redundancy      " << (100.0*m_nSignalClones/m_nSignalPresent) << " %");
+      ATH_MSG_INFO("Track finding efficiency       " << (100.0*m_nSignalTracked/m_nSignalPresent) << " %");
+    }
+  }
+  ATH_MSG_INFO("=========================================================");
+
+  return HLT::OK;
+}
+
+void TrigFastTrackFinder::updateClusterMap(long int trackIdx, const Trk::Track* pTrack, std::map<Identifier, std::vector<long int> >& clusterMap) {
+  //loop over clusters
+
+  for(auto tMOT = pTrack->measurementsOnTrack()->begin(); tMOT != pTrack->measurementsOnTrack()->end(); ++tMOT) { 
+  
+    const InDet::SiClusterOnTrack* siCLOT = dynamic_cast<const InDet::SiClusterOnTrack*>(*tMOT); 
+    if (siCLOT==NULL) continue;
+    const InDet::SiCluster* siCL = dynamic_cast<const InDet::SiCluster*>(siCLOT->prepRawData()); 
+    if (siCL==NULL) continue;
+    Identifier id = siCL->identify(); 
+    clusterMap[id].push_back(trackIdx);
+    //no sorting is needed as the vectors are sorted by the algorithm design
+    //due to monotonically increasing trackIdx
+    // std::map<Identifier, std::vector<long int> >::iterator itm = clusterMap.find(id);
+    //std::sort((*itm).second.begin(),(*itm).second.end());
+    //std::copy((*itm).second.begin(),(*itm).second.end(),std::ostream_iterator<long int>(std::cout," "));
+    //std::cout<<std::endl;
+  }
+}
+
+void TrigFastTrackFinder::extractClusterIds(const Trk::SpacePoint* pSP, std::vector<Identifier>& vIds) {
+  const InDet::SiCluster* pCL = dynamic_cast<const InDet::SiCluster*>(pSP->clusterList().first);
+  if(pCL!=NULL) vIds.push_back(pCL->identify());
+  //check second cluster : SCT uv clusters only !
+  pCL = dynamic_cast<const InDet::SiCluster*>(pSP->clusterList().second);
+  if(pCL!=NULL) vIds.push_back(pCL->identify());
+}
+
+bool TrigFastTrackFinder::usedByAnyTrack(const std::vector<Identifier>& vIds, std::map<Identifier, std::vector<long int> >& clusterMap) {
+
+  std::vector<long int> xSection;
+  //initializing
+  std::map<Identifier, std::vector<long int> >::iterator itm0 = clusterMap.find(*vIds.begin());
+  if(itm0 == clusterMap.end()) return false;
+  xSection.reserve((*itm0).second.size());
+  std::copy((*itm0).second.begin(), (*itm0).second.end(), std::back_inserter(xSection));
+  std::vector<Identifier>::const_iterator it = vIds.begin();it++;
+  for(;it!=vIds.end();++it) {
+    std::map<Identifier, std::vector<long int> >::iterator itm1 = clusterMap.find(*it);
+    if(itm1 == clusterMap.end()) return false;
+    std::vector<long int> tmp;
+    std::set_intersection(xSection.begin(), xSection.end(), (*itm1).second.begin(),(*itm1).second.end(), std::back_inserter(tmp));
+    if(tmp.empty()) return false;
+    //update xSection
+    xSection.clear();
+    xSection.reserve(tmp.size());
+    std::copy(tmp.begin(), tmp.end(), std::back_inserter(xSection));
+  }
+  return !xSection.empty();
+}
+
+int TrigFastTrackFinder::findBarCodeInData(int barCode, const std::vector<TrigSiSpacePointBase>& vSP) {
+  int nFound=0;
+  std::set<int> layerSet;
+  for(auto sp : vSP) {
+    if(barCode==sp.barCode()) {
+      nFound++;
+      layerSet.insert(sp.layer());
+    }
+  }
+  if(int(layerSet.size())<m_minSignalSPs) {//less than N unique layers
+    nFound=0;
+  }
+  return nFound;
+}
+
+void TrigFastTrackFinder::showBarCodeInData(int barCode, const std::vector<TrigSiSpacePointBase>& vSP) {
+  for(auto sp : vSP) {
+    if(barCode==sp.barCode()) {
+      ATH_MSG_DEBUG("L="<<sp.layer()<<" r="<<sp.r()<<" z="<<sp.z());
+    }
+  }
+}
+
+int TrigFastTrackFinder::findBarCodeInTriplets(int barCode, const std::vector<std::shared_ptr<TrigInDetTriplet>>& vTR) {
+  int nFound=0;
+  for(auto tr : vTR) {
+    bool found = (barCode == tr->s1().barCode()) && (barCode == tr->s2().barCode()) && (barCode == tr->s3().barCode());
+    if(found) {
+      nFound++;
+    }
+  }
+  return nFound;
+}
+
+void TrigFastTrackFinder::assignTripletBarCodes(const std::vector<std::shared_ptr<TrigInDetTriplet>>& vTR, std::vector<int>& vBar) {
+  int iTR=0;
+  for(auto tr : vTR) {
+    bool good = (tr->s1().barCode() == tr->s2().barCode()) && (tr->s3().barCode() == tr->s2().barCode());
+    good = good && (tr->s1().barCode() > 0);
+    if(good) {
+      vBar[iTR] = tr->s1().barCode();
+    }
+    iTR++;
+  }
+}
+
+void TrigFastTrackFinder::assignTripletBarCodes(const std::vector<TrigInDetTriplet*>& vTR, std::vector<int>& vBar) {
+  int iTR=0;
+  for(auto tr : vTR) {
+    bool good = (tr->s1().barCode() == tr->s2().barCode()) && (tr->s3().barCode() == tr->s2().barCode());
+    good = good && (tr->s1().barCode() > 0);
+    if(good) {
+      vBar[iTR] = tr->s1().barCode();
+    }
+    iTR++;
+  }
+}
+
+int TrigFastTrackFinder::findBarCodeInDoublets(int barCode, const std::vector<TrigInDetDoublet*>& vDL) {
+  int nFound=0;
+  for(auto tr : vDL) {
+    bool found = (barCode == tr->s1().barCode()) && (barCode == tr->s2().barCode());
+    if(found) nFound++;
+  }
+  return nFound;
+}
+
+void TrigFastTrackFinder::getBeamSpot() {
+  m_vertex = m_iBeamCondSvc->beamPos();
+  ATH_MSG_VERBOSE("Beam spot position " << m_vertex);
+  double xVTX = m_vertex.x();
+  double yVTX = m_vertex.y();
+  double zVTX = m_vertex.z();
+  double tiltXZ = m_iBeamCondSvc->beamTilt(0);
+  double tiltYZ = m_iBeamCondSvc->beamTilt(1);
+  m_shift_x = xVTX - tiltXZ*zVTX;//correction for tilt
+  m_shift_y = yVTX - tiltYZ*zVTX;//correction for tilt	
+  ATH_MSG_VERBOSE("Beam center position:  " << m_shift_x <<"  "<< m_shift_y);
+}
+
+void TrigFastTrackFinder::getMagField() {
+  Amg::Vector3D bField;
+  m_MagFieldSvc->getField(&m_vertex, &bField);
+  bField*=1000.0;//Convert to Tesla
+  m_tcs.m_magFieldZ = bField.z();//configured value
+  ATH_MSG_VERBOSE("bField.x(): " << bField.x());
+  ATH_MSG_VERBOSE("bField.y(): " << bField.y());
+  ATH_MSG_VERBOSE("bField.z(): " << bField.z());
+}
+
+
+HLT::ErrorCode TrigFastTrackFinder::getRoI(const HLT::TriggerElement* inputTE, const IRoiDescriptor*& roi)
+{
+  
+  const TrigRoiDescriptor* externalRoI = nullptr;
+  HLT::ErrorCode ec = getFeature(inputTE, externalRoI, "forID");
+  if(ec != HLT::OK || externalRoI==nullptr ) {
+    ec = getFeature(inputTE, externalRoI);
+    if (!m_roiForIDWarning) {
+      ATH_MSG_INFO("REGTEST / using ordinary RoI ( no forID RoI found ) ");
+      m_roiForIDWarning = true;
+    }
+  }
+  if(ec != HLT::OK) {
+    ATH_MSG_ERROR("REGTEST / Failed to find RoiDescriptor");
+    return HLT::NAV_ERROR;
+  }
+
+  if(externalRoI==nullptr) {
+    ATH_MSG_ERROR("REGTEST / null RoiDescriptor");
+    return HLT::NAV_ERROR;
+  }
+
+  roi = externalRoI;
+  m_roiEta = roi->eta();
+  m_roiEtaWidth = roi->etaPlus() - roi->etaMinus();
+  m_roiPhi = roi->phi();
+  m_roiPhiWidth = HLT::wrapPhi(roi->phiPlus() - roi->phiMinus());
+  ATH_MSG_DEBUG("REGTEST / RoI" << *roi);
+
+  return HLT::OK;
+}
+
+void TrigFastTrackFinder::clearMembers() {
+  m_ntracks = 0;
+  m_recoTracks=nullptr;
+  m_a0beam.clear();
+  m_trkdPhi0.clear();
+  m_trkdEta.clear();
+  m_zVertices.clear();
+
+  m_pixResPhiBarrel.clear();
+  m_pixResEtaBarrel.clear();
+  m_pixPullPhiBarrel.clear();
+  m_pixPullEtaBarrel.clear();
+  m_sctResBarrel.clear();
+  m_sctPullBarrel.clear();
+  m_pixResPhiEC.clear();
+  m_pixResEtaEC.clear();
+  m_pixPullPhiEC.clear();
+  m_pixPullEtaEC.clear();
+  m_sctResEC.clear();
+  m_sctPullEC.clear();
+  //m_sp_x.clear();
+  //m_sp_y.clear();
+  //m_sp_z.clear();
+  //m_sp_r.clear();
+
+ 
+
+  m_nPixSPsInRoI=0;
+  m_nSCTSPsInRoI=0;
+  m_currentStage=0;
+  m_roi_nSPs=0;
+  m_nZvertices=0;
+}
+
+void TrigFastTrackFinder::calculateRecoEfficiency(const std::vector<TrigSiSpacePointBase>& convertedSpacePoints,
+                                                  const std::map<int,int>& nGoodDoublets,
+						  const std::map<int,int>& nGoodTotal, 
+						  const std::map<int,int>& nGoodAccepted) {
+
+  //reco. efficiency analysis
+  for(auto barCode : m_vSignalBarCodes) {
+    int nSignalSPs = findBarCodeInData(barCode, convertedSpacePoints);
+    if(nSignalSPs<m_minSignalSPs) continue;
+    m_nSignalPresent+=1;
+    if((*nGoodDoublets.find(barCode)).second!=0) {
+      m_nGoodDoublets+=1;
+    }
+    int nSignalTracks = (*nGoodTotal.find(barCode)).second;
+    if(nSignalTracks==0) {
+      continue;
+    }
+    m_nSignalDetected+=1;
+    m_nSignalClones+=nSignalTracks;
+    
+    int nGoodTripletsAccepted = (*nGoodAccepted.find(barCode)).second;
+    if(nGoodTripletsAccepted==0) continue;
+    m_nSignalTracked+=1;
+  } 
+}
+
+void TrigFastTrackFinder::fill_a0() {
+  for(TrigInDetTrackCollection::iterator trackIt = m_recoTracks->begin();trackIt != m_recoTracks->end();++trackIt) {
+    float a0 = (*trackIt)->param()->a0();
+    float phi0 = (*trackIt)->param()->phi0();
+    m_a0beam.push_back(a0+m_shift_x*sin(phi0)-m_shift_y*cos(phi0));
+    float dPhi0 = phi0 - m_roiPhi;
+    TrigCombinatorialTrackFinding::correct_phi(phi0);
+    m_trkdPhi0.push_back(dPhi0);
+    m_trkdEta.push_back((*trackIt)->param()->eta() - m_roiEta);
+    //zVTX = m_zPosition; // precise calculation using vertex z, not the beamspot cond service - not needed
+  }
+}
+
+/*
+struct SimpleFunctor {
+public:
+  void operator()(int x) const {
+    std::cout << "Job Id [" << x << "]\n";
+  }
+};
+//tbb::parallel_for(0, m_roads.size(), 1, SimpleFunctor());
+*/
+HLT::ErrorCode TrigFastTrackFinder::makeTripletClusters(const TrigSpacePointStorage& spacePointStorage, 
+                                                        TrigCombinatorialTrackFinding& combinatorial, 
+                                                        std::vector<TrigInDetTripletCluster*>& tripletClusters,  
+                                                        const TrigL2LayerSetLUT* pLUT,
+                                                        std::map<int,int>& nGoodDoublets,
+                                                        const std::vector<TrigSiSpacePointBase>& convertedSpacePoints) { 
+  for(const auto road : m_roads) {
+    unsigned int roadId = road.roadId();
+    unsigned int roadSubId = road.roadSubId();
+    const auto& firstLayerSpacePointVector = spacePointStorage.firstLayerSpacePointVector(roadId, roadSubId);
+    const auto& secondLayerSpacePointVector = spacePointStorage.secondLayerSpacePointVector(roadId, roadSubId);
+
+    // Create doublets
+    std::vector<TrigInDetDoublet*> doublets;
+    if ( timerSvc() ) m_DoubletFindingTimer->resume();
+    StatusCode sc = combinatorial.findDoublets(firstLayerSpacePointVector, secondLayerSpacePointVector, doublets);
+    if ( timerSvc() ) m_DoubletFindingTimer->pause();
+    if(sc.isFailure()) {
+      ATH_MSG_ERROR("Failed producing doublets!");
+      return HLT::TOOL_FAILURE;
+    }
+		if (doublets.size() == 0) {
+			continue;
+		}
+
+    ATH_MSG_VERBOSE("processing road with roadId/roadSubId: " << roadId << "/" << roadSubId);
+    ATH_MSG_VERBOSE("number of doublets found: " << doublets.size());
+    if(msgLvl() <= MSG::VERBOSE) {
+      for(const auto doublet : doublets) {
+        ATH_MSG_VERBOSE("doublet found with z0: " << doublet->z0());
+      }
+    }
+
+    if (m_retrieveBarCodes) {
+      for(auto barCode : m_vSignalBarCodes) {
+        int nSignalSPs = findBarCodeInData(barCode, convertedSpacePoints);
+        if(nSignalSPs<m_minSignalSPs) continue;
+        int nSignalDoublets = findBarCodeInDoublets(barCode, doublets);
+        if(nSignalDoublets==0) continue;
+        (*nGoodDoublets.find(barCode)).second+=1;
+      }
+    }
+
+    // Create triplet clusters
+
+    if ( timerSvc() ) m_TripletFindingTimer->resume();
+    const auto& thirdLayerSpacePointVector = spacePointStorage.thirdLayerSpacePointVector(roadId, roadSubId);
+    sc = combinatorial.findTripletClusters(doublets, thirdLayerSpacePointVector, tripletClusters, pLUT);
+    if ( timerSvc() ) m_TripletFindingTimer->pause();
+    if(sc.isFailure()) {
+      ATH_MSG_ERROR("Failed producing triplets!");
+      for(auto doublet : doublets) delete doublet;
+      return HLT::TOOL_FAILURE;
+    }
+
+    ATH_MSG_VERBOSE("number of triplet clusters found: " << tripletClusters.size());
+    if(msgLvl() <= MSG::VERBOSE) {
+      for(auto cluster : tripletClusters) {
+        for(auto triplet : cluster->triplets()) {
+          ATH_MSG_VERBOSE("triplet found with eta/phi/z0/d0/pt: " << triplet->eta() << " " << triplet->phi() << " " << triplet->z0() << " " << triplet->d0() << " " << triplet->pt());	  
+          if (m_retrieveBarCodes) {
+            ATH_MSG_VERBOSE("spacepoint bar Codes ...");
+            ATH_MSG_VERBOSE(triplet->s1().barCode()<<" "<<triplet->s2().barCode()<<" "<<triplet->s3().barCode());
+          }
+        }
+      }
+    }
+    for(auto doublet : doublets) delete doublet;
+  }
+  return HLT::OK;
+}
+
diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/components/TrigFastTrackFinder_entries.cxx b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/components/TrigFastTrackFinder_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..092c64fb4e3f63984b7e335d1fd23f0730ed285f
--- /dev/null
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/components/TrigFastTrackFinder_entries.cxx
@@ -0,0 +1,9 @@
+#include "GaudiKernel/DeclareFactoryEntries.h"
+
+#include "TrigFastTrackFinder/TrigFastTrackFinder.h"
+
+DECLARE_ALGORITHM_FACTORY( TrigFastTrackFinder)
+DECLARE_FACTORY_ENTRIES( TrigFastTrackFinder )
+{
+  DECLARE_ALGORITHM( TrigFastTrackFinder )
+}
diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/components/TrigFastTrackFinder_load.cxx b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/components/TrigFastTrackFinder_load.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4a3573861e7b3ba5ac833c4cf033446e942fcc8c
--- /dev/null
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/components/TrigFastTrackFinder_load.cxx
@@ -0,0 +1,3 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES( TrigFastTrackFinder )