diff --git a/L1Trigger/TrackFindingTMTT/interface/ChiSquaredFit4.h b/L1Trigger/TrackFindingTMTT/interface/ChiSquaredFit4.h
index 00af64301b6be..a0b866b4a2ff4 100644
--- a/L1Trigger/TrackFindingTMTT/interface/ChiSquaredFit4.h
+++ b/L1Trigger/TrackFindingTMTT/interface/ChiSquaredFit4.h
@@ -10,10 +10,10 @@ namespace tmtt {
     ChiSquaredFit4(const Settings* settings, const uint nPar);
 
   protected:
-    TVectorD seed(const L1track3D& l1track3D);
-    TVectorD residuals(const TVectorD& x);
-    TMatrixD D(const TVectorD& x);
-    TMatrixD Vinv();
+    TVectorD seed(const L1track3D& l1track3D) override;
+    TVectorD residuals(const TVectorD& x) override;
+    TMatrixD D(const TVectorD& x) override;
+    TMatrixD Vinv() override;
   };
 
 }  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/interface/ChiSquaredFitBase.h b/L1Trigger/TrackFindingTMTT/interface/ChiSquaredFitBase.h
index 90c9b825f141e..58be28e604664 100644
--- a/L1Trigger/TrackFindingTMTT/interface/ChiSquaredFitBase.h
+++ b/L1Trigger/TrackFindingTMTT/interface/ChiSquaredFitBase.h
@@ -25,7 +25,7 @@ namespace tmtt {
   public:
     ChiSquaredFitBase(const Settings* settings, const uint nPar);
 
-    L1fittedTrack fit(const L1track3D& l1track3D);
+    L1fittedTrack fit(const L1track3D& l1track3D) override;
 
   protected:
     /* Methods */
diff --git a/L1Trigger/TrackFindingTMTT/interface/DegradeBend.h b/L1Trigger/TrackFindingTMTT/interface/DegradeBend.h
index c43788e878372..66c308061e978 100644
--- a/L1Trigger/TrackFindingTMTT/interface/DegradeBend.h
+++ b/L1Trigger/TrackFindingTMTT/interface/DegradeBend.h
@@ -1,6 +1,9 @@
 #ifndef L1Trigger_TrackFindingTMTT_DegradeBend_h
 #define L1Trigger_TrackFindingTMTT_DegradeBend_h
 
+#include "L1Trigger/TrackFindingTMTT/interface/StubFEWindows.h"
+
+#include "L1Trigger/TrackTrigger/interface/TTStubAlgorithm_official.h"
 #include "DataFormats/DetId/interface/DetId.h"
 
 #include <vector>
@@ -15,9 +18,8 @@ namespace tmtt {
    * Implements reduced bits to encode stub bend information: 3 bits for PS, 4 bits for 2S, since the Tracker
    * doesn't have the bandwidth to output the unreduced data from the FE electronics.
    *
-   * This obtains the stub window sizes from a hard-wired copy of L1Trigger/TrackTrigger/python/TTStubAlgorithmRegister_cfi.py .
-   * Whenever these window sizes are so large that not all bend values allowed within them with the available bits,
-   * then it automatically encodes the bend values within these windows.
+   * This obtains the stub window sizes from L1Trigger/TrackTrigger/python/TTStubAlgorithmRegister_cfi.py ,
+   * which must be loaded into the cfg file (with the same params used originally to make the stubs).
    * 
    * The TMTT L1 tracking code can optionally tighten these windows further (cfg option "KillLowPtStubs").  
    * This gives slightly more granular encoding with Pt > 3 GeV.
@@ -27,9 +29,10 @@ namespace tmtt {
    */
 
   public:
-    DegradeBend(const TrackerTopology* trackerTopo) : theTrackerTopo_(trackerTopo) {}
+    typedef TTStubAlgorithm_official<Ref_Phase2TrackerDigi_> StubAlgorithmOfficial;
 
-    DegradeBend() {}
+    DegradeBend(const TrackerTopology* trackerTopo, const StubFEWindows* sw, const StubAlgorithmOfficial* stubAlgo)
+        : theTrackerTopo_(trackerTopo), sw_(sw), stubAlgo_(stubAlgo) {}
 
     // Given the original bend, flag indicating if this is a PS or 2S module, & detector identifier,
     // this return the degraded stub bend, a boolean indicatng if stub bend was outside the assumed window
@@ -60,15 +63,11 @@ namespace tmtt {
   private:
     const TrackerTopology* theTrackerTopo_;
 
-    // Number of bits used to encoded bend output by FE electronics.
-    const unsigned int bitsPS_ = 3;
-    const unsigned int bits2S_ = 4;
-
     // Stub window sizes as encoded in L1Trigger/TrackTrigger/interface/TTStubAlgorithm_official.h
-    static const std::vector<double> barrelCut_;
-    static const std::vector<std::vector<double> > ringCut_;
-    static const std::vector<std::vector<double> > tiltedCut_;
-    static const std::vector<double> barrelNTilt_;
+    const StubFEWindows* sw_;
+
+    // TTStub produce algo used to make stubs.
+    const StubAlgorithmOfficial* stubAlgo_;
   };
 
 }  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/interface/DupFitTrkKiller.h b/L1Trigger/TrackFindingTMTT/interface/DupFitTrkKiller.h
index 5d003b712271c..6440753c8ef4a 100644
--- a/L1Trigger/TrackFindingTMTT/interface/DupFitTrkKiller.h
+++ b/L1Trigger/TrackFindingTMTT/interface/DupFitTrkKiller.h
@@ -18,6 +18,8 @@ namespace tmtt {
 
   class DupFitTrkKiller {
   public:
+    enum class DupAlgoName { None = 0, Algo1 = 1, Algo2 = 2 };
+
     /**
   *  Make available cfg parameters & specify which algorithm is to be used for duplicate track removal.
   */
@@ -50,7 +52,7 @@ namespace tmtt {
 
   private:
     const Settings* settings_;  // Configuration parameters.
-    unsigned int dupTrkAlg_;    // Specifies choice of algorithm for duplicate track removal.
+    DupAlgoName dupTrkAlg_;     // Specifies choice of algorithm for duplicate track removal.
   };
 
 }  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/interface/GlobalCacheTMTT.h b/L1Trigger/TrackFindingTMTT/interface/GlobalCacheTMTT.h
index f16b73492f4b3..65b394810c0bd 100644
--- a/L1Trigger/TrackFindingTMTT/interface/GlobalCacheTMTT.h
+++ b/L1Trigger/TrackFindingTMTT/interface/GlobalCacheTMTT.h
@@ -20,13 +20,13 @@ namespace tmtt {
 
   namespace {
     std::mutex myMutex;
-  }  
+  }
 
   class GlobalCacheTMTT {
   public:
     GlobalCacheTMTT(const edm::ParameterSet& iConfig)
         : settings_(iConfig),              // Python configuration params
-          htRphiErrMon_(),    // rphi HT error monitoring
+          htRphiErrMon_(),                 // rphi HT error monitoring
           stubWindowSuggest_(&settings_),  // Recommend FE stub window sizes.
           hists_(&settings_)               // Histograms
     {
@@ -46,7 +46,7 @@ namespace tmtt {
       std::lock_guard<std::mutex> myGuard(myMutex);
 
       // Only need one copy of tracker geometry for histogramming.
-      if (listTrackerModule_.size() == 0)
+      if (listTrackerModule_.empty())
         listTrackerModule_ = list;
     }
 
diff --git a/L1Trigger/TrackFindingTMTT/interface/HTrphi.h b/L1Trigger/TrackFindingTMTT/interface/HTrphi.h
index ee7bd894017ad..d5071afe680a6 100644
--- a/L1Trigger/TrackFindingTMTT/interface/HTrphi.h
+++ b/L1Trigger/TrackFindingTMTT/interface/HTrphi.h
@@ -46,7 +46,7 @@ namespace tmtt {
            float phiCentreSector,
            ErrorMonitor* errMon = nullptr);
 
-    ~HTrphi() {}
+    ~HTrphi() override {}
 
     // Add stub to HT array.
     // If eta subsectors are being used within each sector, specify which ones the stub is compatible with.
@@ -64,21 +64,21 @@ namespace tmtt {
     // Get the values of the track helix params corresponding to middle of a specified HT cell (i,j).
     // The helix parameters returned will be those corresponding to the two axes of the HT array.
     // So they might be (q/pt, phi0) or (q/pt, phi65) etc. depending on the configuration.
-    std::pair<float, float> helix2Dhough(unsigned int i, unsigned int j) const;
+    std::pair<float, float> helix2Dhough(unsigned int i, unsigned int j) const override;
 
     // Get the values of the track helix params corresponding to middle of a specified HT cell (i,j).
     // The helix parameters returned will be always be (q/pt, phi0), irrespective of how the axes
     // of the HT array are defined.
-    std::pair<float, float> helix2Dconventional(unsigned int i, unsigned int j) const;
+    std::pair<float, float> helix2Dconventional(unsigned int i, unsigned int j) const override;
 
     // Which cell in HT array should this TP be in, based on its true trajectory?
     // (If TP is outside HT array, it it put in the closest bin inside it).
-    std::pair<unsigned int, unsigned int> trueCell(const TP* tp) const;
+    std::pair<unsigned int, unsigned int> trueCell(const TP* tp) const override;
 
     // Which cell in HT array should this fitted track be in, based on its fitted trajectory?
     // Always uses beam-spot constrained trajectory if available.
     // (If fitted track is outside HT array, it it put in the closest bin inside it).
-    std::pair<unsigned int, unsigned int> cell(const L1fittedTrack* fitTrk) const;
+    std::pair<unsigned int, unsigned int> cell(const L1fittedTrack* fitTrk) const override;
 
     // Check if specified cell has been merged with its 2x2 neighbours into a single cell,
     // as it is in low Pt region.
@@ -104,17 +104,17 @@ namespace tmtt {
                              unsigned int jPhiTrkBinMinLast,
                              unsigned int jPhiTrkBinMaxLast);
 
-    // Calculate maximum |gradient| that any stub's line across this HT array could have, so can check it doesn't exceed 1.
-    float calcMaxLineGradArray() const;
+    // Calculate line |gradient| of stubs in HT array, so can check it doesn't exceed 1.
+    float calcLineGradArray(float r) const;
 
     // If requested, kill those tracks in this sector that can't be read out during the time-multiplexed period, because
     // the HT has associated too many stubs to tracks.
-    std::list<L1track2D> killTracksBusySec(const std::list<L1track2D>& tracks) const;
+    std::list<L1track2D> killTracksBusySec(const std::list<L1track2D>& tracks) const override;
 
     // Define the order in which the hardware processes rows of the HT array when it outputs track candidates.
     // Currently corresponds to highest Pt tracks first.
     // If two tracks have the same Pt, the -ve charge one is output before the +ve charge one.
-    std::vector<unsigned int> rowOrder(unsigned int numRows) const;
+    std::vector<unsigned int> rowOrder(unsigned int numRows) const override;
 
   private:
     float invPtToDphi_;  // conversion constant.
diff --git a/L1Trigger/TrackFindingTMTT/interface/InputData.h b/L1Trigger/TrackFindingTMTT/interface/InputData.h
index fbe7355fa0bea..789c059796171 100644
--- a/L1Trigger/TrackFindingTMTT/interface/InputData.h
+++ b/L1Trigger/TrackFindingTMTT/interface/InputData.h
@@ -13,6 +13,7 @@ namespace tmtt {
 
   class Settings;
   class StubWindowSuggest;
+  class DegradeBend;
 
   //=== Unpacks stub & tracking particle (truth) data into user-friendlier format in Stub & TP classes.
   //=== Also makes B-field available to Settings class.
@@ -23,6 +24,7 @@ namespace tmtt {
               const edm::EventSetup& iSetup,
               const Settings* settings,
               StubWindowSuggest* stubWindowSuggest,
+              const DegradeBend* degradeBend,
               const TrackerGeometry* trackerGeometry,
               const TrackerTopology* trackerTopology,
               const std::list<TrackerModule>& listTrackerModule,
@@ -63,6 +65,8 @@ namespace tmtt {
 
     // Recommends optimal FE stub window sizes.
     StubWindowSuggest* stubWindowSuggest_;
+    // Degrades bend to allow for FE stub bend encoding.
+    const DegradeBend* degradeBend_;
   };
 
 }  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/interface/KFParamsComb.h b/L1Trigger/TrackFindingTMTT/interface/KFParamsComb.h
index e7544f205f770..28bfdadda6aa1 100644
--- a/L1Trigger/TrackFindingTMTT/interface/KFParamsComb.h
+++ b/L1Trigger/TrackFindingTMTT/interface/KFParamsComb.h
@@ -5,6 +5,8 @@
 #include "L1Trigger/TrackFindingTMTT/interface/L1track3D.h"
 #include "TMatrixD.h"
 
+#include <vector>
+
 ///=== This is the Kalman Combinatorial Filter for 4 & 5 helix parameters track fit algorithm.
 ///=== All variable names & equations come from Fruhwirth KF paper
 ///=== http://dx.doi.org/10.1016/0168-9002%2887%2990887-4
@@ -13,35 +15,42 @@ namespace tmtt {
 
   class KFParamsComb : public KFbase {
   public:
-    KFParamsComb(const Settings* settings, const uint nPar, const std::string& fitterName)
-        : KFbase(settings, nPar, fitterName) {}
+    KFParamsComb(const Settings* settings, const uint nHelixPar, const std::string& fitterName);
 
-    virtual ~KFParamsComb() {}
+    ~KFParamsComb() override {}
 
   protected:
     //--- Input data
 
     // Seed track helix params & covariance matrix
-    virtual TVectorD seedX(const L1track3D& l1track3D) const;
-    virtual TMatrixD seedC(const L1track3D& l1track3D) const;
+    TVectorD seedX(const L1track3D& l1track3D) const override;
+    TMatrixD seedC(const L1track3D& l1track3D) const override;
 
     // Stub coordinate measurements & resolution
-    virtual TVectorD vectorM(const Stub* stub) const;
-    virtual TMatrixD matrixV(const Stub* stub, const KalmanState* state) const;
+    TVectorD vectorM(const Stub* stub) const override;
+    TMatrixD matrixV(const Stub* stub, const KalmanState* state) const override;
 
     //--- KF maths matrix multiplications
 
     // Derivate of helix intercept point w.r.t. helix params.
-    virtual TMatrixD matrixH(const Stub* stub) const;
+    TMatrixD matrixH(const Stub* stub) const override;
     // Kalman helix ref point extrapolation matrix
-    virtual TMatrixD matrixF(const Stub* stub, const KalmanState* state) const;
+    TMatrixD matrixF(const Stub* stub, const KalmanState* state) const override;
 
     // Convert to physical helix params instead of local ones used by KF
-    virtual TVectorD trackParams(const KalmanState* state) const;
-    virtual TVectorD trackParams_BeamConstr(const KalmanState* state, double& chi2rphi) const;
+    TVectorD trackParams(const KalmanState* state) const override;
+    TVectorD trackParams_BeamConstr(const KalmanState* state, double& chi2rphi) const override;
 
     // Does helix state pass cuts?
-    virtual bool isGoodState(const KalmanState& state) const;
+    bool isGoodState(const KalmanState& state) const override;
+
+  protected:
+    std::vector<double> kfLayerVsPtToler_;
+    std::vector<double> kfLayerVsD0Cut5_;
+    std::vector<double> kfLayerVsZ0Cut5_;
+    std::vector<double> kfLayerVsZ0Cut4_;
+    std::vector<double> kfLayerVsChiSq5_;
+    std::vector<double> kfLayerVsChiSq4_;
   };
 
 }  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/interface/KFbase.h b/L1Trigger/TrackFindingTMTT/interface/KFbase.h
index 57302237c8eec..8947a04149f9c 100644
--- a/L1Trigger/TrackFindingTMTT/interface/KFbase.h
+++ b/L1Trigger/TrackFindingTMTT/interface/KFbase.h
@@ -36,9 +36,9 @@ namespace tmtt {
 
   public:
     // Initialize configuration
-    KFbase(const Settings *settings, const uint nPar, const std::string &fitterName = "", const uint nMeas = 2);
+    KFbase(const Settings *settings, const uint nHelixPar, const std::string &fitterName = "", const uint nMeas = 2);
 
-    virtual ~KFbase() { this->resetStates(); }
+    ~KFbase() override { this->resetStates(); }
 
     KFbase(const KFbase &kf) = delete;  // Disable copy & move of this class.
     KFbase(KFbase &&kf) = delete;
@@ -46,7 +46,7 @@ namespace tmtt {
     KFbase &operator=(KFbase &&kf) = delete;
 
     // Do KF fit
-    L1fittedTrack fit(const L1track3D &l1track3D);
+    L1fittedTrack fit(const L1track3D &l1track3D) override;
 
   protected:
     // Do KF fit (internal)
@@ -84,7 +84,7 @@ namespace tmtt {
     // Derivate of helix intercept point w.r.t. helix params.
     virtual TMatrixD matrixH(const Stub *stub) const = 0;
     // Kalman helix ref point extrapolation matrix
-    virtual TMatrixD matrixF(const Stub *stub = 0, const KalmanState *state = 0) const = 0;
+    virtual TMatrixD matrixF(const Stub *stub = nullptr, const KalmanState *state = nullptr) const = 0;
     // Product of H*C*H(transpose) (where C = helix covariance matrix)
     TMatrixD matrixHCHt(const TMatrixD &h, const TMatrixD &c) const;
     // Get inverted Kalman R matrix: inverse(V + HCHt)
@@ -150,7 +150,7 @@ namespace tmtt {
     void printStubs(const std::vector<Stub *> &stubs) const;
 
   protected:
-    unsigned nPar_;
+    unsigned nHelixPar_;
     unsigned nMeas_;
     unsigned numEtaRegions_;
 
diff --git a/L1Trigger/TrackFindingTMTT/interface/KalmanState.h b/L1Trigger/TrackFindingTMTT/interface/KalmanState.h
index ced792b5a0702..7e1674c485b2c 100644
--- a/L1Trigger/TrackFindingTMTT/interface/KalmanState.h
+++ b/L1Trigger/TrackFindingTMTT/interface/KalmanState.h
@@ -81,10 +81,6 @@ namespace tmtt {
       chi2rz_ = chi2rz;
     }
 
-    // If using HLS, note/get additional output produced by HLS core.
-    //void setHLSselect(unsigned int mBinHelix, unsigned int cBinHelix, bool consistent) { mBinHelixHLS_ = mBinHelix; cBinHelixHLS_ = cBinHelix; consistentHLS_ = consistent;}
-    //void getHLSselect(unsigned int& mBinHelix, unsigned int& cBinHelix, bool& consistent) const { mBinHelix = mBinHelixHLS_; cBinHelix = cBinHelixHLS_; consistent = consistentHLS_;}
-
   private:
     const Settings *settings_;
     int kLayer_;
@@ -104,11 +100,6 @@ namespace tmtt {
     unsigned nSkipped_;
     L1track3D l1track3D_;
     unsigned int hitPattern_;
-
-    // Additional output from HLS if using it.
-    unsigned int mBinHelixHLS_;
-    unsigned int cBinHelixHLS_;
-    bool consistentHLS_;
   };
 
 }  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/interface/L1fittedTrack.h b/L1Trigger/TrackFindingTMTT/interface/L1fittedTrack.h
index c10253f993d92..53edc8a36b0bf 100644
--- a/L1Trigger/TrackFindingTMTT/interface/L1fittedTrack.h
+++ b/L1Trigger/TrackFindingTMTT/interface/L1fittedTrack.h
@@ -108,7 +108,7 @@ namespace tmtt {
     // Creates track rejected by fitter.
     L1fittedTrack() : L1fittedTrack(nullptr, nullptr, noStubs_, 0, 0., 0., 0., 0., 0., 0., 0., 0, false) {}
 
-    ~L1fittedTrack() {}
+    ~L1fittedTrack() override {}
 
     //--- Optionally std::set track helix params & chi2 if beam-spot constraint is used (for 5-parameter fit).
     void setBeamConstr(float qOverPt_bcon, float phi0_bcon, float chi2rphi_bcon) {
@@ -125,10 +125,6 @@ namespace tmtt {
       nSkippedLayers_ = nSkippedLayers;
       numUpdateCalls_ = numUpdateCalls;
     }
-    void setInfoKF(unsigned int nSkippedLayers, unsigned int numUpdateCalls, bool consistentHLS) {
-      this->setInfoKF(nSkippedLayers_, numUpdateCalls_);
-      // consistentCell_ = consistentHLS; // KF HLS code no longer calculates HT cell consistency.
-    }
     void setInfoLR(int numIterations, std::string lostMatchingState, std::unordered_map<std::string, int> stateCalls) {
       numIterations_ = numIterations;
       lostMatchingState_ = lostMatchingState;
@@ -176,12 +172,12 @@ namespace tmtt {
     const L1track3D* l1track3D() const { return l1track3D_; }
 
     // Get stubs on fitted track (can differ from those on HT track if track fit kicked out stubs with bad residuals)
-    const std::vector<const Stub*>& stubsConst() const { return stubsConst_; }
-    const std::vector<Stub*>& stubs() const { return stubs_; }
+    const std::vector<const Stub*>& stubsConst() const override { return stubsConst_; }
+    const std::vector<Stub*>& stubs() const override { return stubs_; }
     // Get number of stubs on fitted track.
-    unsigned int numStubs() const { return stubs_.size(); }
+    unsigned int numStubs() const override { return stubs_.size(); }
     // Get number of tracker layers these stubs are in.
-    unsigned int numLayers() const { return nLayers_; }
+    unsigned int numLayers() const override { return nLayers_; }
     // Get number of stubs deleted from track candidate by fitter (because they had large residuals)
     unsigned int numKilledStubs() const { return l1track3D_->numStubs() - this->numStubs(); }
     // Get bit-encoded hit pattern (where layer number assigned by increasing distance from origin, according to layers track expected to cross).
@@ -192,19 +188,19 @@ namespace tmtt {
     // (If fitted track is outside HT array, it it put in the closest bin inside it).
     std::pair<unsigned int, unsigned int> cellLocationFit() const { return htRphiTmp_->cell(this); }
     // Also get HT cell determined by Hough transform.
-    std::pair<unsigned int, unsigned int> cellLocationHT() const { return l1track3D_->cellLocationHT(); }
+    std::pair<unsigned int, unsigned int> cellLocationHT() const override { return l1track3D_->cellLocationHT(); }
 
     //--- Get information about its association (if any) to a truth Tracking Particle.
     //--- Can differ from that of corresponding HT track, if track fit kicked out stubs with bad residuals.
 
     // Get best matching tracking particle (=nullptr if none).
-    const TP* matchedTP() const { return matchedTP_; }
+    const TP* matchedTP() const override { return matchedTP_; }
     // Get the matched stubs with this Tracking Particle
-    const std::vector<const Stub*>& matchedStubs() const { return matchedStubs_; }
+    const std::vector<const Stub*>& matchedStubs() const override { return matchedStubs_; }
     // Get number of matched stubs with this Tracking Particle
-    unsigned int numMatchedStubs() const { return matchedStubs_.size(); }
+    unsigned int numMatchedStubs() const override { return matchedStubs_.size(); }
     // Get number of tracker layers with matched stubs with this Tracking Particle
-    unsigned int numMatchedLayers() const { return nMatchedLayers_; }
+    unsigned int numMatchedLayers() const override { return nMatchedLayers_; }
     // Get purity of stubs on track (i.e. fraction matching best Tracking Particle)
     float purity() const { return numMatchedStubs() / float(numStubs()); }
     // Get number of stubs matched to correct TP that were deleted from track candidate by fitter.
@@ -223,7 +219,7 @@ namespace tmtt {
 
     //--- Get the fitted track helix parameters.
 
-    float qOverPt() const { return qOverPt_; }
+    float qOverPt() const override { return qOverPt_; }
     float charge() const { return (qOverPt_ > 0 ? 1 : -1); }
     float invPt() const { return std::abs(qOverPt_); }
     // Protect pt against 1/pt = 0.
@@ -232,7 +228,7 @@ namespace tmtt {
       return 1. / (small + this->invPt());
     }
     float d0() const { return d0_; }
-    float phi0() const { return phi0_; }
+    float phi0() const override { return phi0_; }
     float z0() const { return z0_; }
     float tanLambda() const { return tanLambda_; }
     float theta() const { return atan2(1., tanLambda_); }  // Use atan2 to ensure 0 < theta < pi.
@@ -290,11 +286,11 @@ namespace tmtt {
     float chi2dof_bcon() const { return (this->chi2_bcon()) / this->numDOF_bcon(); }
 
     //--- Get phi sector and eta region used by track finding code that this track is in.
-    unsigned int iPhiSec() const { return iPhiSec_; }
-    unsigned int iEtaReg() const { return iEtaReg_; }
+    unsigned int iPhiSec() const override { return iPhiSec_; }
+    unsigned int iEtaReg() const override { return iEtaReg_; }
 
     //--- Opto-link ID used to send this track from HT to Track Fitter
-    unsigned int optoLinkID() const { return optoLinkID_; }
+    unsigned int optoLinkID() const override { return optoLinkID_; }
 
     //--- Get whether the track has been rejected or accepted by the fit
 
diff --git a/L1Trigger/TrackFindingTMTT/interface/L1track2D.h b/L1Trigger/TrackFindingTMTT/interface/L1track2D.h
index 273e6ee671c6d..8e9cd1c26f2dd 100644
--- a/L1Trigger/TrackFindingTMTT/interface/L1track2D.h
+++ b/L1Trigger/TrackFindingTMTT/interface/L1track2D.h
@@ -50,27 +50,27 @@ namespace tmtt {
 
     L1track2D() : L1trackBase(){};  // Creates track object, but doesn't std::set any variables.
 
-    ~L1track2D() {}
+    ~L1track2D() override {}
 
     //--- Get information about the reconstructed track.
 
     // Get stubs on track candidate.
-    const std::vector<const Stub*>& stubsConst() const { return stubsConst_; }
-    const std::vector<Stub*>& stubs() const { return stubs_; }
+    const std::vector<const Stub*>& stubsConst() const override { return stubsConst_; }
+    const std::vector<Stub*>& stubs() const override { return stubs_; }
     // Get number of stubs on track candidate.
-    unsigned int numStubs() const { return stubs_.size(); }
+    unsigned int numStubs() const override { return stubs_.size(); }
     // Get number of tracker layers these stubs are in.
-    unsigned int numLayers() const { return nLayers_; }
+    unsigned int numLayers() const override { return nLayers_; }
     // Get cell location of track candidate in Hough Transform array in units of bin number.
-    std::pair<unsigned int, unsigned int> cellLocationHT() const { return cellLocationHT_; }
+    std::pair<unsigned int, unsigned int> cellLocationHT() const override { return cellLocationHT_; }
     // The two conventionally agreed track helix parameters relevant in this 2D plane.
     // i.e. (q/Pt, phi0).
     std::pair<float, float> helix2D() const { return helix2D_; }
 
     //--- User-friendlier access to the helix parameters obtained from track location inside HT array.
 
-    float qOverPt() const { return helix2D_.first; }
-    float phi0() const { return helix2D_.second; }
+    float qOverPt() const override { return helix2D_.first; }
+    float phi0() const override { return helix2D_.second; }
 
     //--- In the case of tracks found by the r-phi HT, a rough estimate of the (z0, tan_lambda) may be provided by any r-z
     //--- track filter run after the r-phi HT. These two functions give std::set/get access to these.
@@ -89,11 +89,11 @@ namespace tmtt {
     }
 
     //--- Get phi sector and eta region used by track finding code that this track is in.
-    unsigned int iPhiSec() const { return iPhiSec_; }
-    unsigned int iEtaReg() const { return iEtaReg_; }
+    unsigned int iPhiSec() const override { return iPhiSec_; }
+    unsigned int iEtaReg() const override { return iEtaReg_; }
 
     //--- Opto-link ID used to send this track from HT to Track Fitter. Both read & write functions.
-    unsigned int optoLinkID() const { return optoLinkID_; }
+    unsigned int optoLinkID() const override { return optoLinkID_; }
     void setOptoLinkID(unsigned int linkID) { optoLinkID_ = linkID; }
 
     //--- Was this track produced from a marged HT cell (e.g. 2x2)?
@@ -102,13 +102,13 @@ namespace tmtt {
     //--- Get information about its association (if any) to a truth Tracking Particle.
 
     // Get matching tracking particle (=nullptr if none).
-    const TP* matchedTP() const { return matchedTP_; }
+    const TP* matchedTP() const override { return matchedTP_; }
     // Get the matched stubs.
-    const std::vector<const Stub*>& matchedStubs() const { return matchedStubs_; }
+    const std::vector<const Stub*>& matchedStubs() const override { return matchedStubs_; }
     // Get number of matched stubs.
-    unsigned int numMatchedStubs() const { return matchedStubs_.size(); }
+    unsigned int numMatchedStubs() const override { return matchedStubs_.size(); }
     // Get number of tracker layers with matched stubs.
-    unsigned int numMatchedLayers() const { return nMatchedLayers_; }
+    unsigned int numMatchedLayers() const override { return nMatchedLayers_; }
 
   private:
     //--- Configuration parameters
diff --git a/L1Trigger/TrackFindingTMTT/interface/L1track3D.h b/L1Trigger/TrackFindingTMTT/interface/L1track3D.h
index 25cfa52a64aea..e4e192d258063 100644
--- a/L1Trigger/TrackFindingTMTT/interface/L1track3D.h
+++ b/L1Trigger/TrackFindingTMTT/interface/L1track3D.h
@@ -74,7 +74,7 @@ namespace tmtt {
 
     L1track3D() : L1trackBase(){};  // Creates track object, but doesn't std::set any variables.
 
-    ~L1track3D() {}
+    ~L1track3D() override {}
 
     //--- Set/get optional info for tracklet tracks.
 
@@ -93,14 +93,14 @@ namespace tmtt {
     //--- Get information about the reconstructed track.
 
     // Get stubs on track candidate.
-    const std::vector<const Stub*>& stubsConst() const { return stubsConst_; }
-    const std::vector<Stub*>& stubs() const { return stubs_; }
+    const std::vector<const Stub*>& stubsConst() const override { return stubsConst_; }
+    const std::vector<Stub*>& stubs() const override { return stubs_; }
     // Get number of stubs on track candidate.
-    unsigned int numStubs() const { return stubs_.size(); }
+    unsigned int numStubs() const override { return stubs_.size(); }
     // Get number of tracker layers these stubs are in.
-    unsigned int numLayers() const { return nLayers_; }
+    unsigned int numLayers() const override { return nLayers_; }
     // Get cell location of track candidate in r-phi Hough Transform array in units of bin number.
-    std::pair<unsigned int, unsigned int> cellLocationHT() const { return cellLocationHT_; }
+    std::pair<unsigned int, unsigned int> cellLocationHT() const override { return cellLocationHT_; }
     // The two conventionally agreed track helix parameters relevant in r-phi plane. i.e. (q/Pt, phi0)
     std::pair<float, float> helixRphi() const { return helixRphi_; }
     // The two conventionally agreed track helix parameters relevant in r-z plane. i.e. (z0, tan_lambda)
@@ -148,7 +148,7 @@ namespace tmtt {
 
     //--- User-friendlier access to the helix parameters.
 
-    float qOverPt() const { return helixRphi_.first; }
+    float qOverPt() const override { return helixRphi_.first; }
     float charge() const { return (this->qOverPt() > 0 ? 1 : -1); }
     float invPt() const { return std::abs(this->qOverPt()); }
     // Protect pt against 1/pt = 0.
@@ -157,7 +157,7 @@ namespace tmtt {
       return 1. / (small + this->invPt());
     }
     float d0() const { return helixD0_; }  // Hough transform assumes d0 = 0.
-    float phi0() const { return helixRphi_.second; }
+    float phi0() const override { return helixRphi_.second; }
     float z0() const { return helixRz_.first; }
     float tanLambda() const { return helixRz_.second; }
     float theta() const { return atan2(1., this->tanLambda()); }  // Use atan2 to ensure 0 < theta < pi.
@@ -173,11 +173,11 @@ namespace tmtt {
     }  // neglects transverse impact parameter & track curvature.
 
     //--- Get phi sector and eta region used by track finding code that this track is in.
-    unsigned int iPhiSec() const { return iPhiSec_; }
-    unsigned int iEtaReg() const { return iEtaReg_; }
+    unsigned int iPhiSec() const override { return iPhiSec_; }
+    unsigned int iEtaReg() const override { return iEtaReg_; }
 
     //--- Opto-link ID used to send this track from HT to Track Fitter
-    unsigned int optoLinkID() const { return optoLinkID_; }
+    unsigned int optoLinkID() const override { return optoLinkID_; }
 
     //--- Was this track produced from a marged HT cell (e.g. 2x2)?
     bool mergedHTcell() const { return mergedHTcell_; }
@@ -185,13 +185,13 @@ namespace tmtt {
     //--- Get information about its association (if any) to a truth Tracking Particle.
 
     // Get best matching tracking particle (=nullptr if none).
-    const TP* matchedTP() const { return matchedTP_; }
+    const TP* matchedTP() const override { return matchedTP_; }
     // Get the matched stubs with this Tracking Particle
-    const std::vector<const Stub*>& matchedStubs() const { return matchedStubs_; }
+    const std::vector<const Stub*>& matchedStubs() const override { return matchedStubs_; }
     // Get number of matched stubs with this Tracking Particle
-    unsigned int numMatchedStubs() const { return matchedStubs_.size(); }
+    unsigned int numMatchedStubs() const override { return matchedStubs_.size(); }
     // Get number of tracker layers with matched stubs with this Tracking Particle
-    unsigned int numMatchedLayers() const { return nMatchedLayers_; }
+    unsigned int numMatchedLayers() const override { return nMatchedLayers_; }
     // Get purity of stubs on track candidate (i.e. fraction matching best Tracking Particle)
     float purity() const { return numMatchedStubs() / float(numStubs()); }
 
diff --git a/L1Trigger/TrackFindingTMTT/interface/MiniHTstage.h b/L1Trigger/TrackFindingTMTT/interface/MiniHTstage.h
index f6396fe7da8f6..fce848dd28812 100644
--- a/L1Trigger/TrackFindingTMTT/interface/MiniHTstage.h
+++ b/L1Trigger/TrackFindingTMTT/interface/MiniHTstage.h
@@ -2,6 +2,7 @@
 #define L1Trigger_TrackFindingTMTT_MiniHTstage_h
 
 #include "L1Trigger/TrackFindingTMTT/interface/HTrphi.h"
+#include "L1Trigger/TrackFindingTMTT/interface/MuxHToutputs.h"
 
 using boost::numeric::ublas::matrix;
 #include <memory>
@@ -32,7 +33,7 @@ namespace tmtt {
   private:
     const Settings* settings_;  // Configuration parameters
     bool miniHTstage_;
-    unsigned int muxOutputsHT_;
+    MuxHToutputs::MuxAlgoName muxOutputsHT_;
     unsigned int houghNbinsPt_;
     unsigned int houghNbinsPhi_;
     unsigned int miniHoughLoadBalance_;
diff --git a/L1Trigger/TrackFindingTMTT/interface/MuxHToutputs.h b/L1Trigger/TrackFindingTMTT/interface/MuxHToutputs.h
index 707d0b124521d..db1444f97d4aa 100644
--- a/L1Trigger/TrackFindingTMTT/interface/MuxHToutputs.h
+++ b/L1Trigger/TrackFindingTMTT/interface/MuxHToutputs.h
@@ -28,6 +28,8 @@ namespace tmtt {
 
   class MuxHToutputs {
   public:
+    enum class MuxAlgoName { None = 0, mBinPerLink = 1 };
+
     // Initialize constants from configuration parameters.
     MuxHToutputs(const Settings* settings);
 
@@ -61,7 +63,7 @@ namespace tmtt {
     const Settings* settings_;  // Configuration parameters
 
     // Configuration parameters
-    unsigned int muxOutputsHT_;
+    MuxAlgoName muxOutputsHT_;
     unsigned int numPhiNonants_;
     unsigned int numPhiSectors_;
     unsigned int numPhiSecPerNon_;
diff --git a/L1Trigger/TrackFindingTMTT/interface/Settings.h b/L1Trigger/TrackFindingTMTT/interface/Settings.h
index 0d7921809957f..73613e481374c 100644
--- a/L1Trigger/TrackFindingTMTT/interface/Settings.h
+++ b/L1Trigger/TrackFindingTMTT/interface/Settings.h
@@ -5,6 +5,7 @@
 #include "FWCore/Utilities/interface/InputTag.h"
 #include "FWCore/Utilities/interface/ESInputTag.h"
 #include "FWCore/Utilities/interface/Exception.h"
+#include "CLHEP/Units/PhysicalConstants.h"
 #include <vector>
 #include <iostream>
 #include <atomic>
@@ -27,6 +28,8 @@ namespace tmtt {
     edm::ESInputTag magneticFieldInputTag() const { return magneticFieldInputTag_; }
     edm::ESInputTag trackerGeometryInputTag() const { return trackerGeometryInputTag_; }
     edm::ESInputTag trackerTopologyInputTag() const { return trackerTopologyInputTag_; }
+    edm::ESInputTag ttStubAlgoInputTag() const { return ttStubAlgoInputTag_; }
+
     edm::InputTag stubInputTag() const { return stubInputTag_; }
     edm::InputTag tpInputTag() const { return tpInputTag_; }
     edm::InputTag stubTruthInputTag() const { return stubTruthInputTag_; }
@@ -307,6 +310,14 @@ namespace tmtt {
     unsigned int kalmanMaxSkipLayersEasy() const { return kalmanMaxSkipLayersEasy_; }
     // Max #stubs an input track can have to be defined "easy".
     unsigned int kalmanMaxStubsEasy() const { return kalmanMaxStubsEasy_; }
+    // Cuts applied to KF states as a function of the last KF tracker layer they had a stub in.
+    // (If "4" or "5" in name, cut only applies to 4 or 5 param helix fit).
+    const std::vector<double>& kfLayerVsPtToler() const { return kfLayerVsPtToler_; }
+    const std::vector<double>& kfLayerVsD0Cut5() const { return kfLayerVsD0Cut5_; }
+    const std::vector<double>& kfLayerVsZ0Cut5() const { return kfLayerVsZ0Cut5_; }
+    const std::vector<double>& kfLayerVsZ0Cut4() const { return kfLayerVsZ0Cut4_; }
+    const std::vector<double>& kfLayerVsChiSq5() const { return kfLayerVsChiSq5_; }
+    const std::vector<double>& kfLayerVsChiSq4() const { return kfLayerVsChiSq4_; }
     // KF will consider only this no. of stubs per layer.
     unsigned int kalmanMaxStubsPerLayer() const { return kalmanMaxStubsPerLayer_; }
     // Multiple scattering term - inflate hit phi errors by this divided by Pt
@@ -379,17 +390,11 @@ namespace tmtt {
 
     //=== Hard-wired constants
 
-    double cSpeed() const { return 2.99792458e10; }  // Speed of light (cm/s)
-    double invPtToInvR() const {
-      return (this->magneticField()) * (this->cSpeed()) / 1.0E13;
-    }  // B*c/1E11 - converts q/Pt to 1/radius_of_curvature
-    double invPtToDphi() const {
-      return (this->magneticField()) * (this->cSpeed()) / 2.0E13;
-    }  // B*c/2E11 - converts q/Pt to track angle at some radius from beamline.
-    double trackerOuterRadius() const { return 112.7; }  // max. occuring stub radius.
-    double trackerInnerRadius() const { return 21.8; }   // min. occuring stub radius.
-    double trackerHalfLength() const { return 270.; }    // half-length of tracker.
-
+    double cSpeed() const { return 1.0e8 * CLHEP::c_light; }  // Speed of light, with (mm/ns) to (cm/s)
+    // B*c/1E11 - converts q/Pt to 1/radius_of_curvature
+    double invPtToInvR() const { return (this->magneticField()) * (this->cSpeed()) / 1.0E13; }
+    // B*c/2E11 - converts q/Pt to track angle at some radius from beamline.
+    double invPtToDphi() const { return (this->magneticField()) * (this->cSpeed()) / 2.0E13; }
     //=== Set and get B-field value (mutable) in Tesla.
     // N.B. This must bet std::set for each run, and can't be initialized at the beginning of the job.
     void setMagneticField(float magneticField) const { magneticField_ = magneticField; }
@@ -408,6 +413,8 @@ namespace tmtt {
     const edm::ESInputTag magneticFieldInputTag_;
     const edm::ESInputTag trackerGeometryInputTag_;
     const edm::ESInputTag trackerTopologyInputTag_;
+    const edm::ESInputTag ttStubAlgoInputTag_;
+
     const edm::InputTag stubInputTag_;
     const edm::InputTag tpInputTag_;
     const edm::InputTag stubTruthInputTag_;
@@ -588,6 +595,14 @@ namespace tmtt {
     unsigned int kalmanMaxSkipLayersHard_;
     unsigned int kalmanMaxSkipLayersEasy_;
     unsigned int kalmanMaxStubsEasy_;
+
+    std::vector<double> kfLayerVsPtToler_;
+    std::vector<double> kfLayerVsD0Cut5_;
+    std::vector<double> kfLayerVsZ0Cut5_;
+    std::vector<double> kfLayerVsZ0Cut4_;
+    std::vector<double> kfLayerVsChiSq5_;
+    std::vector<double> kfLayerVsChiSq4_;
+
     unsigned int kalmanMaxStubsPerLayer_;
     double kalmanMultiScattTerm_;
     unsigned int kalmanChi2RphiScale_;
diff --git a/L1Trigger/TrackFindingTMTT/interface/SimpleLR4.h b/L1Trigger/TrackFindingTMTT/interface/SimpleLR4.h
index 90bf7ef9f766e..fa77536aa8e59 100644
--- a/L1Trigger/TrackFindingTMTT/interface/SimpleLR4.h
+++ b/L1Trigger/TrackFindingTMTT/interface/SimpleLR4.h
@@ -21,9 +21,9 @@ namespace tmtt {
   public:
     SimpleLR4(const Settings* settings);
 
-    virtual ~SimpleLR4(){};
+    ~SimpleLR4() override{};
 
-    L1fittedTrack fit(const L1track3D& l1track3D);
+    L1fittedTrack fit(const L1track3D& l1track3D) override;
 
   protected:
     bool debug_;
diff --git a/L1Trigger/TrackFindingTMTT/interface/Stub.h b/L1Trigger/TrackFindingTMTT/interface/Stub.h
index 4e73299917589..a78b3ff564091 100644
--- a/L1Trigger/TrackFindingTMTT/interface/Stub.h
+++ b/L1Trigger/TrackFindingTMTT/interface/Stub.h
@@ -14,7 +14,6 @@
 #include "L1Trigger/TrackFindingTMTT/interface/DigitalStub.h"
 #include "L1Trigger/TrackFindingTMTT/interface/DegradeBend.h"
 #include "L1Trigger/TrackFindingTMTT/interface/TrackerModule.h"
-#include "L1Trigger/TrackFindingTMTT/interface/StubKiller.h"
 
 #include <vector>
 #include <set>
@@ -28,6 +27,8 @@ class TrackerTopology;
 namespace tmtt {
 
   class TP;
+  class DegradeBend;
+  class StubKiller;
 
   typedef edmNew::DetSetVector<TTStub<Ref_Phase2TrackerDigi_> > TTStubDetSetVec;
   typedef edmNew::DetSet<TTStub<Ref_Phase2TrackerDigi_> > TTStubDetSet;
@@ -43,28 +44,29 @@ namespace tmtt {
   public:
     // Hybrid L1 tracking: stub constructor.
     Stub(const Settings* settings,
-             unsigned int idStub,
-	     double phi,
-             double r,
-             double z,
-             double bend,
-             unsigned int iphi,
-             double alpha,
-             unsigned int layerId,
-             unsigned int iPhiSec,
-             bool psModule,
-    	     bool barrel,
-    	     bool tiltedBarrel,
-	     float stripPitch,
-	     float stripLength,
-	     unsigned int nStrips);
- 
+         unsigned int idStub,
+         double phi,
+         double r,
+         double z,
+         double bend,
+         unsigned int iphi,
+         double alpha,
+         unsigned int layerId,
+         unsigned int iPhiSec,
+         bool psModule,
+         bool barrel,
+         bool tiltedBarrel,
+         float stripPitch,
+         float stripLength,
+         unsigned int nStrips);
+
     // TMTT L1 tracking: stub constructor.
     Stub(const TTStubRef& ttStubRef,
          unsigned int index_in_vStubs,
          const Settings* settings,
          const TrackerTopology* trackerTopology,
          const TrackerModule* trackerModule,
+         const DegradeBend* degradeBend,
          const StubKiller* stubKiller);
 
     ~Stub() {}
@@ -164,7 +166,7 @@ namespace tmtt {
     const std::set<const TP*>& assocTPs() const {
       return assocTPs_;
     }  // Return TPs associated to this stub. (Whether only TPs contributing to both clusters are returned is determined by "StubMatchStrict" config param.)
-    bool genuine() const { return (assocTPs_.size() > 0); }  // Did stub match at least one TP?
+    bool genuine() const { return (not assocTPs_.empty()); }  // Did stub match at least one TP?
     const TP* assocTP() const {
       return assocTP_;
     }  // If only one TP contributed to both clusters, this tells you which TP it is. Returns nullptr if none.
@@ -186,9 +188,9 @@ namespace tmtt {
     float sigmaR() const { return (barrel() ? 0. : sigmaPar()); }
     float sigmaZ() const { return (barrel() ? sigmaPar() : 0.); }
     // Hit resolution perpendicular to strip. Measures phi.
-    float sigmaPerp() const {return invRoot12 * stripPitch_;}
+    float sigmaPerp() const { return invRoot12 * stripPitch_; }
     // Hit resolution parallel to strip. Measures r or z.
-    float sigmaPar() const {return invRoot12 * stripLength_;}
+    float sigmaPar() const { return invRoot12 * stripLength_; }
 
     //--- These module variables could be taken directly from trackerModule_, were it not for need
     //--- to support Hybrid.
@@ -274,7 +276,7 @@ namespace tmtt {
     const TrackerModule* trackerModule_;
 
     // Used to degrade stub bend information.
-    DegradeBend degradeBend_;
+    const DegradeBend* degradeBend_;
 
     // These module variables are needed only to support the Hybrid stub constructor.
     // (Otherwise, they could be taken from trackerModule_).
@@ -290,7 +292,7 @@ namespace tmtt {
 
     const float rejectedStubBend_ = 99999.;  // Bend set to this if stub rejected.
 
-    const float invRoot12 = sqrt(1./12.);
+    const float invRoot12 = sqrt(1. / 12.);
   };
 
 }  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/interface/StubFEWindows.h b/L1Trigger/TrackFindingTMTT/interface/StubFEWindows.h
new file mode 100644
index 0000000000000..e07170e35c17b
--- /dev/null
+++ b/L1Trigger/TrackFindingTMTT/interface/StubFEWindows.h
@@ -0,0 +1,53 @@
+#ifndef L1Trigger_TrackFindingTMTT_StubFEWindows_h
+#define L1Trigger_TrackFindingTMTT_StubFEWindows_h
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "DataFormats/DetId/interface/DetId.h"
+
+#include <vector>
+
+// Window sizes used by FE electronics to select stubs.
+
+class TrackerTopology;
+
+namespace tmtt {
+
+  class StubFEWindows {
+  public:
+    StubFEWindows(){};
+    // Initialize stub window sizes from TTStubProducer cfg.
+    StubFEWindows(const edm::ParameterSet& pSetStubAlgo);
+
+    // Set all FE stub bend windows to zero.
+    void setZero();
+
+    // Access window size arrays (const functions).
+    const std::vector<double>& windowSizeBarrelLayers() const { return windowSizeBarrelLayers_; }
+    const std::vector<std::vector<double> >& windowSizeEndcapDisksRings() const { return windowSizeEndcapDisksRings_; }
+    const std::vector<std::vector<double> >& windowSizeTiltedLayersRings() const {
+      return windowSizeTiltedLayersRings_;
+    }
+
+    // Access window size arrays (non-const functions).
+    std::vector<double>& windowSizeBarrelLayers() { return windowSizeBarrelLayers_; }
+    std::vector<std::vector<double> >& windowSizeEndcapDisksRings() { return windowSizeEndcapDisksRings_; }
+    std::vector<std::vector<double> >& windowSizeTiltedLayersRings() { return windowSizeTiltedLayersRings_; }
+
+    // Number of tilted barrel modules each half of each PS barrel layer.
+    const std::vector<double>& numTiltedLayerRings() const { return numTiltedLayerRings_; }
+
+    // Const/non-const access to element of array giving window size for specific module.
+    const double* storedWindowSize(const TrackerTopology* trackerTopo, const DetId& detId) const;
+    double* storedWindowSize(const TrackerTopology* trackerTopo, const DetId& detId);
+
+  private:
+    // Stub window sizes as encoded in L1Trigger/TrackTrigger/interface/TTStubAlgorithm_official.h
+    std::vector<double> windowSizeBarrelLayers_;
+    std::vector<std::vector<double> > windowSizeEndcapDisksRings_;
+    std::vector<std::vector<double> > windowSizeTiltedLayersRings_;
+    std::vector<double> numTiltedLayerRings_;
+  };
+
+}  // namespace tmtt
+
+#endif
diff --git a/L1Trigger/TrackFindingTMTT/interface/StubWindowSuggest.h b/L1Trigger/TrackFindingTMTT/interface/StubWindowSuggest.h
index 1558c8bba1052..4fc9e7272cb04 100644
--- a/L1Trigger/TrackFindingTMTT/interface/StubWindowSuggest.h
+++ b/L1Trigger/TrackFindingTMTT/interface/StubWindowSuggest.h
@@ -2,6 +2,7 @@
 #define L1Trigger_TrackFindingTMTT_StubWindowsSuggest_h
 
 #include "L1Trigger/TrackFindingTMTT/interface/Settings.h"
+#include "L1Trigger/TrackFindingTMTT/interface/StubFEWindows.h"
 
 #include <vector>
 
@@ -25,11 +26,17 @@ namespace tmtt {
 
   class StubWindowSuggest {
   public:
-    // Initialize (for use with TMTT).
+    // Configure
     StubWindowSuggest(const Settings* settings) : settings_(settings), ptMin_(settings->houghMinPt()) {}
 
     ~StubWindowSuggest() {}
 
+    // Get FE window size arrays (via copy) used with stub producer, but set to zero.
+    void setFEWindows(const StubFEWindows* sw) {
+      sw_ = *sw;
+      sw_.setZero();
+    }
+
     // Analyse stub window required for this stub.
     void process(const TrackerTopology* trackerTopo, const Stub* stub);
 
@@ -46,10 +53,7 @@ namespace tmtt {
     const float ptMin_;
 
     // Stub window sizes as encoded in L1Trigger/TrackTrigger/interface/TTStubAlgorithm_official.h
-    std::vector<double> barrelCut_;
-    std::vector<std::vector<double> > ringCut_;
-    std::vector<std::vector<double> > tiltedCut_;
-    std::vector<double> barrelNTilt_;
+    StubFEWindows sw_;
   };
 
 }  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h b/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h
index e676315d2fa27..c386e8d2998dc 100644
--- a/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h
+++ b/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h
@@ -83,9 +83,9 @@ namespace tmtt {
     // Strip length (or pixel pitch along longest axis).
     float stripLength() const { return stripLength_; }
     // Hit resolution perpendicular to strip (or to longest pixel axis). Measures phi.
-    float sigmaPerp() const {return invRoot12 * stripPitch_;}
+    float sigmaPerp() const { return invRoot12 * stripPitch_; }
     // Hit resolution parallel to strip (or to longest pixel axis). Measures r or z.
-    float sigmaPar() const {return invRoot12 * stripLength_;}
+    float sigmaPar() const { return invRoot12 * stripLength_; }
     // Sensor pitch over separation.
     float pitchOverSep() const { return stripPitch_ / sensorSpacing_; }
     // "B" parameter correction for module tilt.
@@ -129,7 +129,7 @@ namespace tmtt {
 
     ModuleTypeCfg moduleTypeCfg_;
 
-    float invRoot12 = sqrt(1./12.);
+    static const float invRoot12;
   };
 
 }  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.cc b/L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.cc
index 99844bf539b82..76b30f009196c 100644
--- a/L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.cc
+++ b/L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.cc
@@ -38,11 +38,11 @@ namespace tmtt {
   }
 
   TMTrackProducer::TMTrackProducer(const edm::ParameterSet& iConfig, GlobalCacheTMTT const* globalCacheTMTT)
-      : debug_(true),                                             // Debug printout
-        settings_(iConfig),                                       // Set configuration parameters
-        hists_(globalCacheTMTT->hists()),                         // Initialize histograms
-        htRphiErrMon_(globalCacheTMTT->htRphiErrMon()),           // rphi HT error monitoring
-        stubWindowSuggest_(globalCacheTMTT->stubWindowSuggest())  // For tuning FE stub window sizes
+      : debug_(true),                                              // Debug printout
+        settings_(iConfig),                                        // Set configuration parameters
+        stubWindowSuggest_(globalCacheTMTT->stubWindowSuggest()),  // For tuning FE stub window sizes
+        hists_(globalCacheTMTT->hists()),                          // Initialize histograms
+        htRphiErrMon_(globalCacheTMTT->htRphiErrMon())             // rphi HT error monitoring
   {
     using namespace edm;
 
@@ -53,6 +53,8 @@ namespace tmtt {
         settings_.trackerGeometryInputTag());
     trackerTopologyToken_ =
         esConsumes<TrackerTopology, TrackerTopologyRcd, Transition::BeginRun>(settings_.trackerTopologyInputTag());
+    ttStubAlgoToken_ =
+        esConsumes<StubAlgorithm, TTStubAlgorithmRecord, Transition::BeginRun>(settings_.ttStubAlgoInputTag());
 
     // Get tokens for ED data access.
     stubToken_ = consumes<TTStubDetSetVec>(settings_.stubInputTag());
@@ -92,6 +94,8 @@ namespace tmtt {
     }
   }
 
+  //=== Run every run
+
   void TMTrackProducer::beginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) {
     // Get the B-field and store its value in the Settings class.
     const MagneticField* theMagneticField = &(iSetup.getData(magneticFieldToken_));
@@ -110,7 +114,7 @@ namespace tmtt {
     trackerGeometry_ = &(iSetup.getData(trackerGeometryToken_));
     trackerTopology_ = &(iSetup.getData(trackerTopologyToken_));
 
-    // Loop over tracker modules to get module info & stubs.
+    // Loop over tracker modules to get module info.
 
     // Identifies tracker module type for firmware.
     TrackerModule::ModuleTypeCfg moduleTypeCfg;
@@ -134,14 +138,27 @@ namespace tmtt {
 
     // Takes one copy of this to GlobalCacheTMTT for later histogramming.
     globalCache()->setListTrackerModule(listTrackerModule_);
+
+    // Get TTStubProducerAlgorithm algorithm, to adjust stub bend FE encoding.
+    stubAlgo_ = dynamic_cast<const StubAlgorithmOfficial*>(&iSetup.getData(ttStubAlgoToken_));
+    // Get FE stub window size from TTStub producer configuration
+    const edm::ESHandle<StubAlgorithm> stubAlgoHandle = iSetup.getHandle(ttStubAlgoToken_);
+    const edm::ParameterSet& pSetStubAlgo = getParameterSet(stubAlgoHandle.description()->pid_);
+    stubFEWindows_ = std::make_unique<StubFEWindows>(pSetStubAlgo);
+    // Initialize utilities needing FE window size.
+    stubWindowSuggest_.setFEWindows(stubFEWindows_.get());
+    degradeBend_ = std::make_unique<DegradeBend>(trackerTopology_, stubFEWindows_.get(), stubAlgo_);
   }
 
+  //=== Run every event
+
   void TMTrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
     // Note useful info about MC truth particles and about reconstructed stubs .
     InputData inputData(iEvent,
                         iSetup,
                         &settings_,
                         &stubWindowSuggest_,
+                        degradeBend_.get(),
                         trackerGeometry_,
                         trackerTopology_,
                         listTrackerModule_,
diff --git a/L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.h b/L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.h
index 9e3aa6bc3f9d8..ce2101176a221 100644
--- a/L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.h
+++ b/L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.h
@@ -6,6 +6,7 @@
 #include "L1Trigger/TrackFindingTMTT/interface/Stub.h"
 #include "L1Trigger/TrackFindingTMTT/interface/L1track3D.h"
 #include "L1Trigger/TrackFindingTMTT/interface/TrackerModule.h"
+#include "L1Trigger/TrackFindingTMTT/interface/StubFEWindows.h"
 #include "L1Trigger/TrackFindingTMTT/interface/StubWindowSuggest.h"
 #include "L1Trigger/TrackFindingTMTT/interface/GlobalCacheTMTT.h"
 
@@ -22,6 +23,9 @@
 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
 #include "MagneticField/Engine/interface/MagneticField.h"
 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
+#include "L1Trigger/TrackTrigger/interface/TTStubAlgorithmRecord.h"
+#include "L1Trigger/TrackTrigger/interface/TTStubAlgorithm_official.h"
+//#include "L1Trigger/TrackTrigger/interface/TTStubAlgorithm.h"
 
 #include <vector>
 #include <list>
@@ -32,10 +36,13 @@ namespace tmtt {
 
   class TrackFitGeneric;
 
+  typedef TTStubAlgorithm<Ref_Phase2TrackerDigi_> StubAlgorithm;
+  typedef TTStubAlgorithm_official<Ref_Phase2TrackerDigi_> StubAlgorithmOfficial;
+
   class TMTrackProducer : public edm::stream::EDProducer<edm::GlobalCache<GlobalCacheTMTT>> {
   public:
     explicit TMTrackProducer(const edm::ParameterSet &, GlobalCacheTMTT const *globalCacheTMTT);
-    ~TMTrackProducer() {}
+    ~TMTrackProducer() override {}
 
     static std::unique_ptr<GlobalCacheTMTT> initializeGlobalCache(edm::ParameterSet const &iConfig);
 
@@ -44,9 +51,9 @@ namespace tmtt {
   private:
     typedef std::vector<TTTrack<Ref_Phase2TrackerDigi_>> TTTrackCollection;
 
-    virtual void beginRun(const edm::Run &, const edm::EventSetup &);
+    void beginRun(const edm::Run &, const edm::EventSetup &) override;
 
-    virtual void produce(edm::Event &, const edm::EventSetup &);
+    void produce(edm::Event &, const edm::EventSetup &) override;
 
   private:
     bool debug_;
@@ -55,6 +62,7 @@ namespace tmtt {
     edm::ESGetToken<MagneticField, IdealMagneticFieldRecord> magneticFieldToken_;
     edm::ESGetToken<TrackerGeometry, TrackerDigiGeometryRecord> trackerGeometryToken_;
     edm::ESGetToken<TrackerTopology, TrackerTopologyRcd> trackerTopologyToken_;
+    edm::ESGetToken<StubAlgorithm, TTStubAlgorithmRecord> ttStubAlgoToken_;
     // ED tokens
     edm::EDGetTokenT<TTStubDetSetVec> stubToken_;
     edm::EDGetTokenT<TrackingParticleCollection> tpToken_;
@@ -73,9 +81,14 @@ namespace tmtt {
     std::vector<std::string> useRZfilter_;
     bool runRZfilter_;
 
+    // Stub window sizes used by FE electronics.
+    const StubAlgorithmOfficial *stubAlgo_;
+    std::unique_ptr<StubFEWindows> stubFEWindows_;
+    StubWindowSuggest &stubWindowSuggest_;
+    std::unique_ptr<DegradeBend> degradeBend_;
+
     Histos &hists_;
     HTrphi::ErrorMonitor &htRphiErrMon_;
-    StubWindowSuggest &stubWindowSuggest_;
 
     std::map<std::string, std::unique_ptr<TrackFitGeneric>> fitterWorkerMap_;
   };
diff --git a/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_Defaults_cfi.py b/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_Defaults_cfi.py
index bb64e14ef0ddc..9e52fe7f1fdba 100644
--- a/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_Defaults_cfi.py
+++ b/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_Defaults_cfi.py
@@ -13,6 +13,7 @@
   magneticFieldInputTag   = cms.ESInputTag( "VolumeBasedMagneticFieldESProducer", "" ), 
   trackerGeometryInputTag = cms.ESInputTag( "trackerGeometry", "" ), 
   trackerTopologyInputTag = cms.ESInputTag( "trackerTopology", "" ), 
+  ttStubAlgoInputTag      = cms.ESInputTag( "TTStubAlgorithm_official_Phase2TrackerDigi_", "" ),
 
   # Tags for ED products
   tpInputTag = cms.InputTag("mix", "MergedTrackTruth"),
@@ -370,6 +371,16 @@
      KalmanMaxSkipLayersHard = cms.uint32(1), # For HT tracks with many stubs
      KalmanMaxSkipLayersEasy = cms.uint32(2), # For HT tracks with few stubs
      KalmanMaxStubsEasy      = cms.uint32(10), # Max stubs an HT track can have to be "easy".
+     #--- Cuts applied to KF states as a function of the last KF tracker layer they had a stub in.
+     # (If "4" or "5" in name, cut only applies to 4 or 5 param helix fit).
+     KFLayerVsPtToler        = cms.vdouble(999., 999., 0.1 , 0.1 , 0.05, 0.05, 0.05),
+     # d0 cut only applied to 5 param helix fit.
+     KFLayerVsD0Cut5         = cms.vdouble(999., 999., 999., 10. , 10. , 10. ,10.  ),
+     KFLayerVsZ0Cut5         = cms.vdouble(999., 999., 25.5, 25.5, 25.5, 25.5,25.5 ),
+     KFLayerVsZ0Cut4         = cms.vdouble(999., 999. ,15. , 15. , 15. , 15. ,15.  ),
+     # Chi2 cuts should be retuned if KalmanMultiScattTerm value changed.
+     KFLayerVsChiSq5         = cms.vdouble(999., 999., 10. , 30. , 80. , 120., 160.),
+     KFLayerVsChiSq4         = cms.vdouble(999., 999., 10. , 30. , 80. , 120., 160.),
      # KF will consider at most this #stubs per layer to save time.
      KalmanMaxStubsPerLayer  = cms.uint32(4),
      # Multiple scattering term - inflate hit phi errors by this divided by Pt
diff --git a/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_Ultimate_cff.py b/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_Ultimate_cff.py
index 03638a3fc59fb..626399a8f8915 100644
--- a/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_Ultimate_cff.py
+++ b/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_Ultimate_cff.py
@@ -9,6 +9,16 @@
 # It represents the tracking as planned for 2026. It is a good basis for L1 trigger studies etc.
 #---------------------------------------------------------------------------------------------------------
 
+#=== TMTT tracking needs to get FE stub window sizes from this.
+
+from L1Trigger.TrackTrigger.TTStubAlgorithmRegister_cfi import *
+
+#=== Random number generator for Stub Killer (dead module emulation)
+
+RandomNumberGeneratorService = cms.Service("RandomNumberGeneratorService",
+    TMTrackProducer = cms.PSet(initialSeed = cms.untracked.uint32(12345))
+)
+
 #=== Import default values for all parameters & define EDProducer.
 
 from L1Trigger.TrackFindingTMTT.TMTrackProducer_Defaults_cfi import TMTrackProducer_params
diff --git a/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_cff.py b/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_cff.py
index 1580c422b662b..498c7e25b3b5a 100644
--- a/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_cff.py
+++ b/L1Trigger/TrackFindingTMTT/python/TMTrackProducer_cff.py
@@ -9,6 +9,17 @@
 # This usually corresponds to the current firmware.
 #---------------------------------------------------------------------------------------------------------
 
+
+#=== TMTT tracking needs to get FE stub window sizes from this.
+
+from L1Trigger.TrackTrigger.TTStubAlgorithmRegister_cfi import *
+
+#=== Random number generator for Stub Killer (dead module emulation)
+
+RandomNumberGeneratorService = cms.Service("RandomNumberGeneratorService",
+    TMTrackProducer = cms.PSet(initialSeed = cms.untracked.uint32(12345))
+)
+
 #=== Import default values for all parameters & define EDProducer.
 
 from L1Trigger.TrackFindingTMTT.TMTrackProducer_Defaults_cfi import TMTrackProducer_params
diff --git a/L1Trigger/TrackFindingTMTT/src/ConverterToTTTrack.cc b/L1Trigger/TrackFindingTMTT/src/ConverterToTTTrack.cc
index 17c2dd1f01a2f..d142946cf0b99 100644
--- a/L1Trigger/TrackFindingTMTT/src/ConverterToTTTrack.cc
+++ b/L1Trigger/TrackFindingTMTT/src/ConverterToTTTrack.cc
@@ -64,7 +64,7 @@ namespace tmtt {
 
   std::vector<TTStubRef> ConverterToTTTrack::stubRefs(const L1trackBase* trk) const {
     std::vector<TTStubRef> ttstubrefs;
-    const std::vector<Stub*> stubs = trk->stubs();
+    const std::vector<Stub*>& stubs = trk->stubs();
     for (Stub* s : stubs) {
       const TTStubRef& ref = s->ttStubRef();
       ttstubrefs.push_back(ref);
diff --git a/L1Trigger/TrackFindingTMTT/src/DegradeBend.cc b/L1Trigger/TrackFindingTMTT/src/DegradeBend.cc
index a2c7c8e74a81b..2f0b0aea42fa0 100644
--- a/L1Trigger/TrackFindingTMTT/src/DegradeBend.cc
+++ b/L1Trigger/TrackFindingTMTT/src/DegradeBend.cc
@@ -9,31 +9,15 @@
 #include <set>
 #include <utility>
 #include <cmath>
+#include <algorithm>
 #include <iostream>
 
 using namespace std;
 
 namespace tmtt {
 
-  //--- Stub window sizes copied from L1Trigger/TrackTrigger/python/TTStubAlgorithmRegister_cfi.py
-
-  const std::vector<double> DegradeBend::barrelCut_ = {0, 2, 2.5, 3.5, 4.5, 5.5, 7};
-  const std::vector<std::vector<double> > DegradeBend::ringCut_ = {  // EndcapCutSet
-      {0},
-      {0, 1, 2.5, 2.5, 3, 2.5, 3, 3.5, 4, 4, 4.5, 3.5, 4, 4.5, 5, 5.5},
-      {0, 0.5, 2.5, 2.5, 3, 2.5, 3, 3, 3.5, 3.5, 4, 3.5, 3.5, 4, 4.5, 5},
-      {0, 1, 3, 3, 2.5, 3.5, 3.5, 3.5, 4, 3.5, 3.5, 4, 4.5},
-      {0, 1, 2.5, 3, 2.5, 3.5, 3, 3, 3.5, 3.5, 3.5, 4, 4},
-      {0, 0.5, 1.5, 3, 2.5, 3.5, 3, 3, 3.5, 4, 3.5, 4, 3.5}};
-  const std::vector<std::vector<double> > DegradeBend::tiltedCut_ = {  // TiltedBarrelCutSet
-      {0},
-      {0, 3, 3., 2.5, 3., 3., 2.5, 2.5, 2., 1.5, 1.5, 1, 1},
-      {0, 4., 4, 4, 4, 4., 4., 4.5, 5, 4., 3.5, 3.5, 3},
-      {0, 5, 5, 5, 5, 5, 5, 5.5, 5, 5, 5.5, 5.5, 5.5}};
-  const std::vector<double> DegradeBend::barrelNTilt_ = {0., 12., 12., 12., 0., 0., 0.};
-
   //--- Given the original bend, flag indicating if this is a PS or 2S module, & detector identifier,
-  //--- this return the degraded stub bend, a boolean indicatng if stub bend was outside the assumed window
+  //--- this returns the degraded stub bend, a boolean indicatng if stub bend was outside the assumed window
   //--- size programmed below, and an integer indicating how many values of the original bend
   //--- were grouped together into this single value of the degraded bend.
 
@@ -58,102 +42,21 @@ namespace tmtt {
                          unsigned int& numInGroup,
                          unsigned int& windowHalfStrips) const {
     // Calculate stub window size in half-strip units used to produce stubs.
-    // This code should be kept identical to that in
-    // L1Trigger/TrackTrigger/src/TTStubAlgorithm_official.cc
-
-    unsigned int window = 0;
+    // Code accessing geometry inspired by L1Trigger/TrackTrigger/src/TTStubAlgorithm_official.cc
 
-    if (stDetId.subdetId() == StripSubdetector::TOB) {
-      int layer = theTrackerTopo_->layer(stDetId);
-      int ladder = theTrackerTopo_->tobRod(stDetId);
-      int type = 2 * theTrackerTopo_->tobSide(stDetId) - 3;  // -1 for tilted-, 1 for tilted+, 3 for flat
-      double corr = 0;
-
-      if (type != TrackerModule::BarrelModuleType::flat)  // Only for tilted modules
-      {
-        corr = (barrelNTilt_.at(layer) + 1) / 2.;
-        ladder =
-            corr - (corr - ladder) * type;  // Corrected ring number, bet 0 and barrelNTilt.at(layer), in ascending |z|
-        window = 2 * (tiltedCut_.at(layer)).at(ladder);
-      } else  // Classic barrel window otherwise
-      {
-        window = 2 * barrelCut_.at(layer);
-      }
-    } else if (stDetId.subdetId() == StripSubdetector::TID) {
-      window = 2 * (ringCut_.at(theTrackerTopo_->tidWheel(stDetId))).at(theTrackerTopo_->tidRing(stDetId));
-    }
+    const double* storedHalfWindow = sw_->storedWindowSize(theTrackerTopo_, stDetId);
 
     // Compare this with the possibly tighter window provided by the user, converting to half-strip units.
-    unsigned int newWindow = (unsigned int)(2 * windowFEnew);
-    if (window > newWindow)
-      window = newWindow;
-
-    // This is the window size measured in half-strips.
-    windowHalfStrips = window;
-
-    // Number of degraded bend values should correspond to 3 bits (PS modules) or 4 bits (2S modules),
-    // so measuring everything in half-strip units, max integer "window" size that can be encoded without
-    // compression given by 2*window+1 <= pow(2,B), where B is number of bits.
-    // Hence no compression required if window cut is abs(b) < 3 (PS) or 7 (2S). Must introduce one merge for
-    // each 1 unit increase in "window" beyond this.
+    const double window = std::min(*storedHalfWindow, double(windowFEnew));
+    windowHalfStrips = (unsigned int)(2 * window);
 
     // Bend is measured with granularity of 0.5 strips.
     // Convert it to integer measured in half-strip units for this calculation!
-
     int b = std::round(2 * bend);
 
-    if ((unsigned int)(abs(b)) <= window) {
-      float degradedB;
-      unsigned int numBends = 2 * window + 1;
-      unsigned int numAllowed = (psModule) ? pow(2, bitsPS_) : pow(2, bits2S_);
-      // Existance of bend = 0 means can only use an odd number of groups.
-      numAllowed -= 1;
-      if (numBends <= numAllowed) {
-        // Can output uncompressed bend info.
-        numInGroup = 1;
-        degradedB = float(b);
-      } else {
-        unsigned int inSmallGroup = numBends / numAllowed;
-        unsigned int numLargeGroups = numBends % numAllowed;
-        unsigned int inLargeGroup = inSmallGroup + 1;
-        unsigned int numSmallGroups = numAllowed - numLargeGroups;
-        // Bend encoding in groups (some large, some small, one large/small, some small, some large).
-        vector<unsigned int> groups;
-        for (unsigned int i = 0; i < numLargeGroups / 2; i++)
-          groups.push_back(inLargeGroup);
-        for (unsigned int i = 0; i < numSmallGroups / 2; i++)
-          groups.push_back(inSmallGroup);
-        // Only one of numLargeGroups & numSmallGroups can be odd, since numAllowed is odd.
-        // And whichever is odd is associated to a group with an odd number of elements since numBends is odd,
-        if (numLargeGroups % 2 == 1 && inLargeGroup % 2 == 1) {
-          groups.push_back(inLargeGroup);
-        } else if (numSmallGroups % 2 == 1 && inSmallGroup % 2 == 1) {
-          groups.push_back(inSmallGroup);
-        } else {
-          throw cms::Exception("LogicError") << "DegradeBend: logic error with odd numbers";
-        }
-        for (unsigned int i = 0; i < numSmallGroups / 2; i++)
-          groups.push_back(inSmallGroup);
-        for (unsigned int i = 0; i < numLargeGroups / 2; i++)
-          groups.push_back(inLargeGroup);
-
-        degradedB = 999;
-        int iUp = -int(window) - 1;
-        for (unsigned int& inGroup : groups) {
-          iUp += inGroup;
-          int iDown = iUp - inGroup + 1;
-          if (b <= iUp && b >= iDown) {
-            numInGroup = inGroup;
-            degradedB = 0.5 * (iUp + iDown);
-          }
-        }
-        if (degradedB == 999)
-          throw cms::Exception("LogicError") << "DegradeResolution: Logic error in loop over groups";
-      }
-
-      // This is degraded bend in full strip units (neglecting bend sign).
-      degradedBend = float(degradedB) / 2.;
-
+    if ((unsigned int)(std::abs(b)) <= windowHalfStrips) {
+      // Call the official CMS bend encoding algorithm.
+      degradedBend = stubAlgo_->degradeBend(psModule, windowHalfStrips, b);
     } else {
       // This should only happen for stubs subsequently rejected by the FE.
       numInGroup = 0;
diff --git a/L1Trigger/TrackFindingTMTT/src/DigitalTrack.cc b/L1Trigger/TrackFindingTMTT/src/DigitalTrack.cc
index f99fa085ca5c6..9586e01c3c55d 100644
--- a/L1Trigger/TrackFindingTMTT/src/DigitalTrack.cc
+++ b/L1Trigger/TrackFindingTMTT/src/DigitalTrack.cc
@@ -86,8 +86,8 @@ namespace tmtt {
     tp_phi0_ = tpOK ? tp->phi0() : 0;
     tp_z0_ = tpOK ? tp->z0() : 0;
     tp_index_ = tpOK ? tp->index() : -1;
-    tp_useForAlgEff_ = tpOK ? tp->useForAlgEff() : 0;
-    tp_useForEff_ = tpOK ? tp->useForEff() : 0;
+    tp_useForAlgEff_ = tpOK ? tp->useForAlgEff() : false;
+    tp_useForEff_ = tpOK ? tp->useForEff() : false;
     tp_pdgId_ = tpOK ? tp->pdgId() : 0;
 
     // Digitize track.
diff --git a/L1Trigger/TrackFindingTMTT/src/DupFitTrkKiller.cc b/L1Trigger/TrackFindingTMTT/src/DupFitTrkKiller.cc
index 4e810cbc745f6..d52f22c321ace 100644
--- a/L1Trigger/TrackFindingTMTT/src/DupFitTrkKiller.cc
+++ b/L1Trigger/TrackFindingTMTT/src/DupFitTrkKiller.cc
@@ -11,12 +11,12 @@ namespace tmtt {
   //=== Make available cfg parameters & specify which algorithm is to be used for duplicate track removal.
 
   DupFitTrkKiller::DupFitTrkKiller(const Settings* settings)
-      : settings_(settings), dupTrkAlg_(settings->dupTrkAlgFit()) {}
+      : settings_(settings), dupTrkAlg_(static_cast<DupAlgoName>(settings->dupTrkAlgFit())) {}
 
   //=== Eliminate duplicate tracks from the input collection, and so return a reduced list of tracks.
 
   list<const L1fittedTrack*> DupFitTrkKiller::filter(const list<L1fittedTrack>& vecTracks) const {
-    if (dupTrkAlg_ == 0) {
+    if (dupTrkAlg_ == DupAlgoName::None) {
       // We are not running duplicate removal, so return original fitted track collection.
       list<const L1fittedTrack*> copyTracks;
       for (const L1fittedTrack& trk : vecTracks) {
@@ -28,10 +28,10 @@ namespace tmtt {
       // Choose which algorithm to run, based on parameter dupTrkAlg_.
       switch (dupTrkAlg_) {
         // Run filters that only work on fitted tracks.
-        case 1:
+        case DupAlgoName::Algo1:
           return filterAlg1(vecTracks);
           break;
-        case 2:
+        case DupAlgoName::Algo2:
           return filterAlg2(vecTracks);
           break;
         default:
@@ -58,7 +58,7 @@ namespace tmtt {
     constexpr bool goOutsideArray = true;  // Also store in memory stubs outside the HT array during 2nd pass.
     constexpr bool limitDiff = true;       // Limit allowed diff. between HT & Fit cell to <= 1.
 
-    if (debug && tracks.size() > 0)
+    if (debug && not tracks.empty())
       PrintL1trk() << "Start DupFitTrkKiller" << tracks.size();
 
     list<const L1fittedTrack*> tracksFiltered;
@@ -211,7 +211,7 @@ namespace tmtt {
     // Hard-wired options to play with.
     const bool debug = false;
 
-    if (debug && tracks.size() > 0)
+    if (debug && not tracks.empty())
       PrintL1trk() << "START " << tracks.size();
 
     list<const L1fittedTrack*> tracksFiltered;
@@ -268,7 +268,7 @@ namespace tmtt {
         }
       }
     }
-    if (tracks.size() > 0)
+    if (not tracks.empty())
       PrintL1trk() << "FOUND " << tracks.size();
   }
 
diff --git a/L1Trigger/TrackFindingTMTT/src/HTbase.cc b/L1Trigger/TrackFindingTMTT/src/HTbase.cc
index d5560e92fbbc3..5629fd6a51087 100644
--- a/L1Trigger/TrackFindingTMTT/src/HTbase.cc
+++ b/L1Trigger/TrackFindingTMTT/src/HTbase.cc
@@ -189,7 +189,7 @@ namespace tmtt {
     // Check if the hardware processes rows of the HT array in a specific order when outputting track candidates.
     // Currently this is by decreasing Pt for r-phi HT and unordered for r-z HT.
     const vector<unsigned int> iOrder = this->rowOrder(nBinsX_);
-    bool wantOrdering = (iOrder.size() > 0);
+    bool wantOrdering = (not iOrder.empty());
 
     // Loop over cells in HT array.
     for (unsigned int i = 0; i < nBinsX_; i++) {
diff --git a/L1Trigger/TrackFindingTMTT/src/HTrphi.cc b/L1Trigger/TrackFindingTMTT/src/HTrphi.cc
index f49d88d866376..192403be46b8f 100644
--- a/L1Trigger/TrackFindingTMTT/src/HTrphi.cc
+++ b/L1Trigger/TrackFindingTMTT/src/HTrphi.cc
@@ -62,12 +62,6 @@ namespace tmtt {
     else if (shape_ == HTshape::diamond)
       binSizePhiTrkAxis_ = 2. * maxAbsPhiTrkAxis_ / (nBinsPhiTrkAxis_ - 1. / 2.);
 
-    // Note max. |gradient| that the line corresponding to any stub in any of the r-phi HT arrays could have.
-    // Firmware assumes this should not exceed 1.0;
-    if (errMon_ != nullptr) {
-      errMon_->maxLineGradient = max(errMon_->maxLineGradient.load(), this->calcMaxLineGradArray());
-    }
-
     // Optionally merge 2x2 neighbouring cells into a single cell at low Pt, to reduce efficiency loss due to
     // scattering. (Do this if either of options EnableMerge2x2 or MiniHTstage are enabled.
     // N.B These two options are never both enabled).
@@ -311,6 +305,11 @@ namespace tmtt {
           }
         }
       }
+      // Note max. |gradient| that the line corresponding to any stub in any of the r-phi HT arrays could have.
+      // Firmware assumes this should not exceed 1.0;
+      if (errMon_ != nullptr) {
+        errMon_->maxLineGradient = max(errMon_->maxLineGradient.load(), this->calcLineGradArray(stub->r()));
+      }
     }
   }
 
@@ -602,22 +601,19 @@ namespace tmtt {
     return merge;
   }
 
-  //=== Calculate maximum |gradient| that any stub's line across this HT array could have, so can check it doesn't exceed 1.
+  //=== Calculate line |gradient| of stubs in HT array, so can check it doesn't exceed 1.
 
-  float HTrphi::calcMaxLineGradArray() const {
-    // Get max. |gradient| possible in this HT array.
-    float gradOuter = std::abs(invPtToDphi_ * (settings_->trackerOuterRadius() - chosenRofPhi_));
-    float gradInner = std::abs(invPtToDphi_ * (settings_->trackerInnerRadius() - chosenRofPhi_));
-    float maxGrad = max(gradOuter, gradInner);
+  float HTrphi::calcLineGradArray(float r) const {
+    float grad = std::abs(invPtToDphi_ * (r - chosenRofPhi_));
     // Convert it to units of bin width.
-    maxGrad *= binSizeQoverPtAxis_ / binSizePhiTrkAxis_;
+    grad *= binSizeQoverPtAxis_ / binSizePhiTrkAxis_;
     if (shape_ == HTshape::hexagon)
-      maxGrad *= 3.;
+      grad *= 3.;
     else if (shape_ == HTshape::diamond)
-      maxGrad *= 2.;
+      grad *= 2.;
     else if (shape_ == HTshape::brick)
-      maxGrad *= 4.;
-    return maxGrad;
+      grad *= 4.;
+    return grad;
   }
 
   //=== If requested, kill those tracks in this sector that can't be read out during the time-multiplexed period, because
diff --git a/L1Trigger/TrackFindingTMTT/src/Histos.cc b/L1Trigger/TrackFindingTMTT/src/Histos.cc
index eb4c0163be66c..ef0070f29a58b 100644
--- a/L1Trigger/TrackFindingTMTT/src/Histos.cc
+++ b/L1Trigger/TrackFindingTMTT/src/Histos.cc
@@ -51,8 +51,8 @@ namespace tmtt {
     chosenRofZ_ = settings->chosenRofZ();
     trackFitters_ = settings->trackFitters();
     useRZfilter_ = settings->useRZfilter();
-    ranRZfilter_ = (useRZfilter_.size() > 0);  // Was any r-z track filter run?
-    resPlotOpt_ = settings->resPlotOpt();      // Only use signal events for helix resolution plots?
+    ranRZfilter_ = (not useRZfilter_.empty());  // Was any r-z track filter run?
+    resPlotOpt_ = settings->resPlotOpt();       // Only use signal events for helix resolution plots?
   }
 
   //=== Book all histograms
@@ -197,7 +197,7 @@ namespace tmtt {
     // Study efficiency for good stubs of tightened front end-electronics cuts.
     for (const TP& tp : vTPs) {
       if (tp.useForAlgEff()) {  // Only bother for stubs that are on TP that we have a chance of reconstructing.
-        const vector<const Stub*> stubs = tp.assocStubs();
+        const vector<const Stub*>& stubs = tp.assocStubs();
         for (const Stub* s : stubs) {
           hisStubIneffiVsInvPt_->Fill(1. / tp.pt(), (!s->frontendPass()));
           hisStubIneffiVsEta_->Fill(std::abs(tp.eta()), (!s->frontendPass()));
diff --git a/L1Trigger/TrackFindingTMTT/src/InputData.cc b/L1Trigger/TrackFindingTMTT/src/InputData.cc
index 173cee073bfbb..4d16a2651cfe5 100644
--- a/L1Trigger/TrackFindingTMTT/src/InputData.cc
+++ b/L1Trigger/TrackFindingTMTT/src/InputData.cc
@@ -16,6 +16,7 @@
 #include "L1Trigger/TrackFindingTMTT/interface/Settings.h"
 #include "L1Trigger/TrackFindingTMTT/interface/StubKiller.h"
 #include "L1Trigger/TrackFindingTMTT/interface/StubWindowSuggest.h"
+#include "L1Trigger/TrackFindingTMTT/interface/DegradeBend.h"
 
 #include <map>
 #include <memory>
@@ -28,6 +29,7 @@ namespace tmtt {
                        const edm::EventSetup& iSetup,
                        const Settings* settings,
                        StubWindowSuggest* stubWindowSuggest,
+                       const DegradeBend* degradeBend,
                        const TrackerGeometry* trackerGeometry,
                        const TrackerTopology* trackerTopology,
                        const list<TrackerModule>& listTrackerModule,
@@ -106,7 +108,8 @@ namespace tmtt {
           const unsigned int stubIndex = vAllStubs_.size();
 
           // Store the Stub info, using class Stub to provide easy access to the most useful info.
-          vAllStubs_.emplace_back(ttStubRef, stubIndex, settings, trackerTopology, &trackerModule, stubKiller.get());
+          vAllStubs_.emplace_back(
+              ttStubRef, stubIndex, settings, trackerTopology, &trackerModule, degradeBend, stubKiller.get());
 
           // Also fill truth associating stubs to tracking particles.
           if (enableMCtruth_) {
diff --git a/L1Trigger/TrackFindingTMTT/src/KFParamsComb.cc b/L1Trigger/TrackFindingTMTT/src/KFParamsComb.cc
index 35762f558ccbb..119f6969c8eb8 100644
--- a/L1Trigger/TrackFindingTMTT/src/KFParamsComb.cc
+++ b/L1Trigger/TrackFindingTMTT/src/KFParamsComb.cc
@@ -5,21 +5,34 @@
 #include "L1Trigger/TrackFindingTMTT/interface/PrintL1trk.h"
 #include "DataFormats/Math/interface/deltaPhi.h"
 
+#include <array>
 #include <sstream>
 
 using namespace std;
 
 namespace tmtt {
 
+  /* Initialize */
+
+  KFParamsComb::KFParamsComb(const Settings* settings, const uint nHelixPar, const std::string& fitterName)
+      : KFbase(settings, nHelixPar, fitterName),
+        // Initialize cuts applied to helix states vs KF layer number of last added stub.
+        kfLayerVsPtToler_(settings->kfLayerVsPtToler()),
+        kfLayerVsD0Cut5_(settings->kfLayerVsD0Cut5()),
+        kfLayerVsZ0Cut5_(settings->kfLayerVsZ0Cut5()),
+        kfLayerVsZ0Cut4_(settings->kfLayerVsZ0Cut4()),
+        kfLayerVsChiSq5_(settings->kfLayerVsChiSq5()),
+        kfLayerVsChiSq4_(settings->kfLayerVsChiSq4()) {}
+
   /* Helix state seed  */
 
   TVectorD KFParamsComb::seedX(const L1track3D& l1track3D) const {
-    TVectorD vecX(nPar_);
+    TVectorD vecX(nHelixPar_);
     vecX[INV2R] = settings_->invPtToInvR() * l1track3D.qOverPt() / 2;
     vecX[PHI0] = reco::deltaPhi(l1track3D.phi0() - sectorPhi(), 0.);
     vecX[Z0] = l1track3D.z0();
     vecX[T] = l1track3D.tanLambda();
-    if (nPar_ == 5) {
+    if (nHelixPar_ == 5) {  // fit without d0 constraint
       vecX[D0] = l1track3D.d0();
     }
 
@@ -29,26 +42,26 @@ namespace tmtt {
   /* Helix state seed covariance matrix */
 
   TMatrixD KFParamsComb::seedC(const L1track3D& l1track3D) const {
-    TMatrixD matC(nPar_, nPar_);
+    TMatrixD matC(nHelixPar_, nHelixPar_);
 
     double invPtToInv2R = settings_->invPtToInvR() / 2;
 
     // Assumed track seed (from HT) uncertainty in transverse impact parameter.
 
     // Constants optimised by hand for TMTT algo.
-    const float inv2Rsigma    = 0.0314 * invPtToInv2R;
+    const float inv2Rsigma = 0.0314 * invPtToInv2R;
     constexpr float phi0sigma = 0.0102;
-    constexpr float z0sigma   = 5.0;
+    constexpr float z0sigma = 5.0;
     constexpr float tanLsigma = 0.5;
-    constexpr float d0Sigma   = 1.0;
+    constexpr float d0Sigma = 1.0;
     // (z0, tanL, d0) uncertainties could be smaller for Hybrid, if seeded in PS? -- To check!
     // if (L1track3D.seedPS() > 0) z0sigma /= 4; ???
     matC[INV2R][INV2R] = pow(inv2Rsigma, 2);
-    matC[PHI0][PHI0]   = pow(phi0sigma, 2);
-    matC[Z0][Z0]       = pow(z0sigma, 2);
-    matC[T][T]         = pow(tanLsigma, 2);
-    if (nPar_ == 5) {
-      matC[D0][D0]     = pow(d0Sigma, 2);
+    matC[PHI0][PHI0] = pow(phi0sigma, 2);
+    matC[Z0][Z0] = pow(z0sigma, 2);
+    matC[T][T] = pow(tanLsigma, 2);
+    if (nHelixPar_ == 5) {  // fit without d0 constraint
+      matC[D0][D0] = pow(d0Sigma, 2);
     }
     return matC;
   }
@@ -76,13 +89,8 @@ namespace tmtt {
     double vz(0);
     double vcorr(0);
 
-    // consider error due to integerisation only for z (r in encap) coord when enabled
-    double err_digi2(0);
-    if (settings_->enableDigitize())
-      err_digi2 = 0.15625 * 0.15625 / 12.0;
-
     double a = stub->sigmaPerp() * stub->sigmaPerp();
-    double b = stub->sigmaPar() * stub->sigmaPar() + err_digi2;
+    double b = stub->sigmaPar() * stub->sigmaPar();
     double r2 = stub->r() * stub->r();
     double invr2 = 1. / r2;
 
@@ -155,11 +163,11 @@ namespace tmtt {
   /* Here I always measure phi(r), and z(r) */
 
   TMatrixD KFParamsComb::matrixH(const Stub* stub) const {
-    TMatrixD matH(2, nPar_);
+    TMatrixD matH(2, nHelixPar_);
     double r = stub->r();
     matH(PHI, INV2R) = -r;
     matH(PHI, PHI0) = 1;
-    if (nPar_ == 5) {
+    if (nHelixPar_ == 5) {  // fit without d0 constraint
       matH(PHI, D0) = -1. / r;
     }
     matH(Z, Z0) = 1;
@@ -170,7 +178,7 @@ namespace tmtt {
   /* Kalman helix ref point extrapolation matrix */
 
   TMatrixD KFParamsComb::matrixF(const Stub* stub, const KalmanState* state) const {
-    const TMatrixD unitMatrix(TMatrixD::kUnit, TMatrixD(nPar_, nPar_));
+    const TMatrixD unitMatrix(TMatrixD::kUnit, TMatrixD(nHelixPar_, nHelixPar_));
     return unitMatrix;
   }
 
@@ -178,12 +186,12 @@ namespace tmtt {
 
   TVectorD KFParamsComb::trackParams(const KalmanState* state) const {
     TVectorD vecX = state->vectorX();
-    TVectorD vecY(nPar_);
+    TVectorD vecY(nHelixPar_);
     vecY[QOVERPT] = 2. * vecX[INV2R] / settings_->invPtToInvR();
     vecY[PHI0] = reco::deltaPhi(vecX[PHI0] + sectorPhi(), 0.);
     vecY[Z0] = vecX[Z0];
     vecY[T] = vecX[T];
-    if (nPar_ == 5) {
+    if (nHelixPar_ == 5) {  // fit without d0 constraint
       vecY[D0] = vecX[D0];
     }
     return vecY;
@@ -193,10 +201,10 @@ namespace tmtt {
   /* (N.B. chi2rz unchanged by constraint) */
 
   TVectorD KFParamsComb::trackParams_BeamConstr(const KalmanState* state, double& chi2rphi) const {
-    if (nPar_ == 5) {
+    if (nHelixPar_ == 5) {  // fit without d0 constraint
       TVectorD vecX = state->vectorX();
       TMatrixD matC = state->matrixC();
-      TVectorD vecY(nPar_);
+      TVectorD vecY(nHelixPar_);
       double delChi2rphi = (vecX[D0] * vecX[D0]) / matC[D0][D0];
       chi2rphi = state->chi2rphi() + delChi2rphi;
       // Apply beam-spot constraint to helix params in transverse plane only, as most sensitive to it.
@@ -217,23 +225,9 @@ namespace tmtt {
   /* Check if helix state passes cuts */
 
   bool KFParamsComb::isGoodState(const KalmanState& state) const {
-    // Cut values. (Layer 0 entry here is dummy). -- todo : make configurable
-
-    vector<float> z0Cut, ptTolerance, d0Cut, chi2Cut;
-    //  Layer   =    0      1      2     3     4      5      6
-    ptTolerance = {999., 999., 0.1, 0.1, 0.05, 0.05, 0.05};
-    d0Cut = {999., 999., 999., 10., 10., 10., 10.};  // Only used for 5 param fit.
-    // Chi2 cuts should be retuned if cfg param KalmanMultiScattTerm is changed!
-    if (nPar_ == 5) {  // specific cuts for displaced tracking case.
-      //  Layer   =    0      1        2         3         4         5           6
-      z0Cut = {
-          999., 999., 1.7 * 15., 1.7 * 15., 1.7 * 15., 1.7 * 15., 1.7 * 15.};  // Larger values require digisation change.
-      chi2Cut = {999., 999., 10., 30., 80., 120., 160.};                       // Maybe loosen for high d0 ?
-    } else {  // specific cuts for prompt tracking case.
-      //  Layer   =    0      1      2     3     4      5      6
-      z0Cut = {999., 999., 15., 15., 15., 15., 15.};
-      chi2Cut = {999., 999., 10., 30., 80., 120., 160.};
-    }
+    // Set cut values that are different for 4 & 5 param helix fits.
+    vector<double> kfLayerVsZ0Cut = (nHelixPar_ == 5) ? kfLayerVsZ0Cut5_ : kfLayerVsZ0Cut4_;
+    vector<double> kfLayerVsChiSqCut = (nHelixPar_ == 5) ? kfLayerVsChiSq5_ : kfLayerVsChiSq4_;
 
     unsigned nStubLayers = state.nStubLayers();
     bool goodState(true);
@@ -245,13 +239,13 @@ namespace tmtt {
 
     // state parameter selections
 
-    if (z0 > z0Cut[nStubLayers])
+    if (z0 > kfLayerVsZ0Cut[nStubLayers])
       goodState = false;
-    if (pt < settings_->houghMinPt() - ptTolerance[nStubLayers])
+    if (pt < settings_->houghMinPt() - kfLayerVsPtToler_[nStubLayers])
       goodState = false;
-    if (nPar_ == 5) {
+    if (nHelixPar_ == 5) {  // fit without d0 constraint
       double d0 = std::abs(state.vectorX()[D0]);
-      if (d0 > d0Cut[nStubLayers])
+      if (d0 > kfLayerVsD0Cut5_[nStubLayers])
         goodState = false;
     }
 
@@ -259,7 +253,7 @@ namespace tmtt {
 
     double chi2scaled = state.chi2scaled();  // chi2(r-phi) scaled down to improve electron performance.
 
-    if (chi2scaled > chi2Cut[nStubLayers])
+    if (chi2scaled > kfLayerVsChiSqCut[nStubLayers])
       goodState = false;  // No separate pT selection needed
 
     const bool countUpdateCalls = false;  // Print statement to count calls to Updator.
@@ -277,7 +271,7 @@ namespace tmtt {
         text << " pt(mc)=" << tpa_->pt();
       text << " pt=" << pt << " q/pt=" << qOverPt << " tanL=" << vecY[T] << " z0=" << vecY[Z0]
            << " phi0=" << vecY[PHI0];
-      if (nPar_ == 5)
+      if (nHelixPar_ == 5)  // fit without d0 constraint
         text << " d0=" << vecY[D0];
       text << " fake" << (tpa_ == nullptr);
       if (tpa_ != nullptr)
diff --git a/L1Trigger/TrackFindingTMTT/src/KFbase.cc b/L1Trigger/TrackFindingTMTT/src/KFbase.cc
index 88ac5fb54c5e0..f0f20e2c0ada1 100644
--- a/L1Trigger/TrackFindingTMTT/src/KFbase.cc
+++ b/L1Trigger/TrackFindingTMTT/src/KFbase.cc
@@ -26,9 +26,9 @@ namespace tmtt {
 
   /* Initialize cfg parameters */
 
-  KFbase::KFbase(const Settings *settings, const uint nPar, const string &fitterName, const uint nMeas)
+  KFbase::KFbase(const Settings *settings, const uint nHelixPar, const string &fitterName, const uint nMeas)
       : TrackFitGeneric(settings, fitterName) {
-    nPar_ = nPar;
+    nHelixPar_ = nHelixPar;
     nMeas_ = nMeas;
     numEtaRegions_ = settings->numEtaRegions();
   }
@@ -47,7 +47,7 @@ namespace tmtt {
     sort(stubs.begin(), stubs.end(), orderByLayer);  // Makes debug printout pretty.
 
     //TP
-    const TP *tpa(0);
+    const TP *tpa(nullptr);
     if (l1track3D.matchedTP()) {
       tpa = l1track3D.matchedTP();
     }
@@ -78,7 +78,7 @@ namespace tmtt {
     if (cand != nullptr) {
       // Get track helix params.
       TVectorD trackPars = trackParams(cand);
-      double d0 = (nPar_ == 5) ? trackPars[D0] : 0.;
+      double d0 = (nHelixPar_ == 5) ? trackPars[D0] : 0.;
 
       L1fittedTrack fitTrk(settings_,
                            &l1track3D,
@@ -91,32 +91,15 @@ namespace tmtt {
                            trackPars[T],
                            cand->chi2rphi(),
                            cand->chi2rz(),
-                           nPar_);
-
-      bool consistentHLS = false;  // No longer used
-      //    if (this->isHLS()) {
-      //      unsigned int mBinHelixHLS, cBinHelixHLS;
-      //      cand->getHLSselect(mBinHelixHLS, cBinHelixHLS, consistentHLS);
-      //      if( settings_->kalmanDebugLevel() >= 3 ){
-      //        // Check if (m,c) corresponding to helix params are correctly calculated by HLS code.
-      //        bool HLS_OK = ((mBinHelixHLS == fitTrk.cellLocationFit().first) && (cBinHelixHLS == fitTrk.cellLocationFit().second));
-      //        if (not HLS_OK) PrintL1trk()<<"WARNING HLS mBinHelix disagrees with C++:"
-      //                                 <<" (HLS,C++) m=("<<mBinHelixHLS<<","<<fitTrk.cellLocationFit().first <<")"
-      //                                 <<" c=("<<cBinHelixHLS<<","<<fitTrk.cellLocationFit().second<<")";
-      //      }
-      //    }
+                           nHelixPar_);
 
       // Store supplementary info, specific to KF fitter.
-      if (this->isHLS() && nPar_ == 4) {
-        fitTrk.setInfoKF(cand->nSkippedLayers(), numUpdateCalls_, consistentHLS);
-      } else {
-        fitTrk.setInfoKF(cand->nSkippedLayers(), numUpdateCalls_);
-      }
+      fitTrk.setInfoKF(cand->nSkippedLayers(), numUpdateCalls_);
 
       // If doing 5 parameter fit, optionally also calculate helix params & chi2 with beam-spot constraint applied,
       // and store inside L1fittedTrack object.
       if (settings_->kalmanAddBeamConstr()) {
-        if (nPar_ == 5) {
+        if (nHelixPar_ == 5) {
           double chi2rphi_bcon = 0.;
           TVectorD trackPars_bcon = trackParams_BeamConstr(cand, chi2rphi_bcon);
           fitTrk.setBeamConstr(trackPars_bcon[QOVERPT], trackPars_bcon[PHI0], chi2rphi_bcon);
@@ -158,7 +141,7 @@ namespace tmtt {
             for (const TP *tp_i : stub->assocTPs())
               text << " " << tp_i->index();
             PrintL1trk() << text.str();
-            if (stub->assocTPs().size() == 0)
+            if (stub->assocTPs().empty())
               PrintL1trk() << " none";
           }
           PrintL1trk() << "=====================";
@@ -189,7 +172,7 @@ namespace tmtt {
     // seed helix params & their covariance.
     TVectorD x0 = seedX(l1track3D);
     TMatrixD pxx0 = seedC(l1track3D);
-    TMatrixD K(nPar_, 2);
+    TMatrixD K(nHelixPar_, 2);
     TMatrixD dcov(2, 2);
 
     const KalmanState *state0 = mkState(l1track3D, 0, -1, nullptr, x0, pxx0, K, dcov, nullptr, 0, 0);
@@ -211,7 +194,8 @@ namespace tmtt {
       // Get Kalman encoded layer ID for this stub.
       int kalmanLay = this->kalmanLayer(etaReg, stub->layerIdReduced(), stub->barrel(), stub->r(), stub->z());
 
-      if (kalmanLay != 7) {
+      constexpr unsigned int invalidKFlayer = 7;
+      if (kalmanLay != invalidKFlayer) {
         if (layerStubs[kalmanLay].size() < settings_->kalmanMaxStubsPerLayer()) {
           layerStubs[kalmanLay].push_back(stub);
         } else {
@@ -222,7 +206,9 @@ namespace tmtt {
     }
 
     // iterate using state->nextLayer() to determine next Kalman layer(s) to add stubs from
-    const unsigned int maxIterations = 6;  // Increase if you want to allow 7 stubs per fitted track.
+    constexpr unsigned int nTypicalLayers = 6;  // Number of tracker layers a typical track can pass through.
+    // If user asked to add up to 7 layers to track, increase number of iterations by 1.
+    const unsigned int maxIterations = std::max(nTypicalLayers, settings_->kalmanMaxNumStubs());
     for (unsigned iteration = 0; iteration < maxIterations; iteration++) {
       int combinations_per_iteration = 0;
 
@@ -244,11 +230,11 @@ namespace tmtt {
         // Continue to skip until you reach a functioning layer (or a layer with stubs)
         unsigned nSkippedDeadLayers = 0;
         unsigned nSkippedAmbiguousLayers = 0;
-        while (kfDeadLayers.find(layer) != kfDeadLayers.end() && layerStubs[layer].size() == 0) {
+        while (kfDeadLayers.find(layer) != kfDeadLayers.end() && layerStubs[layer].empty()) {
           layer += 1;
           ++nSkippedDeadLayers;
         }
-        while (this->kalmanAmbiguousLayer(etaReg, layer) && layerStubs[layer].size() == 0) {
+        while (this->kalmanAmbiguousLayer(etaReg, layer) && layerStubs[layer].empty()) {
           layer += 1;
           ++nSkippedAmbiguousLayers;
         }
@@ -270,10 +256,10 @@ namespace tmtt {
         unsigned nSkippedDeadLayers_nextStubs = 0;
         unsigned nSkippedAmbiguousLayers_nextStubs = 0;
         if (nSkipped < kalmanMaxSkipLayers) {
-          if (kfDeadLayers.find(layer + 1) != kfDeadLayers.end() && layerStubs[layer + 1].size() == 0) {
+          if (kfDeadLayers.find(layer + 1) != kfDeadLayers.end() && layerStubs[layer + 1].empty()) {
             nextlay_stubs = layerStubs[layer + 2];
             nSkippedDeadLayers_nextStubs++;
-          } else if (this->kalmanAmbiguousLayer(etaReg, layer) && layerStubs[layer + 1].size() == 0) {
+          } else if (this->kalmanAmbiguousLayer(etaReg, layer) && layerStubs[layer + 1].empty()) {
             nextlay_stubs = layerStubs[layer + 2];
             nSkippedAmbiguousLayers_nextStubs++;
           } else {
@@ -283,8 +269,8 @@ namespace tmtt {
 
         // If track was not rejected by isGoodState() is previous iteration, failure here usually means the tracker ran out of layers to explore.
         // (Due to "kalmanLay" not having unique ID for each layer within a given eta sector).
-        if (settings_->kalmanDebugLevel() >= 2 && best_state_by_nstubs.size() == 0 && thislay_stubs.size() == 0 &&
-            nextlay_stubs.size() == 0)
+        if (settings_->kalmanDebugLevel() >= 2 && best_state_by_nstubs.empty() && thislay_stubs.empty() &&
+            nextlay_stubs.empty())
           PrintL1trk() << "State is lost by start of iteration " << iteration
                        << " : #thislay_stubs=" << thislay_stubs.size() << " #nextlay_stubs=" << nextlay_stubs.size()
                        << " layer=" << layer << " eta=" << l1track3D.iEtaReg();
@@ -374,7 +360,7 @@ namespace tmtt {
 
       unsigned int nStubs = iteration + 1;
       // Success. We have at least one state that passes all cuts. Save best state found with this number of stubs.
-      if (nStubs >= settings_->kalmanMinNumStubs() && new_states.size() > 0)
+      if (nStubs >= settings_->kalmanMinNumStubs() && not new_states.empty())
         best_state_by_nstubs[nStubs] = new_states[0];
 
       if (nStubs == settings_->kalmanMaxNumStubs()) {
@@ -389,7 +375,7 @@ namespace tmtt {
       }
     }
 
-    if (best_state_by_nstubs.size()) {
+    if (not best_state_by_nstubs.empty()) {
       // Select state with largest number of stubs.
       finished_state = best_state_by_nstubs.begin()->second;  // First element has largest number of stubs.
       if (settings_->kalmanDebugLevel() >= 1) {
@@ -401,7 +387,7 @@ namespace tmtt {
              << l1track3D.cellLocationHT().first << "," << l1track3D.cellLocationHT().second << ")";
         TVectorD y = trackParams(finished_state);
         text << " q/pt=" << y[QOVERPT] << " tanL=" << y[T] << " z0=" << y[Z0] << " phi0=" << y[PHI0];
-        if (nPar_ == 5)
+        if (nHelixPar_ == 5)
           text << " d0=" << y[D0];
         text << " chosen from states:";
         for (const auto &p : best_state_by_nstubs)
@@ -459,7 +445,7 @@ namespace tmtt {
     TVectorD vecXref = matF * vecX;
     if (settings_->kalmanDebugLevel() >= 4) {
       PrintL1trk() << "vecFref = [";
-      for (unsigned i = 0; i < nPar_; i++)
+      for (unsigned i = 0; i < nHelixPar_; i++)
         PrintL1trk() << vecXref[i] << ", ";
       PrintL1trk() << "]";
     }
@@ -482,7 +468,7 @@ namespace tmtt {
       matC.Print();
     }
     // Get scattering contribution to helix parameter covariance (currently zero).
-    TMatrixD matScat(nPar_, nPar_);
+    TMatrixD matScat(nHelixPar_, nHelixPar_);
 
     // Get covariance on helix parameters at new reference point including scattering..
     TMatrixD matCref = matF * matC * matFtrans + matScat;
@@ -511,8 +497,8 @@ namespace tmtt {
     }
 
     // Update helix state & its covariance matrix with new stub.
-    TVectorD new_vecX(nPar_);
-    TMatrixD new_matC(nPar_, nPar_);
+    TVectorD new_vecX(nHelixPar_);
+    TMatrixD new_matC(nHelixPar_, nHelixPar_);
     adjustState(matK, matCref, vecXref, matH, delta, new_vecX, new_matC);
 
     // Update track fit chi2 with new stub.
@@ -520,10 +506,10 @@ namespace tmtt {
     this->adjustChi2(state, matRinv, delta, new_chi2rphi, new_chi2rz);
 
     if (settings_->kalmanDebugLevel() >= 4) {
-      if (nPar_ == 4)
+      if (nHelixPar_ == 4)
         PrintL1trk() << "adjusted x = " << new_vecX[0] << ", " << new_vecX[1] << ", " << new_vecX[2] << ", "
                      << new_vecX[3];
-      else if (nPar_ == 5)
+      else if (nHelixPar_ == 5)
         PrintL1trk() << "adjusted x = " << new_vecX[0] << ", " << new_vecX[1] << ", " << new_vecX[2] << ", "
                      << new_vecX[3] << ", " << new_vecX[4];
       PrintL1trk() << "adjusted C ";
@@ -575,7 +561,7 @@ namespace tmtt {
       matRinv = TMatrixD(TMatrixD::kInverted, matR);
     } else {
       // Protection against rare maths instability.
-      const TMatrixD unitMatrix(TMatrixD::kUnit, TMatrixD(nPar_, nPar_));
+      const TMatrixD unitMatrix(TMatrixD::kUnit, TMatrixD(nHelixPar_, nHelixPar_));
       const double big = 9.9e9;
       matRinv = big * unitMatrix;
     }
@@ -663,7 +649,7 @@ namespace tmtt {
                            TVectorD &new_vecX,
                            TMatrixD &new_matC) const {
     new_vecX = vecXref + matK * delta;
-    const TMatrixD unitMatrix(TMatrixD::kUnit, TMatrixD(nPar_, nPar_));
+    const TMatrixD unitMatrix(TMatrixD::kUnit, TMatrixD(nHelixPar_, nHelixPar_));
     TMatrixD tmp = unitMatrix - matK * matH;
     new_matC = tmp * matCref;
   }
@@ -742,19 +728,21 @@ namespace tmtt {
     if (not barrel) {
       switch (kfEtaReg) {
         case 4:  // B1 B2 B3 B4 B5/D1 B6/D2 D3
-          if (layerIDreduced == 3)
+          if (layerIDreduced == 3) {
             kalmanLay = 4;
-          if (layerIDreduced == 4)
+          } else if (layerIDreduced == 4) {
             kalmanLay = 5;
-          if (layerIDreduced == 5)
+          } else if (layerIDreduced == 5) {
             kalmanLay = 6;
+          }
           break;
           //case 5:  // B1 B2 B3+B4 D1 D2 D3 D4/D5
         case 5:  // B1 B2 B3 D1+B4 D2 D3 D4/D5
-          if (layerIDreduced == 5)
+          if (layerIDreduced == 5) {
             kalmanLay = 5;
-          if (layerIDreduced == 7)
+          } else if (layerIDreduced == 7) {
             kalmanLay = 6;
+          }
           break;
         default:
           break;
@@ -763,7 +751,7 @@ namespace tmtt {
 
     /*
   // Fix cases where a barrel layer only partially crosses the eta sector.
-  // (Logically should work, but actually reduces efficiency).
+  // (Logically should work, but actually reduces efficiency -- INVESTIGATE).
 
   const float barrelHalfLength = 120.;
   const float barrel4Radius = 68.8;
@@ -801,6 +789,7 @@ namespace tmtt {
 
   bool KFbase::kalmanAmbiguousLayer(unsigned int iEtaReg, unsigned int kfLayer) {
     // Only helps in extreme forward sector, and there not significantly.
+    // UNDERSTAND IF CAN BE USED ELSEWHERE.
 
     /*
   const unsigned int nEta = 16;
@@ -841,44 +830,40 @@ namespace tmtt {
     // Should TMTT tracking be modified to reduce efficiency loss due to dead modules?
     const bool killRecover = settings_->killRecover();
 
-    set<pair<unsigned, bool>> deadLayers;  // GP layer ID & boolean indicating if in barrel.
+    set<pair<unsigned, bool>> deadGPlayers;  // GP layer ID & boolean indicating if in barrel.
 
+    // Range of sectors chosen to cover dead regions from StubKiller.
     if (killRecover) {
       if (killScenario == StubKiller::KillOptions::layer5) {  // barrel layer 5
-        deadLayers.insert(pair<unsigned, bool>(4, true));
-        if (iEtaReg_ < 5 || iEtaReg_ > 8 || iPhiSec_ < 8 || iPhiSec_ > 11) {
-          deadLayers.clear();
+        if (iEtaReg_ >= 3 && iEtaReg_ <= 7 && iPhiSec_ >= 1 && iPhiSec_ <= 5) {
+          deadGPlayers.insert(pair<unsigned, bool>(4, true));
         }
-
       } else if (killScenario == StubKiller::KillOptions::layer1) {  // barrel layer 1
-        deadLayers.insert(pair<unsigned, bool>(1, true));
-        if (iEtaReg_ > 8 || iPhiSec_ < 8 || iPhiSec_ > 11) {
-          deadLayers.clear();
+        if (iEtaReg_ <= 7 && iPhiSec_ >= 1 && iPhiSec_ <= 5) {
+          deadGPlayers.insert(pair<unsigned, bool>(1, true));
         }
         remove2PSCut = true;
       } else if (killScenario == StubKiller::KillOptions::layer1layer2) {  // barrel layers 1 & 2
-        deadLayers.insert(pair<unsigned, bool>(1, true));
-        deadLayers.insert(pair<unsigned, bool>(2, true));
-        if (iEtaReg_ > 8 || iPhiSec_ < 8 || iPhiSec_ > 11) {
-          deadLayers.clear();
-        } else if (iEtaReg_ < 1) {
-          deadLayers.insert(pair<unsigned, bool>(0, true));  // What is this doing?
+        if (iEtaReg_ <= 7 && iPhiSec_ >= 1 && iPhiSec_ <= 5) {
+          deadGPlayers.insert(pair<unsigned, bool>(1, true));
+        }
+        if (iEtaReg_ >= 1 && iEtaReg_ <= 7 && iPhiSec_ >= 1 && iPhiSec_ <= 5) {
+          deadGPlayers.insert(pair<unsigned, bool>(2, true));
         }
         remove2PSCut = true;
       } else if (killScenario == StubKiller::KillOptions::layer1disk1) {  // barrel layer 1 & disk 1
-        deadLayers.insert(pair<unsigned, bool>(1, true));
-        deadLayers.insert(pair<unsigned, bool>(3, false));
-        if (iEtaReg_ > 8 || iPhiSec_ < 8 || iPhiSec_ > 11) {
-          deadLayers.clear();
-        } else if (iEtaReg_ > 3) {
-          deadLayers.insert(pair<unsigned, bool>(0, true));
+        if (iEtaReg_ <= 7 && iPhiSec_ >= 1 && iPhiSec_ <= 5) {
+          deadGPlayers.insert(pair<unsigned, bool>(1, true));
+        }
+        if (iEtaReg_ <= 3 && iPhiSec_ >= 1 && iPhiSec_ <= 5) {
+          deadGPlayers.insert(pair<unsigned, bool>(3, false));
         }
         remove2PSCut = true;
       }
     }
 
     set<unsigned> kfDeadLayers;
-    for (const auto &p : deadLayers) {
+    for (const auto &p : deadGPlayers) {
       unsigned int layer = p.first;
       bool barrel = p.second;
       float r = 0.;  // This fails for r-dependent parts of kalmanLayer(). FIX
@@ -929,7 +914,7 @@ namespace tmtt {
   void KFbase::printStubLayers(const vector<Stub *> &stubs, unsigned int iEtaReg) const {
     std::stringstream text;
     text << std::fixed << std::setprecision(4);
-    if (stubs.size() == 0)
+    if (stubs.empty())
       text << "stub layers = []\n";
     else {
       text << "stub layers = [ ";
diff --git a/L1Trigger/TrackFindingTMTT/src/KalmanState.cc b/L1Trigger/TrackFindingTMTT/src/KalmanState.cc
index a73140feb59bb..7aa9d42af6cc0 100644
--- a/L1Trigger/TrackFindingTMTT/src/KalmanState.cc
+++ b/L1Trigger/TrackFindingTMTT/src/KalmanState.cc
@@ -135,7 +135,7 @@ namespace tmtt {
         return state;
       state = state->last_state();
     }
-    return 0;
+    return nullptr;
   }
 
   std::vector<Stub *> KalmanState::stubs() const {
diff --git a/L1Trigger/TrackFindingTMTT/src/Make3Dtracks.cc b/L1Trigger/TrackFindingTMTT/src/Make3Dtracks.cc
index 3bf0eae7191c5..4e401ec8c8cdf 100644
--- a/L1Trigger/TrackFindingTMTT/src/Make3Dtracks.cc
+++ b/L1Trigger/TrackFindingTMTT/src/Make3Dtracks.cc
@@ -28,7 +28,7 @@ namespace tmtt {
         phiCentreSector_(phiCentreSector),  // Centre of phi sector
 
         // Note if any fitters require an r-z track filter to be run.
-        runRZfilter_(settings->useRZfilter().size() > 0) {
+        runRZfilter_(not settings->useRZfilter().empty()) {
     // Initialize any track filters (e.g. r-z) run after the r-phi Hough transform.
     if (runRZfilter_)
       rzFilter_ =
diff --git a/L1Trigger/TrackFindingTMTT/src/MiniHTstage.cc b/L1Trigger/TrackFindingTMTT/src/MiniHTstage.cc
index 460c88715ddb2..625b1305841e5 100644
--- a/L1Trigger/TrackFindingTMTT/src/MiniHTstage.cc
+++ b/L1Trigger/TrackFindingTMTT/src/MiniHTstage.cc
@@ -9,7 +9,7 @@ namespace tmtt {
   MiniHTstage::MiniHTstage(const Settings* settings)
       : settings_(settings),
         miniHTstage_(settings_->miniHTstage()),
-        muxOutputsHT_(settings_->muxOutputsHT()),
+        muxOutputsHT_(static_cast<MuxHToutputs::MuxAlgoName>(settings_->muxOutputsHT())),
         houghNbinsPt_(settings_->houghNbinsPt()),
         houghNbinsPhi_(settings_->houghNbinsPhi()),
         miniHoughLoadBalance_(settings_->miniHoughLoadBalance()),
@@ -34,7 +34,7 @@ namespace tmtt {
     nMiniHTcells_ = miniHoughNbinsPt_ * miniHoughNbinsPhi_;
 
     if (miniHoughLoadBalance_ != 0) {
-      if (muxOutputsHT_ == 1) {  // Multiplexer at output of HT enabled.
+      if (muxOutputsHT_ == MuxHToutputs::MuxAlgoName::mBinPerLink) {  // Multiplexer at output of HT enabled.
         nHTlinksPerNonant_ = busySectorMbinRanges_.size() - 1;
       } else {
         throw cms::Exception("BadConfig") << "MiniHTstage: Unknown MuxOutputsHT configuration option!";
@@ -44,11 +44,12 @@ namespace tmtt {
 
   void MiniHTstage::exec(matrix<unique_ptr<HTrphi>>& mHtRphis) {
     for (unsigned int iPhiNon = 0; iPhiNon < numPhiNonants_; iPhiNon++) {
-      map<pair<unsigned int, unsigned int>, unsigned int>
-          numStubsPerLinkStage1;  // Indices are ([link ID, MHT cell], #stubs).
-      map<pair<unsigned int, unsigned int>, unsigned int>
-          numStubsPerLinkStage2;                        // Indices are ([link ID, MHT cell], #stubs).
-      map<unsigned int, unsigned int> numStubsPerLink;  // Indices are ([link ID, MHT cell], #stubs).
+      // Indices are ([link ID, MHT cell], #stubs).
+      map<pair<unsigned int, unsigned int>, unsigned int> numStubsPerLinkStage1;
+      // Indices are ([link ID, MHT cell], #stubs).
+      map<pair<unsigned int, unsigned int>, unsigned int> numStubsPerLinkStage2;
+      // Indices are (link ID, #stubs).
+      map<unsigned int, unsigned int> numStubsPerLink;
       for (unsigned int iSecInNon = 0; iSecInNon < numPhiSecPerNon_; iSecInNon++) {
         unsigned int iPhiSec = iPhiNon * numPhiSecPerNon_ + iSecInNon;
         for (unsigned int iEtaReg = 0; iEtaReg < numEtaRegions_; iEtaReg++) {
@@ -184,7 +185,9 @@ namespace tmtt {
       unsigned int mBin,
       unsigned int cBin,
       unsigned int numStubs,
+      // Indices are ([link ID, MHT cell], #stubs).
       map<pair<unsigned int, unsigned int>, unsigned int>& numStubsPerLinkStage1,
+      // Indices are ([link ID, MHT cell], #stubs).
       map<pair<unsigned int, unsigned int>, unsigned int>& numStubsPerLinkStage2,
       bool test) const {
     unsigned int mhtCell = miniHoughNbinsPhi_ * mBin + cBin;  // Send each mini-cell to a different output link
diff --git a/L1Trigger/TrackFindingTMTT/src/MuxHToutputs.cc b/L1Trigger/TrackFindingTMTT/src/MuxHToutputs.cc
index 650f1e14617fc..77dc7146eb7b0 100644
--- a/L1Trigger/TrackFindingTMTT/src/MuxHToutputs.cc
+++ b/L1Trigger/TrackFindingTMTT/src/MuxHToutputs.cc
@@ -22,7 +22,7 @@ namespace tmtt {
 
   MuxHToutputs::MuxHToutputs(const Settings* settings)
       : settings_(settings),
-        muxOutputsHT_(settings_->muxOutputsHT()),
+        muxOutputsHT_(static_cast<MuxAlgoName>(settings_->muxOutputsHT())),
         numPhiNonants_(settings_->numPhiNonants()),
         numPhiSectors_(settings_->numPhiSectors()),
         numPhiSecPerNon_(numPhiSectors_ / numPhiNonants_),
@@ -31,7 +31,7 @@ namespace tmtt {
         busySectorNumStubs_(settings_->busySectorNumStubs()),  // Max. num. of stubs that can be sent within TM period
         busySectorMbinRanges_(
             settings_->busySectorMbinRanges()),  // Individual m bin (=q/Pt) ranges to be output to opto-links.
-        busySectorUseMbinRanges_(busySectorMbinRanges_.size() > 0)  // m bin ranges option disabled if vector empty.
+        busySectorUseMbinRanges_(not busySectorMbinRanges_.empty())  // m bin ranges option disabled if vector empty.
   {
     // Implemented MUX algorithm relies on same number of sectors per nonant.
     if (numPhiSectors_ % numPhiNonants_ != 0)
@@ -104,7 +104,7 @@ namespace tmtt {
   //=== Define the number of (eta,phi) sectors that each output opto-link takes tracks from. (Depends on MUX scheme).
 
   unsigned int MuxHToutputs::muxFactor() const {
-    if (muxOutputsHT_ == 1) {
+    if (muxOutputsHT_ == MuxAlgoName::mBinPerLink) {
       return numEtaRegions_ * numPhiSecPerNon_;
     } else {
       throw cms::Exception("BadConfig") << "MuxHToutputs: Unknown MuxOutputsHT configuration option!";
@@ -117,7 +117,7 @@ namespace tmtt {
   unsigned int MuxHToutputs::linkID(unsigned int iSecInNon, unsigned int iEtaReg, unsigned int mBinRange) const {
     unsigned int link;
 
-    if (muxOutputsHT_ == 1) {
+    if (muxOutputsHT_ == MuxAlgoName::mBinPerLink) {
       //--- This is the Sept. 2019 Mux for the transverse HT readout organised by m-bin. (Each m bin in entire nonant goes to a different link).
 
       link = 0;
diff --git a/L1Trigger/TrackFindingTMTT/src/Settings.cc b/L1Trigger/TrackFindingTMTT/src/Settings.cc
index 46cc178090bd0..0146ea6df187f 100644
--- a/L1Trigger/TrackFindingTMTT/src/Settings.cc
+++ b/L1Trigger/TrackFindingTMTT/src/Settings.cc
@@ -10,54 +10,59 @@ namespace tmtt {
   ///=== Hybrid Tracking
   ///=== Set config params for HYBRID TRACKING via hard-wired consts to allow use outside CMSSW.
 
-Settings::Settings():
-    //--------------------------------------------------------------------------------------------------
-    // TMTT related configuration parameters, including Kalman Filter.
-    // Meaning of these parameters explained in TrackFindingTMTT/python/TMTrackProducer_Defaults_cfi.py
-    //--------------------------------------------------------------------------------------------------
-
-    // General cfg params
-    enableDigitize_(false),
-    useApproxB_(true),
-    bApprox_gradient_(0.886454),
-    bApprox_intercept_(0.504148),
-    numPhiNonants_(9),
-    numPhiSectors_(9),    
-    chosenRofPhi_(55.), // Hourglass radius in r-phi (tracklet)
-etaRegions_({-2.4,-2.08,-1.68,-1.26,-0.90,-0.62,-0.41,-0.20,0.0,0.20,0.41,0.62,0.90,1.26,1.68,2.08,2.4}),  
-    chosenRofZ_(50.0), // Hourglass radius in r-z (this must be tmtt)
-    houghMinPt_(2.0), // L1 track pt cut
-    minStubLayers_(4),
-    minPtToReduceLayers_(99999.),
-    reduceLayerID_(true),
-    minFracMatchStubsOnReco_(-99),
-    minFracMatchStubsOnTP_(-99),
-    minNumMatchLayers_(4),
-    minNumMatchPSLayers_(0),
-    stubMatchStrict_(false),
-
-    // Kalman filter track fit cfg
-    kalmanDebugLevel_(0),
-    //kalmanDebugLevel_(2), // Good for debugging
-    kalmanMinNumStubs_(4),
-    kalmanMaxNumStubs_(6),
-    kalmanRemove2PScut_(true),
-    kalmanMaxSkipLayersHard_(1),  // On "hard" input tracks
-    kalmanMaxSkipLayersEasy_(2),  // On "easy" input tracks
-    kalmanMaxStubsEasy_(10),      // Max. #stubs an input track can have to be defined "easy"
-    kalmanMaxStubsPerLayer_(4),   // To save resources, consider at most this many stubs per layer per track.
-    kalmanMultiScattTerm_(0.00075),
-    kalmanChi2RphiScale_(8),
-    kalmanHOtilted_(true),
-    kalmanHOhelixExp_(true),
-    kalmanHOalpha_(1),
-    kalmanHOprojZcorr_(1),
-    kalmanHOfw_(false)    
-      {
-
+  Settings::Settings()
+      :  //--------------------------------------------------------------------------------------------------
+        // TMTT related configuration parameters, including Kalman Filter.
+        // Meaning of these parameters explained in TrackFindingTMTT/python/TMTrackProducer_Defaults_cfi.py
+        //--------------------------------------------------------------------------------------------------
+
+        // General cfg params
+        enableDigitize_(false),
+        useApproxB_(true),
+        bApprox_gradient_(0.886454),
+        bApprox_intercept_(0.504148),
+        numPhiNonants_(9),
+        numPhiSectors_(9),
+        chosenRofPhi_(55.),  // Hourglass radius in r-phi (tracklet)
+        etaRegions_(
+            {-2.4, -2.08, -1.68, -1.26, -0.90, -0.62, -0.41, -0.20, 0.0, 0.20, 0.41, 0.62, 0.90, 1.26, 1.68, 2.08, 2.4}),
+        chosenRofZ_(50.0),  // Hourglass radius in r-z (this must be tmtt)
+        houghMinPt_(2.0),   // L1 track pt cut
+        minStubLayers_(4),
+        minPtToReduceLayers_(99999.),
+        reduceLayerID_(true),
+        minFracMatchStubsOnReco_(-99),
+        minFracMatchStubsOnTP_(-99),
+        minNumMatchLayers_(4),
+        minNumMatchPSLayers_(0),
+        stubMatchStrict_(false),
+
+        // Kalman filter track fit cfg
+        kalmanDebugLevel_(0),
+        //kalmanDebugLevel_(2), // Good for debugging
+        kalmanMinNumStubs_(4),
+        kalmanMaxNumStubs_(6),
+        kalmanRemove2PScut_(true),
+        kalmanMaxSkipLayersHard_(1),  // On "hard" input tracks
+        kalmanMaxSkipLayersEasy_(2),  // On "easy" input tracks
+        kalmanMaxStubsEasy_(10),      // Max. #stubs an input track can have to be defined "easy"
+        kfLayerVsPtToler_({999., 999., 0.1, 0.1, 0.05, 0.05, 0.05}),
+        kfLayerVsD0Cut5_({999., 999., 999., 10., 10., 10., 10.}),
+        kfLayerVsZ0Cut5_({999., 999., 25.5, 25.5, 25.5, 25.5, 25.5}),
+        kfLayerVsZ0Cut4_({999., 999., 15., 15., 15., 15., 15.}),
+        kfLayerVsChiSq5_({999., 999., 10., 30., 80., 120., 160.}),
+        kfLayerVsChiSq4_({999., 999., 10., 30., 80., 120., 160.}),
+        kalmanMaxStubsPerLayer_(4),  // To save resources, consider at most this many stubs per layer per track.
+        kalmanMultiScattTerm_(0.00075),
+        kalmanChi2RphiScale_(8),
+        kalmanHOtilted_(true),
+        kalmanHOhelixExp_(true),
+        kalmanHOalpha_(1),
+        kalmanHOprojZcorr_(1),
+        kalmanHOfw_(false) {
     hybrid_ = true;
-    magneticField_ = 0.; // Value set later
-    killScenario_ = 0; // Emulation of dead modules
+    magneticField_ = 0.;  // Value set later
+    killScenario_ = 0;    // Emulation of dead modules
 
     if (hybrid_) {
       if (not useApproxB_) {
@@ -79,6 +84,8 @@ etaRegions_({-2.4,-2.08,-1.68,-1.26,-0.90,-0.62,-0.41,-0.20,0.0,0.20,0.41,0.62,0
         magneticFieldInputTag_(iConfig.getParameter<edm::ESInputTag>("magneticFieldInputTag")),
         trackerGeometryInputTag_(iConfig.getParameter<edm::ESInputTag>("trackerGeometryInputTag")),
         trackerTopologyInputTag_(iConfig.getParameter<edm::ESInputTag>("trackerTopologyInputTag")),
+        ttStubAlgoInputTag_(iConfig.getParameter<edm::ESInputTag>("ttStubAlgoInputTag")),
+
         stubInputTag_(iConfig.getParameter<edm::InputTag>("stubInputTag")),
         tpInputTag_(iConfig.getParameter<edm::InputTag>("tpInputTag")),
         stubTruthInputTag_(iConfig.getParameter<edm::InputTag>("stubTruthInputTag")),
@@ -266,6 +273,14 @@ etaRegions_({-2.4,-2.08,-1.68,-1.26,-0.90,-0.62,-0.41,-0.20,0.0,0.20,0.41,0.62,0
         kalmanMaxSkipLayersHard_(trackFitSettings_.getParameter<unsigned>("KalmanMaxSkipLayersHard")),
         kalmanMaxSkipLayersEasy_(trackFitSettings_.getParameter<unsigned>("KalmanMaxSkipLayersEasy")),
         kalmanMaxStubsEasy_(trackFitSettings_.getParameter<unsigned>("KalmanMaxStubsEasy")),
+
+        kfLayerVsPtToler_(trackFitSettings_.getParameter<vector<double>>("KFLayerVsPtToler")),
+        kfLayerVsD0Cut5_(trackFitSettings_.getParameter<vector<double>>("KFLayerVsD0Cut5")),
+        kfLayerVsZ0Cut5_(trackFitSettings_.getParameter<vector<double>>("KFLayerVsZ0Cut5")),
+        kfLayerVsZ0Cut4_(trackFitSettings_.getParameter<vector<double>>("KFLayerVsZ0Cut4")),
+        kfLayerVsChiSq5_(trackFitSettings_.getParameter<vector<double>>("KFLayerVsChiSq5")),
+        kfLayerVsChiSq4_(trackFitSettings_.getParameter<vector<double>>("KFLayerVsChiSq4")),
+
         kalmanMaxStubsPerLayer_(trackFitSettings_.getParameter<unsigned>("KalmanMaxStubsPerLayer")),
         kalmanMultiScattTerm_(trackFitSettings_.getParameter<double>("KalmanMultiScattTerm")),
         kalmanChi2RphiScale_(trackFitSettings_.getParameter<unsigned>("KalmanChi2RphiScale")),
@@ -325,8 +340,7 @@ etaRegions_({-2.4,-2.08,-1.68,-1.26,-0.90,-0.62,-0.41,-0.20,0.0,0.20,0.41,0.62,0
         magneticField_(0.),
 
         // Hybrid tracking
-        hybrid_(iConfig.getParameter<bool>("Hybrid"))
-  {
+        hybrid_(iConfig.getParameter<bool>("Hybrid")) {
     // If user didn't specify any PDG codes, use e,mu,pi,K,p, to avoid picking up unstable particles like Xi-.
     vector<unsigned int> genPdgIdsUnsigned(genCuts_.getParameter<vector<unsigned int>>("GenPdgIds"));
     if (genPdgIdsUnsigned.empty()) {
@@ -373,7 +387,7 @@ etaRegions_({-2.4,-2.08,-1.68,-1.26,-0.90,-0.62,-0.41,-0.20,0.0,0.20,0.41,0.62,0
           << "Settings: Invalid cfg parameters - You are setting the minimum number of layers incorrectly : type C.";
 
     // If reducing number of required layers for high Pt tracks, then above checks must be redone.
-    bool doReduceLayers = (minPtToReduceLayers_ < 10000. || etaSecsReduceLayers_.size() > 0);
+    bool doReduceLayers = (minPtToReduceLayers_ < 10000. || not etaSecsReduceLayers_.empty());
     if (doReduceLayers && minStubLayers_ > 4) {
       if (minNumMatchLayers_ > minStubLayers_ - 1)
         throw cms::Exception("BadConfig")
diff --git a/L1Trigger/TrackFindingTMTT/src/Stub.cc b/L1Trigger/TrackFindingTMTT/src/Stub.cc
index 86364219165af..81263a78085e7 100644
--- a/L1Trigger/TrackFindingTMTT/src/Stub.cc
+++ b/L1Trigger/TrackFindingTMTT/src/Stub.cc
@@ -7,6 +7,7 @@
 
 #include "L1Trigger/TrackFindingTMTT/interface/Stub.h"
 #include "L1Trigger/TrackFindingTMTT/interface/TP.h"
+#include "L1Trigger/TrackFindingTMTT/interface/StubKiller.h"
 #include "L1Trigger/TrackFindingTMTT/interface/PrintL1trk.h"
 
 #include <iostream>
@@ -18,8 +19,8 @@ namespace tmtt {
   //=== Hybrid L1 tracking: stub constructor.
 
   Stub::Stub(const Settings* settings,
-	     unsigned int idStub,
-	     double phi,
+             unsigned int idStub,
+             double phi,
              double r,
              double z,
              double bend,
@@ -29,11 +30,11 @@ namespace tmtt {
              unsigned int iPhiSec,
              bool psModule,
              bool barrel,
-	     bool tiltedBarrel,
-	     float stripPitch,
-	     float stripLength,
-	     unsigned int nStrips)
-    :   index_in_vStubs_(idStub),  // A unique ID to label the stub.
+             bool tiltedBarrel,
+             float stripPitch,
+             float stripLength,
+             unsigned int nStrips)
+      : index_in_vStubs_(idStub),  // A unique ID to label the stub.
         phi_(phi),
         r_(r),
         z_(z),
@@ -48,8 +49,7 @@ namespace tmtt {
         tiltedBarrel_(tiltedBarrel),
         stripPitch_(stripPitch),
         stripLength_(stripLength),
-        nStrips_(nStrips)
-{}
+        nStrips_(nStrips) {}
 
   //=== TMTT L1 tracking: stub constructor.
 
@@ -58,6 +58,7 @@ namespace tmtt {
              const Settings* settings,
              const TrackerTopology* trackerTopology,
              const TrackerModule* trackerModule,
+             const DegradeBend* degradeBend,
              const StubKiller* stubKiller)
       : ttStubRef_(ttStubRef),
         settings_(settings),
@@ -66,8 +67,8 @@ namespace tmtt {
         digitizeWarningsOn_(true),
         lastDigiStep_(Stub::DigiStage::NONE),
         trackerModule_(trackerModule),  // Info about tracker module containing stub
-        degradeBend_(trackerTopology),  // Used to degrade stub bend information.
-                                        // Module related variables (need to be stored for Hybrid)
+        degradeBend_(degradeBend),      // Used to degrade stub bend information.
+        // Module related variables (need to be stored for Hybrid)
         psModule_(trackerModule->psModule()),
         layerId_(trackerModule->layerId()),
         layerIdReduced_(trackerModule->layerIdReduced()),
@@ -90,13 +91,6 @@ namespace tmtt {
     r_ = pos.perp();
     z_ = pos.z();
 
-    if (r_ < settings_->trackerInnerRadius() || r_ > settings_->trackerOuterRadius() ||
-        std::abs(z_) > settings_->trackerHalfLength()) {
-      throw cms::Exception("BadConfig") << "Stub: Stub found outside assumed tracker volume. Please update tracker "
-                                           "dimensions specified in Settings.h!"
-                                        << " r=" << r_ << " z=" << z_ << " id=" << trackerModule_->detId().subdetId();
-    }
-
     // Get the coordinates of the two clusters that make up this stub, measured in units of strip pitch, and measured
     // in the local frame of the sensor. They have a granularity  of 0.5*pitch.
     for (unsigned int iClus = 0; iClus <= 1; iClus++) {  // Loop over two clusters in stub.
@@ -264,7 +258,7 @@ namespace tmtt {
       windowFE = rejectedStubBend_;  // TMTT is not tightening windows.
     }
 
-    degradeBend_.degrade(bend, psModule(), trackerModule_->detId(), windowFE, degradedBend, num);
+    degradeBend_->degrade(bend, psModule(), trackerModule_->detId(), windowFE, degradedBend, num);
   }
 
   //=== Set flag indicating if stub will be output by front-end readout electronics
@@ -286,8 +280,8 @@ namespace tmtt {
 
     if (frontendPass_ && this->bend() == rejectedStubBend_) {
       throw cms::Exception(
-          "LogicError: Window sizes assumed in DegradeBend are tighter than those used for TTStub production. Please "
-          "fix them");
+          "BadConfig: FE stub bend window sizes provided in cfg ES source are tighter than those to make the stubs. "
+          "Please fix them");
     }
 
     if (settings_->killLowPtStubs()) {
diff --git a/L1Trigger/TrackFindingTMTT/src/StubFEWindows.cc b/L1Trigger/TrackFindingTMTT/src/StubFEWindows.cc
new file mode 100644
index 0000000000000..29301fe732d79
--- /dev/null
+++ b/L1Trigger/TrackFindingTMTT/src/StubFEWindows.cc
@@ -0,0 +1,78 @@
+#include "L1Trigger/TrackFindingTMTT/interface/StubFEWindows.h"
+#include "L1Trigger/TrackFindingTMTT/interface/TrackerModule.h"
+#include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
+#include "DataFormats/SiStripDetId/interface/StripSubdetector.h"
+
+#include <algorithm>
+
+using namespace std;
+
+namespace tmtt {
+
+  //=== Initialize stub window sizes from TTStubProducer cfg.
+
+  StubFEWindows::StubFEWindows(const edm::ParameterSet& pSetStubAlgo) {
+    numTiltedLayerRings_ = pSetStubAlgo.getParameter<vector<double>>("NTiltedRings");
+    windowSizeBarrelLayers_ = pSetStubAlgo.getParameter<vector<double>>("BarrelCut");
+    const auto& pSetTiltedLayer = pSetStubAlgo.getParameter<vector<edm::ParameterSet>>("TiltedBarrelCutSet");
+    const auto& pSetEncapDisks = pSetStubAlgo.getParameter<vector<edm::ParameterSet>>("EndcapCutSet");
+    windowSizeTiltedLayersRings_.reserve(pSetTiltedLayer.size());
+    for (const auto& pSet : pSetTiltedLayer) {
+      windowSizeTiltedLayersRings_.emplace_back(pSet.getParameter<vector<double>>("TiltedCut"));
+    }
+    windowSizeEndcapDisksRings_.reserve(pSetEncapDisks.size());
+    for (const auto& pSet : pSetEncapDisks) {
+      windowSizeEndcapDisksRings_.emplace_back(pSet.getParameter<vector<double>>("EndcapCut"));
+    }
+  }
+
+  //=== Set all FE stub bend windows to zero.
+
+  void StubFEWindows::setZero() {
+    std::fill(windowSizeBarrelLayers_.begin(), windowSizeBarrelLayers_.end(), 0.);
+    for (auto& x : windowSizeEndcapDisksRings_)
+      std::fill(x.begin(), x.end(), 0.);
+    for (auto& y : windowSizeTiltedLayersRings_)
+      std::fill(y.begin(), y.end(), 0.);
+  }
+
+  //=== Const/non-const access to element of array giving window size for specific module.
+
+  const double* StubFEWindows::storedWindowSize(const TrackerTopology* trackerTopo, const DetId& detId) const {
+    // Code accessing geometry inspired by L1Trigger/TrackTrigger/src/TTStubAlgorithm_official.cc
+
+    const double* storedHalfWindow = nullptr;
+    if (detId.subdetId() == StripSubdetector::TOB) {
+      unsigned int layer = trackerTopo->layer(detId);
+      unsigned int ladder = trackerTopo->tobRod(detId);
+      int type = 2 * trackerTopo->tobSide(detId) - 3;  // -1 for tilted-, 1 for tilted+, 3 for flat
+      double corr = 0;
+
+      if (type != TrackerModule::BarrelModuleType::flat) {
+        // Tilted barrel
+        corr = (numTiltedLayerRings_.at(layer) + 1) / 2.;
+        // Corrected ring number, between 0 and barrelNTilt.at(layer), in ascending |z|
+        ladder = corr - (corr - ladder) * type;
+        storedHalfWindow = &(windowSizeTiltedLayersRings_.at(layer).at(ladder));
+      } else {
+        // Flat barrel
+        storedHalfWindow = &(windowSizeBarrelLayers_.at(layer));
+      }
+
+    } else if (detId.subdetId() == StripSubdetector::TID) {
+      // Endcap
+      unsigned int wheel = trackerTopo->tidWheel(detId);
+      unsigned int ring = trackerTopo->tidRing(detId);
+      storedHalfWindow = &(windowSizeEndcapDisksRings_.at(wheel).at(ring));
+    }
+    return storedHalfWindow;
+  }
+
+  double* StubFEWindows::storedWindowSize(const TrackerTopology* trackerTopo, const DetId& detId) {
+    // Code accessing geometry inspired by L1Trigger/TrackTrigger/src/TTStubAlgorithm_official.cc
+
+    // Scott Meyers's solution to give const & non-const versions of same function, without
+    // code duplication.
+    return const_cast<double*>((static_cast<const StubFEWindows*>(this))->storedWindowSize(trackerTopo, detId));
+  }
+}  // namespace tmtt
diff --git a/L1Trigger/TrackFindingTMTT/src/StubKiller.cc b/L1Trigger/TrackFindingTMTT/src/StubKiller.cc
index 0845c47251000..df9351eacac80 100644
--- a/L1Trigger/TrackFindingTMTT/src/StubKiller.cc
+++ b/L1Trigger/TrackFindingTMTT/src/StubKiller.cc
@@ -111,6 +111,8 @@ namespace tmtt {
     if (killScenario_ == KillOptions::none)
       return false;
     else {
+      // Check if stub is in dead region specified by *ToKill_
+      // And randomly kill stubs throughout tracker (not just thos in specific regions/modules)
       bool killStubRandomly = killStub(stub,
                                        layersToKill_,
                                        minPhiToKill_,
@@ -121,13 +123,15 @@ namespace tmtt {
                                        maxRToKill_,
                                        fractionOfStubsToKillInLayers_,
                                        fractionOfStubsToKillEverywhere_);
+      // Kill modules in specifid modules
+      // Random modules throughout the tracker, and those modules in specific regions (so may already have been killed by killStub above)
       bool killStubInDeadModules = killStubInDeadModule(stub);
       return killStubRandomly || killStubInDeadModules;
     }
   }
 
-  // Indicate if given stub was killed by dead tracker module, based on dead regions specified here,
-  // and ignoring dead module scenario.
+  // Indicate if given stub was killed by dead tracker module, based on specified dead regions
+  // rather than based on the dead module scenario.
   // layersToKill - a vector stating the layers we are killing stubs in.  Can be an empty vector.
   // Barrel layers are encoded as 1-6. The endcap layers are encoded as 11-15 (-z) and 21-25 (+z)
   // min/max Phi/Z/R - stubs within the region specified by these boundaries and layersToKill are flagged for killing
@@ -145,39 +149,42 @@ namespace tmtt {
                             const double fractionOfStubsToKillInLayers,
                             const double fractionOfStubsToKillEverywhere) const {
     // Only kill stubs in specified layers
-    if (layersToKill.size() > 0) {
+    if (not layersToKill.empty()) {
       // Get the layer the stub is in, and check if it's in the layer you want to kill
       DetId stackDetid = stub->getDetId();
       DetId geoDetId(stackDetid.rawId() + 1);
 
-      bool isInBarrel = geoDetId.subdetId() == StripSubdetector::TOB || geoDetId.subdetId() == StripSubdetector::TIB;
+      // If this module is in the deadModule list, don't also try to kill the stub here
+      if (deadModules_.empty() || deadModules_.find(geoDetId) == deadModules_.end()) {
+        bool isInBarrel = geoDetId.subdetId() == StripSubdetector::TOB || geoDetId.subdetId() == StripSubdetector::TIB;
 
-      int layerID = 0;
-      if (isInBarrel) {
-        layerID = trackerTopology_->layer(geoDetId);
-      } else {
-        layerID = 10 * trackerTopology_->side(geoDetId) + trackerTopology_->tidWheel(geoDetId);
-      }
+        int layerID = 0;
+        if (isInBarrel) {
+          layerID = trackerTopology_->layer(geoDetId);
+        } else {
+          layerID = 10 * trackerTopology_->side(geoDetId) + trackerTopology_->tidWheel(geoDetId);
+        }
 
-      if (find(layersToKill.begin(), layersToKill.end(), layerID) != layersToKill.end()) {
-        // Get the phi and z of stub, and check if it's in the region you want to kill
-        const GeomDetUnit* det0 = trackerGeometry_->idToDetUnit(geoDetId);
-        const PixelGeomDetUnit* theGeomDet = dynamic_cast<const PixelGeomDetUnit*>(det0);
-        const PixelTopology* topol = dynamic_cast<const PixelTopology*>(&(theGeomDet->specificTopology()));
-        MeasurementPoint measurementPoint = stub->clusterRef(0)->findAverageLocalCoordinatesCentered();
-        LocalPoint clustlp = topol->localPosition(measurementPoint);
-        GlobalPoint pos = theGeomDet->surface().toGlobal(clustlp);
-
-        double stubPhi = reco::deltaPhi(pos.phi(), 0.);
-
-        if (stubPhi > minPhiToKill && stubPhi < maxPhiToKill && pos.z() > minZToKill && pos.z() < maxZToKill &&
-            pos.perp() > minRToKill && pos.perp() < maxRToKill) {
-          // Kill fraction of stubs
-          if (fractionOfStubsToKillInLayers == 1) {
-            return true;
-          } else {
-            if (rndmEngine_->flat() < fractionOfStubsToKillInLayers) {
+        if (find(layersToKill.begin(), layersToKill.end(), layerID) != layersToKill.end()) {
+          // Get the phi and z of stub, and check if it's in the region you want to kill
+          const GeomDetUnit* det0 = trackerGeometry_->idToDetUnit(geoDetId);
+          const PixelGeomDetUnit* theGeomDet = dynamic_cast<const PixelGeomDetUnit*>(det0);
+          const PixelTopology* topol = dynamic_cast<const PixelTopology*>(&(theGeomDet->specificTopology()));
+          MeasurementPoint measurementPoint = stub->clusterRef(0)->findAverageLocalCoordinatesCentered();
+          LocalPoint clustlp = topol->localPosition(measurementPoint);
+          GlobalPoint pos = theGeomDet->surface().toGlobal(clustlp);
+
+          double stubPhi = reco::deltaPhi(pos.phi(), 0.);
+
+          if (stubPhi > minPhiToKill && stubPhi < maxPhiToKill && pos.z() > minZToKill && pos.z() < maxZToKill &&
+              pos.perp() > minRToKill && pos.perp() < maxRToKill) {
+            // Kill fraction of stubs
+            if (fractionOfStubsToKillInLayers == 1) {
               return true;
+            } else {
+              if (rndmEngine_->flat() < fractionOfStubsToKillInLayers) {
+                return true;
+              }
             }
           }
         }
@@ -197,11 +204,19 @@ namespace tmtt {
   // Indicate if given stub was in (partially) dead tracker module, based on dead module scenario.
 
   bool StubKiller::killStubInDeadModule(const TTStub<Ref_Phase2TrackerDigi_>* stub) const {
-    if (deadModules_.size() > 0) {
+    if (not deadModules_.empty()) {
       DetId stackDetid = stub->getDetId();
       DetId geoDetId(stackDetid.rawId() + 1);
-      if (deadModules_.find(geoDetId) != deadModules_.end())
-        return true;
+      auto deadModule = deadModules_.find(geoDetId);
+      if (deadModule != deadModules_.end()) {
+        if (deadModule->second == 1) {
+          return true;
+        } else {
+          if (rndmEngine_->flat() < deadModule->second) {
+            return true;
+          }
+        }
+      }
     }
 
     return false;
diff --git a/L1Trigger/TrackFindingTMTT/src/StubWindowSuggest.cc b/L1Trigger/TrackFindingTMTT/src/StubWindowSuggest.cc
index feb536692f9a9..dc2d3326480cb 100644
--- a/L1Trigger/TrackFindingTMTT/src/StubWindowSuggest.cc
+++ b/L1Trigger/TrackFindingTMTT/src/StubWindowSuggest.cc
@@ -39,17 +39,12 @@ namespace tmtt {
   void StubWindowSuggest::updateStoredWindow(const TrackerTopology* trackerTopo,
                                              const Stub* stub,
                                              double bendHalfWind) {
-    // Values set according to L1Trigger/TrackTrigger/python/TTStubAlgorithmRegister_cfi.py
-    // parameter NTiltedRings for whichever tracker geometry (T3, T4, T5 ...) is used..
-    const vector<double> barrelNTilt_init = {0., 12., 12., 12., 0., 0., 0.};
-    barrelNTilt_ = barrelNTilt_init;
-
-    // This code should be kept almost identical to that in
-    // L1Trigger/TrackTrigger/src/TTStubAlgorithm_official.cc
-    // The only exceptions are lines marked "Modified by TMTT group"
+    // Code accessing geometry inspired by L1Trigger/TrackTrigger/src/TTStubAlgorithm_official.cc
 
     DetId stDetId(stub->trackerModule()->detId());
 
+    double* storedHalfWindow = sw_.storedWindowSize(trackerTopo, stDetId);
+    /*
     if (stDetId.subdetId() == StripSubdetector::TOB) {
       unsigned int layer = trackerTopo->layer(stDetId);
       unsigned int ladder = trackerTopo->tobRod(stDetId);
@@ -58,39 +53,29 @@ namespace tmtt {
 
       if (type != TrackerModule::BarrelModuleType::flat)  // Only for tilted modules
       {
-        corr = (barrelNTilt_.at(layer) + 1) / 2.;
-        ladder =
-            corr - (corr - ladder) * type;  // Corrected ring number, bet 0 and barrelNTilt.at(layer), in ascending |z|
-        // Modified by TMTT group, to expland arrays if necessary, divide by 2, & update the stored window sizes.
-        if (tiltedCut_.size() < (layer + 1))
-          tiltedCut_.resize(layer + 1);
-        if (tiltedCut_.at(layer).size() < (ladder + 1))
-          tiltedCut_.at(layer).resize(ladder + 1, 0.);
-        double& storedHalfWindow = (tiltedCut_.at(layer)).at(ladder);
+        corr = (sw_.numTiltedLayerRings().at(layer) + 1) / 2.;
+	// Corrected ring number, between 0 and barrelNTilt.at(layer), in ascending |z|
+        ladder = corr - (corr - ladder) * type;  
+        double& storedHalfWindow = (sw_.windowSizeTiltedLayersRings().at(layer)).at(ladder);
         if (storedHalfWindow < bendHalfWind)
           storedHalfWindow = bendHalfWind;
       } else  // Classic barrel window otherwise
       {
-        // Modified by TMTT group, to expand arrays if necessary, divide by 2, & update the stored window sizes.
-        if (barrelCut_.size() < (layer + 1))
-          barrelCut_.resize(layer + 1, 0.);
-        double& storedHalfWindow = barrelCut_.at(layer);
+        double& storedHalfWindow = sw_.windowSizeBarrelLayers().at(layer);
         if (storedHalfWindow < bendHalfWind)
           storedHalfWindow = bendHalfWind;
       }
 
     } else if (stDetId.subdetId() == StripSubdetector::TID) {
-      // Modified by TMTT group, to expland arrays if necessary, divide by 2, & update the stored window sizes
       unsigned int wheel = trackerTopo->tidWheel(stDetId);
       unsigned int ring = trackerTopo->tidRing(stDetId);
-      if (ringCut_.size() < (wheel + 1))
-        ringCut_.resize(wheel + 1);
-      if (ringCut_.at(wheel).size() < (ring + 1))
-        ringCut_.at(wheel).resize(ring + 1, 0.);
-      double& storedHalfWindow = ringCut_.at(wheel).at(ring);
+      double& storedHalfWindow = sw_.windowSizeEndcapDisksRings().at(wheel).at(ring);
       if (storedHalfWindow < bendHalfWind)
         storedHalfWindow = bendHalfWind;
     }
+*/
+    if (*storedHalfWindow < bendHalfWind)
+      *storedHalfWindow = bendHalfWind;
   }
 
   //=== Print results (should be done in endJob();
@@ -108,7 +93,7 @@ namespace tmtt {
 
     text << "BarrelCut = cms.vdouble( ";
     div = "";
-    for (const auto& cut : barrelCut_) {
+    for (const auto& cut : sw_.windowSizeBarrelLayers()) {
       text << div << cut;
       div = ", ";
     }
@@ -116,7 +101,7 @@ namespace tmtt {
     PrintL1trk(1) << text.str();
 
     PrintL1trk(1) << "TiltedBarrelCutSet = cms.VPSET( ";
-    for (const auto& cutVec : tiltedCut_) {
+    for (const auto& cutVec : sw_.windowSizeTiltedLayersRings()) {
       text.str("");
       text << "     cms.PSet( TiltedCut = cms.vdouble(";
       if (cutVec.empty())
@@ -132,7 +117,7 @@ namespace tmtt {
     PrintL1trk(1) << "),";
 
     PrintL1trk(1) << "EndcapCutSet = cms.VPSET( ";
-    for (const auto& cutVec : ringCut_) {
+    for (const auto& cutVec : sw_.windowSizeEndcapDisksRings()) {
       text.str("");
       text << "     cms.PSet( EndcapCut = cms.vdouble(";
       if (cutVec.empty())
diff --git a/L1Trigger/TrackFindingTMTT/src/TP.cc b/L1Trigger/TrackFindingTMTT/src/TP.cc
index 580044a68f665..832ae09949768 100644
--- a/L1Trigger/TrackFindingTMTT/src/TP.cc
+++ b/L1Trigger/TrackFindingTMTT/src/TP.cc
@@ -5,6 +5,8 @@
 #include "L1Trigger/TrackFindingTMTT/interface/Utility.h"
 #include "DataFormats/Math/interface/deltaR.h"
 
+#include <array>
+
 using namespace std;
 
 namespace tmtt {
@@ -63,11 +65,11 @@ namespace tmtt {
     // Keep only those TP that have a chance (allowing for finite track resolution) of being reconstructed as L1 tracks. L1 tracks not matching these TP will be defined as fake.
 
     // Include all possible particle types here, as if some are left out, L1 tracks matching one of missing types will be declared fake.
-    static const vector<int> genPdgIdsAllUnsigned = {11, 13, 211, 321, 2212};
+    constexpr std::array<int, 5> genPdgIdsAllUnsigned = {{11, 13, 211, 321, 2212}};
     vector<int> genPdgIdsAll;
-    for (unsigned int i = 0; i < genPdgIdsAllUnsigned.size(); i++) {
-      genPdgIdsAll.push_back(genPdgIdsAllUnsigned[i]);
-      genPdgIdsAll.push_back(-genPdgIdsAllUnsigned[i]);
+    for (const int& iPdg : genPdgIdsAllUnsigned) {
+      genPdgIdsAll.push_back(iPdg);
+      genPdgIdsAll.push_back(-iPdg);
     }
 
     // Range big enough to include all TP needed to measure tracking efficiency
diff --git a/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc b/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc
index 767b2aa701c2e..e79389e097e35 100644
--- a/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc
+++ b/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc
@@ -19,6 +19,8 @@ namespace tmtt {
     std::once_flag printOnce;
   }
 
+  const float TrackerModule::invRoot12 = sqrt(1. / 12.);
+
   //=== Get info about tracker module (where detId is ID of lower sensor in stacked module).
 
   TrackerModule::TrackerModule(const TrackerGeometry* trackerGeometry,
diff --git a/L1Trigger/TrackFindingTMTT/src/TrkRZfilter.cc b/L1Trigger/TrackFindingTMTT/src/TrkRZfilter.cc
index 6d37a6432f26b..26832f16e8bfd 100644
--- a/L1Trigger/TrackFindingTMTT/src/TrkRZfilter.cc
+++ b/L1Trigger/TrackFindingTMTT/src/TrkRZfilter.cc
@@ -184,6 +184,7 @@ namespace tmtt {
 
               // Estimate a value of z at the beam spot using the two seeding stubs
               double z0 = s1->z() + (-s1->z() + s0->z()) * s1->r() / (s1->r() - s0->r());
+              // COMMENTED OUT CODE GIVES OPTION OF ALLOWING FOR UNCERTAINTY. NOT WORTH IT?
               //double z0err = s1->sigmaZ() + ( s1->sigmaZ() + s0->sigmaZ() )*s1->r()/std::abs(s1->r()-s0->r()) + std::abs(-s1->z()+s0->z())*(s1->sigmaR()*std::abs(s1->r()-s0->r()) + s1->r()*(s1->sigmaR() + s0->sigmaR()) )/((s1->r()-s0->r())*(s1->r()-s0->r()));
               // Estimate a value of z at a chosen Radius using the two seeding stubs
               float zTrk = s1->z() + (-s1->z() + s0->z()) * (s1->r() - chosenRofZ_) / (s1->r() - s0->r());
diff --git a/L1Trigger/TrackFindingTMTT/src/Utility.cc b/L1Trigger/TrackFindingTMTT/src/Utility.cc
index ee6fca615aa0a..32f285571f150 100644
--- a/L1Trigger/TrackFindingTMTT/src/Utility.cc
+++ b/L1Trigger/TrackFindingTMTT/src/Utility.cc
@@ -5,7 +5,7 @@
 
 #include "FWCore/Utilities/interface/Exception.h"
 
-#include <set>
+#include <unordered_set>
 
 using namespace std;
 
@@ -35,7 +35,7 @@ namespace tmtt {
     bool reduce = (disableReducedLayerID) ? false : reduceLayerID;
 
     // Count layers using CMSSW layer ID.
-    set<unsigned int> foundLayers;
+    unordered_set<unsigned int> foundLayers;
     for (const Stub* stub : vstubs) {
       if ((!onlyPS) || stub->psModule()) {  // Consider only stubs in PS modules if that option specified.
         // Use either normal or reduced layer ID depending on request.
@@ -157,7 +157,7 @@ namespace tmtt {
         reduce = true;
 
       // or to increase efficiency in the barrel-endcap transition or very forward regions.
-      const vector<unsigned int> etaSecsRed = settings->etaSecsReduceLayers();
+      const vector<unsigned int>& etaSecsRed = settings->etaSecsReduceLayers();
       if (std::count(etaSecsRed.begin(), etaSecsRed.end(), iEtaReg) != 0)
         reduce = true;
 
diff --git a/L1Trigger/TrackFindingTMTT/test/tmtt_tf_analysis_cfg.py b/L1Trigger/TrackFindingTMTT/test/tmtt_tf_analysis_cfg.py
index e24fb509e4280..60807b026a2f4 100644
--- a/L1Trigger/TrackFindingTMTT/test/tmtt_tf_analysis_cfg.py
+++ b/L1Trigger/TrackFindingTMTT/test/tmtt_tf_analysis_cfg.py
@@ -91,13 +91,6 @@ def getTxtFile(txtFileName):
 
 process.Timing = cms.Service("Timing", summaryOnly = cms.untracked.bool(True))
 
-# Random number generator for Stub Killer (dead module emulation)
-process.RandomNumberGeneratorService = cms.Service("RandomNumberGeneratorService",
-    TMTrackProducer = cms.PSet(
-        initialSeed = cms.untracked.uint32(12345)
-    )
-)
-
 #--- Load code that produces our L1 tracks and makes corresponding histograms.
 #process.load('L1Trigger.TrackFindingTMTT.TMTrackProducer_cff')
 
@@ -158,7 +151,7 @@ def getTxtFile(txtFileName):
 
         else:
           # S.Viret's July 2017 stub windows (tight) from commented out part of
-         # L1Trigger/TrackTrigger/python/TTStubAlgorithmRegister_cfi.py in CMSSW 9.3.2
+          # L1Trigger/TrackTrigger/python/TTStubAlgorithmRegister_cfi.py in CMSSW 9.3.2
 
           process.TTStubAlgorithm_official_Phase2TrackerDigi_ = cms.ESProducer("TTStubAlgorithm_official_Phase2TrackerDigi_",
           zMatchingPS  = cms.bool(True),