diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/CMakeLists.txt b/Trigger/TrigAlgorithms/TrigFastTrackFinder/CMakeLists.txt
index 36f2826c618e36760c606af16e665e9c995a929c..f080fbfce9febdd5a8dbe0f4dca148cd7be93b76 100644
--- a/Trigger/TrigAlgorithms/TrigFastTrackFinder/CMakeLists.txt
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/CMakeLists.txt
@@ -7,7 +7,8 @@ atlas_subdir( TrigFastTrackFinder )
 atlas_add_component( TrigFastTrackFinder
                      src/*.cxx
                      src/components/*.cxx
-                     LINK_LIBRARIES AthenaBaseComps AthenaMonitoringKernelLib BeamSpotConditionsData CxxUtils GaudiKernel InDetIdentifier InDetPrepRawData InDetRIO_OnTrack InDetRecToolInterfaces SiSPSeededTrackFinderData SiSpacePointsSeed TrigInDetEvent TrigInDetPattRecoEvent TrigInDetPattRecoTools TrigInDetToolInterfacesLib TrigInterfacesLib TrigNavigationLib TrigSteeringEvent TrigTimeAlgsLib TrkEventPrimitives TrkEventUtils TrkParameters TrkRIO_OnTrack TrkToolInterfaces TrkTrack TrkTrackSummary TrigAccelEvent TrigInDetAccelerationToolLib TrigInDetAccelerationServiceLib)
+                     LINK_LIBRARIES AthenaBaseComps AthenaMonitoringKernelLib BeamSpotConditionsData CxxUtils GaudiKernel PathResolver InDetIdentifier InDetPrepRawData InDetRIO_OnTrack InDetRecToolInterfaces SiSPSeededTrackFinderData SiSpacePointsSeed TrigInDetEvent TrigInDetPattRecoEvent TrigInDetPattRecoTools TrigInDetToolInterfacesLib TrigInterfacesLib TrigNavigationLib TrigSteeringEvent TrigTimeAlgsLib TrkEventPrimitives TrkEventUtils TrkParameters TrkRIO_OnTrack TrkToolInterfaces TrkTrack TrkTrackSummary TrigAccelEvent TrigInDetAccelerationToolLib TrigInDetAccelerationServiceLib)
 
 # Install files from the package:
 atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} )
+atlas_install_runtime( share/*.lut )
diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/share/trigseed_ml_pixel_barrel_kde.lut b/Trigger/TrigAlgorithms/TrigFastTrackFinder/share/trigseed_ml_pixel_barrel_kde.lut
new file mode 100644
index 0000000000000000000000000000000000000000..c06e539346610bf1a00f13c190062bdbe2cf0bed
--- /dev/null
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/share/trigseed_ml_pixel_barrel_kde.lut
@@ -0,0 +1,45 @@
+0 0 8
+1 0 8
+2 0 9
+3 0 9
+4 0 9
+5 0 10
+6 0 11
+7 0 12
+8 1 12
+9 2 12
+10 3 12
+11 4 13
+12 5 14
+13 6 15
+14 6 16
+15 7 17
+16 8 17
+17 8 18
+18 8 18
+19 9 18
+20 10 19
+21 10 19
+22 11 19
+23 11 19
+24 11 19
+25 12 20
+26 12 20
+27 12 20
+28 13 21
+29 13 21
+30 14 21
+31 14 22
+32 14 22
+33 15 23
+34 15 23
+35 15 24
+36 16 24
+37 16 24
+38 17 25
+39 18 26
+40 18 26
+41 18 27
+42 19 27
+43 19 28
+44 19 29
diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.cxx b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.cxx
index 7d4a74efaee0ff69fd22308c4577c55ebb26317f..f3c6a3bf5270273ab4a2c626b9d0272efd6f5caa 100644
--- a/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.cxx
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.cxx
@@ -80,6 +80,8 @@
 #include "TrigAccelEvent/TrigInDetAccelEDM.h"
 #include "TrigAccelEvent/TrigInDetAccelCodes.h"
 
+#include "PathResolver/PathResolver.h"
+
 TrigFastTrackFinder::TrigFastTrackFinder(const std::string& name, ISvcLocator* pSvcLocator) : 
 
   HLT::FexAlgo(name, pSvcLocator), 
@@ -108,7 +110,8 @@ TrigFastTrackFinder::TrigFastTrackFinder(const std::string& name, ISvcLocator* p
   m_particleHypothesis(Trk::pion),
   m_useNewLayerNumberScheme(false), 
   m_useGPU(false),
-  m_LRTmode(false)
+  m_LRTmode(false),
+  m_trigseedML_LUT("")
 {
 
   /** Doublet finding properties. */
@@ -127,6 +130,12 @@ TrigFastTrackFinder::TrigFastTrackFinder(const std::string& name, ISvcLocator* p
   
   declareProperty("Triplet_DtCut",            m_tcs.m_tripletDtCut      = 10.0);//i.e. 10*sigma_MS
 
+  /** settings for the ML-enhanced track seeding */
+
+  declareProperty("UseTrigSeedML",              m_tcs.m_useTrigSeedML = 0);
+  declareProperty("TrigSeedML_LUT",             m_trigseedML_LUT = "trigseed_ml_pixel_barrel_kde.lut");
+  declareProperty("maxEC_Pixel_cluster_length", m_tcs.m_maxEC_len = 1.5);
+
   declareProperty( "VertexSeededMode",    m_vertexSeededMode = false);
   declareProperty( "doZFinder",           m_doZFinder = true);
   declareProperty( "doZFinderOnly",       m_doZFinderOnly = false);
@@ -318,11 +327,38 @@ HLT::ErrorCode TrigFastTrackFinder::hltInitialize() {
   ATH_MSG_INFO("Use GPU acceleration : "<<std::boolalpha<<m_useGPU);
 
   if (m_LRTmode) {
-    ATH_MSG_INFO(" FTF configures in Long Range Tracking Mode");
+    ATH_MSG_INFO(" FTF configures in Large Radius Tracking Mode");
     // set TrigTrackSeedGenerator to LRTmode
     m_tcs.m_LRTmode=m_LRTmode;
 
   }
+
+  if(m_tcs.m_useTrigSeedML > 0) {
+    //LUT params
+    int lut_w = 30;
+    int lut_h = 45;
+    float lut_range[4] = {0.0,3.0,0.0,9.0};
+    TrigSeedML_LUT L(1,lut_w,lut_h,lut_range);
+    //read data from LUT file 
+    std::string lut_fileName = PathResolver::find_file(m_trigseedML_LUT, "DATAPATH");
+    if (lut_fileName.empty()) {
+      ATH_MSG_ERROR("Cannot find TrigSeedML LUT file " << lut_fileName);
+      return HLT::BAD_JOB_SETUP;
+    }
+    else {
+      ATH_MSG_INFO(lut_fileName);
+      std::ifstream ifs(lut_fileName.c_str());
+      int row, col0, col1;
+      while(!ifs.eof()) {
+        ifs >> row >> col0 >> col1;
+        if(ifs.eof()) break;
+        for(int c=col0;c<=col1;c++) L.setBin(row, c);
+      }
+      ifs.close();
+      ATH_MSG_INFO("TrigSeedML LUT initialized from file " << m_trigseedML_LUT);
+      m_tcs.m_vLUT.push_back(L);
+    }
+  }
   
   ATH_MSG_DEBUG(" Initialized successfully"); 
   return HLT::OK;
diff --git a/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.h b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.h
index d73b3de4f191501788feeebef6035045681a6ea5..c1837c63bc424220817a021e191f2a69c880111a 100644
--- a/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.h
+++ b/Trigger/TrigAlgorithms/TrigFastTrackFinder/src/TrigFastTrackFinder.h
@@ -187,7 +187,7 @@ protected:
   // Large Radius Tracking
   bool m_LRTmode;
   
-
+  std::string m_trigseedML_LUT;//ML-based track seeding LUT name
 };
 
 #endif // not TRIGFASTTRACKFINDER_TRIGFASTTRACKFINDER_H
diff --git a/Trigger/TrigTools/TrigInDetPattRecoTools/CMakeLists.txt b/Trigger/TrigTools/TrigInDetPattRecoTools/CMakeLists.txt
index 9429b5539d2ee7e7d2c35ff7113b5ca82b082021..2ad189d31d09bcaa15ca57ab4501b72034f21464 100644
--- a/Trigger/TrigTools/TrigInDetPattRecoTools/CMakeLists.txt
+++ b/Trigger/TrigTools/TrigInDetPattRecoTools/CMakeLists.txt
@@ -8,7 +8,7 @@ atlas_add_library( TrigInDetPattRecoTools
                    src/*.cxx
                    PUBLIC_HEADERS TrigInDetPattRecoTools
                    LINK_LIBRARIES TrigInDetPattRecoEvent
-                   PRIVATE_LINK_LIBRARIES IRegionSelector TrigInDetEvent )
+                   PRIVATE_LINK_LIBRARIES IRegionSelector TrigInDetEvent InDetPrepRawData )
 
 find_package(Boost)
 
diff --git a/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigCombinatorialSettings.h b/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigCombinatorialSettings.h
index 35f7cf986adf3669ad91342b0480f7133069977c..ac4f93724fdd1ac7fd5e30aa19a971d3f5d13648 100644
--- a/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigCombinatorialSettings.h
+++ b/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigCombinatorialSettings.h
@@ -8,6 +8,7 @@
 class IRoiDescriptor;
 #include <vector>
 #include "TrigInDetPattRecoEvent/TrigInDetSiLayer.h"
+#include "TrigInDetPattRecoTools/TrigSeedML_LUT.h"
 
 typedef struct TrigCombinatorialSettings {
 public:
@@ -36,6 +37,9 @@ public:
     m_zvError = 10.0;
     m_LRTmode=false;
     m_layerGeometry.clear();
+    m_useTrigSeedML = 0;
+    m_maxEC_len = 1.5;
+    m_vLUT.clear();
   }
 
   int m_maxBarrelPix, m_minEndcapPix, m_maxEndcapPix, m_maxSiliconLayer;
@@ -58,6 +62,11 @@ public:
   bool m_LRTmode;
 
   std::vector<TRIG_INDET_SI_LAYER> m_layerGeometry;
+
+  int m_useTrigSeedML;
+  std::vector<TrigSeedML_LUT> m_vLUT;
+  float m_maxEC_len;
+
 } TRIG_COMBINATORIAL_SETTINGS;
 
 
diff --git a/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigSeedML_LUT.h b/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigSeedML_LUT.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2e9f7837014570c23435234ebcc77d80a00c13c
--- /dev/null
+++ b/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigSeedML_LUT.h
@@ -0,0 +1,108 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef __TRIG_SEED_ML_LUT_H__
+#define __TRIG_SEED_ML_LUT_H__
+
+#include <vector>
+
+typedef struct TrigSeedML_LUT {
+public:
+TrigSeedML_LUT() : m_id(-1), m_w(0), m_h(0), m_data(0), m_invBinWidthX(0), m_invBinWidthY(0) {};
+
+TrigSeedML_LUT(int id, int w, int h, float c[4]) : m_id(id), m_w(w), m_h(h) {
+  for(int i=0;i<4;i++) m_c[i] = c[i];
+  initialize();
+}
+
+TrigSeedML_LUT(const TrigSeedML_LUT& tsl) : m_id(tsl.m_id), m_w(tsl.m_w), m_h(tsl.m_h), m_data(tsl.m_data) {
+  for(int i=0;i<4;i++) m_c[i] = tsl.m_c[i];
+  m_invBinWidthX = m_w/(m_c[1]-m_c[0]);
+  m_invBinWidthY = m_h/(m_c[3]-m_c[2]);
+}
+
+  ~TrigSeedML_LUT() {m_data.clear();}
+
+  bool check(float fX, float fY) const {
+
+    int i = (fY - m_c[2])*m_invBinWidthY;
+    int j = (fX - m_c[0])*m_invBinWidthX;
+
+    if(i<0 || i>= m_h || j<0 || j>=m_w) return false;
+
+    return (m_data[j+i*m_w] != 0);
+  }
+
+  bool getValidRange(float fX, float& min, float& max) const {
+    min = m_c[2];
+    max = m_c[3];
+    int j = (fX - m_c[0])*m_invBinWidthX;
+    if(j<0 || j>=m_w) return false;
+
+    int idx=j;
+    int i1=0;
+    int i2=0;
+    int i=0;
+    for(;i<m_h;i++, idx+=m_w) {
+      if(m_data[idx] == 0) continue;
+      else {
+        i1 = i;
+        i2 = i1;
+        break;  
+      }    
+    }
+    for(;i<m_h;i++, idx+=m_w) {
+      if(m_data[idx] != 0) i2++;
+      else break;
+    }
+
+    min = m_c[2] + i1/m_invBinWidthY;
+    max = m_c[2] + i2/m_invBinWidthY;
+    return true;
+  }
+  void initialize() {
+    m_invBinWidthX = m_w/(m_c[1]-m_c[0]);
+    m_invBinWidthY = m_h/(m_c[3]-m_c[2]);
+    m_data.resize(m_h*m_w, 0);
+  }
+
+  void setBin(int r, int c) {
+    m_data[c + r*m_w] = 1;
+  }
+
+  void generate(float offset, float slope, float hwm, float hwp) {
+    
+    m_data.resize(m_h*m_w, 0);
+
+    for(int j=0;j<m_w;j++) {
+      float x = m_c[0] + j/m_invBinWidthX;
+
+      float y = offset + x*slope;
+      float yp= y+hwp;
+      float ym= y+hwm;
+
+      if(yp < m_c[2]) yp = m_c[2];
+      if(yp > m_c[3]) yp = m_c[3];
+      
+      if(ym < m_c[2]) ym = m_c[2];
+      if(ym > m_c[3]) ym = m_c[3];
+
+      int i1 = int((ym-m_c[2])*m_invBinWidthY);
+      int i2 = int((yp-m_c[2])*m_invBinWidthY);
+
+      for(int i=i1;i<i2;i++) {
+        m_data[j+m_w*i] = 1;
+      }
+
+    }
+  }
+  
+  int m_id;
+  int m_w, m_h;
+  float m_c[4];
+  std::vector<unsigned char> m_data;
+  float m_invBinWidthX, m_invBinWidthY;
+} TRIG_SEED_ML_LUT;
+
+#endif
diff --git a/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigTrackSeedGenerator.h b/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigTrackSeedGenerator.h
index 584dbcf05c52614955ffd53f16e7b9fa58eca9a9..f616c38be4d073da2b9195a627e2b9daa80d2a54 100644
--- a/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigTrackSeedGenerator.h
+++ b/Trigger/TrigTools/TrigInDetPattRecoTools/TrigInDetPattRecoTools/TrigTrackSeedGenerator.h
@@ -13,160 +13,83 @@
 
 class TrigInDetTriplet;
 
-
-typedef struct PhiSector {
-
-public:
-  
-  struct compareZ {
-    bool operator()(const TrigSiSpacePointBase* p1, const TrigSiSpacePointBase* p2) {
-      return p1->z()<p2->z();
-    }
-  };
-
-  struct greaterThanZ {
-    bool operator()(float z, const TrigSiSpacePointBase* const& p) const {
-      return z < p->z();
-    }
-  };
-
-  struct smallerThanZ {
-    bool operator()(const TrigSiSpacePointBase* const& p, float z) const {
-      return p->z() < z;
-    }
-  };
-
-PhiSector() : m_nSP(0) {m_radBins.clear();}
-PhiSector(int nBins) : m_nSP(0) {
-  m_radBins.resize(nBins);
-}
-PhiSector(const PhiSector& ps) : m_nSP(ps.m_nSP), m_radBins(ps.m_radBins) {};
-
-  const PhiSector& operator = (const PhiSector& ps) {
-    m_nSP = ps.m_nSP;
-    m_radBins = ps.m_radBins;
-    return *this;
+typedef struct IndexedSP {
+public :
+IndexedSP() : m_pSP(0), m_idx(-1) {};
+IndexedSP(const TrigSiSpacePointBase* p, int idx) : m_pSP(p), m_idx(idx) {};
+IndexedSP(const IndexedSP& isp) : m_pSP(isp.m_pSP), m_idx(isp.m_idx) {};
+
+  void set(const TrigSiSpacePointBase* p, int idx) {
+    m_pSP = p;
+    m_idx = idx;
   }
 
-  void reset() {
-    for(std::vector<std::vector<const TrigSiSpacePointBase*> >::iterator it=m_radBins.begin();it!=m_radBins.end();++it) {
-      (*it).clear();
-    }
-  }
+  const TrigSiSpacePointBase* m_pSP;
+  int m_idx;
 
-  void addSpacePoint(int rIdx, const TrigSiSpacePointBase* p) {
-    m_nSP++;
-    m_radBins[rIdx].push_back(p);
-  }
-
-  void sortSpacePoints() {
-    for(std::vector<std::vector<const TrigSiSpacePointBase*> >::iterator it=m_radBins.begin();it!=m_radBins.end();++it) {
-      if((*it).empty()) continue;
-      std::sort(it->begin(), it->end(), compareZ());
-    }
-    
-  }
-
-  int size() const { return m_nSP; }
-  
-  int m_nSP;
-  std::vector<std::vector<const TrigSiSpacePointBase*> > m_radBins;
-
-} PHI_SECTOR;
-
-
-typedef struct PhiR_Storage {
-
-public:
-
-  PhiR_Storage(int nPhiSectors, int nRBins) {
-    m_phiSectors.reserve(nPhiSectors);
-    for(int i = 0;i<nPhiSectors;i++) m_phiSectors.push_back(PHI_SECTOR(nRBins));
-  }
-
-  void addSpacePoint(int phiIdx, int rIdx, const TrigSiSpacePointBase* p) {
-    m_phiSectors[phiIdx].addSpacePoint(rIdx, p);
-  }
-
-  void reset() {
-    for(std::vector<PHI_SECTOR>::iterator it=m_phiSectors.begin();it!=m_phiSectors.end();++it) {
-      if((*it).m_nSP==0) continue;
-      (*it).reset();
-    }
-  }
-   
-  void sortSpacePoints() {
-    for(std::vector<PHI_SECTOR>::iterator it=m_phiSectors.begin();it!=m_phiSectors.end();++it) {
-      if((*it).m_nSP==0) continue;
-      (*it).sortSpacePoints();
-    }
-  }
-
-  std::vector<PHI_SECTOR> m_phiSectors;
-
-} PHI_R_STORAGE;
+} INDEXED_SP;
 
 typedef struct LPhiSector {
 
 public:
   
   struct compareZ {
-    bool operator()(const TrigSiSpacePointBase* p1, const TrigSiSpacePointBase* p2) {
-      return p1->z()<p2->z();
+    bool operator()(const INDEXED_SP* p1, const INDEXED_SP* p2) {
+      return p1->m_pSP->z()<p2->m_pSP->z();
     }
   };
 
   struct compareR {
-    bool operator()(const TrigSiSpacePointBase* p1, const TrigSiSpacePointBase* p2) {
-      return p1->r()<p2->r();
+    bool operator()(const INDEXED_SP* p1, const INDEXED_SP* p2) {
+      return p1->m_pSP->r()<p2->m_pSP->r();
     }
   };
 
   struct compareRless {
-    bool operator()(const TrigSiSpacePointBase* p1, const TrigSiSpacePointBase* p2) {
-      return p1->r()>p2->r();
+    bool operator()(const INDEXED_SP* p1, const INDEXED_SP* p2) {
+      return p1->m_pSP->r()>p2->m_pSP->r();
     }
   };
 
   struct greaterThanZ {
-    bool operator()(float z, const TrigSiSpacePointBase* const& p) const {
-      return z < p->z();
+    bool operator()(float z, const INDEXED_SP* const& p) const {
+      return z < p->m_pSP->z();
     }
   };
 
   struct smallerThanZ {
-    bool operator()(const TrigSiSpacePointBase* const& p, float z) const {
-      return p->z() < z;
+    bool operator()(const INDEXED_SP* const& p, float z) const {
+      return p->m_pSP->z() < z;
     }
   };
 
   struct greaterThanR {
-    bool operator()(float r, const TrigSiSpacePointBase* const& p) const {
-      return r < p->r();
+    bool operator()(float r, const INDEXED_SP* const& p) const {
+      return r < p->m_pSP->r();
     }
   };
 
   struct greaterThanR_i {
-    bool operator()(const TrigSiSpacePointBase* const& p, float r) const {
-      return r < p->r();
+    bool operator()(const INDEXED_SP* const& p, float r) const {
+      return r < p->m_pSP->r();
     }
   };
 
   struct smallerThanR {
-    bool operator()(const TrigSiSpacePointBase* const& p, float r) const {
-      return p->r() < r;
+    bool operator()(const INDEXED_SP* const& p, float r) const {
+      return p->m_pSP->r() < r;
     }
   };
 
   struct smallerThanR_i {
-    bool operator()(float r, const TrigSiSpacePointBase* const& p) const {
-      return p->r() < r;
+    bool operator()(float r, const INDEXED_SP* const& p) const {
+      return p->m_pSP->r() < r;
     }
   };
 
   //LPhiSector() : m_nSP(0) {m_phiSlices.clear();}
 LPhiSector(int nPhiSlices) : m_nSP(0) {
-  std::vector<const TrigSiSpacePointBase*> d;
+  std::vector<const INDEXED_SP*> d;
   m_phiSlices.resize(nPhiSlices, d);
   m_phiThreeSlices.resize(nPhiSlices, d);
   if(nPhiSlices == 1) {//special case
@@ -214,16 +137,16 @@ LPhiSector(const LPhiSector& ps) : m_nSP(ps.m_nSP), m_phiSlices(ps.m_phiSlices),
   }
 
   void reset() {
-    for(std::vector<std::vector<const TrigSiSpacePointBase*> >::iterator it = m_phiSlices.begin();it!=m_phiSlices.end();++it) {
+    for(std::vector<std::vector<const INDEXED_SP*> >::iterator it = m_phiSlices.begin();it!=m_phiSlices.end();++it) {
       (*it).clear();
     }
-    for(std::vector<std::vector<const TrigSiSpacePointBase*> >::iterator it = m_phiThreeSlices.begin();it!=m_phiThreeSlices.end();++it) {
+    for(std::vector<std::vector<const INDEXED_SP*> >::iterator it = m_phiThreeSlices.begin();it!=m_phiThreeSlices.end();++it) {
       (*it).clear();
     }
     m_nSP = 0;
   }
 
-  void addSpacePoint(int phiIndex, const TrigSiSpacePointBase* p) {
+  void addSpacePoint(int phiIndex, const INDEXED_SP* p) {
     m_nSP++;
     m_phiSlices[phiIndex].push_back(p);
     for(int i=0;i<3;i++) {
@@ -233,12 +156,12 @@ LPhiSector(const LPhiSector& ps) : m_nSP(ps.m_nSP), m_phiSlices(ps.m_phiSlices),
   }
 
   void sortSpacePoints(bool isBarrel) {
-    for(std::vector<std::vector<const TrigSiSpacePointBase*> >::iterator it=m_phiSlices.begin();it!=m_phiSlices.end();++it) {
+    for(std::vector<std::vector<const INDEXED_SP*> >::iterator it=m_phiSlices.begin();it!=m_phiSlices.end();++it) {
       if((*it).empty()) continue;
       if(isBarrel) std::sort(it->begin(), it->end(), compareZ());
       else std::sort(it->begin(), it->end(), compareR());
     }
-    for(std::vector<std::vector<const TrigSiSpacePointBase*> >::iterator it=m_phiThreeSlices.begin();it!=m_phiThreeSlices.end();++it) {
+    for(std::vector<std::vector<const INDEXED_SP*> >::iterator it=m_phiThreeSlices.begin();it!=m_phiThreeSlices.end();++it) {
       if((*it).empty()) continue;
       if(isBarrel) std::sort(it->begin(), it->end(), compareZ());
       else std::sort(it->begin(), it->end(), compareR());
@@ -246,7 +169,7 @@ LPhiSector(const LPhiSector& ps) : m_nSP(ps.m_nSP), m_phiSlices(ps.m_phiSlices),
   }
 
   void sortSpacePoints(bool isBarrel, bool isPositive) {
-    for(std::vector<std::vector<const TrigSiSpacePointBase*> >::iterator it=m_phiSlices.begin();it!=m_phiSlices.end();++it) {
+    for(std::vector<std::vector<const INDEXED_SP*> >::iterator it=m_phiSlices.begin();it!=m_phiSlices.end();++it) {
       if((*it).empty()) continue;
       if(isBarrel) std::sort(it->begin(), it->end(), compareZ());
       else {
@@ -254,7 +177,7 @@ LPhiSector(const LPhiSector& ps) : m_nSP(ps.m_nSP), m_phiSlices(ps.m_phiSlices),
 	else std::sort(it->begin(), it->end(), compareR());
       }
     }
-    for(std::vector<std::vector<const TrigSiSpacePointBase*> >::iterator it=m_phiThreeSlices.begin();it!=m_phiThreeSlices.end();++it) {
+    for(std::vector<std::vector<const INDEXED_SP*> >::iterator it=m_phiThreeSlices.begin();it!=m_phiThreeSlices.end();++it) {
       if((*it).empty()) continue;
       if(isBarrel) std::sort(it->begin(), it->end(), compareZ());
       else {
@@ -267,8 +190,8 @@ LPhiSector(const LPhiSector& ps) : m_nSP(ps.m_nSP), m_phiSlices(ps.m_phiSlices),
   int size() const { return m_nSP; }
   
   int m_nSP;
-  std::vector<std::vector<const TrigSiSpacePointBase*> > m_phiSlices;
-  std::vector<std::vector<const TrigSiSpacePointBase*> > m_phiThreeSlices;
+  std::vector<std::vector<const INDEXED_SP*> > m_phiSlices;
+  std::vector<std::vector<const INDEXED_SP*> > m_phiThreeSlices;
   std::vector<int> m_threeIndices[3];
 
 private:
@@ -297,7 +220,7 @@ public:
     */
   }
 
-  void addSpacePoint(int phiIdx, int layerId, const TrigSiSpacePointBase* p) {
+  void addSpacePoint(int phiIdx, int layerId, const INDEXED_SP* p) {
     m_layers[layerId].addSpacePoint(phiIdx, p);
   }
 
@@ -442,7 +365,7 @@ InternalSoA() : m_spi(0), m_spo(0), m_r(0), m_u(0), m_v(0), m_t(0), m_ti(0), m_t
 } INTERNAL_SOA;
 
 
-typedef std::pair<std::vector<const TrigSiSpacePointBase*>::const_iterator, std::vector<const TrigSiSpacePointBase*>::const_iterator> SP_RANGE;
+typedef std::pair<std::vector<const INDEXED_SP*>::const_iterator, std::vector<const INDEXED_SP*>::const_iterator> SP_RANGE;
 
 typedef class TrigTrackSeedGenerator {
 
@@ -457,12 +380,15 @@ typedef class TrigTrackSeedGenerator {
   void getSeeds(std::vector<TrigInDetTriplet>&);
 
 private:
-  //bool validateLayerPair(int, int, float, float); 
-  //bool validateLayerPair(int, int, float, float, float); 
+
+  std::vector<INDEXED_SP> m_spStorage;
+  std::vector<float> m_minTau;
+  std::vector<float> m_maxTau;
+
   bool validateLayerPairNew(int, int, float, float); 
-  bool getSpacepointRange(int, const std::vector<const TrigSiSpacePointBase*>&, SP_RANGE&);
-  int processSpacepointRange(int, float, float, bool, const SP_RANGE&, const IRoiDescriptor*);
-  int processSpacepointRangeZv(float, float, bool, const SP_RANGE&);
+  bool getSpacepointRange(int, const std::vector<const INDEXED_SP*>&, SP_RANGE&);
+  int processSpacepointRange(int, const INDEXED_SP*, bool, const SP_RANGE&, const IRoiDescriptor*);
+  int processSpacepointRangeZv(const INDEXED_SP*, bool, const SP_RANGE&, bool, const float&, const float&);
   void createTriplets(const TrigSiSpacePointBase*, int, int, std::vector<TrigInDetTriplet>&, const IRoiDescriptor*);
   void createTripletsNew(const TrigSiSpacePointBase*, int, int, std::vector<TrigInDetTriplet>&, const IRoiDescriptor*);
   void storeTriplets(std::vector<TrigInDetTriplet>&);
diff --git a/Trigger/TrigTools/TrigInDetPattRecoTools/src/TrigTrackSeedGenerator.cxx b/Trigger/TrigTools/TrigInDetPattRecoTools/src/TrigTrackSeedGenerator.cxx
index c437be3d577d327f664e946529560be8a5206e80..49e60cb6ffabc4cde2c2984e355a62643d1a16e7 100644
--- a/Trigger/TrigTools/TrigInDetPattRecoTools/src/TrigTrackSeedGenerator.cxx
+++ b/Trigger/TrigTools/TrigInDetPattRecoTools/src/TrigTrackSeedGenerator.cxx
@@ -13,6 +13,7 @@
 #include "TrigInDetPattRecoTools/TrigTrackSeedGenerator.h"
 #include "IRegionSelector/IRoiDescriptor.h"
 #include "IRegionSelector/RoiUtil.h"
+#include "InDetPrepRawData/PixelCluster.h"
 
 TrigTrackSeedGenerator::TrigTrackSeedGenerator(const TrigCombinatorialSettings& tcs) 
   : m_settings(tcs), 
@@ -47,10 +48,43 @@ void TrigTrackSeedGenerator::loadSpacePoints(const std::vector<TrigSiSpacePointB
 
   m_SoA.clear();
 
+  m_spStorage.clear();
+
+  m_spStorage.resize(vSP.size());
+
+  m_minTau.resize(vSP.size(), 0.0);
+  m_maxTau.resize(vSP.size(), 100.0);
+
+  int spIndex = 0;
+  
   for(std::vector<TrigSiSpacePointBase>::const_iterator it = vSP.begin();it != vSP.end();++it) {
     //  if((*it).r()>m_maxRadius || (*it).r() < m_minRadius) continue;
     // int rIdx = ((*it).r()-m_minRadius)/m_radBinWidth;
     int layerId = (*it).layer();
+
+    bool isPixel = (m_settings.m_layerGeometry[layerId].m_subdet == 1);
+    bool isEndcap = (m_settings.m_layerGeometry[layerId].m_type != 0);
+
+    bool updateTauRange = false;
+    float minTau = 0.0;
+    float maxTau = 100.0;
+
+    if((m_settings.m_useTrigSeedML > 0) && isPixel) {
+      const Trk::SpacePoint* osp = (*it).offlineSpacePoint();
+      const InDet::PixelCluster* pCL = dynamic_cast<const InDet::PixelCluster*>(osp->clusterList().first);
+
+      float cluster_width = pCL->width().widthPhiRZ().y();
+      if(isEndcap) {
+	if(cluster_width > m_settings.m_maxEC_len) continue;
+      }
+      else {//Barrel
+	if(!m_settings.m_vLUT.empty()) {
+	  const TrigSeedML_LUT& LUT = (*m_settings.m_vLUT.begin());
+	  updateTauRange = LUT.getValidRange(cluster_width, minTau, maxTau);
+	}
+      }
+    }
+    
     int phiIdx = ((*it).phi()+M_PI)/m_phiSliceWidth;
     if (phiIdx >= m_settings.m_nMaxPhiSlice) {
       phiIdx %= m_settings.m_nMaxPhiSlice;
@@ -59,7 +93,15 @@ void TrigTrackSeedGenerator::loadSpacePoints(const std::vector<TrigSiSpacePointB
       phiIdx += m_settings.m_nMaxPhiSlice;
       phiIdx %= m_settings.m_nMaxPhiSlice;
     }
-    m_pStore->addSpacePoint(phiIdx, layerId, &(*it));
+    m_spStorage[spIndex].set(&(*it), spIndex);
+    m_pStore->addSpacePoint(phiIdx, layerId, &m_spStorage[spIndex]);
+
+    if(updateTauRange) {
+      m_minTau[spIndex] = minTau;
+      m_maxTau[spIndex] = maxTau;
+    }
+    spIndex++;
+
   }
 
   m_pStore->sortSpacePoints2(m_settings.m_layerGeometry);
@@ -147,11 +189,11 @@ void TrigTrackSeedGenerator::createSeeds(const IRoiDescriptor* roiDescriptor) {
       */
       for(auto spm : S.m_phiSlices[phiI]) {//loop over middle spacepoints
 
-	float zm = spm->z();
-	float rm = spm->r();
+	float zm = spm->m_pSP->z();
+	float rm = spm->m_pSP->r();
 
 	//    const std::pair<IdentifierHash, IdentifierHash>& deIds = spm->offlineSpacePoint()->elementIdList();
-	    
+	
 	int nSP=0;
 
 	m_nInner = 0;
@@ -176,8 +218,8 @@ void TrigTrackSeedGenerator::createSeeds(const IRoiDescriptor* roiDescriptor) {
 	  //for(auto phiJ : phiVec) {
 
 	  //  const std::vector<const TrigSiSpacePointBase*>& spVec = m_pStore->m_layers[layerJ].m_phiSlices.at(phiJ);
-
-	  const std::vector<const TrigSiSpacePointBase*>& spVec = m_pStore->m_layers[layerJ].m_phiThreeSlices.at(phiI);
+	  
+	  const std::vector<const INDEXED_SP*>& spVec = m_pStore->m_layers[layerJ].m_phiThreeSlices.at(phiI);
 
 	  if(spVec.empty()) continue;
 
@@ -188,7 +230,7 @@ void TrigTrackSeedGenerator::createSeeds(const IRoiDescriptor* roiDescriptor) {
 	  int nI = m_nInner;
 	  int nO = m_nOuter;
 	      
-	  nSP += processSpacepointRange(layerJ, rm, zm, checkPSS, delta, roiDescriptor);
+	  nSP += processSpacepointRange(layerJ, spm, checkPSS, delta, roiDescriptor);
 
 	  if(m_nInner > nI) m_innerMarkers.push_back(m_nInner);
 	  if(m_nOuter > nO) m_outerMarkers.push_back(m_nOuter);
@@ -205,7 +247,7 @@ void TrigTrackSeedGenerator::createSeeds(const IRoiDescriptor* roiDescriptor) {
 	if(m_nInner != 0 && m_nOuter != 0) {
 	  std::vector<TrigInDetTriplet> tripletVec;
 	    
-	  createTripletsNew(spm, m_nInner, m_nOuter, tripletVec, roiDescriptor);
+	  createTripletsNew(spm->m_pSP, m_nInner, m_nOuter, tripletVec, roiDescriptor);
 	    
 	  if(!tripletVec.empty()) storeTriplets(tripletVec);	
 	  tripletVec.clear();
@@ -239,6 +281,9 @@ void TrigTrackSeedGenerator::createSeeds(const IRoiDescriptor* roiDescriptor, co
     if(S.m_nSP==0) continue;
 
     bool isSct = (m_settings.m_layerGeometry[layerI].m_subdet == 2);
+    bool isBarrel = (m_settings.m_layerGeometry[layerI].m_type == 0);
+    
+    bool checkWidth = isBarrel && (!isSct) && (m_settings.m_useTrigSeedML > 0);
     
     for(int phiI=0;phiI<m_settings.m_nMaxPhiSlice;phiI++) {
 
@@ -259,9 +304,17 @@ void TrigTrackSeedGenerator::createSeeds(const IRoiDescriptor* roiDescriptor, co
 
 	for(auto spm : S.m_phiSlices[phiI]) {//loop over middle spacepoints
 
-	  float zm = spm->z();
-	  float rm = spm->r();
+	  float zm = spm->m_pSP->z();
+	  float rm = spm->m_pSP->r();
 
+	  float minTau = 0.0;
+	  float maxTau = 100.0;
+
+	  if(checkWidth) {
+	    minTau = m_minTau[spm->m_idx];
+	    maxTau = m_maxTau[spm->m_idx];
+	  }
+	  
 	  std::vector<TrigInDetTriplet> tripletVec;
 
 	  for(const auto zVertex : vZv) {//loop over zvertices
@@ -287,21 +340,21 @@ void TrigTrackSeedGenerator::createSeeds(const IRoiDescriptor* roiDescriptor, co
 	      bool checkPSS = (!m_settings.m_tripletDoPSS) && (isSct && isPixel2);
 
 	      for(auto phiJ : phiVec) {
-
-		const std::vector<const TrigSiSpacePointBase*>& spVec = m_pStore->m_layers[layerJ].m_phiSlices.at(phiJ);
-
+		
+		const std::vector<const INDEXED_SP*>& spVec = m_pStore->m_layers[layerJ].m_phiSlices.at(phiJ);
+		
 		if(spVec.empty()) continue;
 
 		SP_RANGE delta;
 
 		if(!getSpacepointRange(layerJ, spVec, delta)) continue;
 	      
-		nSP += processSpacepointRangeZv(rm, zm, checkPSS, delta);
+		nSP += processSpacepointRangeZv(spm, checkPSS, delta, checkWidth, minTau, maxTau);
 	      }//loop over phi bins
 
 	    }//loop over inner/outer layers
 	    if(m_nInner != 0 && m_nOuter != 0) {
-	      createTriplets(spm, m_nInner, m_nOuter, tripletVec, roiDescriptor);
+	      createTriplets(spm->m_pSP, m_nInner, m_nOuter, tripletVec, roiDescriptor);
 	    }
 	  }//loop over zvertices
 	  if(!tripletVec.empty()) storeTriplets(tripletVec);
@@ -482,13 +535,13 @@ bool TrigTrackSeedGenerator::validateLayerPairNew(int layerI, int layerJ, float
 
 
 
-bool TrigTrackSeedGenerator::getSpacepointRange(int lJ, const std::vector<const TrigSiSpacePointBase*>& spVec, SP_RANGE& delta) {
+bool TrigTrackSeedGenerator::getSpacepointRange(int lJ, const std::vector<const INDEXED_SP*>& spVec, SP_RANGE& delta) {
   
   int typeJ = m_settings.m_layerGeometry[lJ].m_type;
   bool isBarrel = (typeJ == 0);
   bool isPositiveEC = m_settings.m_layerGeometry[lJ].m_refCoord > 0; 
-  float minSpCoord = (isBarrel) ? (*spVec.begin())->z() : (*spVec.begin())->r();
-  float maxSpCoord = (isBarrel) ? (*spVec.rbegin())->z() : (*spVec.rbegin())->r();
+  float minSpCoord = (isBarrel) ? (*spVec.begin())->m_pSP->z() : (*spVec.begin())->m_pSP->r();
+  float maxSpCoord = (isBarrel) ? (*spVec.rbegin())->m_pSP->z() : (*spVec.rbegin())->m_pSP->r();
 
   if(!isBarrel && isPositiveEC) {//forward endcap SPs are sorted differently
     float tmp = minSpCoord;minSpCoord = maxSpCoord;maxSpCoord = tmp;
@@ -499,8 +552,8 @@ bool TrigTrackSeedGenerator::getSpacepointRange(int lJ, const std::vector<const
 
   //identify the range of spacepoints in the layer
 
-  std::vector<const TrigSiSpacePointBase*>::const_iterator it1 = spVec.end();
-  std::vector<const TrigSiSpacePointBase*>::const_iterator it2 = spVec.end();
+  std::vector<const INDEXED_SP*>::const_iterator it1 = spVec.end();
+  std::vector<const INDEXED_SP*>::const_iterator it2 = spVec.end();
   
   if(isBarrel) {
     it1 = std::lower_bound(spVec.begin(), spVec.end(), m_minCoord, L_PHI_SECTOR::smallerThanZ());
@@ -523,20 +576,25 @@ bool TrigTrackSeedGenerator::getSpacepointRange(int lJ, const std::vector<const
   return true;
 }
 
-int TrigTrackSeedGenerator::processSpacepointRange(int lJ, float rm, float zm, bool checkPSS, const SP_RANGE& delta, const IRoiDescriptor* roiDescriptor) {
+int TrigTrackSeedGenerator::processSpacepointRange(int lJ, const INDEXED_SP* spm, bool checkPSS, const SP_RANGE& delta, const IRoiDescriptor* roiDescriptor) {
 
   int nSP=0;
 
   bool isBarrel = (m_settings.m_layerGeometry[lJ].m_type==0);
   float refCoord = m_settings.m_layerGeometry[lJ].m_refCoord;
 
+  float rm = spm->m_pSP->r();
+  float zm = spm->m_pSP->z();
+
   float dZ = refCoord-zm;
   float dR_i = isBarrel ? 1.0/(refCoord-rm) : 1.0;
 
-  for(std::vector<const TrigSiSpacePointBase*>::const_iterator spIt=delta.first; spIt!=delta.second; ++spIt) {
+  int SeedML = m_settings.m_useTrigSeedML;
+
+  for(std::vector<const INDEXED_SP*>::const_iterator spIt=delta.first; spIt!=delta.second; ++spIt) {
     // if(deIds == (*spIt)->offlineSpacePoint()->elementIdList()) continue;
-    float zsp = (*spIt)->z();
-    float rsp = (*spIt)->r();
+    float zsp = (*spIt)->m_pSP->z();
+    float rsp = (*spIt)->m_pSP->r();
     
     float dr = rsp - rm;
     
@@ -549,8 +607,13 @@ int TrigTrackSeedGenerator::processSpacepointRange(int lJ, float rm, float zm, b
     
     float dz = zsp - zm;
     float tau = dz/dr;
-    if (std::fabs(tau) > 7.41) continue;
+    float ftau = std::fabs(tau);
+    if (ftau > 7.41) continue;
     
+    if(spm->m_pSP->isPixel() && SeedML > 0) {
+      if(ftau < m_minTau[spm->m_idx] || ftau > m_maxTau[spm->m_idx]) continue;
+    }
+
     
     float z0  = zm - rm*tau;
     if (m_settings.m_doubletFilterRZ) {
@@ -560,12 +623,22 @@ int TrigTrackSeedGenerator::processSpacepointRange(int lJ, float rm, float zm, b
     float t = isBarrel ? dz*dR_i : dZ/dr;
     
     if(dr<0) {
-      m_SoA.m_spi[m_nInner] = *spIt;
+      if(isBarrel && (*spIt)->m_pSP->isPixel()) {
+	if(SeedML == 3 || SeedML == 4) {
+	  if(ftau < m_minTau[(*spIt)->m_idx] || ftau > m_maxTau[(*spIt)->m_idx]) continue;
+	}
+      }
+      m_SoA.m_spi[m_nInner] = (*spIt)->m_pSP;
       m_SoA.m_ti[m_nInner] = t;
       m_nInner++;
     }
     else {
-      m_SoA.m_spo[m_nOuter] = *spIt;
+      if(isBarrel && (*spIt)->m_pSP->isPixel()) {
+	if(SeedML == 2 || SeedML == 4) {
+	  if(ftau < m_minTau[(*spIt)->m_idx] || ftau > m_maxTau[(*spIt)->m_idx]) continue;
+	}
+      }
+      m_SoA.m_spo[m_nOuter] = (*spIt)->m_pSP;
       m_SoA.m_to[m_nOuter] = t;
       m_nOuter++;
     }
@@ -575,13 +648,19 @@ int TrigTrackSeedGenerator::processSpacepointRange(int lJ, float rm, float zm, b
   return nSP;
 }
 
-int TrigTrackSeedGenerator::processSpacepointRangeZv(float rm, float zm, bool checkPSS, const SP_RANGE& delta) {
+int TrigTrackSeedGenerator::processSpacepointRangeZv(const INDEXED_SP* spm, bool checkPSS, const SP_RANGE& delta, bool checkWidth, const float& minTau, const float& maxTau) {
 
-  int nSP=0;	    
-  for(std::vector<const TrigSiSpacePointBase*>::const_iterator spIt=delta.first; spIt!=delta.second; ++spIt) {
+  int nSP=0;
+
+  float rm = spm->m_pSP->r();
+  float zm = spm->m_pSP->z();
+
+  int SeedML = m_settings.m_useTrigSeedML;
+  
+  for(std::vector<const INDEXED_SP*>::const_iterator spIt=delta.first; spIt!=delta.second; ++spIt) {
 
-    float rsp = (*spIt)->r(); 
-    float zsp = (*spIt)->z();  
+    float rsp = (*spIt)->m_pSP->r(); 
+    float zsp = (*spIt)->m_pSP->z();  
     float dr = rsp - rm;
 	      
     if(std::fabs(dr)>m_maxDeltaRadius ) continue;
@@ -593,14 +672,31 @@ int TrigTrackSeedGenerator::processSpacepointRangeZv(float rm, float zm, bool ch
  
     float dz = zsp - zm;
     float tau = dz/dr;
-    if (std::fabs(tau) > 7.41) continue;//|eta|<2.7
+    float ftau = std::fabs(tau);
+    
+    if (ftau > 7.41) continue;//|eta|<2.7
 
+    if(checkWidth) {
+      if(ftau < minTau || ftau > maxTau) continue;
+    }
+    
     if(dr<0) {
-      m_SoA.m_spi[m_nInner++] = *spIt;
+      if((*spIt)->m_pSP->isPixel()) {
+      	if(SeedML == 3 || SeedML == 4) {
+	  if(ftau < m_minTau[(*spIt)->m_idx] || ftau > m_maxTau[(*spIt)->m_idx]) continue;
+	}
+      }
+      m_SoA.m_spi[m_nInner++] = (*spIt)->m_pSP;
     }
     else {
-      m_SoA.m_spo[m_nOuter++] = *spIt;
+      if((*spIt)->m_pSP->isPixel()) {
+	if(SeedML == 2 || SeedML == 4) {
+	  if(ftau < m_minTau[(*spIt)->m_idx] || ftau > m_maxTau[(*spIt)->m_idx]) continue;
+	}
+      }
+      m_SoA.m_spo[m_nOuter++] = (*spIt)->m_pSP;
     }
+
     nSP++;  
   }