diff --git a/Framework/API/inc/MantidAPI/AlgorithmHistory.h b/Framework/API/inc/MantidAPI/AlgorithmHistory.h
index 78b04c21c1de57618a493758e1ad7931035ea2b3..59f63f111216a0b39aebb39d3384b48d3908dec0 100644
--- a/Framework/API/inc/MantidAPI/AlgorithmHistory.h
+++ b/Framework/API/inc/MantidAPI/AlgorithmHistory.h
@@ -15,8 +15,6 @@
 #include "MantidKernel/PropertyHistory.h"
 #include <nexus/NeXusFile.hpp>
 
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
 #include <ctime>
 #include <set>
 #include <vector>
diff --git a/Framework/API/src/IMDWorkspace.cpp b/Framework/API/src/IMDWorkspace.cpp
index 248fd5c8d146a679d3a461add5e28f3342ef6d39..10f38bf13e560010e83054376d1e331a90f7f327 100644
--- a/Framework/API/src/IMDWorkspace.cpp
+++ b/Framework/API/src/IMDWorkspace.cpp
@@ -135,7 +135,7 @@ const std::string IMDWorkspace::toString() const {
 void IMDWorkspace::makeSinglePointWithNaN(std::vector<coord_t> &x,
                                           std::vector<signal_t> &y,
                                           std::vector<signal_t> &e) const {
-  x.emplace_back(0);
+  x.emplace_back(0.f);
   y.emplace_back(std::numeric_limits<signal_t>::quiet_NaN());
   e.emplace_back(std::numeric_limits<signal_t>::quiet_NaN());
 }
diff --git a/Framework/API/src/IndexProperty.cpp b/Framework/API/src/IndexProperty.cpp
index 3a14b0852a07770cd4c520dd2c601999b6b55d40..977b69f8056ba68787fb6168c491932a0be54a7b 100644
--- a/Framework/API/src/IndexProperty.cpp
+++ b/Framework/API/src/IndexProperty.cpp
@@ -9,6 +9,7 @@
 #include "MantidIndexing/GlobalSpectrumIndex.h"
 #include "MantidIndexing/IndexInfo.h"
 #include "MantidIndexing/SpectrumNumber.h"
+#include "MantidKernel/WarningSuppressions.h"
 
 namespace Mantid {
 namespace API {
@@ -73,6 +74,7 @@ Indexing::SpectrumIndexSet IndexProperty::getIndices() const {
             static_cast<Indexing::SpectrumNumber>(static_cast<int32_t>(max)));
       }
     } else {
+      MSVC_DIAG_OFF(4244);
       switch (type) {
       case IndexType::WorkspaceIndex:
         return indexInfo.makeIndexSet(
@@ -84,6 +86,7 @@ Indexing::SpectrumIndexSet IndexProperty::getIndices() const {
         return indexInfo.makeIndexSet(spectrumNumbers);
       }
       }
+      MSVC_DIAG_ON(4244);
     }
   }
 
diff --git a/Framework/Algorithms/src/ConvertSpectrumAxis.cpp b/Framework/Algorithms/src/ConvertSpectrumAxis.cpp
index 310b43ca6fafb02cc4e5c378e66fd8b4b5ac68ac..28d196f097e56f70f08d1a8b30832e622d616093 100644
--- a/Framework/Algorithms/src/ConvertSpectrumAxis.cpp
+++ b/Framework/Algorithms/src/ConvertSpectrumAxis.cpp
@@ -20,9 +20,6 @@
 #include "MantidKernel/Unit.h"
 #include "MantidKernel/UnitFactory.h"
 
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-
 #include <cfloat>
 
 namespace Mantid {
@@ -129,13 +126,14 @@ void ConvertSpectrumAxis::exec() {
   } else {
     // Set up binding to memeber funtion. Avoids condition as part of loop over
     // nHistograms.
-    boost::function<double(const IDetector &)> thetaFunction;
+    using namespace std::placeholders;
+    std::function<double(const IDetector &)> thetaFunction;
     if (unitTarget == "signed_theta") {
       thetaFunction =
-          boost::bind(&MatrixWorkspace::detectorSignedTwoTheta, inputWS, _1);
+          std::bind(&MatrixWorkspace::detectorSignedTwoTheta, inputWS, _1);
     } else {
       thetaFunction =
-          boost::bind(&MatrixWorkspace::detectorTwoTheta, inputWS, _1);
+          std::bind(&MatrixWorkspace::detectorTwoTheta, inputWS, _1);
     }
 
     bool warningGiven = false;
diff --git a/Framework/Algorithms/src/ConvertUnitsUsingDetectorTable.cpp b/Framework/Algorithms/src/ConvertUnitsUsingDetectorTable.cpp
index 0861c9b73c47da9f2964ae34321506b742fc5bea..ffbf9b641d7ba3332b2c76eda1dff17fa56af839 100644
--- a/Framework/Algorithms/src/ConvertUnitsUsingDetectorTable.cpp
+++ b/Framework/Algorithms/src/ConvertUnitsUsingDetectorTable.cpp
@@ -18,7 +18,6 @@
 #include "MantidKernel/Unit.h"
 #include "MantidKernel/UnitFactory.h"
 
-#include <boost/bind.hpp>
 #include <boost/function.hpp>
 
 #include <algorithm>
diff --git a/Framework/Algorithms/test/WienerSmoothTest.h b/Framework/Algorithms/test/WienerSmoothTest.h
index 2e23642e37ab259b48dfb7aeaaee2913128084b4..eb772bfbdb3df66222ed75313a7000b3ef0dcd95 100644
--- a/Framework/Algorithms/test/WienerSmoothTest.h
+++ b/Framework/Algorithms/test/WienerSmoothTest.h
@@ -647,8 +647,9 @@ private:
       Y.assign(y, y + ny);
       E.assign(e, e + ny);
       using std::placeholders::_1;
-      std::transform(Y.begin(), Y.end(), Y.begin(),
-                     std::bind(std::multiplies<double>(), _1, i + 1));
+      std::transform(
+          Y.begin(), Y.end(), Y.begin(),
+          std::bind(std::multiplies<double>(), _1, static_cast<double>(i + 1)));
     }
 
     return dataWS;
diff --git a/Framework/CMakeLists.txt b/Framework/CMakeLists.txt
index fe0306b6dc98d20734dea40df4d2b182a1915cbd..fe0655675f91b6948921ffcf5e23375d1d1e97a0 100644
--- a/Framework/CMakeLists.txt
+++ b/Framework/CMakeLists.txt
@@ -212,8 +212,13 @@ foreach(_bundle ${BUNDLES})
 
     # Also ship mingw libraries for Inelastic fortran code. We need to do a
     # better job here and build things
-    file(GLOB MINGW_DLLS "${THIRD_PARTY_DIR}/bin/mingw/*.dll")
-    install(FILES ${MINGW_DLLS} DESTINATION ${_bundle}scripts/Inelastic)
+    if(WITH_PYTHON3)
+      install(FILES "${THIRD_PARTY_DIR}/bin/libquadmath-0.dll" "${THIRD_PARTY_DIR}/bin/libgcc_s_seh-1.dll"
+              DESTINATION ${_bundle}scripts/Inelastic)
+    else()
+      file(GLOB MINGW_DLLS "${THIRD_PARTY_DIR}/bin/mingw/*.dll")
+      install(FILES ${MINGW_DLLS} DESTINATION ${_bundle}scripts/Inelastic)
+    endif()
   else()
     install(DIRECTORY ../scripts/
             DESTINATION ${_bundle}scripts
diff --git a/Framework/CurveFitting/src/Functions/ComptonScatteringCountRate.cpp b/Framework/CurveFitting/src/Functions/ComptonScatteringCountRate.cpp
index 9866ce0bfe5e761f3e992b01c85b8f3c1c83a57b..b0e6ce7ceac7568a3e2fb2d13a8233a40083f8d4 100644
--- a/Framework/CurveFitting/src/Functions/ComptonScatteringCountRate.cpp
+++ b/Framework/CurveFitting/src/Functions/ComptonScatteringCountRate.cpp
@@ -10,8 +10,6 @@
 #include "MantidCurveFitting/AugmentedLagrangianOptimizer.h"
 #include "MantidKernel/Math/Optimization/SLSQPMinimizer.h"
 
-#include <boost/bind.hpp>
-
 #include <sstream>
 
 namespace Mantid {
@@ -166,8 +164,9 @@ void ComptonScatteringCountRate::iterationStarting() {
 
   if (m_bkgdPolyN > 0) {
     BkgdNorm2 objf(m_cmatrix, m_dataErrorRatio);
+    using namespace std::placeholders;
     AugmentedLagrangianOptimizer::ObjFunction objfunc =
-        boost::bind(&BkgdNorm2::eval, objf, _1, _2);
+        std::bind(&BkgdNorm2::eval, objf, _1, _2);
     AugmentedLagrangianOptimizer lsqmin(nparams, objfunc, m_eqMatrix,
                                         m_cmatrix);
     lsqmin.minimize(x0);
diff --git a/Framework/CurveFitting/test/AugmentedLagrangianOptimizerTest.h b/Framework/CurveFitting/test/AugmentedLagrangianOptimizerTest.h
index 627d83ab81ea44cab3480af4ae9981e334ff00c2..32ecca97fac0a8edc26b0231be199383a5d46ed2 100644
--- a/Framework/CurveFitting/test/AugmentedLagrangianOptimizerTest.h
+++ b/Framework/CurveFitting/test/AugmentedLagrangianOptimizerTest.h
@@ -12,7 +12,6 @@
 #include "MantidCurveFitting/AugmentedLagrangianOptimizer.h"
 #include "MantidKernel/Matrix.h"
 
-#include <boost/bind.hpp>
 #include <boost/make_shared.hpp>
 
 class AugmentedLagrangianOptimizerTest : public CxxTest::TestSuite {
@@ -78,11 +77,12 @@ public:
 
   void test_minimizer_calls_user_function() {
     using Mantid::CurveFitting::AugmentedLagrangianOptimizer;
+    using namespace std::placeholders;
 
     bool userFuncCalled = false;
     TestUserFuncCall testFunc(userFuncCalled);
     AugmentedLagrangianOptimizer::ObjFunction userFunc =
-        boost::bind(&TestUserFuncCall::eval, testFunc, _1, _2);
+        std::bind(&TestUserFuncCall::eval, testFunc, _1, _2);
     AugmentedLagrangianOptimizer lsqmin(2, userFunc);
 
     std::vector<double> xv(2, 1);
diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadAscii2.h b/Framework/DataHandling/inc/MantidDataHandling/LoadAscii2.h
index 561ff25566b17da2ee974d01b3877a4e7bce8288..df4771a4f6a17577b9718e31bbeb5ef7532ae010 100644
--- a/Framework/DataHandling/inc/MantidDataHandling/LoadAscii2.h
+++ b/Framework/DataHandling/inc/MantidDataHandling/LoadAscii2.h
@@ -40,7 +40,7 @@ public:
   /// Summary of algorithms purpose
   const std::string summary() const override {
     return "Loads data from a text file and stores it in a 2D workspace "
-           "(Workspace2D class).";
+           "or Table Workspace.";
   }
 
   /// The version number
@@ -56,6 +56,8 @@ public:
 protected:
   /// Read the data from the file
   virtual API::Workspace_sptr readData(std::ifstream &file);
+  /// Read the data from the file into a table workspace
+  virtual API::Workspace_sptr readTable(std::ifstream &file);
   /// Return true if the line is to be skipped
   bool skipLine(const std::string &line, bool header = false) const;
   /// Return true if the line doesn't start with a valid character
diff --git a/Framework/DataHandling/inc/MantidDataHandling/SaveAscii2.h b/Framework/DataHandling/inc/MantidDataHandling/SaveAscii2.h
index 9ff03e61e77ad02bbca8b757ba929631d8aae959..4f189859690356d091e1df104ebce941bf1fc99e 100644
--- a/Framework/DataHandling/inc/MantidDataHandling/SaveAscii2.h
+++ b/Framework/DataHandling/inc/MantidDataHandling/SaveAscii2.h
@@ -12,6 +12,7 @@
 //----------------------------------------------------------------------
 #include "MantidAPI/Algorithm.h"
 #include "MantidAPI/Axis.h"
+#include "MantidAPI/ITableWorkspace_fwd.h"
 #include "MantidAPI/MatrixWorkspace_fwd.h"
 
 namespace Mantid {
@@ -71,6 +72,10 @@ private:
   void init() override;
   /// Overwrites Algorithm method
   void exec() override;
+  void writeTableWorkspace(API::ITableWorkspace_const_sptr tws,
+                           const std::string &filename, bool appendToFile,
+                           bool writeHeader, int prec, bool scientific,
+                           const std::string &comment);
   /// Writes a spectrum to the file using a workspace index
   void writeSpectrum(const int &wsIndex, std::ofstream &file);
   std::vector<std::string> stringListToVector(std::string &inputString);
diff --git a/Framework/DataHandling/src/EventWorkspaceCollection.cpp b/Framework/DataHandling/src/EventWorkspaceCollection.cpp
index dbe936af1fcb85a392855f991a6bf86947938086..7d570943446221361b908e4cd2307b0f2f15fcea 100644
--- a/Framework/DataHandling/src/EventWorkspaceCollection.cpp
+++ b/Framework/DataHandling/src/EventWorkspaceCollection.cpp
@@ -14,7 +14,6 @@
 #include "MantidIndexing/IndexInfo.h"
 #include "MantidKernel/UnitFactory.h"
 
-#include <boost/bind.hpp>
 #include <memory>
 #include <set>
 #include <unordered_set>
diff --git a/Framework/DataHandling/src/LoadAscii.cpp b/Framework/DataHandling/src/LoadAscii.cpp
index 8b102fc8a0d07d35873b061f4e708b2d85836af4..edbef52288ce83bb3b3b5809059ad6a1af212c83 100644
--- a/Framework/DataHandling/src/LoadAscii.cpp
+++ b/Framework/DataHandling/src/LoadAscii.cpp
@@ -45,9 +45,14 @@ int LoadAscii::confidence(Kernel::FileDescriptor &descriptor) const {
 
   // Avoid some known file types that have different loaders
   int confidence(0);
-  if (filePath.compare(filenameLength - 12, 12, "_runinfo.xml") == 0 ||
-      filePath.compare(filenameLength - 6, 6, ".peaks") == 0 ||
-      filePath.compare(filenameLength - 10, 10, ".integrate") == 0) {
+  if (filenameLength > 12
+          ? (filePath.compare(filenameLength - 12, 12, "_runinfo.xml") == 0)
+          : false || filenameLength > 6
+                ? (filePath.compare(filenameLength - 6, 6, ".peaks") == 0)
+                : false || filenameLength > 10
+                      ? (filePath.compare(filenameLength - 10, 10,
+                                          ".integrate") == 0)
+                      : false) {
     confidence = 0;
   } else if (descriptor.isAscii()) {
     confidence = 9; // Low so that others may try but not stopping version 2
diff --git a/Framework/DataHandling/src/LoadAscii2.cpp b/Framework/DataHandling/src/LoadAscii2.cpp
index 75a208de12569937a509d8b089bca07ec6fbcfcd..9bce357a49ad3f82f0ed9327a97574a1aa91fd58 100644
--- a/Framework/DataHandling/src/LoadAscii2.cpp
+++ b/Framework/DataHandling/src/LoadAscii2.cpp
@@ -10,7 +10,9 @@
 #include "MantidAPI/NumericAxis.h"
 #include "MantidAPI/RegisterFileLoader.h"
 #include "MantidAPI/Run.h"
+#include "MantidAPI/TableRow.h"
 #include "MantidAPI/WorkspaceFactory.h"
+#include "MantidDataObjects/TableWorkspace.h"
 #include "MantidDataObjects/Workspace2D.h"
 #include "MantidHistogramData/HistogramMath.h"
 #include "MantidKernel/BoundedValidator.h"
@@ -51,9 +53,14 @@ int LoadAscii2::confidence(Kernel::FileDescriptor &descriptor) const {
 
   // Avoid some known file types that have different loaders
   int confidence(0);
-  if (filePath.compare(filenameLength - 12, 12, "_runinfo.xml") == 0 ||
-      filePath.compare(filenameLength - 6, 6, ".peaks") == 0 ||
-      filePath.compare(filenameLength - 10, 10, ".integrate") == 0) {
+  if (filenameLength > 12
+          ? (filePath.compare(filenameLength - 12, 12, "_runinfo.xml") == 0)
+          : false || filenameLength > 6
+                ? (filePath.compare(filenameLength - 6, 6, ".peaks") == 0)
+                : false || filenameLength > 10
+                      ? (filePath.compare(filenameLength - 10, 10,
+                                          ".integrate") == 0)
+                      : false) {
     confidence = 0;
   } else if (descriptor.isAscii()) {
     confidence = 10; // Low so that others may try
@@ -78,6 +85,12 @@ API::Workspace_sptr LoadAscii2::readData(std::ifstream &file) {
   // there is still flexibility, but the format should just make more sense in
   // general
 
+  // if the file appears to be a table workspace then read it as such
+  auto ws = readTable(file);
+  if (ws) {
+    return ws;
+  }
+
   m_baseCols = 0;
   m_specNo = 0;
   m_lastBins = 0;
@@ -134,6 +147,140 @@ API::Workspace_sptr LoadAscii2::readData(std::ifstream &file) {
   return localWorkspace;
 }
 
+/// Attempts to read a table workspace from the file.
+/// Failing early if the format does not match.
+/// @param file the file handle to load from
+/// @returns a populated table workspace or an empty shared pointer
+API::Workspace_sptr LoadAscii2::readTable(std::ifstream &file) {
+
+  DataObjects::TableWorkspace_sptr ws;
+  // We need to see two rows commented out
+  // the first with column names
+  // the second with column types
+  // Then we need data, with the same number of columns as the first two lines
+
+  try {
+    size_t colNames = 0;
+    size_t colTypes = 0;
+    std::string line;
+    std::list<std::string> names;
+    std::list<std::string> types;
+    std::list<std::string> data;
+
+    while (getline(file, line)) {
+      boost::trim(line);
+
+      std::list<std::string> columns;
+
+      if (!line.empty()) {
+        // if line starts with a comment
+        if (line.at(0) == m_comment.at(0)) {
+          // remove the comment character
+          line.erase(0, 1);
+          size_t lineCols = this->splitIntoColumns(columns, line);
+          if (colNames == 0) {
+            colNames = lineCols;
+            names = columns;
+            continue;
+          }
+          if (colTypes == 0) {
+            colTypes = lineCols;
+            types = columns;
+            continue;
+          }
+        }
+
+        if (colTypes != colNames) {
+          // no point going further, the types and names differ in quantity
+          break;
+        }
+
+        size_t colData = this->splitIntoColumns(data, line);
+        if (colNames > 0 && colNames == colTypes && colTypes == colData) {
+          // we seem to have a table workspace
+          // if we have no already created a workspace
+          if (!ws) {
+            ws = boost::make_shared<DataObjects::TableWorkspace>();
+            // create the columns
+            auto itName = names.begin();
+            auto itTypes = types.begin();
+            for (size_t i = 0; i < colNames; i++) {
+              std::string name = *itName;
+              std::string type = *itTypes;
+              // trim the strings
+              boost::trim(name);
+              boost::trim(type);
+              ws->addColumn(std::move(type), std::move(name));
+              itName++;
+              itTypes++;
+            }
+          }
+          // add the data
+          TableRow row = ws->appendRow();
+          auto itTypes = types.begin();
+          for (auto itData = data.begin(); itData != data.end(); itData++) {
+            // direct assignment only works for strings, we ill need to handle
+            // the other data types here
+            std::string type = *itTypes;
+            boost::trim(type);
+            if (type == "str") {
+              row << *itData;
+            } else if (type == "int") {
+              int num = boost::lexical_cast<int>(*itData);
+              row << num;
+            } else if (type == "uint") {
+              uint32_t num = boost::lexical_cast<uint32_t>(*itData);
+              row << num;
+            } else if (type == "long64") {
+              auto num = boost::lexical_cast<int64_t>(*itData);
+              row << num;
+            } else if (type == "size_t") {
+              size_t num = boost::lexical_cast<size_t>(*itData);
+              row << num;
+            } else if (type == "float") {
+              float num = boost::lexical_cast<float>(*itData);
+              row << num;
+            } else if (type == "double") {
+              double num = boost::lexical_cast<double>(*itData);
+              row << num;
+            } else if (type == "bool") {
+              bool val = (itData->at(0) == 't');
+              row << val;
+            } else if (type == "V3D") {
+              V3D val;
+              std::stringstream ss(*itData);
+              val.readPrinted(ss);
+              row << val;
+            } else {
+              throw std::runtime_error("unknown column data type " + type);
+            }
+            itTypes++;
+          }
+        }
+      }
+    }
+    // if the file does not have more than rowsToCheck, it will
+    // stop
+    // and raise the EndOfFile, this may cause problems for small workspaces.
+    // In this case clear the flag
+    if (file.eof()) {
+      file.clear(file.eofbit);
+    }
+  } catch (std::exception &ex) {
+    // log and squash the error, so we can still try to load the file as a
+    // matrix workspace
+    g_log.warning() << "Error while trying to read ascii file as table, "
+                       "continuing to load as matrix workspace.\n"
+                    << ex.what() << "\n";
+    // clear any workspace that we started loading
+    ws.reset();
+  }
+
+  // Seek the file pointer back to the start.
+  file.seekg(0, std::ios::beg);
+  return ws;
+}
+
 /**
  * Check the start of the file for the first data set, then set the number of
  * columns that hsould be expected thereafter
@@ -754,8 +901,10 @@ void LoadAscii2::exec() {
   }
   MatrixWorkspace_sptr outputWS =
       boost::dynamic_pointer_cast<MatrixWorkspace>(rd);
-  outputWS->mutableRun().addProperty("Filename", filename);
-  setProperty("OutputWorkspace", outputWS);
+  if (outputWS) {
+    outputWS->mutableRun().addProperty("Filename", filename);
+  }
+  setProperty("OutputWorkspace", rd);
 }
 } // namespace DataHandling
 } // namespace Mantid
diff --git a/Framework/DataHandling/src/LoadHFIRSANS.cpp b/Framework/DataHandling/src/LoadHFIRSANS.cpp
index fff19d713188c0ba730189b0b288a2024e00f3f8..f1e86e0da34f44707ca679d0953b454b9b961b6d 100644
--- a/Framework/DataHandling/src/LoadHFIRSANS.cpp
+++ b/Framework/DataHandling/src/LoadHFIRSANS.cpp
@@ -538,10 +538,20 @@ void LoadHFIRSANS::storeMetaDataIntoWS() {
       "source-aperture-diameter",
       boost::lexical_cast<double>(m_metadata["Header/source_aperture_size"]),
       "mm");
+  addRunProperty<double>(
+      "source_aperture_diameter",
+      boost::lexical_cast<double>(m_metadata["Header/source_aperture_size"]),
+      "mm");
+
   addRunProperty<double>(
       "sample-aperture-diameter",
       boost::lexical_cast<double>(m_metadata["Header/sample_aperture_size"]),
       "mm");
+  addRunProperty<double>(
+      "sample_aperture_diameter",
+      boost::lexical_cast<double>(m_metadata["Header/sample_aperture_size"]),
+      "mm");
+
   addRunProperty<double>(
       "number-of-guides",
       boost::lexical_cast<double>(m_metadata["Motor_Positions/nguides"]));
@@ -629,6 +639,9 @@ void LoadHFIRSANS::setDetectorDistance() {
                 << " mm." << '\n';
   addRunProperty<double>("sample-detector-distance", m_sampleDetectorDistance,
                          "mm");
+  addRunProperty<double>("sample_detector_distance", m_sampleDetectorDistance,
+                         "mm");
+
   addRunTimeSeriesProperty<double>("sdd", m_sampleDetectorDistance);
 }
 
@@ -736,6 +749,9 @@ void LoadHFIRSANS::setBeamDiameter() {
   double sourceToSampleDistance = getSourceToSampleDistance();
   addRunProperty<double>("source-sample-distance", sourceToSampleDistance,
                          "mm");
+  addRunProperty<double>("source_sample_distance", sourceToSampleDistance,
+                         "mm");
+
   const auto sampleAperture =
       boost::lexical_cast<double>(m_metadata["Header/sample_aperture_size"]);
   const auto sourceAperture =
diff --git a/Framework/DataHandling/src/LoadPreNexus.cpp b/Framework/DataHandling/src/LoadPreNexus.cpp
index bd0e5c8407fdbb5a577e8e9e5e43575196813ce1..b59b0a213fd2420d645dc461c6501ee6c0c8b759 100644
--- a/Framework/DataHandling/src/LoadPreNexus.cpp
+++ b/Framework/DataHandling/src/LoadPreNexus.cpp
@@ -62,7 +62,9 @@ const std::string LoadPreNexus::category() const {
  */
 int LoadPreNexus::confidence(Kernel::FileDescriptor &descriptor) const {
   const std::string &filename = descriptor.filename();
-  if (filename.compare(filename.size() - 12, 12, "_runinfo.xml") == 0)
+  if (filename.size() > 12
+          ? (filename.compare(filename.size() - 12, 12, "_runinfo.xml") == 0)
+          : false)
     return 80;
   else
     return 0;
diff --git a/Framework/DataHandling/src/LoadTBL.cpp b/Framework/DataHandling/src/LoadTBL.cpp
index 1a13221e1807ea618236cb224b855a3999b4af4c..ba9169b5b1fa1285cce080d3f9ae950cf01e3ee0 100644
--- a/Framework/DataHandling/src/LoadTBL.cpp
+++ b/Framework/DataHandling/src/LoadTBL.cpp
@@ -42,9 +42,14 @@ int LoadTBL::confidence(Kernel::FileDescriptor &descriptor) const {
 
   // Avoid some known file types that have different loaders
   int confidence(0);
-  if (filePath.compare(filenameLength - 12, 12, "_runinfo.xml") == 0 ||
-      filePath.compare(filenameLength - 6, 6, ".peaks") == 0 ||
-      filePath.compare(filenameLength - 10, 10, ".integrate") == 0) {
+  if (filenameLength > 12
+          ? (filePath.compare(filenameLength - 12, 12, "_runinfo.xml") == 0)
+          : false || filenameLength > 6
+                ? (filePath.compare(filenameLength - 6, 6, ".peaks") == 0)
+                : false || filenameLength > 10
+                      ? (filePath.compare(filenameLength - 10, 10,
+                                          ".integrate") == 0)
+                      : false) {
     confidence = 0;
   } else if (descriptor.isAscii()) {
     std::istream &stream = descriptor.data();
diff --git a/Framework/DataHandling/src/SaveAscii2.cpp b/Framework/DataHandling/src/SaveAscii2.cpp
index fab6e66fffee6d0a258b62cd72a2f382b63ab56e..97e0db1dfc76654d38cdd0fe362f4c0ed356840d 100644
--- a/Framework/DataHandling/src/SaveAscii2.cpp
+++ b/Framework/DataHandling/src/SaveAscii2.cpp
@@ -11,6 +11,7 @@
 #include "MantidAPI/FileProperty.h"
 #include "MantidAPI/MatrixWorkspace.h"
 #include "MantidAPI/SpectrumInfo.h"
+#include "MantidDataObjects/TableWorkspace.h"
 #include "MantidGeometry/Instrument.h"
 #include "MantidKernel/ArrayProperty.h"
 #include "MantidKernel/BoundedValidator.h"
@@ -42,8 +43,8 @@ SaveAscii2::SaveAscii2()
 /// Initialisation method.
 void SaveAscii2::init() {
   declareProperty(
-      std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "",
-                                                           Direction::Input),
+      std::make_unique<WorkspaceProperty<Workspace>>("InputWorkspace", "",
+                                                     Direction::Input),
       "The name of the workspace containing the data you want to save to a "
       "Ascii file.");
 
@@ -56,26 +57,29 @@ void SaveAscii2::init() {
   mustBePositive->setLower(1);
   auto mustBeZeroGreater = boost::make_shared<BoundedValidator<int>>();
   mustBeZeroGreater->setLower(0);
-  declareProperty("WorkspaceIndexMin", EMPTY_INT(), mustBeZeroGreater,
-                  "The starting workspace index.");
+  declareProperty(
+      "WorkspaceIndexMin", EMPTY_INT(), mustBeZeroGreater,
+      "The starting workspace index. Ignored for Table Workspaces.");
   declareProperty("WorkspaceIndexMax", EMPTY_INT(), mustBeZeroGreater,
-                  "The ending workspace index.");
-  declareProperty(std::make_unique<ArrayProperty<int>>("SpectrumList"),
-                  "List of workspace indices to save.");
+                  "The ending workspace index. Ignored for Table Workspaces.");
+  declareProperty(
+      std::make_unique<ArrayProperty<int>>("SpectrumList"),
+      "List of workspace indices to save. Ignored for Table Workspaces.");
   declareProperty("Precision", EMPTY_INT(), mustBePositive,
                   "Precision of output double values.");
   declareProperty("ScientificFormat", false,
                   "If true, the values will be "
                   "written to the file in "
                   "scientific notation.");
+  declareProperty("WriteXError", false,
+                  "If true, the error on X will be written as the fourth "
+                  "column. Ignored for Table Workspaces.");
   declareProperty(
-      "WriteXError", false,
-      "If true, the error on X will be written as the fourth column.");
-  declareProperty("WriteSpectrumID", true,
-                  "If false, the spectrum No will not be written for "
-                  "single-spectrum workspaces. "
-                  "It is always written for workspaces with multiple spectra, "
-                  "unless spectrum axis value is written.");
+      "WriteSpectrumID", true,
+      "If false, the spectrum No will not be written for "
+      "single-spectrum workspaces. "
+      "It is always written for workspaces with multiple spectra, "
+      "unless spectrum axis value is written. Ignored for Table Workspaces.");
 
   declareProperty("CommentIndicator", "#",
                   "Character(s) to put in front of comment lines.");
@@ -113,18 +117,19 @@ void SaveAscii2::init() {
   declareProperty("SpectrumMetaData", "",
                   "A comma separated list that defines data that describes "
                   "each spectrum in a workspace. The valid options for this "
-                  "are: SpectrumNumber,Q,Angle");
+                  "are: SpectrumNumber,Q,Angle. Ignored for Table Workspaces.");
 
   declareProperty(
       "AppendToFile", false,
       "If true, don't overwrite the file. Append to the end of it. ");
 
-  declareProperty(
-      "RaggedWorkspace", true,
-      "If true, ensure that more than one xspectra is used. "); // in testing
+  declareProperty("RaggedWorkspace", true,
+                  "If true, ensure that more than one xspectra is used. "
+                  "Ignored for Table Workspaces."); // in testing
 
   declareProperty("WriteSpectrumAxisValue", false,
-                  "Write the spectrum axis value if requested");
+                  "Write the spectrum axis value if requested. Ignored for "
+                  "Table Workspaces.");
 }
 
 /**
@@ -132,10 +137,60 @@ void SaveAscii2::init() {
  */
 void SaveAscii2::exec() {
   // Get the workspace
-  m_ws = getProperty("InputWorkspace");
-  auto nSpectra = static_cast<int>(m_ws->getNumberHistograms());
-  m_nBins = static_cast<int>(m_ws->blocksize());
-  m_isCommonBins = m_ws->isCommonBins(); // checking for ragged workspace
+  Workspace_const_sptr ws = getProperty("InputWorkspace");
+  m_ws = boost::dynamic_pointer_cast<const MatrixWorkspace>(ws);
+  ITableWorkspace_const_sptr tws =
+      boost::dynamic_pointer_cast<const ITableWorkspace>(ws);
+
+  // Get the properties valid for all workspaces
+  const bool writeHeader = getProperty("ColumnHeader");
+  const bool appendToFile = getProperty("AppendToFile");
+  std::string filename = getProperty("Filename");
+  int prec = getProperty("Precision");
+  bool scientific = getProperty("ScientificFormat");
+  std::string comment = getPropertyValue("CommentIndicator");
+
+  const std::string choice = getPropertyValue("Separator");
+  const std::string custom = getPropertyValue("CustomSeparator");
+  // If the custom separator property is not empty, then we use that under
+  // any circumstance.
+  if (!custom.empty()) {
+    m_sep = custom;
+  }
+  // Else if the separator drop down choice is not UserDefined then we use
+  // that.
+  else if (choice != "UserDefined") {
+    auto it = m_separatorIndex.find(choice);
+    m_sep = it->second;
+  }
+  // If we still have nothing, then we are forced to use a default.
+  if (m_sep.empty()) {
+    g_log.notice() << "\"UserDefined\" has been selected, but no custom "
+                      "separator has been entered."
+                      " Using default instead.";
+    m_sep = ",";
+  }
+
+  if (tws) {
+    writeTableWorkspace(tws, filename, appendToFile, writeHeader, prec,
+                        scientific, comment);
+    // return here as the rest of the class is all about matrix workspace saving
+    return;
+  }
+
+  if (!m_ws) {
+    throw std::runtime_error(
+        "SaveAscii does not now how to save this workspace type, " +
+        ws->getName());
+  }
+
+  // Get the properties valid for matrix workspaces
+  std::vector<int> spec_list = getProperty("SpectrumList");
+  const int spec_min = getProperty("WorkspaceIndexMin");
+  const int spec_max = getProperty("WorkspaceIndexMax");
+  m_writeSpectrumAxisValue = getProperty("WriteSpectrumAxisValue");
+  m_writeDX = getProperty("WriteXError");
+
   m_writeID = getProperty("WriteSpectrumID");
   std::string metaDataString = getPropertyValue("SpectrumMetaData");
   if (!metaDataString.empty()) {
@@ -161,14 +216,6 @@ void SaveAscii2::exec() {
     }
   }
 
-  // Get the properties
-  std::vector<int> spec_list = getProperty("SpectrumList");
-  const int spec_min = getProperty("WorkspaceIndexMin");
-  const int spec_max = getProperty("WorkspaceIndexMax");
-  const bool writeHeader = getProperty("ColumnHeader");
-  const bool appendToFile = getProperty("AppendToFile");
-  m_writeSpectrumAxisValue = getProperty("WriteSpectrumAxisValue");
-
   if (m_writeSpectrumAxisValue) {
     auto spectrumAxis = m_ws->getAxis(1);
     if (dynamic_cast<BinEdgeAxis *>(spectrumAxis)) {
@@ -180,30 +227,10 @@ void SaveAscii2::exec() {
   }
 
   // Check whether we need to write the fourth column
-  m_writeDX = getProperty("WriteXError");
   if (!m_ws->hasDx(0) && m_writeDX) {
     throw std::runtime_error(
         "x data errors have been requested but do not exist.");
   }
-  const std::string choice = getPropertyValue("Separator");
-  const std::string custom = getPropertyValue("CustomSeparator");
-  // If the custom separator property is not empty, then we use that under any
-  // circumstance.
-  if (!custom.empty()) {
-    m_sep = custom;
-  }
-  // Else if the separator drop down choice is not UserDefined then we use that.
-  else if (choice != "UserDefined") {
-    auto it = m_separatorIndex.find(choice);
-    m_sep = it->second;
-  }
-  // If we still have nothing, then we are forced to use a default.
-  if (m_sep.empty()) {
-    g_log.notice() << "\"UserDefined\" has been selected, but no custom "
-                      "separator has been entered."
-                      " Using default instead.";
-    m_sep = ",";
-  }
 
   // e + and - are included as they're part of the scientific notation
   if (!boost::regex_match(m_sep.begin(), m_sep.end(),
@@ -212,8 +239,6 @@ void SaveAscii2::exec() {
                                 "plus signs, hyphens or 'e'");
   }
 
-  std::string comment = getPropertyValue("CommentIndicator");
-
   if (comment.at(0) == m_sep.at(0) ||
       !boost::regex_match(
           comment.begin(), comment.end(),
@@ -226,6 +251,10 @@ void SaveAscii2::exec() {
   // Create an spectra index list for output
   std::set<int> idx;
 
+  auto nSpectra = static_cast<int>(m_ws->getNumberHistograms());
+  m_nBins = static_cast<int>(m_ws->blocksize());
+  m_isCommonBins = m_ws->isCommonBins(); // checking for ragged workspace
+
   // Add spectra interval into the index list
   if (spec_max != EMPTY_INT() && spec_min != EMPTY_INT()) {
     if (spec_min >= nSpectra || spec_max >= nSpectra || spec_min < 0 ||
@@ -255,7 +284,6 @@ void SaveAscii2::exec() {
   if (m_nBins == 0 || nSpectra == 0) {
     throw std::runtime_error("Trying to save an empty workspace");
   }
-  std::string filename = getProperty("Filename");
   std::ofstream file(filename.c_str(),
                      (appendToFile ? std::ios::app : std::ios::out));
 
@@ -264,11 +292,9 @@ void SaveAscii2::exec() {
     throw Exception::FileError("Unable to create file: ", filename);
   }
   // Set the number precision
-  int prec = getProperty("Precision");
   if (prec != EMPTY_INT()) {
     file.precision(prec);
   }
-  bool scientific = getProperty("ScientificFormat");
   if (scientific) {
     file << std::scientific;
   }
@@ -448,5 +474,69 @@ bool SaveAscii2::findElementInUnorderedStringVector(
   return std::find(vector.cbegin(), vector.cend(), toFind) != vector.cend();
 }
 
+void SaveAscii2::writeTableWorkspace(ITableWorkspace_const_sptr tws,
+                                     const std::string &filename,
+                                     bool appendToFile, bool writeHeader,
+                                     int prec, bool scientific,
+                                     const std::string &comment) {
+
+  std::ofstream file(filename.c_str(),
+                     (appendToFile ? std::ios::app : std::ios::out));
+
+  if (!file) {
+    g_log.error("Unable to create file: " + filename);
+    throw Exception::FileError("Unable to create file: ", filename);
+  }
+  // Set the number precision
+  if (prec != EMPTY_INT()) {
+    file.precision(prec);
+  }
+  if (scientific) {
+    file << std::scientific;
+  }
+
+  const auto columnCount = tws->columnCount();
+  if (writeHeader) {
+    // write the column names
+    file << comment << " ";
+    for (size_t colIndex = 0; colIndex < columnCount; colIndex++) {
+      file << tws->getColumn(colIndex)->name() << " ";
+      if (colIndex < columnCount - 1) {
+        file << m_sep << " ";
+      }
+    }
+    file << '\n';
+    // write the column types
+    file << comment << " ";
+    for (size_t colIndex = 0; colIndex < columnCount; colIndex++) {
+      file << tws->getColumn(colIndex)->type() << " ";
+      if (colIndex < columnCount - 1) {
+        file << m_sep << " ";
+      }
+    }
+    file << '\n';
+  } else {
+    g_log.warning("Please note that files written without headers cannot be "
+                  "reloaded back into Mantid with LoadAscii.");
+  }
+
+  // write the data
+  const auto rowCount = tws->rowCount();
+  Progress progress(this, 0.0, 1.0, rowCount);
+  for (size_t rowIndex = 0; rowIndex < rowCount; rowIndex++) {
+    for (size_t colIndex = 0; colIndex < columnCount; colIndex++) {
+      tws->getColumn(colIndex)->print(rowIndex, file);
+      if (colIndex < columnCount - 1) {
+        file << m_sep;
+      }
+    }
+    file << "\n";
+    progress.report();
+  }
+
+  file.unsetf(std::ios_base::floatfield);
+  file.close();
+}
+
 } // namespace DataHandling
 } // namespace Mantid
diff --git a/Framework/DataHandling/test/LoadAscii2Test.h b/Framework/DataHandling/test/LoadAscii2Test.h
index 862d32c4f0589a4fedee888962ffb82b45127019..2154b18ca91a01a8d1e6853c5330f7bf0ddf3598 100644
--- a/Framework/DataHandling/test/LoadAscii2Test.h
+++ b/Framework/DataHandling/test/LoadAscii2Test.h
@@ -8,6 +8,7 @@
 #define LOADASCIITEST_H_
 
 #include "MantidDataHandling/LoadAscii2.h"
+#include "SaveAscii2Test.h"
 #include "cxxtest/TestSuite.h"
 
 #include "MantidAPI/AnalysisDataService.h"
@@ -15,6 +16,7 @@
 #include "MantidAPI/Run.h"
 #include "MantidAPI/WorkspaceFactory.h"
 #include "MantidDataHandling/SaveAscii2.h"
+#include "MantidDataObjects/TableWorkspace.h"
 #include "MantidDataObjects/Workspace2D.h"
 #include "MantidKernel/Unit.h"
 
@@ -154,8 +156,8 @@ public:
 
   void test_fail_five_columns() {
     m_testno++;
-    std::ofstream file(getTestFileName().c_str());
     m_abspath = getAbsPath();
+    std::ofstream file(m_abspath.c_str());
     file << std::scientific;
     file << "# X , Y, E, DX, Z\n";
     for (int i = 0; i < 5; i++) {
@@ -174,8 +176,8 @@ public:
 
   void test_fail_one_column() {
     m_testno++;
-    std::ofstream file(getTestFileName().c_str());
     m_abspath = getAbsPath();
+    std::ofstream file(m_abspath.c_str());
     file << std::scientific;
     file << "# X\n";
     for (int i = 0; i < 5; i++) {
@@ -192,8 +194,8 @@ public:
 
   void test_fail_mismatching_bins() {
     m_testno++;
-    std::ofstream file(getTestFileName().c_str());
     m_abspath = getAbsPath();
+    std::ofstream file(m_abspath.c_str());
     file << std::scientific;
     file << "# X , Y, E, DX\n";
     for (int i = 0; i < 5; i++) {
@@ -213,8 +215,8 @@ public:
 
   void test_fail_mismatching_columns() {
     m_testno++;
-    std::ofstream file(getTestFileName().c_str());
     m_abspath = getAbsPath();
+    std::ofstream file(m_abspath.c_str());
     file << std::scientific;
     file << "# X , Y, E, DX\n";
     for (int i = 0; i < 5; i++) {
@@ -237,8 +239,8 @@ public:
 
   void test_fail_line_start_letter() {
     m_testno++;
-    std::ofstream file(getTestFileName().c_str());
     m_abspath = getAbsPath();
+    std::ofstream file(m_abspath.c_str());
     file << std::scientific;
     file << "# X , Y, E, DX\n";
     for (int i = 0; i < 5; i++) {
@@ -263,8 +265,8 @@ public:
 
   void test_fail_line_start_noncomment_symbol() {
     m_testno++;
-    std::ofstream file(getTestFileName().c_str());
     m_abspath = getAbsPath();
+    std::ofstream file(m_abspath.c_str());
     file << std::scientific;
     file << "# X , Y, E, DX\n";
     for (int i = 0; i < 5; i++) {
@@ -288,8 +290,8 @@ public:
 
   void test_fail_line_mixed_letter_number() {
     m_testno++;
-    std::ofstream file(getTestFileName().c_str());
     m_abspath = getAbsPath();
+    std::ofstream file(m_abspath.c_str());
     file << std::scientific;
     file << "# X , Y, E, DX\n";
     for (int i = 0; i < 5; i++) {
@@ -314,8 +316,8 @@ public:
 
   void test_fail_line_mixed_symbol_number() {
     m_testno++;
-    std::ofstream file(getTestFileName().c_str());
     m_abspath = getAbsPath();
+    std::ofstream file(m_abspath.c_str());
     file << std::scientific;
     file << "# X , Y, E, DX\n";
     for (int i = 0; i < 5; i++) {
@@ -339,8 +341,8 @@ public:
 
   void test_fail_spectra_ID_inclusion_inconisitant() {
     m_testno++;
-    std::ofstream file(getTestFileName().c_str());
     m_abspath = getAbsPath();
+    std::ofstream file(m_abspath.c_str());
 
     file << std::scientific;
     file << "# X , Y, E, DX\n";
@@ -361,6 +363,45 @@ public:
     TS_ASSERT_THROWS_NOTHING(Poco::File(m_abspath).remove());
   }
 
+  void test_tableworkspace() {
+    m_testno++;
+    m_abspath = writeTableTestFile("Tab");
+
+    LoadAscii2 loader;
+    loader.initialize();
+    loader.setRethrows(true);
+
+    const std::string outputName(getTestFileName());
+    TS_ASSERT_THROWS_NOTHING(loader.setPropertyValue("Filename", m_abspath));
+    TS_ASSERT_THROWS_NOTHING(
+        loader.setPropertyValue("OutputWorkspace", outputName));
+    TS_ASSERT_THROWS_NOTHING(loader.setPropertyValue("Separator", "Tab"));
+    TS_ASSERT_THROWS_NOTHING(loader.setPropertyValue("CustomSeparator", ""));
+
+    TS_ASSERT_THROWS_NOTHING(loader.execute());
+
+    TS_ASSERT_EQUALS(loader.isExecuted(), true);
+
+    // Check the workspace
+    AnalysisDataServiceImpl &dataStore = AnalysisDataService::Instance();
+    if (dataStore.doesExist(outputName)) {
+      TS_ASSERT_EQUALS(dataStore.doesExist(outputName), true);
+      Workspace_sptr output;
+      TS_ASSERT_THROWS_NOTHING(output = dataStore.retrieve(outputName));
+      TableWorkspace_sptr outputWS =
+          boost::dynamic_pointer_cast<TableWorkspace>(output);
+      if (outputWS) {
+        checkTableData(outputWS);
+      } else {
+        TS_FAIL("Workspace is not a table workspace");
+      }
+    } else {
+      TS_FAIL(outputName + " does not exist.");
+    }
+    dataStore.remove(outputName);
+    TS_ASSERT_THROWS_NOTHING(Poco::File(m_abspath).remove());
+  }
+
 private:
   const std::string getTestFileName() const {
     return m_filename + boost::lexical_cast<std::string>(m_testno) + m_ext;
@@ -371,6 +412,54 @@ private:
     save.setPropertyValue("Filename", getTestFileName());
     return save.getPropertyValue("Filename");
   }
+
+  // Write the test file for a table workspace
+  std::string writeTableTestFile(const std::string &sep = "CSV",
+                                 const std::string &custsep = "") {
+    SaveAscii2 save;
+    save.initialize();
+    save.setPropertyValue("Filename", getTestFileName());
+
+    const std::string name = "SaveTableAsciiWS";
+    auto wsToSave = SaveAscii2Test::writeTableWS(name);
+
+    save.initialize();
+    save.isInitialized();
+    save.setPropertyValue("InputWorkspace", name);
+    save.setPropertyValue("Separator", sep);
+    save.setPropertyValue("CustomSeparator", custsep);
+    save.execute();
+
+    AnalysisDataService::Instance().remove(name);
+
+    return save.getPropertyValue("Filename");
+  }
+
+  void checkTableData(const Mantid::API::ITableWorkspace_sptr outputWS) {
+
+    const std::string name = "Compare_SaveAsciiWS";
+    auto wsToCompare = SaveAscii2Test::writeTableWS(name);
+    TS_ASSERT_EQUALS(outputWS->columnCount(), wsToCompare->columnCount());
+    TS_ASSERT_EQUALS(outputWS->rowCount(), wsToCompare->rowCount());
+
+    for (size_t colIndex = 0; colIndex < outputWS->columnCount(); colIndex++) {
+      auto outputCol = outputWS->getColumn(colIndex);
+      auto compareCol = wsToCompare->getColumn(colIndex);
+      TS_ASSERT_EQUALS(outputCol->name(), compareCol->name());
+      TS_ASSERT_EQUALS(outputCol->type(), compareCol->type());
+      for (size_t rowIndex = 0; rowIndex < outputWS->rowCount(); rowIndex++) {
+
+        std::stringstream ssOutput;
+        std::stringstream ssCompare;
+        outputCol->print(rowIndex, ssOutput);
+        compareCol->print(rowIndex, ssCompare);
+        TS_ASSERT_EQUALS(ssOutput.str(), ssCompare.str());
+      }
+    }
+
+    AnalysisDataService::Instance().remove(name);
+  }
+
   // Write the test file
   std::string writeTestFile(const int cols, const bool header = true,
                             const std::string &comment = "#",
@@ -381,9 +470,10 @@ private:
     SaveAscii2 save;
     save.initialize();
     save.setPropertyValue("Filename", getTestFileName());
+    std::string filePath = save.getPropertyValue("Filename");
     if (cols < 3) {
       // saveascii2 doens't save 2 column files it has to be made manually
-      std::ofstream file(getTestFileName().c_str());
+      std::ofstream file(filePath.c_str());
       if (scientific) {
         file << std::scientific;
       }
@@ -435,10 +525,12 @@ private:
       save.setPropertyValue("Separator", sep);
       save.setPropertyValue("CustomSeparator", custsep);
       save.execute();
-
+      TSM_ASSERT("Failed to save test data using SaveAscii2.",
+                 save.isExecuted());
       AnalysisDataService::Instance().remove(name);
     }
-    return save.getPropertyValue("Filename");
+
+    return filePath;
   }
 
   Mantid::API::MatrixWorkspace_sptr
diff --git a/Framework/DataHandling/test/SaveAscii2Test.h b/Framework/DataHandling/test/SaveAscii2Test.h
index 9d972f7534fd70849e307d194cafa413d0ef1864..7631fce85b1ad5c607e1297a34ec957e60a86724 100644
--- a/Framework/DataHandling/test/SaveAscii2Test.h
+++ b/Framework/DataHandling/test/SaveAscii2Test.h
@@ -9,9 +9,11 @@
 
 #include "MantidAPI/Axis.h"
 #include "MantidAPI/FrameworkManager.h"
+#include "MantidAPI/TableRow.h"
 #include "MantidAPI/TextAxis.h"
 #include "MantidAPI/WorkspaceFactory.h"
 #include "MantidDataHandling/SaveAscii2.h"
+#include "MantidDataObjects/TableWorkspace.h"
 #include "MantidDataObjects/Workspace2D.h"
 #include "MantidTestHelpers/WorkspaceCreationHelper.h"
 #include <Poco/File.h>
@@ -863,6 +865,81 @@ public:
     AnalysisDataService::Instance().remove(m_name);
   }
 
+  void test_TableWorkspace() {
+    Workspace_sptr wsToSave = writeTableWS(m_name);
+
+    SaveAscii2 save;
+    std::string filename = initSaveAscii2(save);
+
+    TS_ASSERT_THROWS_NOTHING(save.execute());
+
+    // has the algorithm written a file to disk?
+    TS_ASSERT(Poco::File(filename).exists());
+
+    // Now make some checks on the content of the file
+    std::ifstream in(filename.c_str());
+    std::string header1, header2, header3, header4, header5, header6, header7,
+        header8, header9, separator, comment, type1, type2;
+
+    // Test that the first few column headers, separator and first two types are
+    // as expected
+    in >> comment >> header1 >> separator >> header2 >> separator >> header3 >>
+        separator >> header4 >> separator >> header5 >> separator >> header6 >>
+        separator >> header7 >> separator >> header8 >> separator >> header9 >>
+        separator >> type1 >> separator >> type2;
+
+    TS_ASSERT_EQUALS(comment, "#");
+    TS_ASSERT_EQUALS(separator, ",");
+    TS_ASSERT_EQUALS(header1, "int");
+    TS_ASSERT_EQUALS(header2, "uint");
+    TS_ASSERT_EQUALS(header3, "int64");
+    TS_ASSERT_EQUALS(header4, "size_t");
+    TS_ASSERT_EQUALS(header5, "float");
+    TS_ASSERT_EQUALS(header6, "double");
+    TS_ASSERT_EQUALS(header7, "bool");
+    TS_ASSERT_EQUALS(header8, "string");
+    TS_ASSERT_EQUALS(header9, "V3D");
+    TS_ASSERT_EQUALS(type1, "int");
+    TS_ASSERT_EQUALS(type2, "uint");
+
+    in.close();
+
+    Poco::File(filename).remove();
+    AnalysisDataService::Instance().remove(m_name);
+  }
+
+  // public as it is used in LoadAsciiTest as well.
+  static ITableWorkspace_sptr writeTableWS(const std::string &name) {
+    auto table = WorkspaceFactory::Instance().createTable();
+    // One column of each type
+    table->addColumn("int", "int");
+    table->addColumn("uint", "uint");
+    table->addColumn("long64", "int64");
+    table->addColumn("size_t", "size_t");
+    table->addColumn("float", "float");
+    table->addColumn("double", "double");
+    table->addColumn("bool", "bool");
+    table->addColumn("str", "string");
+    table->addColumn("V3D", "V3D");
+
+    // A few rows
+    TableRow row1 = table->appendRow();
+    row1 << -1 << static_cast<uint32_t>(0) << static_cast<int64_t>(1)
+         << static_cast<size_t>(10) << 5.5f << -9.9 << true << "Hello"
+         << Mantid::Kernel::V3D();
+    TableRow row2 = table->appendRow();
+    row2 << 1 << static_cast<uint32_t>(2) << static_cast<int64_t>(-2)
+         << static_cast<size_t>(100) << 0.0f << 101.0 << false << "World"
+         << Mantid::Kernel::V3D(-1, 3, 4);
+    TableRow row3 = table->appendRow();
+    row3 << 6 << static_cast<uint32_t>(3) << static_cast<int64_t>(0)
+         << static_cast<size_t>(0) << -99.0f << 0.0 << false << "!"
+         << Mantid::Kernel::V3D(1, 6, 10);
+
+    AnalysisDataService::Instance().add(name, table);
+    return table;
+  }
+
 private:
   void writeSampleWS(Mantid::DataObjects::Workspace2D_sptr &wsToSave,
                      const bool &isSpectra = true) {
diff --git a/Framework/DataObjects/inc/MantidDataObjects/MDGridBox.tcc b/Framework/DataObjects/inc/MantidDataObjects/MDGridBox.tcc
index 9e52f7ceabfd04efa842d5aaedf57a34b32dee7a..ba010e243f169a1c8a6d1450eee7da23d257b438 100644
--- a/Framework/DataObjects/inc/MantidDataObjects/MDGridBox.tcc
+++ b/Framework/DataObjects/inc/MantidDataObjects/MDGridBox.tcc
@@ -708,7 +708,7 @@ TMDE(void MDGridBox)::splitContents(size_t index, Kernel::ThreadScheduler *ts) {
   if (ts) {
     // Create a task to split the newly created MDGridBox.
     ts->push(std::make_shared<Kernel::FunctionTask>(
-        boost::bind(&MDGridBox<MDE, nd>::splitAllIfNeeded, &*gridbox, ts)));
+        std::bind(&MDGridBox<MDE, nd>::splitAllIfNeeded, &*gridbox, ts)));
   } else {
     gridbox->splitAllIfNeeded(nullptr);
   }
@@ -761,7 +761,7 @@ TMDE(void MDGridBox)::splitAllIfNeeded(Kernel::ThreadScheduler *ts) {
           // So we create a task to split this MDBox,
           // Task is : this->splitContents(i, ts);
           ts->push(std::make_shared<Kernel::FunctionTask>(
-              boost::bind(&MDGridBox<MDE, nd>::splitContents, &*this, i, ts)));
+              std::bind(&MDGridBox<MDE, nd>::splitContents, &*this, i, ts)));
         }
       } else {
         // This box does NOT have enough events to be worth splitting, if it do
@@ -789,8 +789,8 @@ TMDE(void MDGridBox)::splitAllIfNeeded(Kernel::ThreadScheduler *ts) {
         else
           // Go parallel if this is a big enough gridbox.
           // Task is : gridBox->splitAllIfNeeded(ts);
-          ts->push(std::make_shared<Kernel::FunctionTask>(boost::bind(
-              &MDGridBox<MDE, nd>::splitAllIfNeeded, &*gridBox, ts)));
+          ts->push(std::make_shared<Kernel::FunctionTask>(
+              std::bind(&MDGridBox<MDE, nd>::splitAllIfNeeded, &*gridBox, ts)));
       }
     }
   }
diff --git a/Framework/DataObjects/inc/MantidDataObjects/MortonIndex/WideIntImpl.h b/Framework/DataObjects/inc/MantidDataObjects/MortonIndex/WideIntImpl.h
index 9a24430634ccf7e190222b89033dc66541ea2491..31313e3657c05a51c406255901a4fdd35cc9ead8 100644
--- a/Framework/DataObjects/inc/MantidDataObjects/MortonIndex/WideIntImpl.h
+++ b/Framework/DataObjects/inc/MantidDataObjects/MortonIndex/WideIntImpl.h
@@ -512,16 +512,24 @@ public:
     }
   }
 
-  template <size_t Bits2, typename Signed2,
-            class = __need_increase_size<Bits2, Signed2>>
-  constexpr static wide_integer<Bits2, Signed>
-  operator_plus(const wide_integer<Bits, Signed> &lhs,
-                const wide_integer<Bits2, Signed2>
-                    &rhs) noexcept(is_same<Signed, unsigned>::value) {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed2>>::_impl::
-        operator_plus(wide_integer<Bits2, Signed>(lhs), rhs);
-  }
+  // clang-format off
+  // The __need_increase_size variants are currently disabled due to a suspected bug in the MSVC
+  // compiler producing warnings such as:
+  //   warning C4717: 'operator_amp<128, ?? :: ?? >': recursive on all control paths, function will cause runtime stack overflow
+  // `class = __need_increase_size<Bits2, Signed2>>` should fail substitution when Bits2 == Bits - the arguments have the same width, but it doesn't.  
+  // Mantid only uses a single type of wide integer so these functions are not currently required.
+  // clang-format on
+
+  // template <size_t Bits2, typename Signed2,
+  // class = __need_increase_size<Bits2, Signed2>>
+  // constexpr static typename std::enable_if<Bits2==Bits,wide_integer<Bits2,
+  // Signed>>::type operator_plus(const wide_integer<Bits, Signed> &lhs, const
+  // wide_integer<Bits2, Signed2> &rhs) noexcept(is_same<Signed,
+  // unsigned>::value) {
+  // return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed2>>::_impl::
+  // operator_plus(wide_integer<Bits2, Signed>(lhs), rhs);
+  // }
 
   template <typename T, class = __keep_size<T>>
   constexpr static wide_integer<Bits, Signed>
@@ -535,16 +543,16 @@ public:
     }
   }
 
-  template <size_t Bits2, typename Signed2,
-            class = __need_increase_size<Bits2, Signed2>>
-  constexpr static wide_integer<Bits2, Signed>
-  operator_minus(const wide_integer<Bits, Signed> &lhs,
-                 const wide_integer<Bits2, Signed2>
-                     &rhs) noexcept(is_same<Signed, unsigned>::value) {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed2>>::_impl::
-        operator_minus(wide_integer<Bits2, Signed>(lhs), rhs);
-  }
+  // template <size_t Bits2, typename Signed2,
+  // class = __need_increase_size<Bits2, Signed2>>
+  // constexpr static typename std::enable_if<Bits2==Bits,wide_integer<Bits2,
+  // Signed>>::type operator_minus(const wide_integer<Bits, Signed> &lhs, const
+  // wide_integer<Bits2, Signed2> &rhs) noexcept(is_same<Signed,
+  // unsigned>::value) {
+  // return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed2>>::_impl::
+  // operator_minus(wide_integer<Bits2, Signed>(lhs), rhs);
+  // }
 
 private:
   constexpr static wide_integer<Bits, Signed> _operator_minus_wide_integer(
@@ -623,15 +631,15 @@ public:
     return res;
   }
 
-  template <size_t Bits2, typename Signed2,
-            class = __need_increase_size<Bits2, Signed2>>
-  constexpr static wide_integer<Bits2, Signed2>
-  operator_star(const wide_integer<Bits, Signed> &lhs,
-                const wide_integer<Bits2, Signed2> &rhs) {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed2>>::_impl::
-        operator_star(wide_integer<Bits2, Signed2>(lhs), rhs);
-  }
+  // template <size_t Bits2, typename Signed2,
+  // class = __need_increase_size<Bits2, Signed2>>
+  // constexpr static typename std::enable_if<Bits == Bits2, wide_integer<Bits2,
+  // Signed2>>::type operator_star(const wide_integer<Bits, Signed> &lhs, const
+  // wide_integer<Bits2, Signed2> &rhs) {
+  // return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed2>>::_impl::
+  // operator_star(wide_integer<Bits2, Signed2>(lhs), rhs);
+  // }
 
   template <typename T, class = __keep_size<T>>
   constexpr static bool operator_more(const wide_integer<Bits, Signed> &lhs,
@@ -656,14 +664,14 @@ public:
     return false;
   }
 
-  template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
-  constexpr static bool
-  operator_more(const wide_integer<Bits, Signed> &lhs,
-                const wide_integer<Bits2, Signed> &rhs) noexcept {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed>>::_impl::
-        operator_more(wide_integer<Bits2, Signed>(lhs), rhs);
-  }
+  // template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
+  // constexpr static bool
+  // operator_more(const wide_integer<Bits, Signed> &lhs,
+  // const wide_integer<Bits2, Signed> &rhs) noexcept {
+  // return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed>>::_impl::
+  // operator_more(wide_integer<Bits2, Signed>(lhs), rhs);
+  // }
 
   template <typename T, class = __keep_size<T>>
   constexpr static bool operator_less(const wide_integer<Bits, Signed> &lhs,
@@ -688,14 +696,14 @@ public:
     return false;
   }
 
-  template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
-  constexpr static bool
-  operator_less(const wide_integer<Bits, Signed> &lhs,
-                const wide_integer<Bits2, Signed> &rhs) noexcept {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed>>::_impl::
-        operator_less(wide_integer<Bits2, Signed>(lhs), rhs);
-  }
+  // template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
+  // constexpr static bool
+  // operator_less(const wide_integer<Bits, Signed> &lhs,
+  // const wide_integer<Bits2, Signed> &rhs) noexcept {
+  // return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed>>::_impl::
+  // operator_less(wide_integer<Bits2, Signed>(lhs), rhs);
+  // }
 
   template <typename T, class = __keep_size<T>>
   constexpr static bool operator_eq(const wide_integer<Bits, Signed> &lhs,
@@ -711,14 +719,14 @@ public:
     return true;
   }
 
-  template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
-  constexpr static bool
-  operator_eq(const wide_integer<Bits, Signed> &lhs,
-              const wide_integer<Bits2, Signed> &rhs) noexcept {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed>>::_impl::
-        operator_eq(wide_integer<Bits2, Signed>(lhs), rhs);
-  }
+  // template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
+  // constexpr static bool
+  // operator_eq(const wide_integer<Bits, Signed> &lhs,
+  // const wide_integer<Bits2, Signed> &rhs) noexcept {
+  // return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed>>::_impl::
+  // operator_eq(wide_integer<Bits2, Signed>(lhs), rhs);
+  // }
 
   template <typename T, class = __keep_size<T>>
   constexpr static wide_integer<Bits, Signed>
@@ -733,14 +741,16 @@ public:
     return res;
   }
 
-  template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
-  constexpr static wide_integer<Bits2, Signed>
-  operator_pipe(const wide_integer<Bits, Signed> &lhs,
-                const wide_integer<Bits2, Signed> &rhs) noexcept {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed>>::_impl::
-        operator_pipe(wide_integer<Bits2, Signed>(lhs), rhs);
-  }
+  // template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
+  // constexpr static typename std::enable_if<Bits == Bits2, wide_integer<Bits2,
+  // Signed>>::type operator_pipe(const wide_integer<Bits, Signed> &lhs, const
+  // wide_integer<Bits2, Signed> &rhs) noexcept {
+  // static_assert(!std::is_same_v<wide_integer<Bits, Signed>,
+  // std::common_type_t<wide_integer<Bits, Signed>, wide_integer<Bits2,
+  // Signed>>>); return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed>>::_impl::
+  // operator_pipe(wide_integer<Bits2, Signed>(lhs), rhs);
+  // }
 
   template <typename T, class = __keep_size<T>>
   constexpr static wide_integer<Bits, Signed>
@@ -755,14 +765,14 @@ public:
     return res;
   }
 
-  template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
-  constexpr static wide_integer<Bits2, Signed>
-  operator_amp(const wide_integer<Bits, Signed> &lhs,
-               const wide_integer<Bits2, Signed> &rhs) noexcept {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed>>::_impl::
-        operator_amp(wide_integer<Bits2, Signed>(lhs), rhs);
-  }
+  // template <size_t Bits2, class = __need_increase_size<Bits2, Signed>>
+  // constexpr static typename std::enable_if<Bits == Bits2, wide_integer<Bits2,
+  // Signed>>::type operator_amp(const wide_integer<Bits, Signed> &lhs, const
+  // wide_integer<Bits2, Signed> &rhs) noexcept {
+  // return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed>>::_impl::
+  // operator_amp(wide_integer<Bits2, Signed>(lhs), rhs);
+  // }
 
 private:
   template <typename T>
@@ -821,15 +831,15 @@ public:
     return quotient;
   }
 
-  template <size_t Bits2, typename Signed2,
-            class = __need_increase_size<Bits2, Signed2>>
-  constexpr static wide_integer<Bits2, Signed2>
-  operator_slash(const wide_integer<Bits, Signed> &lhs,
-                 const wide_integer<Bits2, Signed2> &rhs) {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed>>::
-        operator_slash(wide_integer<Bits2, Signed2>(lhs), rhs);
-  }
+  // template <size_t Bits2, typename Signed2,
+  // class = __need_increase_size<Bits2, Signed2>>
+  // constexpr static wide_integer<Bits2, Signed2>
+  // operator_slash(const wide_integer<Bits, Signed> &lhs,
+  // const wide_integer<Bits2, Signed2> &rhs) {
+  // return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed>>::
+  // operator_slash(wide_integer<Bits2, Signed2>(lhs), rhs);
+  // }
 
   template <typename T, class = __keep_size<T>>
   constexpr static wide_integer<Bits, Signed>
@@ -843,15 +853,15 @@ public:
     return remainder;
   }
 
-  template <size_t Bits2, typename Signed2,
-            class = __need_increase_size<Bits2, Signed2>>
-  constexpr static wide_integer<Bits2, Signed2>
-  operator_percent(const wide_integer<Bits, Signed> &lhs,
-                   const wide_integer<Bits2, Signed2> &rhs) {
-    return std::common_type_t<wide_integer<Bits, Signed>,
-                              wide_integer<Bits2, Signed>>::
-        operator_percent(wide_integer<Bits2, Signed2>(lhs), rhs);
-  }
+  // template <size_t Bits2, typename Signed2,
+  // class = __need_increase_size<Bits2, Signed2>>
+  // constexpr static wide_integer<Bits2, Signed2>
+  // operator_percent(const wide_integer<Bits, Signed> &lhs,
+  // const wide_integer<Bits2, Signed2> &rhs) {
+  // return std::common_type_t<wide_integer<Bits, Signed>,
+  // wide_integer<Bits2, Signed>>::
+  // operator_percent(wide_integer<Bits2, Signed2>(lhs), rhs);
+  // }
 
   // ^
   template <typename T, class = __keep_size<T>>
@@ -868,14 +878,14 @@ public:
     return res;
   }
 
-  template <size_t Bits2, typename Signed2,
-            class = __need_increase_size<Bits2, Signed2>>
-  constexpr static wide_integer<Bits2, Signed2>
-  operator_circumflex(const wide_integer<Bits, Signed> &lhs,
-                      const wide_integer<Bits2, Signed2> &rhs) noexcept {
-    return wide_integer<Bits2, Signed2>::operator_circumflex(
-        wide_integer<Bits2, Signed2>(lhs), rhs);
-  }
+  // template <size_t Bits2, typename Signed2,
+  // class = __need_increase_size<Bits2, Signed2>>
+  // constexpr static wide_integer<Bits2, Signed2>
+  // operator_circumflex(const wide_integer<Bits, Signed> &lhs,
+  // const wide_integer<Bits2, Signed2> &rhs) noexcept {
+  // return wide_integer<Bits2, Signed2>::operator_circumflex(
+  // wide_integer<Bits2, Signed2>(lhs), rhs);
+  // }
 
   constexpr static wide_integer<Bits, Signed> from_str(const char *c) {
     wide_integer<Bits, Signed> res = 0;
diff --git a/Framework/DataObjects/test/Histogram1DTest.h b/Framework/DataObjects/test/Histogram1DTest.h
index 5ff45b6a1ef48468e829eacd1e15deff057e1114..8509ef2d3769eeb13f035354a3e609ec8ca0b657 100644
--- a/Framework/DataObjects/test/Histogram1DTest.h
+++ b/Framework/DataObjects/test/Histogram1DTest.h
@@ -175,7 +175,7 @@ public:
     // throws so suppress the warning
     MSVC_DIAG_OFF(4834)
     TS_ASSERT_THROWS(h.dataX().at(nel), const std::out_of_range &);
-    MSVC_DIAG_ON()
+    MSVC_DIAG_ON(4834)
   }
   void testrangeexceptionY() {
     h.setCounts(y1);
@@ -183,7 +183,7 @@ public:
     // throws so suppress the warning
     MSVC_DIAG_OFF(4834)
     TS_ASSERT_THROWS(h.dataY().at(nel), const std::out_of_range &);
-    MSVC_DIAG_ON()
+    MSVC_DIAG_ON(4834)
   }
   void testrangeexceptionE() {
     h.setCounts(y1);
@@ -192,7 +192,7 @@ public:
     // throws so suppress the warning
     MSVC_DIAG_OFF(4834)
     TS_ASSERT_THROWS(h.dataE().at(nel), const std::out_of_range &);
-    MSVC_DIAG_ON()
+    MSVC_DIAG_ON(4834)
   }
 
   void test_copy_constructor() {
diff --git a/Framework/DataObjects/test/MDEventWorkspaceTest.h b/Framework/DataObjects/test/MDEventWorkspaceTest.h
index aac5b398a2728f7abc4dbbf6a999a152159268a1..0a152faa94fa28edf7e0f11c8c6a8e83d3914117 100644
--- a/Framework/DataObjects/test/MDEventWorkspaceTest.h
+++ b/Framework/DataObjects/test/MDEventWorkspaceTest.h
@@ -408,12 +408,12 @@ public:
     std::vector<coord_t> min;
     std::vector<coord_t> max;
 
-    min.emplace_back(0);
-    min.emplace_back(0);
-    min.emplace_back(0);
-    max.emplace_back(1.5);
-    max.emplace_back(1.5);
-    max.emplace_back(1.5);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    max.emplace_back(1.5f);
+    max.emplace_back(1.5f);
+    max.emplace_back(1.5f);
 
     // Create a function to mask some of the workspace.
     auto function = std::make_unique<MDBoxImplicitFunction>(min, max);
@@ -570,12 +570,12 @@ public:
     std::vector<coord_t> min;
     std::vector<coord_t> max;
 
-    min.emplace_back(0);
-    min.emplace_back(0);
-    min.emplace_back(0);
-    max.emplace_back(10);
-    max.emplace_back(10);
-    max.emplace_back(10);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
 
     // Create an function that encompases 1/4 of the total bins.
     auto function = std::make_unique<MDBoxImplicitFunction>(min, max);
@@ -593,9 +593,9 @@ public:
     std::vector<coord_t> max;
 
     // Make the box lay over a non-intersecting region of space.
-    min.emplace_back(-1);
-    min.emplace_back(-1);
-    min.emplace_back(-1);
+    min.emplace_back(-1.f);
+    min.emplace_back(-1.f);
+    min.emplace_back(-1.f);
     max.emplace_back(-0.01f);
     max.emplace_back(-0.01f);
     max.emplace_back(-0.01f);
@@ -611,11 +611,11 @@ public:
     std::vector<coord_t> max;
 
     // Make the box that covers half the bins in the workspace.
-    min.emplace_back(0);
-    min.emplace_back(0);
-    min.emplace_back(0);
-    max.emplace_back(10);
-    max.emplace_back(10);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
     max.emplace_back(4.99f);
 
     // Create an function that encompases 1/4 of the total bins.
@@ -628,12 +628,12 @@ public:
     // Create a function that masks everything.
     std::vector<coord_t> min;
     std::vector<coord_t> max;
-    min.emplace_back(0);
-    min.emplace_back(0);
-    min.emplace_back(0);
-    max.emplace_back(10);
-    max.emplace_back(10);
-    max.emplace_back(10);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
     auto function = std::make_unique<MDBoxImplicitFunction>(min, max);
 
     MDEventWorkspace3Lean::sptr ws =
diff --git a/Framework/DataObjects/test/MDHistoWorkspaceIteratorTest.h b/Framework/DataObjects/test/MDHistoWorkspaceIteratorTest.h
index 89d16b77bb1492be7f94fc018e50483a7def7b9c..8d1e7eefe1755409175621a04fc7348e849b8e5e 100644
--- a/Framework/DataObjects/test/MDHistoWorkspaceIteratorTest.h
+++ b/Framework/DataObjects/test/MDHistoWorkspaceIteratorTest.h
@@ -16,8 +16,6 @@
 #include "MantidKernel/Timer.h"
 #include "MantidKernel/VMD.h"
 #include "MantidTestHelpers/MDEventsTestHelper.h"
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <cmath>
 #include <cxxtest/TestSuite.h>
@@ -106,8 +104,8 @@ public:
 
     std::vector<coord_t> normal_vector;
     std::vector<coord_t> bound_vector;
-    normal_vector.emplace_back(1.);
-    bound_vector.emplace_back(3.);
+    normal_vector.emplace_back(1.f);
+    bound_vector.emplace_back(3.f);
 
     MDImplicitFunction *function = new MDImplicitFunction();
     function->addPlane(MDPlane(normal_vector, bound_vector));
diff --git a/Framework/DataObjects/test/MDHistoWorkspaceTest.h b/Framework/DataObjects/test/MDHistoWorkspaceTest.h
index 88f393ec266d59cc4595f060c088250841d48e99..f51d8d524774535b1f23e47b52374a01bd0f537d 100644
--- a/Framework/DataObjects/test/MDHistoWorkspaceTest.h
+++ b/Framework/DataObjects/test/MDHistoWorkspaceTest.h
@@ -561,10 +561,10 @@ public:
 
     std::vector<coord_t> min;
     std::vector<coord_t> max;
-    min.emplace_back(0);
-    min.emplace_back(0);
-    max.emplace_back(5);
-    max.emplace_back(5);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    max.emplace_back(5.f);
+    max.emplace_back(5.f);
 
     // Mask part of the workspace
     auto function = std::make_unique<MDBoxImplicitFunction>(min, max);
@@ -982,12 +982,12 @@ public:
     std::vector<coord_t> max;
 
     // Make the box that covers the whole workspace.
-    min.emplace_back(0);
-    min.emplace_back(0);
-    min.emplace_back(0);
-    max.emplace_back(10);
-    max.emplace_back(10);
-    max.emplace_back(10);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
 
     // Create an function that encompases ALL of the total bins.
     auto function = std::make_unique<MDBoxImplicitFunction>(min, max);
@@ -1114,12 +1114,12 @@ public:
     std::vector<coord_t> max;
 
     // Make the box that covers half the bins in the workspace.
-    min.emplace_back(0);
-    min.emplace_back(0);
-    min.emplace_back(0);
-    max.emplace_back(10);
-    max.emplace_back(10);
-    max.emplace_back(10);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
 
     // Create an function that encompases ALL of the total bins.
     auto function = std::make_unique<MDBoxImplicitFunction>(min, max);
@@ -1131,11 +1131,11 @@ public:
     std::vector<coord_t> max;
 
     // Make the box that covers half the bins in the workspace.
-    min.emplace_back(0);
-    min.emplace_back(0);
-    min.emplace_back(0);
-    max.emplace_back(10);
-    max.emplace_back(10);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
     max.emplace_back(4.99f);
 
     // Create an function that encompases 1/2 of the total bins.
@@ -1147,12 +1147,12 @@ public:
     // Create a function that masks everything.
     std::vector<coord_t> min;
     std::vector<coord_t> max;
-    min.emplace_back(0);
-    min.emplace_back(0);
-    min.emplace_back(0);
-    max.emplace_back(10);
-    max.emplace_back(10);
-    max.emplace_back(10);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    min.emplace_back(0.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
+    max.emplace_back(10.f);
     auto function = std::make_unique<MDBoxImplicitFunction>(min, max);
 
     MDEventWorkspace3Lean::sptr ws =
diff --git a/Framework/DataObjects/test/WorkspaceIteratorTest.h b/Framework/DataObjects/test/WorkspaceIteratorTest.h
index c78953f3b4fda7f971ec3483b34bb2f815616303..5e065da91af21ec836cf3bdf1a1027bc69fcedc3 100644
--- a/Framework/DataObjects/test/WorkspaceIteratorTest.h
+++ b/Framework/DataObjects/test/WorkspaceIteratorTest.h
@@ -8,7 +8,6 @@
 #define TRIPLEITERATORTEST_
 
 #include <algorithm>
-#include <boost/bind.hpp>
 #include <boost/shared_ptr.hpp>
 #include <cxxtest/TestSuite.h>
 
diff --git a/Framework/Geometry/src/Crystal/CrystalStructure.cpp b/Framework/Geometry/src/Crystal/CrystalStructure.cpp
index 7f2deee0a7bdf68e9fc8f6b26ae18b33ab085778..c1fd3338236677f3e6754a6dfbd0ac9a336506bb 100644
--- a/Framework/Geometry/src/Crystal/CrystalStructure.cpp
+++ b/Framework/Geometry/src/Crystal/CrystalStructure.cpp
@@ -6,7 +6,6 @@
 // SPDX - License - Identifier: GPL - 3.0 +
 #include "MantidGeometry/Crystal/CrystalStructure.h"
 #include <algorithm>
-#include <boost/bind.hpp>
 #include <stdexcept>
 
 #include "MantidGeometry/Crystal/BasicHKLFilters.h"
diff --git a/Framework/Geometry/src/Crystal/StructureFactorCalculator.cpp b/Framework/Geometry/src/Crystal/StructureFactorCalculator.cpp
index 837279174da60aa2b09e11ec4485beebe95463a0..777a4df11da610f880182fc07b1e22b07654279e 100644
--- a/Framework/Geometry/src/Crystal/StructureFactorCalculator.cpp
+++ b/Framework/Geometry/src/Crystal/StructureFactorCalculator.cpp
@@ -6,8 +6,6 @@
 // SPDX - License - Identifier: GPL - 3.0 +
 #include "MantidGeometry/Crystal/StructureFactorCalculator.h"
 
-#include <boost/bind.hpp>
-
 namespace Mantid {
 namespace Geometry {
 
@@ -47,9 +45,9 @@ double StructureFactorCalculator::getFSquared(const Kernel::V3D &hkl) const {
 std::vector<StructureFactor>
 StructureFactorCalculator::getFs(const std::vector<Kernel::V3D> &hkls) const {
   std::vector<StructureFactor> structureFactors(hkls.size());
-
+  using namespace std::placeholders;
   std::transform(hkls.begin(), hkls.end(), structureFactors.begin(),
-                 boost::bind(&StructureFactorCalculator::getF, this, _1));
+                 std::bind(&StructureFactorCalculator::getF, this, _1));
 
   return structureFactors;
 }
@@ -67,10 +65,9 @@ StructureFactorCalculator::getFs(const std::vector<Kernel::V3D> &hkls) const {
 std::vector<double> StructureFactorCalculator::getFsSquared(
     const std::vector<Kernel::V3D> &hkls) const {
   std::vector<double> fSquareds(hkls.size());
-
-  std::transform(
-      hkls.begin(), hkls.end(), fSquareds.begin(),
-      boost::bind(&StructureFactorCalculator::getFSquared, this, _1));
+  using namespace std::placeholders;
+  std::transform(hkls.begin(), hkls.end(), fSquareds.begin(),
+                 std::bind(&StructureFactorCalculator::getFSquared, this, _1));
 
   return fSquareds;
 }
diff --git a/Framework/Geometry/src/Surfaces/LineIntersectVisit.cpp b/Framework/Geometry/src/Surfaces/LineIntersectVisit.cpp
index ad25cc8d4c395f4df138ada5a9f02fa78f7c9d52..16bf817fa13e6f3baa3f196542721d62100809b6 100644
--- a/Framework/Geometry/src/Surfaces/LineIntersectVisit.cpp
+++ b/Framework/Geometry/src/Surfaces/LineIntersectVisit.cpp
@@ -15,7 +15,6 @@
 #include "MantidKernel/Exception.h"
 #include "MantidKernel/Strings.h"
 #include <algorithm>
-#include <boost/bind.hpp>
 
 namespace Mantid {
 
diff --git a/Framework/Geometry/test/CMakeLists.txt b/Framework/Geometry/test/CMakeLists.txt
index ec68a77093eab05529b47876ee807473f99de36f..9c2f5e681b2b6000ccd073e693931904bb946389 100644
--- a/Framework/Geometry/test/CMakeLists.txt
+++ b/Framework/Geometry/test/CMakeLists.txt
@@ -18,6 +18,7 @@ if(CXXTEST_FOUND)
       ../../TestHelpers/src/LoggingCleaner.cpp)
 
   cxxtest_add_test(GeometryTest ${TEST_FILES} ${GMOCK_TEST_FILES})
+  target_compile_definitions(GeometryTest PRIVATE -D_SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING)
   target_link_libraries(GeometryTest
                         LINK_PRIVATE
                         ${TCMALLOC_LIBRARIES_LINKTIME}
diff --git a/Framework/Kernel/inc/MantidKernel/FunctionTask.h b/Framework/Kernel/inc/MantidKernel/FunctionTask.h
index 69732403625fb2ac8ab6d91815ddd8dde3da5aa0..9b561ac92ab4e2f0a21f184cfba6bfa5a54169bb 100644
--- a/Framework/Kernel/inc/MantidKernel/FunctionTask.h
+++ b/Framework/Kernel/inc/MantidKernel/FunctionTask.h
@@ -9,10 +9,10 @@
 
 #include "MantidKernel/DllConfig.h"
 #include "MantidKernel/Task.h"
+#include <functional>
 #include <stdexcept>
 
 #ifndef Q_MOC_RUN
-#include <boost/bind.hpp>
 #include <boost/function.hpp>
 #endif
 
@@ -35,12 +35,12 @@ public:
   //---------------------------------------------------------------------------------------------
   /** Constructor for a simple void function.
    *
-   * Pro-tip: use boost::bind(f, argument1, argument2) (for example) to turn a
+   * Pro-tip: use std::bind(f, argument1, argument2) (for example) to turn a
    *function that takes
    * an argument into a argument-less function pointer.
    *
-   * Use boost::bind(&ClassName::function, &*this, arg1, arg2) to bind to a
-   *class method of this.
+   * Use std::bind(&ClassName::function, &*this, arg1, arg2) to bind to a
+   * class method of this.
    *
    * @param func :: pointer to a void function()
    * @param cost :: computational cost
@@ -51,17 +51,17 @@ public:
   //---------------------------------------------------------------------------------------------
   /** Constructor for a simple boost bound function.
    *
-   * Pro-tip: use boost::bind(f, argument1, argument2) (for example) to turn a
+   * Pro-tip: use std::bind(f, argument1, argument2) (for example) to turn a
    *function that takes
    * an argument into a argument-less function pointer.
    *
-   * Use boost::bind(&ClassName::function, &*this, arg1, arg2) to bind to a
+   * Use std::bind(&ClassName::function, &*this, arg1, arg2) to bind to a
    *class method of this.
    *
-   * @param func :: boost::function<> returned by boost::bind()
+   * @param func :: std::function<> returned by std::bind()
    * @param cost :: computational cost
    */
-  FunctionTask(boost::function<void()> func, double cost = 1.0)
+  FunctionTask(std::function<void()> func, double cost = 1.0)
       : Task(cost), m_voidFunc(func) {}
 
   //---------------------------------------------------------------------------------------------
@@ -74,7 +74,7 @@ public:
   }
 
 protected:
-  boost::function<void()> m_voidFunc;
+  std::function<void()> m_voidFunc;
 };
 
 } // namespace Kernel
diff --git a/Framework/Kernel/inc/MantidKernel/PropertyWithValueJSON.h b/Framework/Kernel/inc/MantidKernel/PropertyWithValueJSON.h
index 4982aab0b2e50ddf34105d45706153100e3c14b8..bb33edc4ece29e7d35a6f608d8944a4d3be8ef51 100644
--- a/Framework/Kernel/inc/MantidKernel/PropertyWithValueJSON.h
+++ b/Framework/Kernel/inc/MantidKernel/PropertyWithValueJSON.h
@@ -38,11 +38,11 @@ template <> struct ToCpp<int> {
 };
 /// Specialization of ToCpp for long long
 template <> struct ToCpp<long long> {
-  long operator()(const Json::Value &value) { return value.asInt64(); }
+  long long operator()(const Json::Value &value) { return value.asInt64(); }
 };
 /// Specialization of ToCpp for long
 template <> struct ToCpp<long> {
-  Json::Int64 operator()(const Json::Value &value) { return value.asInt64(); }
+  long operator()(const Json::Value &value) { return value.asInt(); }
 };
 /// Specialization of ToCpp for unsigned int
 template <> struct ToCpp<unsigned int> {
diff --git a/Framework/Kernel/inc/MantidKernel/TimeSeriesProperty.h b/Framework/Kernel/inc/MantidKernel/TimeSeriesProperty.h
index 9577b09385a152a2453bebb36129d1deeb1a11b2..91a34719d8cd5647ad769d09efa35ade5a825220 100644
--- a/Framework/Kernel/inc/MantidKernel/TimeSeriesProperty.h
+++ b/Framework/Kernel/inc/MantidKernel/TimeSeriesProperty.h
@@ -159,10 +159,10 @@ public:
                    bool isPeriodic) const override;
 
   /// New split method
-  void
-  splitByTimeVector(std::vector<Types::Core::DateAndTime> &splitter_time_vec,
-                    std::vector<int> &target_vec,
-                    std::vector<TimeSeriesProperty *> outputs);
+  void splitByTimeVector(
+      const std::vector<Types::Core::DateAndTime> &splitter_time_vec,
+      const std::vector<int> &target_vec,
+      const std::vector<TimeSeriesProperty *> &outputs);
 
   /// Fill a TimeSplitterType that will filter the events by matching
   void makeFilterByValue(std::vector<SplittingInterval> &split, double min,
diff --git a/Framework/Kernel/inc/MantidKernel/WarningSuppressions.h b/Framework/Kernel/inc/MantidKernel/WarningSuppressions.h
index 1d9de27ec97d7c72883cd7de67407c7dbbf4b999..1ffd322d9e56c56417e35e304542cadaaa39bd18 100644
--- a/Framework/Kernel/inc/MantidKernel/WarningSuppressions.h
+++ b/Framework/Kernel/inc/MantidKernel/WarningSuppressions.h
@@ -82,7 +82,7 @@
 #define MSVC_DIAG_OFF(id)                                                        \
   __pragma(warning(push))                                                        \
   __pragma(warning(disable : id))
-#define MSVC_DIAG_ON() __pragma(warning(pop))
+#define MSVC_DIAG_ON(id) __pragma(warning(pop))
 // clang-format on
 #else
 #define MSVC_DIAG_OFF(x)
diff --git a/Framework/Kernel/src/MultiFileNameParser.cpp b/Framework/Kernel/src/MultiFileNameParser.cpp
index 413d8dbf446312a63b860a910281b055ca68915d..513a52158fb9c009d76cff3727fd9f23e300e09a 100644
--- a/Framework/Kernel/src/MultiFileNameParser.cpp
+++ b/Framework/Kernel/src/MultiFileNameParser.cpp
@@ -17,7 +17,6 @@
 #include <sstream>
 
 #include <boost/algorithm/string.hpp>
-#include <boost/bind.hpp>
 #include <boost/regex.hpp>
 
 namespace Mantid {
diff --git a/Framework/Kernel/src/NetworkProxyWin.cpp b/Framework/Kernel/src/NetworkProxyWin.cpp
index f7c8c7a6b1267f4e277306d2ce7837732d5ff9f0..b04c02cb17419fe9725476c1c5c4f2ecb4968549 100644
--- a/Framework/Kernel/src/NetworkProxyWin.cpp
+++ b/Framework/Kernel/src/NetworkProxyWin.cpp
@@ -8,6 +8,7 @@
 #if defined(_WIN32) || defined(_WIN64)
 
 #include "MantidKernel/NetworkProxy.h"
+#include "MantidKernel/WarningSuppressions.h"
 // std
 #include <sstream>
 // windows
@@ -117,7 +118,9 @@ bool get_proxy_configuration_win(const std::string &target_url,
   if (fail) {
     err_msg = info.str();
   }
+  MSVC_DIAG_OFF(4244)
   proxy_str = std::string(proxy.begin(), proxy.end());
+  MSVC_DIAG_ON(4244)
   return !fail;
 }
 
diff --git a/Framework/Kernel/src/PropertyWithValue.cpp b/Framework/Kernel/src/PropertyWithValue.cpp
index 47868ff329fe36f42dd34d9964f747eb5f9e6db1..eb1172d7bed782715095f4fccf3d2a4e9c340dad 100644
--- a/Framework/Kernel/src/PropertyWithValue.cpp
+++ b/Framework/Kernel/src/PropertyWithValue.cpp
@@ -21,6 +21,9 @@ namespace Kernel {
   void PropertyWithValue<type>::saveProperty(::NeXus::File *file) {            \
     file->makeGroup(this->name(), "NXlog", true);                              \
     file->writeData("value", m_value);                                         \
+    file->openData("value");                                                   \
+    file->putAttr("units", this->units());                                     \
+    file->closeData();                                                         \
     file->closeGroup();                                                        \
   }
 
diff --git a/Framework/Kernel/src/TimeSeriesProperty.cpp b/Framework/Kernel/src/TimeSeriesProperty.cpp
index de59d2083d617bbba74344fac15952dbf7a5b463..dcd59531bfd0f4e71a480356659bb5c14fbbc869 100644
--- a/Framework/Kernel/src/TimeSeriesProperty.cpp
+++ b/Framework/Kernel/src/TimeSeriesProperty.cpp
@@ -414,12 +414,12 @@ void TimeSeriesProperty<TYPE>::filterByTimes(
  * property according to number of distinct splitters' indexes, such as 0 and 1
  *
  * NOTE: If the input TSP has a single value, it is assumed to be a constant
- *  and so is not split, but simply copied to all outputs.
+ *  and so is not split, but simply copied to all output.
  *
  * @param splitter :: a TimeSplitterType object containing the list of intervals
  *                     and destinations.
- * @param outputs  :: A vector of output TimeSeriesProperty pointers of the same
- *                    type.
+ * @param outputs  :: A vector of output TimeSeriesProperty
+ * pointers of the same type.
  * @param isPeriodic :: whether the log (this TSP) is periodic. For example
  *                    proton-charge is periodic log.
  */
@@ -541,209 +541,118 @@ void TimeSeriesProperty<TYPE>::splitByTime(
 }
 
 /// Split this TimeSeriresProperty by a vector of time with N entries,
-/// and by the target workspace index defined by target_vec
+/// and by the wsIndex workspace index defined by inputWorkspaceIndicies
 /// Requirements:
-/// vector outputs must be defined before this method is called
+/// vector output must be defined before this method is called
 template <typename TYPE>
 void TimeSeriesProperty<TYPE>::splitByTimeVector(
-    std::vector<DateAndTime> &splitter_time_vec, std::vector<int> &target_vec,
-    std::vector<TimeSeriesProperty *> outputs) {
-
-  // check target vector to make it a set
-  std::set<int> target_set;
-  for (auto target : target_vec)
-    target_set.insert(target);
+    const std::vector<DateAndTime> &timeToFilterTo,
+    const std::vector<int> &inputWorkspaceIndicies,
+    const std::vector<TimeSeriesProperty *> &output) {
 
   // check inputs
-  if (splitter_time_vec.size() != target_vec.size() + 1) {
-    std::stringstream errss;
-    errss << "Try to split TSP " << this->m_name
-          << ": Input time vector's size " << splitter_time_vec.size()
-          << " does not match (one more larger than) taget "
-             "workspace index vector's size "
-          << target_vec.size() << "\n";
-    throw std::runtime_error(errss.str());
+  if (timeToFilterTo.size() != inputWorkspaceIndicies.size() + 1) {
+    throw std::runtime_error(
+        "Input time vector's size does not match(one more larger than) target "
+        "workspace index vector's size inputWorkspaceIndicies.size() \n");
   }
+
   // return if the output vector TimeSeriesProperties is not defined
-  if (outputs.empty())
+  if (output.empty())
     return;
 
-  // sort if necessary
   sortIfNecessary();
 
   // work on m_values, m_size, and m_time
-  std::vector<Types::Core::DateAndTime> tsp_time_vec = this->timesAsVector();
-
-  // go over both filter time vector and time series property time vector
+  auto const currentTimes = timesAsVector();
+  auto const currentValues = valuesAsVector();
   size_t index_splitter = 0;
-  size_t index_tsp_time = 0;
-
-  // tsp_time is start time of time series property
-  DateAndTime tsp_time = tsp_time_vec[index_tsp_time];
-  DateAndTime split_start_time = splitter_time_vec[index_splitter];
-  DateAndTime split_stop_time = splitter_time_vec[index_splitter + 1];
 
   // move splitter index such that the first entry of TSP is before the stop
   // time of a splitter
-  bool continue_search = true;
-  bool no_entry_in_range = false;
-
-  std::vector<DateAndTime>::iterator splitter_iter;
-  splitter_iter = std::lower_bound(splitter_time_vec.begin(),
-                                   splitter_time_vec.end(), tsp_time);
-  if (splitter_iter == splitter_time_vec.begin()) {
+  DateAndTime firstPropTime = currentTimes[0];
+  auto firstFilterTime = std::lower_bound(timeToFilterTo.begin(),
+                                          timeToFilterTo.end(), firstPropTime);
+  if (firstFilterTime == timeToFilterTo.end()) {
     // do nothing as the first TimeSeriesProperty entry's time is before any
     // splitters
-    ;
-  } else if (splitter_iter == splitter_time_vec.end()) {
-    // already search to the last splitter which is still earlier than first TSP
-    // entry
-    no_entry_in_range = true;
-  } else {
+    return;
+  } else if (firstFilterTime != timeToFilterTo.begin()) {
     // calculate the splitter's index (now we check the stop time)
-    index_splitter = splitter_iter - splitter_time_vec.begin() - 1;
-    split_start_time = splitter_time_vec[index_splitter];
-    split_stop_time = splitter_time_vec[index_splitter + 1];
+    index_splitter = firstFilterTime - timeToFilterTo.begin() - 1;
   }
 
-  // move along the entries to find the entry inside the current splitter
-  bool first_splitter_after_last_entry(false);
-  if (!no_entry_in_range) {
-    std::vector<DateAndTime>::iterator tsp_time_iter;
-    tsp_time_iter = std::lower_bound(tsp_time_vec.begin(), tsp_time_vec.end(),
-                                     split_start_time);
-    if (tsp_time_iter == tsp_time_vec.end()) {
-      // the first splitter's start time is LATER than the last TSP entry, then
-      // there won't be any
-      // TSP entry to be split into any target splitter.
-      no_entry_in_range = true;
-      first_splitter_after_last_entry = true;
-    } else {
-      // first splitter start time is between tsp_time_iter and the one before
-      // it.
-      // so the index for tsp_time_iter is the first TSP entry in the splitter
-      index_tsp_time = tsp_time_iter - tsp_time_vec.begin();
-      tsp_time = *tsp_time_iter;
-    }
-  } else {
-    // no entry in range is true, which corresponding to the previous case
-    // "already search to the last splitter which is still earlier than first
-    // TSP
-    // entry"
-    ;
-  }
+  DateAndTime filterStartTime = timeToFilterTo[index_splitter];
+  DateAndTime filterEndTime = timeToFilterTo[index_splitter + 1];
 
-  if (no_entry_in_range && first_splitter_after_last_entry) {
-    // initialize all the splitters with the last value
+  // move along the entries to find the entry inside the current splitter
+  auto firstEntryInSplitter = std::lower_bound(
+      currentTimes.begin(), currentTimes.end(), filterStartTime);
+  if (firstEntryInSplitter == currentTimes.end()) {
+    // the first splitter's start time is LATER than the last TSP entry, then
+    // there won't be any
+    // TSP entry to be split into any wsIndex splitter.
     DateAndTime last_entry_time = this->lastTime();
     TYPE last_entry_value = this->lastValue();
-    for (size_t i = 0; i < outputs.size(); ++i)
-      outputs[i]->addValue(last_entry_time, last_entry_value);
+    for (auto &i : output) {
+      i->addValue(last_entry_time, last_entry_value);
+    }
+    return;
   }
 
-  // now it is the time to put TSP's entries to corresponding
-  continue_search = !no_entry_in_range;
-  size_t outer_while_counter = 0;
-  bool partial_target_filled(false);
-  while (continue_search) {
-    // get next target
-    int target = target_vec[index_splitter];
+  // first splitter start time is between firstEntryInSplitter and the one
+  // before it. so the index for firstEntryInSplitter is the first TSP entry
+  // in the splitter
+  size_t timeIndex = firstEntryInSplitter - currentTimes.begin();
+  firstPropTime = *firstEntryInSplitter;
 
-    // get the first entry index (overlap)
-    if (index_tsp_time > 0)
-      --index_tsp_time;
-
-    // add the continous entries to same target time series property
-    const size_t tspTimeVecSize = tsp_time_vec.size();
-    bool continue_add = true;
-    while (continue_add) {
-      size_t inner_while_counter = 0;
-      if (index_tsp_time == tspTimeVecSize) {
-        // last entry. quit all loops
-        continue_add = false;
-        continue_search = false;
-        partial_target_filled = true;
-        break;
-      }
+  for (; index_splitter < timeToFilterTo.size() - 1; ++index_splitter) {
+    int wsIndex = inputWorkspaceIndicies[index_splitter];
 
-      // add current entry
-      if (outputs[target]->size() == 0 ||
-          outputs[target]->lastTime() < tsp_time_vec[index_tsp_time]) {
-        // avoid to add duplicate entry
-        outputs[target]->addValue(m_values[index_tsp_time].time(),
-                                  m_values[index_tsp_time].value());
-      }
+    filterStartTime = timeToFilterTo[index_splitter];
+    filterEndTime = timeToFilterTo[index_splitter + 1];
 
-      const size_t nextTspIndex = index_tsp_time + 1;
-      if (nextTspIndex < tspTimeVecSize) {
-        if (tsp_time_vec[nextTspIndex] > split_stop_time) {
-          // next entry is out of this splitter: add the next one and quit
-          if (outputs[target]->lastTime() < m_values[nextTspIndex].time()) {
-            // avoid the duplicate cases occurred in fast frequency issue
-            outputs[target]->addValue(m_values[nextTspIndex].time(),
-                                      m_values[nextTspIndex].value());
-          }
-          // FIXME - in future, need to find out WHETHER there is way to
-          // skip the
-          // rest without going through the whole sequence
-          continue_add = false;
-        }
+    // get the first entry index (overlap)
+    if (timeIndex > 0)
+      --timeIndex;
+
+    // add the continuous entries to same wsIndex time series property
+    const size_t numEntries = currentTimes.size();
+
+    // Add properties to the current wsIndex.
+    if (timeIndex >= numEntries) {
+      // We have run out of TSP entries, so use the last TSP value
+      // for all remaining outputs
+      auto currentTime = currentTimes.back();
+      if (output[wsIndex]->size() == 0 ||
+          output[wsIndex]->lastTime() != currentTime) {
+        output[wsIndex]->addValue(currentTime, currentValues.back());
       }
-
-      // advance to next entry
-      ++index_tsp_time;
-
-      ++inner_while_counter;
-    } // END-WHILE continue add
-
-    // make splitters to advance to next
-    ++index_splitter;
-    if (index_splitter == splitter_time_vec.size() - 1) {
-      // already last splitters
-      continue_search = false;
     } else {
-      split_start_time = split_stop_time;
-      split_stop_time = splitter_time_vec[index_splitter + 1];
-    }
-
-    ++outer_while_counter;
-  } // END-OF-WHILE
-
-  // Still in 'continue search'-while-loop.  But the TSP runs over before
-  // splitters.
-  // Therefore, the rest of the chopper must have one more entry added!
-  if (partial_target_filled) {
-    // fill the target
-    std::set<int> fill_target_set;
-    for (size_t isplitter = index_splitter;
-         isplitter < splitter_time_vec.size() - 1; ++isplitter) {
-      int target_i = target_vec[isplitter];
-      if (fill_target_set.find(target_i) == fill_target_set.end()) {
-        if (outputs[target_i]->size() == 0 ||
-            outputs[target_i]->lastTime() != m_values.back().time())
-          outputs[target_i]->addValue(m_values.back().time(),
-                                      m_values.back().value());
-        fill_target_set.insert(target_i);
-        // quit loop if it goes over all the targets
-        if (fill_target_set.size() == target_set.size())
+      // Add TSP values until we run out or go past the current filter
+      // end time.
+      for (; timeIndex < numEntries; ++timeIndex) {
+        auto currentTime = currentTimes[timeIndex];
+        if (output[wsIndex]->size() == 0 ||
+            output[wsIndex]->lastTime() < currentTime) {
+          // avoid to add duplicate entry
+          output[wsIndex]->addValue(currentTime, currentValues[timeIndex]);
+        }
+        if (currentTime > filterEndTime)
           break;
       }
     }
   }
 
   // Add a debugging check such that there won't be any time entry with zero log
-  for (size_t i = 0; i < outputs.size(); ++i) {
-    if (outputs[i]->size() == 0) {
+  for (size_t i = 0; i < output.size(); ++i) {
+    if (output[i]->size() == 0) {
       std::stringstream errss;
-      errss << i << "-th split-out term (out of " << outputs.size()
-            << " total output TSP) of '" << m_name << "'' has "
-            << outputs[i]->size() << " size, whose first entry is at "
+      errss << "entry " << m_name << " has 0 size, whose first entry is at "
             << this->firstTime().toSimpleString();
-      g_log.debug(errss.str());
+      g_log.warning(errss.str());
     }
   }
-
-  return;
 }
 
 // The makeFilterByValue & expandFilterToRange methods generate a bunch of
diff --git a/Framework/Kernel/src/UsageService.cpp b/Framework/Kernel/src/UsageService.cpp
index 81a8a3630baeb6e5449e0a71ca655eb128d8ade7..3de84a525e3fdc1aa278b75b03e579f8377c453d 100644
--- a/Framework/Kernel/src/UsageService.cpp
+++ b/Framework/Kernel/src/UsageService.cpp
@@ -19,7 +19,6 @@
 #include <algorithm>
 #include <boost/algorithm/string/join.hpp>
 #include <boost/algorithm/string/trim.hpp>
-#include <boost/bind.hpp>
 
 #include <json/json.h>
 
diff --git a/Framework/Kernel/test/FunctionTaskTest.h b/Framework/Kernel/test/FunctionTaskTest.h
index 01097633b7f5b4c40b55248b1045e9dd131703ba..ea0ceb4b6c98a6f1d90cf7b8aa7ae3611d079cc8 100644
--- a/Framework/Kernel/test/FunctionTaskTest.h
+++ b/Framework/Kernel/test/FunctionTaskTest.h
@@ -42,14 +42,14 @@ public:
   }
 
   void test_Function_using_bind() {
-    FunctionTask mytask(boost::bind<void, int>(my_int_function, 34));
+    FunctionTask mytask(std::bind(my_int_function, 34));
     TS_ASSERT_DIFFERS(my_check_value, 34);
     TS_ASSERT_THROWS_NOTHING(mytask.run());
     TS_ASSERT_EQUALS(my_check_value, 34);
   }
 
   void test_Function_using_bind_complicated() {
-    FunctionTask mytask(boost::bind(my_complicated_function, 56, 12.0));
+    FunctionTask mytask(std::bind(my_complicated_function, 56, 12.0));
     TS_ASSERT_DIFFERS(my_check_value, 68);
     TS_ASSERT_THROWS_NOTHING(mytask.run());
     TS_ASSERT_EQUALS(my_check_value, 68);
diff --git a/Framework/Kernel/test/LoggerTest.h b/Framework/Kernel/test/LoggerTest.h
index eae3879505ea1299cbd9103899157ab09df0dffb..e6babd11b539b8384975481e09fbcc2492fd69e9 100644
--- a/Framework/Kernel/test/LoggerTest.h
+++ b/Framework/Kernel/test/LoggerTest.h
@@ -94,7 +94,7 @@ public:
     ThreadPool tp;
     for (int i = 0; i < 1000; i++)
       tp.schedule(std::make_shared<FunctionTask>(
-          boost::bind(&LoggerTest::doLogInParallel, &*this, i)));
+          std::bind(&LoggerTest::doLogInParallel, &*this, i)));
     tp.joinAll();
   }
 };
diff --git a/Framework/Kernel/test/ThreadPoolTest.h b/Framework/Kernel/test/ThreadPoolTest.h
index 7975ddfbad3baccb7342b9fbf667ac4272146bfe..9ae602e264b4f59eba40ca65a7167378737fea91 100644
--- a/Framework/Kernel/test/ThreadPoolTest.h
+++ b/Framework/Kernel/test/ThreadPoolTest.h
@@ -18,7 +18,6 @@
 
 #include <Poco/Thread.h>
 
-#include <boost/bind.hpp>
 #include <boost/make_shared.hpp>
 #include <cstdlib>
 
@@ -133,7 +132,7 @@ public:
       double cost = i; // time is exactly i
       // Bind to a member function of mywaster
       p.schedule(std::make_shared<FunctionTask>(
-          boost::bind(&TimeWaster::waste_time_with_lock, &mywaster, i), cost));
+          std::bind(&TimeWaster::waste_time_with_lock, &mywaster, i), cost));
     }
 
     Timer overall;
@@ -281,7 +280,7 @@ public:
     for (int i = 0; i < 10; i++) {
       double cost = i;
       p.schedule(std::make_shared<FunctionTask>(
-          boost::bind(threadpooltest_adding_stuff, i), cost));
+          std::bind(threadpooltest_adding_stuff, i), cost));
     }
     TS_ASSERT_THROWS_NOTHING(p.joinAll());
     TS_ASSERT_EQUALS(threadpooltest_vec.size(), 10);
@@ -300,7 +299,7 @@ public:
     for (int i = 0; i < 10; i++) {
       double cost = i;
       p.schedule(std::make_shared<FunctionTask>(
-          boost::bind(threadpooltest_adding_stuff, i), cost));
+          std::bind(threadpooltest_adding_stuff, i), cost));
     }
     TS_ASSERT_THROWS_NOTHING(p.joinAll());
     TS_ASSERT_EQUALS(threadpooltest_vec.size(), 10);
@@ -318,7 +317,7 @@ public:
     for (int i = 0; i < 10; i++) {
       double cost = i;
       p.schedule(std::make_shared<FunctionTask>(
-          boost::bind(threadpooltest_adding_stuff, i), cost));
+          std::bind(threadpooltest_adding_stuff, i), cost));
     }
     TS_ASSERT_THROWS_NOTHING(p.joinAll());
     TS_ASSERT_EQUALS(threadpooltest_vec.size(), 10);
@@ -342,7 +341,7 @@ public:
     boost::shared_ptr<std::mutex> lastMutex;
     for (size_t i = 0; i <= num; i++) {
       auto task = std::make_shared<FunctionTask>(
-          boost::bind(&TimeWaster::add_to_number, &mywaster, i),
+          std::bind(&TimeWaster::add_to_number, &mywaster, i),
           static_cast<double>(i));
       // Create a new mutex every 1000 tasks. This is more relevant to the
       // ThreadSchedulerMutexes; others ignore it.
diff --git a/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Integrate3DEvents.h b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Integrate3DEvents.h
index 8e02f3ff53e98783a48e810c39260548bd904afc..45a1687ada2f33ff87e8cc5aab5fae9533c8f4f0 100644
--- a/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Integrate3DEvents.h
+++ b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/Integrate3DEvents.h
@@ -51,21 +51,23 @@ struct IntegrationParameters {
 
  */
 
-using EventListMap =
-    std::unordered_map<int64_t,
-                       std::vector<std::pair<double, Mantid::Kernel::V3D>>>;
+using EventListMap = std::unordered_map<
+    int64_t,
+    std::vector<std::pair<std::pair<double, double>, Mantid::Kernel::V3D>>>;
 using PeakQMap = std::unordered_map<int64_t, Mantid::Kernel::V3D>;
 
 class DLLExport Integrate3DEvents {
 public:
   /// Construct object to store events around peaks and integrate peaks
   Integrate3DEvents(
-      const std::vector<std::pair<double, Mantid::Kernel::V3D>> &peak_q_list,
+      const std::vector<std::pair<std::pair<double, double>,
+                                  Mantid::Kernel::V3D>> &peak_q_list,
       Kernel::DblMatrix const &UBinv, double radius,
       const bool useOnePercentBackgroundCorrection = true);
 
   Integrate3DEvents(
-      const std::vector<std::pair<double, Mantid::Kernel::V3D>> &peak_q_list,
+      const std::vector<std::pair<std::pair<double, double>,
+                                  Mantid::Kernel::V3D>> &peak_q_list,
       std::vector<Mantid::Kernel::V3D> const &hkl_list,
       std::vector<Mantid::Kernel::V3D> const &mnp_list,
       Kernel::DblMatrix const &UBinv, Kernel::DblMatrix const &ModHKL,
@@ -73,9 +75,9 @@ public:
       const bool useOnePercentBackgroundCorrection = true);
 
   /// Add event Q's to lists of events near peaks
-  void
-  addEvents(std::vector<std::pair<double, Mantid::Kernel::V3D>> const &event_qs,
-            bool hkl_integ);
+  void addEvents(std::vector<std::pair<std::pair<double, double>,
+                                       Mantid::Kernel::V3D>> const &event_qs,
+                 bool hkl_integ);
 
   /// Find the net integrated intensity of a peak, using ellipsoidal volumes
   boost::shared_ptr<const Mantid::Geometry::PeakShape> ellipseIntegrateEvents(
@@ -114,7 +116,7 @@ public:
 
 private:
   /// Get a list of events for a given Q
-  const std::vector<std::pair<double, Mantid::Kernel::V3D>> *
+  const std::vector<std::pair<std::pair<double, double>, Mantid::Kernel::V3D>> *
   getEvents(const Mantid::Kernel::V3D &peak_q);
 
   bool correctForDetectorEdges(std::tuple<double, double, double> &radii,
@@ -125,21 +127,25 @@ private:
                                const std::vector<double> &bkgOuterRadii);
 
   /// Calculate the number of events in an ellipsoid centered at 0,0,0
-  static double numInEllipsoid(
-      std::vector<std::pair<double, Mantid::Kernel::V3D>> const &events,
-      std::vector<Mantid::Kernel::V3D> const &directions,
-      std::vector<double> const &sizes);
+  static std::pair<double, double>
+  numInEllipsoid(std::vector<std::pair<std::pair<double, double>,
+                                       Mantid::Kernel::V3D>> const &events,
+                 std::vector<Mantid::Kernel::V3D> const &directions,
+                 std::vector<double> const &sizes);
 
   /// Calculate the number of events in an ellipsoid centered at 0,0,0
-  static double numInEllipsoidBkg(
-      std::vector<std::pair<double, Mantid::Kernel::V3D>> const &events,
-      std::vector<Mantid::Kernel::V3D> const &directions,
-      std::vector<double> const &sizes, std::vector<double> const &sizesIn,
-      const bool useOnePercentBackgroundCorrection);
+  static std::pair<double, double>
+  numInEllipsoidBkg(std::vector<std::pair<std::pair<double, double>,
+                                          Mantid::Kernel::V3D>> const &events,
+                    std::vector<Mantid::Kernel::V3D> const &directions,
+                    std::vector<double> const &sizes,
+                    std::vector<double> const &sizesIn,
+                    const bool useOnePercentBackgroundCorrection);
 
   /// Calculate the 3x3 covariance matrix of a list of Q-vectors at 0,0,0
   static void makeCovarianceMatrix(
-      std::vector<std::pair<double, Mantid::Kernel::V3D>> const &events,
+      std::vector<std::pair<std::pair<double, double>,
+                            Mantid::Kernel::V3D>> const &events,
       Kernel::DblMatrix &matrix, double radius);
 
   /// Calculate the eigen vectors of a 3x3 real symmetric matrix
@@ -148,7 +154,8 @@ private:
 
   /// Calculate the standard deviation of 3D events in a specified direction
   static double
-  stdDev(std::vector<std::pair<double, Mantid::Kernel::V3D>> const &events,
+  stdDev(std::vector<std::pair<std::pair<double, double>,
+                               Mantid::Kernel::V3D>> const &events,
          Mantid::Kernel::V3D const &direction, double radius);
 
   /// Form a map key as 10^12*h + 10^6*k + l from the integers h, k, l
@@ -163,15 +170,19 @@ private:
   int64_t getHklMnpKey2(Mantid::Kernel::V3D const &hkl);
 
   /// Add an event to the vector of events for the closest h,k,l
-  void addEvent(std::pair<double, Mantid::Kernel::V3D> event_Q, bool hkl_integ);
-  void addModEvent(std::pair<double, Mantid::Kernel::V3D> event_Q,
-                   bool hkl_integ);
+  void
+  addEvent(std::pair<std::pair<double, double>, Mantid::Kernel::V3D> event_Q,
+           bool hkl_integ);
+  void
+  addModEvent(std::pair<std::pair<double, double>, Mantid::Kernel::V3D> event_Q,
+              bool hkl_integ);
 
   /// Find the net integrated intensity of a list of Q's using ellipsoids
   boost::shared_ptr<const Mantid::DataObjects::PeakShapeEllipsoid>
   ellipseIntegrateEvents(
       std::vector<Kernel::V3D> E1Vec, Kernel::V3D const &peak_q,
-      std::vector<std::pair<double, Mantid::Kernel::V3D>> const &ev_list,
+      std::vector<std::pair<std::pair<double, double>,
+                            Mantid::Kernel::V3D>> const &ev_list,
       std::vector<Mantid::Kernel::V3D> const &directions,
       std::vector<double> const &sigmas, bool specify_size, double peak_radius,
       double back_inner_radius, double back_outer_radius,
diff --git a/Framework/MDAlgorithms/src/AccumulateMD.cpp b/Framework/MDAlgorithms/src/AccumulateMD.cpp
index a631a4299fb5db51b00e608304d0456a4c895f76..84a76dcfcb80c874ae39399c1611c0feefb91f07 100644
--- a/Framework/MDAlgorithms/src/AccumulateMD.cpp
+++ b/Framework/MDAlgorithms/src/AccumulateMD.cpp
@@ -196,9 +196,9 @@ void insertDataSources(
   boost::split(data_split, data_sources, boost::is_any_of(","));
 
   // Trim any whitespace from ends of each data source string
-  std::for_each(
-      data_split.begin(), data_split.end(),
-      boost::bind(boost::algorithm::trim<std::string>, _1, std::locale()));
+  std::for_each(data_split.begin(), data_split.end(),
+                std::bind(boost::algorithm::trim<std::string>,
+                          std::placeholders::_1, std::locale()));
 
   // Insert each data source into our complete set of historical data sources
   historical_data_sources.insert(data_split.begin(), data_split.end());
diff --git a/Framework/MDAlgorithms/src/Integrate3DEvents.cpp b/Framework/MDAlgorithms/src/Integrate3DEvents.cpp
index 582b88eecac4332057ce4dc0a9f712f9d29a19f5..1313c9f7391c8b521afb1b9e8500ca2dbd9d659d 100644
--- a/Framework/MDAlgorithms/src/Integrate3DEvents.cpp
+++ b/Framework/MDAlgorithms/src/Integrate3DEvents.cpp
@@ -45,7 +45,8 @@ using Mantid::Kernel::V3D;
  *                       correction should be used.
  */
 Integrate3DEvents::Integrate3DEvents(
-    const std::vector<std::pair<double, Mantid::Kernel::V3D>> &peak_q_list,
+    const std::vector<std::pair<std::pair<double, double>, Mantid::Kernel::V3D>>
+        &peak_q_list,
     Kernel::DblMatrix const &UBinv, double radius,
     const bool useOnePercentBackgroundCorrection)
     : m_UBinv(UBinv), m_radius(radius), maxOrder(0), crossterm(0),
@@ -80,9 +81,9 @@ Integrate3DEvents::Integrate3DEvents(
  *                       correction should be used.
  */
 Integrate3DEvents::Integrate3DEvents(
-    const std::vector<std::pair<double, Mantid::Kernel::V3D>> &peak_q_list,
-    std::vector<Mantid::Kernel::V3D> const &hkl_list,
-    std::vector<Mantid::Kernel::V3D> const &mnp_list,
+    const std::vector<std::pair<std::pair<double, double>, Mantid::Kernel::V3D>>
+        &peak_q_list,
+    std::vector<V3D> const &hkl_list, std::vector<V3D> const &mnp_list,
     Kernel::DblMatrix const &UBinv, Kernel::DblMatrix const &ModHKL,
     double radius_m, double radius_s, int MaxO, const bool CrossT,
     const bool useOnePercentBackgroundCorrection)
@@ -120,7 +121,8 @@ Integrate3DEvents::Integrate3DEvents(
  * @param hkl_integ
  */
 void Integrate3DEvents::addEvents(
-    std::vector<std::pair<double, V3D>> const &event_qs, bool hkl_integ) {
+    std::vector<std::pair<std::pair<double, double>, V3D>> const &event_qs,
+    bool hkl_integ) {
   if (!maxOrder)
     for (const auto &event_q : event_qs)
       addEvent(event_q, hkl_integ);
@@ -199,17 +201,17 @@ Integrate3DEvents::integrateStrongPeak(const IntegrationParameters &params,
   const auto peak = numInEllipsoid(events, eigen_vectors, peakRadii);
   const auto ratio = pow(r1, 3) / (pow(r3, 3) - pow(r2, 3));
 
-  inti = peak - ratio * backgrd;
-  sigi = sqrt(peak + ratio * ratio * backgrd);
+  inti = peak.first - ratio * backgrd.first;
+  sigi = sqrt(peak.second + ratio * ratio * backgrd.second);
 
   // compute the fraction of peak within the standard core
-  const auto total = (core + peak) - ratio * backgrd;
+  const auto total = (core.first + peak.first) - ratio * backgrd.first;
   const auto frac = std::min(1.0, std::abs(inti / total));
   // compute the uncertainty in the fraction
-  const auto df_ds_core = (1 - frac) / peak;
-  const auto df_ds_peak = frac / peak;
+  const auto df_ds_core = (1 - frac) / peak.first;
+  const auto df_ds_peak = frac / peak.first;
   const auto fracError =
-      sqrt(peak * pow(df_ds_core, 2) + core * pow(df_ds_peak, 2));
+      sqrt(peak.first * pow(df_ds_core, 2) + core.first * pow(df_ds_peak, 2));
 
   // create the peaks shape for the strong peak
   const auto shape = boost::make_shared<const PeakShapeEllipsoid>(
@@ -254,16 +256,17 @@ Integrate3DEvents::integrateWeakPeak(
                r3 = std::get<2>(rValues);
 
   // integrate
-  double backgrd = numInEllipsoidBkg(
+  std::pair<double, double> backgrd = numInEllipsoidBkg(
       events, directions, abcBackgroundOuterRadii, abcBackgroundInnerRadii,
       m_useOnePercentBackgroundCorrection);
-  double peak_w_back = numInEllipsoid(events, directions, abcRadii);
+  std::pair<double, double> peak_w_back =
+      numInEllipsoid(events, directions, abcRadii);
   double ratio = pow(r1, 3) / (pow(r3, 3) - pow(r2, 3));
 
   const auto frac = std::get<0>(libPeak);
   const auto fracError = std::get<1>(libPeak);
 
-  inti = peak_w_back - ratio * backgrd;
+  inti = peak_w_back.first - ratio * backgrd.first;
 
   // correct for fractional intensity
   sigi = sigi / pow(inti, 2);
@@ -324,20 +327,21 @@ double Integrate3DEvents::estimateSignalToNoiseRatio(
   }
 
   // Background / Peak / Background
-  double backgrd = numInEllipsoidBkg(
+  std::pair<double, double> backgrd = numInEllipsoidBkg(
       events, eigen_vectors, abcBackgroundOuterRadii, abcBackgroundInnerRadii,
       m_useOnePercentBackgroundCorrection);
 
-  double peak_w_back = numInEllipsoid(events, eigen_vectors, peakRadii);
+  std::pair<double, double> peak_w_back =
+      numInEllipsoid(events, eigen_vectors, peakRadii);
 
   double ratio = pow(r1, 3) / (pow(r3, 3) - pow(r2, 3));
-  auto inti = peak_w_back - ratio * backgrd;
-  auto sigi = sqrt(peak_w_back + ratio * ratio * backgrd);
+  auto inti = peak_w_back.first - ratio * backgrd.first;
+  auto sigi = sqrt(peak_w_back.second + ratio * ratio * backgrd.second);
 
   return inti / sigi;
 }
 
-const std::vector<std::pair<double, V3D>> *
+const std::vector<std::pair<std::pair<double, double>, V3D>> *
 Integrate3DEvents::getEvents(const V3D &peak_q) {
   auto hkl_key = getHklKey(peak_q);
   if (maxOrder)
@@ -429,7 +433,7 @@ bool Integrate3DEvents::correctForDetectorEdges(
  */
 Mantid::Geometry::PeakShape_const_sptr
 Integrate3DEvents::ellipseIntegrateEvents(
-    std::vector<Kernel::V3D> E1Vec, V3D const &peak_q, bool specify_size,
+    std::vector<V3D> E1Vec, V3D const &peak_q, bool specify_size,
     double peak_radius, double back_inner_radius, double back_outer_radius,
     std::vector<double> &axes_radii, double &inti, double &sigi) {
   inti = 0.0; // default values, in case something
@@ -446,7 +450,8 @@ Integrate3DEvents::ellipseIntegrateEvents(
     return boost::make_shared<NoShape>();
   ;
 
-  std::vector<std::pair<double, V3D>> &some_events = pos->second;
+  std::vector<std::pair<std::pair<double, double>, V3D>> &some_events =
+      pos->second;
 
   if (some_events.size() < 3) // if there are not enough events to
   {                           // find covariance matrix, return
@@ -482,10 +487,10 @@ Integrate3DEvents::ellipseIntegrateEvents(
 
 Mantid::Geometry::PeakShape_const_sptr
 Integrate3DEvents::ellipseIntegrateModEvents(
-    std::vector<Kernel::V3D> E1Vec, V3D const &peak_q, V3D const &hkl,
-    V3D const &mnp, bool specify_size, double peak_radius,
-    double back_inner_radius, double back_outer_radius,
-    std::vector<double> &axes_radii, double &inti, double &sigi) {
+    std::vector<V3D> E1Vec, V3D const &peak_q, V3D const &hkl, V3D const &mnp,
+    bool specify_size, double peak_radius, double back_inner_radius,
+    double back_outer_radius, std::vector<double> &axes_radii, double &inti,
+    double &sigi) {
   inti = 0.0; // default values, in case something
   sigi = 0.0; // is wrong with the peak.
 
@@ -503,7 +508,8 @@ Integrate3DEvents::ellipseIntegrateModEvents(
     return boost::make_shared<NoShape>();
   ;
 
-  std::vector<std::pair<double, V3D>> &some_events = pos->second;
+  std::vector<std::pair<std::pair<double, double>, V3D>> &some_events =
+      pos->second;
 
   if (some_events.size() < 3) // if there are not enough events to
   {                           // find covariance matrix, return
@@ -551,18 +557,21 @@ Integrate3DEvents::ellipseIntegrateModEvents(
  *                     of the three axes of the ellisoid.
  * @return Then number of events that are in or on the specified ellipsoid.
  */
-double Integrate3DEvents::numInEllipsoid(
-    std::vector<std::pair<double, V3D>> const &events,
+std::pair<double, double> Integrate3DEvents::numInEllipsoid(
+    std::vector<std::pair<std::pair<double, double>, V3D>> const &events,
     std::vector<V3D> const &directions, std::vector<double> const &sizes) {
-  double count = 0;
+
+  std::pair<double, double> count(0, 0);
   for (const auto &event : events) {
     double sum = 0;
     for (size_t k = 0; k < 3; k++) {
       double comp = event.second.scalar_prod(directions[k]) / sizes[k];
       sum += comp * comp;
     }
-    if (sum <= 1)
-      count += event.first;
+    if (sum <= 1) {
+      count.first += event.first.first;   // count
+      count.second += event.first.second; // error squared (add in quadrature)
+    }
   }
 
   return count;
@@ -584,13 +593,13 @@ double Integrate3DEvents::numInEllipsoid(
  correction should be used.
  * @return Then number of events that are in or on the specified ellipsoid.
  */
-double Integrate3DEvents::numInEllipsoidBkg(
-    std::vector<std::pair<double, V3D>> const &events,
+std::pair<double, double> Integrate3DEvents::numInEllipsoidBkg(
+    std::vector<std::pair<std::pair<double, double>, V3D>> const &events,
     std::vector<V3D> const &directions, std::vector<double> const &sizes,
     std::vector<double> const &sizesIn,
     const bool useOnePercentBackgroundCorrection) {
-  double count = 0;
-  std::vector<double> eventVec;
+  std::pair<double, double> count(0, 0);
+  std::vector<std::pair<double, double>> eventVec;
   for (const auto &event : events) {
     double sum = 0;
     double sumIn = 0;
@@ -607,12 +616,16 @@ double Integrate3DEvents::numInEllipsoidBkg(
   auto endIndex = eventVec.size();
   if (useOnePercentBackgroundCorrection) {
     // Remove top 1% of background
-    std::sort(eventVec.begin(), eventVec.end());
+    std::sort(
+        eventVec.begin(), eventVec.end(),
+        [](const std::pair<double, double> &a,
+           const std::pair<double, double> &b) { return a.first < b.first; });
     endIndex = static_cast<size_t>(0.99 * static_cast<double>(endIndex));
   }
 
   for (size_t k = 0; k < endIndex; ++k) {
-    count += eventVec[k];
+    count.first += eventVec[k].first;
+    count.second += eventVec[k].second;
   }
 
   return count;
@@ -646,8 +659,8 @@ double Integrate3DEvents::numInEllipsoidBkg(
  */
 
 void Integrate3DEvents::makeCovarianceMatrix(
-    std::vector<std::pair<double, V3D>> const &events, DblMatrix &matrix,
-    double radius) {
+    std::vector<std::pair<std::pair<double, double>, V3D>> const &events,
+    DblMatrix &matrix, double radius) {
   for (int row = 0; row < 3; row++) {
     for (int col = 0; col < 3; col++) {
       double sum = 0;
@@ -713,9 +726,9 @@ void Integrate3DEvents::getEigenVectors(DblMatrix const &cov_matrix,
  *  @param  radius      Maximun size of event vectors that will be used
  *                      in calculating the standard deviation.
  */
-double
-Integrate3DEvents::stdDev(std::vector<std::pair<double, V3D>> const &events,
-                          V3D const &direction, double radius) {
+double Integrate3DEvents::stdDev(
+    std::vector<std::pair<std::pair<double, double>, V3D>> const &events,
+    V3D const &direction, double radius) {
   double sum = 0;
   double sum_sq = 0;
   double stdev = 0;
@@ -1004,8 +1017,8 @@ int64_t Integrate3DEvents::getHklMnpKey(V3D const &q_vector) {
  *                     event_lists map, if it is close enough to some peak
  * @param hkl_integ
  */
-void Integrate3DEvents::addEvent(std::pair<double, V3D> event_Q,
-                                 bool hkl_integ) {
+void Integrate3DEvents::addEvent(
+    std::pair<std::pair<double, double>, V3D> event_Q, bool hkl_integ) {
   int64_t hkl_key;
   if (hkl_integ)
     hkl_key = getHklKey2(event_Q.second);
@@ -1043,8 +1056,8 @@ void Integrate3DEvents::addEvent(std::pair<double, V3D> event_Q,
  *                     event_lists map, if it is close enough to some peak
  * @param hkl_integ
  */
-void Integrate3DEvents::addModEvent(std::pair<double, V3D> event_Q,
-                                    bool hkl_integ) {
+void Integrate3DEvents::addModEvent(
+    std::pair<std::pair<double, double>, V3D> event_Q, bool hkl_integ) {
   int64_t hklmnp_key;
 
   if (hkl_integ)
@@ -1111,12 +1124,13 @@ void Integrate3DEvents::addModEvent(std::pair<double, V3D> event_Q,
  *
  */
 PeakShapeEllipsoid_const_sptr Integrate3DEvents::ellipseIntegrateEvents(
-    std::vector<Kernel::V3D> E1Vec, V3D const &peak_q,
-    std::vector<std::pair<double, Mantid::Kernel::V3D>> const &ev_list,
-    std::vector<Mantid::Kernel::V3D> const &directions,
-    std::vector<double> const &sigmas, bool specify_size, double peak_radius,
-    double back_inner_radius, double back_outer_radius,
-    std::vector<double> &axes_radii, double &inti, double &sigi) {
+    std::vector<V3D> E1Vec, V3D const &peak_q,
+    std::vector<std::pair<std::pair<double, double>, Mantid::Kernel::V3D>> const
+        &ev_list,
+    std::vector<V3D> const &directions, std::vector<double> const &sigmas,
+    bool specify_size, double peak_radius, double back_inner_radius,
+    double back_outer_radius, std::vector<double> &axes_radii, double &inti,
+    double &sigi) {
   // r1, r2 and r3 will give the sizes of the major axis of
   // the peak ellipsoid, and of the inner and outer surface
   // of the background ellipsoidal shell, respectively.
@@ -1187,16 +1201,17 @@ PeakShapeEllipsoid_const_sptr Integrate3DEvents::ellipseIntegrateEvents(
     }
   }
 
-  double backgrd = numInEllipsoidBkg(
+  std::pair<double, double> backgrd = numInEllipsoidBkg(
       ev_list, directions, abcBackgroundOuterRadii, abcBackgroundInnerRadii,
       m_useOnePercentBackgroundCorrection);
 
-  double peak_w_back = numInEllipsoid(ev_list, directions, axes_radii);
+  std::pair<double, double> peak_w_back =
+      numInEllipsoid(ev_list, directions, axes_radii);
 
   double ratio = pow(r1, 3) / (pow(r3, 3) - pow(r2, 3));
 
-  inti = peak_w_back - ratio * backgrd;
-  sigi = sqrt(peak_w_back + ratio * ratio * backgrd);
+  inti = peak_w_back.first - ratio * backgrd.first;
+  sigi = sqrt(peak_w_back.second + ratio * ratio * backgrd.second);
 
   // Make the shape and return it.
   return boost::make_shared<const PeakShapeEllipsoid>(
@@ -1214,8 +1229,7 @@ PeakShapeEllipsoid_const_sptr Integrate3DEvents::ellipseIntegrateEvents(
  * @param QLabFrame: The Peak center.
  * @param r: Peak radius.
  */
-double Integrate3DEvents::detectorQ(std::vector<Kernel::V3D> E1Vec,
-                                    const Mantid::Kernel::V3D QLabFrame,
+double Integrate3DEvents::detectorQ(std::vector<V3D> E1Vec, const V3D QLabFrame,
                                     const std::vector<double> &r) {
   double quot = 1.0;
   for (auto &E1 : E1Vec) {
diff --git a/Framework/MDAlgorithms/src/IntegrateEllipsoids.cpp b/Framework/MDAlgorithms/src/IntegrateEllipsoids.cpp
index e085ec8cb58680b1c9d5344d13f9d008ec773e5b..ed049f7dac573fc625664926908cc37362829daf 100644
--- a/Framework/MDAlgorithms/src/IntegrateEllipsoids.cpp
+++ b/Framework/MDAlgorithms/src/IntegrateEllipsoids.cpp
@@ -101,7 +101,7 @@ void IntegrateEllipsoids::qListFromEventWS(Integrate3DEvents &integrator,
     double errorSq(1.); // ignorable garbage
     const std::vector<WeightedEventNoTime> &raw_events =
         events.getWeightedEventsNoTime();
-    std::vector<std::pair<double, V3D>> qList;
+    std::vector<std::pair<std::pair<double, double>, V3D>> qList;
     for (const auto &raw_event : raw_events) {
       double val = unitConverter.convertUnits(raw_event.tof());
       qConverter.calcMatrixCoord(val, locCoord, signal, errorSq);
@@ -111,7 +111,9 @@ void IntegrateEllipsoids::qListFromEventWS(Integrate3DEvents &integrator,
       V3D qVec(buffer[0], buffer[1], buffer[2]);
       if (hkl_integ)
         qVec = UBinv * qVec;
-      qList.emplace_back(raw_event.m_weight, qVec);
+      qList.emplace_back(std::pair<double, double>(raw_event.m_weight,
+                                                   raw_event.m_errorSquared),
+                         qVec);
     } // end of loop over events in list
     PARALLEL_CRITICAL(addEvents) { integrator.addEvents(qList, hkl_integ); }
 
@@ -155,6 +157,7 @@ void IntegrateEllipsoids::qListFromHistoWS(Integrate3DEvents &integrator,
     // get tof and y values
     const auto &xVals = wksp->points(i);
     const auto &yVals = wksp->y(i);
+    const auto &eVals = wksp->e(i);
 
     // update which pixel is being converted
     std::vector<Mantid::coord_t> locCoord(DIMS, 0.);
@@ -165,10 +168,11 @@ void IntegrateEllipsoids::qListFromHistoWS(Integrate3DEvents &integrator,
     double signal(1.);  // ignorable garbage
     double errorSq(1.); // ignorable garbage
 
-    std::vector<std::pair<double, V3D>> qList;
+    std::vector<std::pair<std::pair<double, double>, V3D>> qList;
 
     for (size_t j = 0; j < yVals.size(); ++j) {
       const double &yVal = yVals[j];
+      const double &esqVal = eVals[j] * eVals[j]; // error squared (variance)
       if (yVal > 0) // TODO, is this condition right?
       {
         double val = unitConverter.convertUnits(xVals[j]);
@@ -186,7 +190,7 @@ void IntegrateEllipsoids::qListFromHistoWS(Integrate3DEvents &integrator,
           continue;
         // Account for counts in histograms by increasing the qList with the
         // same q-point
-        qList.emplace_back(yVal, qVec);
+        qList.emplace_back(std::pair<double, double>(yVal, esqVal), qVec);
       }
     }
     PARALLEL_CRITICAL(addHisto) { integrator.addEvents(qList, hkl_integ); }
@@ -384,7 +388,7 @@ void IntegrateEllipsoids::exec() {
   size_t n_peaks = peak_ws->getNumberPeaks();
   size_t indexed_count = 0;
   std::vector<V3D> peak_q_list;
-  std::vector<std::pair<double, V3D>> qList;
+  std::vector<std::pair<std::pair<double, double>, V3D>> qList;
   std::vector<V3D> hkl_vectors;
   std::vector<V3D> mnp_vectors;
   int ModDim = 0;
@@ -403,7 +407,8 @@ void IntegrateEllipsoids::exec() {
     // use tolerance == 1 to just check for (0,0,0,0,0,0)
     if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0)) {
       peak_q_list.emplace_back(peaks[i].getQLabFrame());
-      qList.emplace_back(1., V3D(peaks[i].getQLabFrame()));
+      qList.emplace_back(std::pair<double, double>(1., 1.),
+                         V3D(peaks[i].getQLabFrame()));
       hkl_vectors.emplace_back(hkl);
       mnp_vectors.emplace_back(mnp);
       indexed_count++;
diff --git a/Framework/MDAlgorithms/src/IntegrateEllipsoidsTwoStep.cpp b/Framework/MDAlgorithms/src/IntegrateEllipsoidsTwoStep.cpp
index 6926b137fc3de5be6ae12b678ef4710bf8e9b54f..88fcf9b563fb2bdfc5f7ca2e1c27f474fb5f21b1 100644
--- a/Framework/MDAlgorithms/src/IntegrateEllipsoidsTwoStep.cpp
+++ b/Framework/MDAlgorithms/src/IntegrateEllipsoidsTwoStep.cpp
@@ -183,9 +183,10 @@ void IntegrateEllipsoidsTwoStep::exec() {
   UBinv.Invert();
   UBinv *= (1.0 / (2.0 * M_PI));
 
-  std::vector<std::pair<double, V3D>> qList;
+  std::vector<std::pair<std::pair<double, double>, V3D>> qList;
   for (size_t i = 0; i < n_peaks; i++) {
-    qList.emplace_back(1., V3D(peaks[i].getQLabFrame()));
+    qList.emplace_back(std::pair<double, double>(1.0, 1.0),
+                       V3D(peaks[i].getQLabFrame()));
   }
 
   const bool integrateEdge = getProperty("IntegrateIfOnEdge");
@@ -410,7 +411,7 @@ void IntegrateEllipsoidsTwoStep::qListFromEventWS(Integrate3DEvents &integrator,
     double errorSq(1.); // ignorable garbage
     const std::vector<WeightedEventNoTime> &raw_events =
         events.getWeightedEventsNoTime();
-    std::vector<std::pair<double, V3D>> qList;
+    std::vector<std::pair<std::pair<double, double>, V3D>> qList;
     for (const auto &raw_event : raw_events) {
       double val = unitConverter.convertUnits(raw_event.tof());
       qConverter.calcMatrixCoord(val, locCoord, signal, errorSq);
@@ -420,7 +421,9 @@ void IntegrateEllipsoidsTwoStep::qListFromEventWS(Integrate3DEvents &integrator,
       V3D qVec(buffer[0], buffer[1], buffer[2]);
       if (hkl_integ)
         qVec = UBinv * qVec;
-      qList.emplace_back(raw_event.m_weight, qVec);
+      qList.emplace_back(std::pair<double, double>(raw_event.m_weight,
+                                                   raw_event.m_errorSquared),
+                         qVec);
     } // end of loop over events in list
     PARALLEL_CRITICAL(addEvents) { integrator.addEvents(qList, hkl_integ); }
 
@@ -488,6 +491,7 @@ void IntegrateEllipsoidsTwoStep::qListFromHistoWS(Integrate3DEvents &integrator,
     // get tof and y values
     const auto &xVals = wksp->points(i);
     const auto &yVals = wksp->y(i);
+    const auto &eVals = wksp->e(i);
 
     // update which pixel is being converted
     std::vector<Mantid::coord_t> locCoord(DIMS, 0.);
@@ -498,10 +502,11 @@ void IntegrateEllipsoidsTwoStep::qListFromHistoWS(Integrate3DEvents &integrator,
     double signal(1.);  // ignorable garbage
     double errorSq(1.); // ignorable garbage
 
-    std::vector<std::pair<double, V3D>> qList;
+    std::vector<std::pair<std::pair<double, double>, V3D>> qList;
 
     for (size_t j = 0; j < yVals.size(); ++j) {
       const double &yVal = yVals[j];
+      const double &esqVal = eVals[j] * eVals[j]; // error squared (variance)
       if (yVal > 0) // TODO, is this condition right?
       {
         double val = unitConverter.convertUnits(xVals[j]);
@@ -514,7 +519,7 @@ void IntegrateEllipsoidsTwoStep::qListFromHistoWS(Integrate3DEvents &integrator,
           continue;
         // Account for counts in histograms by increasing the qList with the
         // same q-point
-        qList.emplace_back(yVal, qVec);
+        qList.emplace_back(std::pair<double, double>(yVal, esqVal), qVec);
       }
     }
     PARALLEL_CRITICAL(addHisto) { integrator.addEvents(qList, hkl_integ); }
diff --git a/Framework/MDAlgorithms/src/MDNorm.cpp b/Framework/MDAlgorithms/src/MDNorm.cpp
index 8522a1c76b7d86d7ac9c78e248287ff4f3107d42..44e17c6971223581b36f3eba4ad4f655be04f2cc 100644
--- a/Framework/MDAlgorithms/src/MDNorm.cpp
+++ b/Framework/MDAlgorithms/src/MDNorm.cpp
@@ -652,10 +652,10 @@ std::map<std::string, std::string> MDNorm::getBinParameters() {
       for (size_t j = 0; j < originalDimensionNames.size(); j++) {
         if (j == static_cast<size_t>(dimIndex)) {
           propertyValue << ",1";
-          transformation.emplace_back(1.);
+          transformation.emplace_back(1.f);
         } else {
           propertyValue << ",0";
-          transformation.emplace_back(0.);
+          transformation.emplace_back(0.f);
         }
       }
       parameters.emplace(property, propertyValue.str());
diff --git a/Framework/MDAlgorithms/src/MDNormDirectSC.cpp b/Framework/MDAlgorithms/src/MDNormDirectSC.cpp
index 48121788de18a066d3ddff530b7610ee09534066..6d589fc3c09784cae697dcc236221c96b18993cb 100644
--- a/Framework/MDAlgorithms/src/MDNormDirectSC.cpp
+++ b/Framework/MDAlgorithms/src/MDNormDirectSC.cpp
@@ -531,7 +531,7 @@ for (int64_t i = 0; i < ndets; i++) {
   // pre-allocate for efficiency and copy non-hkl dim values into place
   pos.resize(vmdDims + otherValues.size() + 1);
   std::copy(otherValues.begin(), otherValues.end(), pos.begin() + vmdDims);
-  pos.emplace_back(1.);
+  pos.emplace_back(1.f);
   auto intersectionsBegin = intersections.begin();
   for (auto it = intersectionsBegin + 1; it != intersections.end(); ++it) {
     const auto &curIntSec = *it;
diff --git a/Framework/MDAlgorithms/src/MDNormSCD.cpp b/Framework/MDAlgorithms/src/MDNormSCD.cpp
index 5f31243d10a167bc4123deabc470d6475fd7bfdb..6472c722160e7f5e2d513d00ec4cda1b1adcfc45 100644
--- a/Framework/MDAlgorithms/src/MDNormSCD.cpp
+++ b/Framework/MDAlgorithms/src/MDNormSCD.cpp
@@ -495,7 +495,7 @@ for (int64_t i = 0; i < ndets; i++) {
   // pre-allocate for efficiency and copy non-hkl dim values into place
   pos.resize(vmdDims + otherValues.size());
   std::copy(otherValues.begin(), otherValues.end(), pos.begin() + vmdDims - 1);
-  pos.emplace_back(1.);
+  pos.emplace_back(1.f);
 
   for (auto it = intersectionsBegin + 1; it != intersections.end(); ++it) {
     const auto &curIntSec = *it;
diff --git a/Framework/MDAlgorithms/src/MDTransfQ3D.cpp b/Framework/MDAlgorithms/src/MDTransfQ3D.cpp
index 521b7b57eb1a967f39d34f7998eb20af1d5296a6..124fb981074c5a5cd3b2419547f0231b831c3562 100644
--- a/Framework/MDAlgorithms/src/MDTransfQ3D.cpp
+++ b/Framework/MDAlgorithms/src/MDTransfQ3D.cpp
@@ -152,26 +152,22 @@ bool MDTransfQ3D::calcMatrixCoord3DElastic(const double &k0,
 
   // Dimension limits have to be converted to coord_t, otherwise floating point
   // error will cause valid events to be discarded.
-  std::vector<coord_t> dim_min;
-  dim_min.reserve(m_DimMin.size());
-  std::copy(m_DimMin.cbegin(), m_DimMin.cend(), std::back_inserter(dim_min));
-  std::vector<coord_t> dim_max;
-  dim_max.reserve(m_DimMax.size());
-  std::copy(m_DimMax.cbegin(), m_DimMax.cend(), std::back_inserter(dim_max));
-
   Coord[0] = static_cast<coord_t>(m_RotMat[0] * qx + m_RotMat[1] * qy +
                                   m_RotMat[2] * qz);
-  if (Coord[0] < dim_min[0] || Coord[0] >= dim_max[0])
+  if (Coord[0] < static_cast<coord_t>(m_DimMin[0]) ||
+      Coord[0] >= static_cast<coord_t>(m_DimMax[0]))
     return false;
 
   Coord[1] = static_cast<coord_t>(m_RotMat[3] * qx + m_RotMat[4] * qy +
                                   m_RotMat[5] * qz);
-  if (Coord[1] < dim_min[1] || Coord[1] >= dim_max[1])
+  if (Coord[1] < static_cast<coord_t>(m_DimMin[1]) ||
+      Coord[1] >= static_cast<coord_t>(m_DimMax[1]))
     return false;
 
   Coord[2] = static_cast<coord_t>(m_RotMat[6] * qx + m_RotMat[7] * qy +
                                   m_RotMat[8] * qz);
-  if (Coord[2] < dim_min[2] || Coord[2] >= dim_max[2])
+  if (Coord[2] < static_cast<coord_t>(m_DimMin[2]) ||
+      Coord[2] >= static_cast<coord_t>(m_DimMax[2]))
     return false;
 
   if (std::sqrt(Coord[0] * Coord[0] + Coord[1] * Coord[1] +
diff --git a/Framework/MDAlgorithms/src/SmoothMD.cpp b/Framework/MDAlgorithms/src/SmoothMD.cpp
index 5fcd208b7eb1d66a74a061df4338deb2f8a73fee..f31fc9b04f891d3bf311500b824666471a38bc78 100644
--- a/Framework/MDAlgorithms/src/SmoothMD.cpp
+++ b/Framework/MDAlgorithms/src/SmoothMD.cpp
@@ -17,8 +17,6 @@
 #include "MantidKernel/MandatoryValidator.h"
 #include "MantidKernel/MultiThreaded.h"
 #include "MantidKernel/PropertyWithValue.h"
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
 #include <boost/make_shared.hpp>
 #include <boost/tuple/tuple.hpp>
 #include <limits>
@@ -45,7 +43,7 @@ using OptionalIMDHistoWorkspace_const_sptr =
     boost::optional<IMDHistoWorkspace_const_sptr>;
 
 // Typedef for a smoothing function
-using SmoothFunction = boost::function<IMDHistoWorkspace_sptr(
+using SmoothFunction = std::function<IMDHistoWorkspace_sptr(
     IMDHistoWorkspace_const_sptr, const WidthVector &,
     OptionalIMDHistoWorkspace_const_sptr)>;
 
@@ -59,11 +57,12 @@ namespace {
  * @return function map
  */
 SmoothFunctionMap makeFunctionMap(Mantid::MDAlgorithms::SmoothMD *instance) {
+  using namespace std::placeholders;
   return {
-      {"Hat", boost::bind(&Mantid::MDAlgorithms::SmoothMD::hatSmooth, instance,
-                          _1, _2, _3)},
-      {"Gaussian", boost::bind(&Mantid::MDAlgorithms::SmoothMD::gaussianSmooth,
-                               instance, _1, _2, _3)}};
+      {"Hat", std::bind(&Mantid::MDAlgorithms::SmoothMD::hatSmooth, instance,
+                        _1, _2, _3)},
+      {"Gaussian", std::bind(&Mantid::MDAlgorithms::SmoothMD::gaussianSmooth,
+                             instance, _1, _2, _3)}};
 }
 } // namespace
 
@@ -227,9 +226,10 @@ SmoothMD::hatSmooth(IMDHistoWorkspace_const_sptr toSmooth,
       // We've already checked in the validator that the doubles we have are odd
       // integer values and well below max int
       std::vector<int> widthVectorInt;
-      widthVectorInt.reserve(widthVector.size());
-      std::copy(widthVector.cbegin(), widthVector.cend(),
-                std::back_inserter(widthVectorInt));
+      widthVectorInt.resize(widthVector.size());
+      std::transform(widthVector.cbegin(), widthVector.cend(),
+                     widthVectorInt.begin(),
+                     [](double w) -> int { return static_cast<int>(w); });
 
       std::vector<size_t> neighbourIndexes =
           iterator->findNeighbourIndexesByWidth(widthVectorInt);
diff --git a/Framework/MDAlgorithms/src/ThresholdMD.cpp b/Framework/MDAlgorithms/src/ThresholdMD.cpp
index 00584f9711b84b0b476a8d79677cdbec10b49fe3..79dae015e69b07575917e189309beb835d83b76a 100644
--- a/Framework/MDAlgorithms/src/ThresholdMD.cpp
+++ b/Framework/MDAlgorithms/src/ThresholdMD.cpp
@@ -11,7 +11,6 @@
 #include "MantidKernel/EnabledWhenProperty.h"
 #include "MantidKernel/ListValidator.h"
 #include "MantidKernel/MultiThreaded.h"
-#include <boost/bind.hpp>
 #include <boost/function.hpp>
 
 using namespace Mantid::Kernel;
@@ -104,10 +103,11 @@ void ThresholdMD::exec() {
 
   const int64_t nPoints = inputWS->getNPoints();
 
+  using namespace std::placeholders;
   boost::function<bool(double)> comparitor =
-      boost::bind(std::less<double>(), _1, referenceValue);
+      std::bind(std::less<double>(), _1, referenceValue);
   if (condition == GreaterThan()) {
-    comparitor = boost::bind(std::greater<double>(), _1, referenceValue);
+    comparitor = std::bind(std::greater<double>(), _1, referenceValue);
   }
 
   Progress prog(this, 0.0, 1.0, 100);
diff --git a/Framework/MDAlgorithms/test/Integrate3DEventsTest.h b/Framework/MDAlgorithms/test/Integrate3DEventsTest.h
index d74188d3dc3432dba901bf7d83f5ff6da70ba902..ae945d3fb497c83aecff1d60b2d98ec12d5e592b 100644
--- a/Framework/MDAlgorithms/test/Integrate3DEventsTest.h
+++ b/Framework/MDAlgorithms/test/Integrate3DEventsTest.h
@@ -27,7 +27,7 @@ public:
   // expected integration results are obtained using either fixed size
   // ellipsoids, or using ellipsoids with axis half-lengths set to
   // three standard deviations.
-  void test_1() {
+  void test_integrateMainPeaksWithFixedRadiiandDefaultScaledRadii() {
     double inti_all[] = {755, 704, 603};
     double sigi_all[] = {27.4773, 26.533, 24.5561};
 
@@ -39,8 +39,10 @@ public:
     V3D peak_1(10, 0, 0);
     V3D peak_2(0, 5, 0);
     V3D peak_3(0, 0, 4);
-    std::vector<std::pair<double, V3D>> peak_q_list{
-        {1., peak_1}, {1., peak_2}, {1., peak_3}};
+    std::vector<std::pair<std::pair<double, double>, V3D>> peak_q_list{
+        {std::make_pair(1., 1.), peak_1},
+        {std::make_pair(1., 1.), peak_2},
+        {std::make_pair(1., 1.), peak_3}};
 
     // synthesize a UB-inverse to map
     DblMatrix UBinv(3, 3, false); // Q to h,k,l
@@ -54,40 +56,40 @@ public:
     // around peak 1, 704 events around
     // peak 2, and 603 events around
     // peak 3.
-    std::vector<std::pair<double, V3D>> event_Qs;
+    std::vector<std::pair<std::pair<double, double>, V3D>> event_Qs;
     for (int i = -100; i <= 100; i++) {
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D((double)i / 100.0, 0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_2 + V3D((double)i / 100.0, 0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_3 + V3D((double)i / 100.0, 0, 0))));
-
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D(0, (double)i / 200.0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_2 + V3D(0, (double)i / 200.0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_3 + V3D(0, (double)i / 200.0, 0))));
-
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D(0, 0, (double)i / 300.0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_2 + V3D(0, 0, (double)i / 300.0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_3 + V3D(0, 0, (double)i / 300.0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_1 + V3D((double)i / 100.0, 0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_2 + V3D((double)i / 100.0, 0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_3 + V3D((double)i / 100.0, 0, 0))));
+
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_1 + V3D(0, (double)i / 200.0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_2 + V3D(0, (double)i / 200.0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_3 + V3D(0, (double)i / 200.0, 0))));
+
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_1 + V3D(0, 0, (double)i / 300.0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_2 + V3D(0, 0, (double)i / 300.0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_3 + V3D(0, 0, (double)i / 300.0))));
     }
 
     for (int i = -50; i <= 50; i++) {
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D(0, (double)i / 147.0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_2 + V3D(0, (double)i / 147.0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_1 + V3D(0, (double)i / 147.0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_2 + V3D(0, (double)i / 147.0, 0))));
     }
 
     for (int i = -25; i <= 25; i++) {
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D(0, 0, (double)i / 61.0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(2., 1.), V3D(peak_1 + V3D(0, 0, (double)i / 61.0))));
     }
 
     double radius = 1.3;
@@ -109,7 +111,7 @@ public:
       auto shape = integrator.ellipseIntegrateEvents(
           E1Vec, peak_q_list[i].second, specify_size, peak_radius,
           back_inner_radius, back_outer_radius, new_sigma, inti, sigi);
-      TS_ASSERT_DELTA(inti, inti_all[i], 0.1);
+      TS_ASSERT_DELTA(inti, 2 * inti_all[i], 0.1);
       TS_ASSERT_DELTA(sigi, sigi_all[i], 0.01);
 
       auto ellipsoid_shape = boost::dynamic_pointer_cast<
@@ -125,7 +127,7 @@ public:
       integrator.ellipseIntegrateEvents(
           E1Vec, peak_q_list[i].second, specify_size, peak_radius,
           back_inner_radius, back_outer_radius, new_sigma, inti, sigi);
-      TS_ASSERT_DELTA(inti, inti_some[i], 0.1);
+      TS_ASSERT_DELTA(inti, 2 * inti_some[i], 0.1);
       TS_ASSERT_DELTA(sigi, sigi_some[i], 0.01);
     }
   }
@@ -142,8 +144,10 @@ public:
     V3D peak_1(6, 0, 0);
     V3D peak_2(0, 5, 0);
     V3D peak_3(0, 0, 4);
-    std::vector<std::pair<double, V3D>> peak_q_list{
-        {1., peak_1}, {1., peak_2}, {1., peak_3}};
+    std::vector<std::pair<std::pair<double, double>, V3D>> peak_q_list{
+        {std::make_pair(1., 1.), peak_1},
+        {std::make_pair(1., 1.), peak_2},
+        {std::make_pair(1., 1.), peak_3}};
 
     // synthesize a UB-inverse to map
     DblMatrix UBinv(3, 3, false); // Q to h,k,l
@@ -167,40 +171,40 @@ public:
     // around peak 1, 704 events around
     // peak 2, and 603 events around
     // peak 3.
-    std::vector<std::pair<double, V3D>> event_Qs;
+    std::vector<std::pair<std::pair<double, double>, V3D>> event_Qs;
     for (int i = -100; i <= 100; i++) {
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D((double)i / 100.0, 0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_2 + V3D((double)i / 100.0, 0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_3 + V3D((double)i / 100.0, 0, 0))));
-
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D(0, (double)i / 200.0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_2 + V3D(0, (double)i / 200.0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_3 + V3D(0, (double)i / 200.0, 0))));
-
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D(0, 0, (double)i / 300.0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_2 + V3D(0, 0, (double)i / 300.0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_3 + V3D(0, 0, (double)i / 300.0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_1 + V3D((double)i / 100.0, 0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_2 + V3D((double)i / 100.0, 0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_3 + V3D((double)i / 100.0, 0, 0))));
+
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_1 + V3D(0, (double)i / 200.0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_2 + V3D(0, (double)i / 200.0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_3 + V3D(0, (double)i / 200.0, 0))));
+
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_1 + V3D(0, 0, (double)i / 300.0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_2 + V3D(0, 0, (double)i / 300.0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_3 + V3D(0, 0, (double)i / 300.0))));
     }
 
     for (int i = -50; i <= 50; i++) {
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D(0, (double)i / 147.0, 0))));
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_2 + V3D(0, (double)i / 147.0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_1 + V3D(0, (double)i / 147.0, 0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_2 + V3D(0, (double)i / 147.0, 0))));
     }
 
     for (int i = -25; i <= 25; i++) {
-      event_Qs.emplace_back(
-          std::make_pair(1., V3D(peak_1 + V3D(0, 0, (double)i / 61.0))));
+      event_Qs.emplace_back(std::make_pair(
+          std::make_pair(1., 1.), V3D(peak_1 + V3D(0, 0, (double)i / 61.0))));
     }
 
     double radius = 0.3;
@@ -260,8 +264,10 @@ public:
     V3D peak_1(20, 0, 0);
     V3D peak_2(0, 20, 0);
     V3D peak_3(0, 0, 20);
-    std::vector<std::pair<double, V3D>> peak_q_list{
-        {1., peak_1}, {1., peak_2}, {1., peak_3}};
+    std::vector<std::pair<std::pair<double, double>, V3D>> peak_q_list{
+        {std::make_pair(1., 1.), peak_1},
+        {std::make_pair(1., 1.), peak_2},
+        {std::make_pair(1., 1.), peak_3}};
 
     // synthesize a UB-inverse to map
     DblMatrix UBinv(3, 3, false); // Q to h,k,l
@@ -269,7 +275,7 @@ public:
     UBinv.setRow(1, V3D(0, .2, 0));
     UBinv.setRow(2, V3D(0, 0, .25));
 
-    std::vector<std::pair<double, V3D>> event_Qs;
+    std::vector<std::pair<std::pair<double, double>, V3D>> event_Qs;
     const int numStrongEvents = 10000;
     const int numWeakEvents = 100;
     generatePeak(event_Qs, peak_1, 0.1, numStrongEvents, 1); // strong peak
@@ -336,7 +342,8 @@ public:
     // synthesize two peaks
     V3D peak_1(20, 0, 0);
     V3D peak_2(0, 20, 0);
-    std::vector<std::pair<double, V3D>> peak_q_list{{1., peak_1}, {1., peak_2}};
+    std::vector<std::pair<std::pair<double, double>, V3D>> peak_q_list{
+        {std::make_pair(1., 1.), peak_1}, {std::make_pair(1., 1.), peak_2}};
 
     // synthesize a UB-inverse to map
     DblMatrix UBinv(3, 3, false); // Q to h,k,l
@@ -344,7 +351,7 @@ public:
     UBinv.setRow(1, V3D(0, .2, 0));
     UBinv.setRow(2, V3D(0, 0, .25));
 
-    std::vector<std::pair<double, V3D>> event_Qs;
+    std::vector<std::pair<std::pair<double, double>, V3D>> event_Qs;
     const int numStrongEvents = 10000;
     const int numWeakEvents = 100;
     generatePeak(event_Qs, peak_1, 0.1, numStrongEvents, 1); // strong peak
@@ -394,8 +401,10 @@ public:
     V3D peak_1(20, 0, 0);
     V3D peak_2(0, 20, 0);
     V3D peak_3(0, 0, 20);
-    std::vector<std::pair<double, V3D>> peak_q_list{
-        {1., peak_1}, {1., peak_2}, {1., peak_3}};
+    std::vector<std::pair<std::pair<double, double>, V3D>> peak_q_list{
+        {std::make_pair(1., 1.), peak_1},
+        {std::make_pair(1., 1.), peak_2},
+        {std::make_pair(1., 1.), peak_3}};
 
     // synthesize a UB-inverse to map
     DblMatrix UBinv(3, 3, false); // Q to h,k,l
@@ -403,7 +412,7 @@ public:
     UBinv.setRow(1, V3D(0, .2, 0));
     UBinv.setRow(2, V3D(0, 0, .25));
 
-    std::vector<std::pair<double, V3D>> event_Qs;
+    std::vector<std::pair<std::pair<double, double>, V3D>> event_Qs;
     const int numStrongEvents = 10000;
     const int numWeakEvents = 100;
     generatePeak(event_Qs, peak_1, 0.1, numStrongEvents, 1);   // strong peak
@@ -446,8 +455,10 @@ private:
     V3D peak_1(20, 0, 0);
     V3D peak_2(0, 20, 0);
     V3D peak_3(0, 0, 20);
-    std::vector<std::pair<double, V3D>> peak_q_list{
-        {1., peak_1}, {1., peak_2}, {1., peak_3}};
+    std::vector<std::pair<std::pair<double, double>, V3D>> peak_q_list{
+        {std::make_pair(1., 1.), peak_1},
+        {std::make_pair(1., 1.), peak_2},
+        {std::make_pair(1., 1.), peak_3}};
 
     // synthesize a UB-inverse to map
     DblMatrix UBinv(3, 3, false); // Q to h,k,l
@@ -455,7 +466,7 @@ private:
     UBinv.setRow(1, V3D(0, .2, 0));
     UBinv.setRow(2, V3D(0, 0, .25));
 
-    std::vector<std::pair<double, V3D>> event_Qs;
+    std::vector<std::pair<std::pair<double, double>, V3D>> event_Qs;
     const int numStrongEvents = 10000;
     const int numWeakEvents = 100;
     generatePeak(event_Qs, peak_1, 0.1, numStrongEvents, 1);   // strong peak
@@ -492,8 +503,10 @@ private:
    * @param numSamples :: number of samples to draw
    * @param seed :: the seed to the pseudo-random number generator
    */
-  void generatePeak(std::vector<std::pair<double, V3D>> &event_Qs, V3D center,
-                    double sigma = 5, size_t numSamples = 1000, int seed = 1) {
+  void
+  generatePeak(std::vector<std::pair<std::pair<double, double>, V3D>> &event_Qs,
+               V3D center, double sigma = 5, size_t numSamples = 1000,
+               int seed = 1) {
 
     std::mt19937 gen;
     std::normal_distribution<> d(0, sigma);
@@ -501,7 +514,8 @@ private:
 
     for (size_t i = 0; i < numSamples; ++i) {
       V3D offset(d(gen), d(gen), d(gen));
-      event_Qs.emplace_back(std::make_pair(1., center + offset));
+      event_Qs.emplace_back(
+          std::make_pair(std::make_pair(1., 1.), center + offset));
     }
   }
 
@@ -514,11 +528,10 @@ private:
    * @param countVariation :: how much the average background can vary by
    * @param seed :: the random seed to use (default 1)
    */
-  void generateUniformBackground(std::vector<std::pair<double, V3D>> &event_Qs,
-                                 size_t countsPerQ, const double lower,
-                                 const double upper,
-                                 const int countVariation = 3,
-                                 const double step = 0.5, int seed = 1) {
+  void generateUniformBackground(
+      std::vector<std::pair<std::pair<double, double>, V3D>> &event_Qs,
+      size_t countsPerQ, const double lower, const double upper,
+      const int countVariation = 3, const double step = 0.5, int seed = 1) {
     const auto counts = static_cast<double>(countsPerQ);
     std::mt19937 gen;
     std::uniform_real_distribution<> d(-countVariation, countVariation);
@@ -527,7 +540,8 @@ private:
     for (double i = lower; i < upper; i += step) {
       for (double j = lower; j < upper; j += step) {
         for (double k = lower; k < upper; k += step) {
-          event_Qs.emplace_back(counts + d(gen), V3D(i, j, k));
+          double cts = counts + d(gen);
+          event_Qs.emplace_back(std::make_pair(cts, cts), V3D(i, j, k));
         }
       }
     }
diff --git a/Framework/MDAlgorithms/test/SaveMD2Test.h b/Framework/MDAlgorithms/test/SaveMD2Test.h
index eb43936b5d81ceb03f51e7e618777591b9f54a13..617e3330cdbeec1cb367562100cd961db3507d54 100644
--- a/Framework/MDAlgorithms/test/SaveMD2Test.h
+++ b/Framework/MDAlgorithms/test/SaveMD2Test.h
@@ -217,7 +217,7 @@ public:
     alg.execute();
     TS_ASSERT(alg.isExecuted());
     std::string this_filename = alg.getProperty("Filename");
-    long unsigned int fileSize = Poco::File(this_filename).getSize();
+    const auto fileSize = Poco::File(this_filename).getSize();
     if (Poco::File(this_filename).exists())
       Poco::File(this_filename).remove();
 
@@ -235,7 +235,7 @@ public:
     alg2.execute();
     TS_ASSERT(alg2.isExecuted());
     std::string this_filename2 = alg2.getProperty("Filename");
-    long unsigned int fileSize2 = Poco::File(this_filename2).getSize();
+    const auto fileSize2 = Poco::File(this_filename2).getSize();
     if (Poco::File(this_filename2).exists())
       Poco::File(this_filename2).remove();
 
diff --git a/Framework/PythonInterface/core/src/Converters/DateAndTime.cpp b/Framework/PythonInterface/core/src/Converters/DateAndTime.cpp
index da7c57aa4596d14aec763d7c71700082c2e2d9df..7c7c8a4f37d2cc9329f2d0d022428d9301711cf2 100644
--- a/Framework/PythonInterface/core/src/Converters/DateAndTime.cpp
+++ b/Framework/PythonInterface/core/src/Converters/DateAndTime.cpp
@@ -99,7 +99,8 @@ to_dateandtime(const boost::python::api::object &value) {
 
   boost::python::extract<double> converter_dbl(value);
   if (converter_dbl.check()) {
-    return boost::make_shared<DateAndTime>(converter_dbl());
+    return boost::make_shared<DateAndTime>(
+        static_cast<int64_t>(converter_dbl()));
   }
 
   boost::python::extract<int64_t> converter_int64(value);
diff --git a/Framework/PythonInterface/mantid/BundlePython.cmake b/Framework/PythonInterface/mantid/BundlePython.cmake
index 88b40ede3d6794f851353a96f1fb63640be9a37b..4f9752453ad877029cfdccc92fadb5ee0d916805 100644
--- a/Framework/PythonInterface/mantid/BundlePython.cmake
+++ b/Framework/PythonInterface/mantid/BundlePython.cmake
@@ -6,16 +6,6 @@
 ###############################################################################
 
 if( MSVC )
-  #####################################################################
-  # Bundled Python for dev build. Assumes PYTHON_DIR has been set in
-  # MSVCSetup.cmake
-  #####################################################################
-  file(TO_NATIVE_PATH ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} BIN_NATIVE)
-  add_custom_command( TARGET ${PYBUNDLE_POST_TARGET} POST_BUILD
-                      COMMAND ${CMAKE_COMMAND}
-                      ARGS -E copy_if_different ${PYTHON_DIR}/python27.dll ${BIN_NATIVE}/python27.dll
-                      COMMENT "Copying Python27 dll to bin" )
- 
   #####################################################################
   # Bundle for package
   #####################################################################
@@ -24,5 +14,7 @@ if( MSVC )
   install ( DIRECTORY ${PYTHON_DIR}/Lib DESTINATION bin PATTERN ".svn" EXCLUDE PATTERN ".git" EXCLUDE PATTERN "*_d.pyd" EXCLUDE )
   install ( DIRECTORY ${PYTHON_DIR}/Scripts DESTINATION bin PATTERN ".svn" EXCLUDE PATTERN ".git" EXCLUDE PATTERN "*_d.py" EXCLUDE )
   install ( DIRECTORY ${PYTHON_DIR}/tcl DESTINATION bin PATTERN ".svn" EXCLUDE PATTERN ".git" EXCLUDE )
-  install ( FILES ${PYTHON_DIR}/python27.dll ${PYTHON_EXECUTABLE} ${PYTHONW_EXECUTABLE} DESTINATION bin )
+  install ( FILES ${PYTHON_DIR}/python${PYTHON_MAJOR_VERSION}${PYTHON_MINOR_VERSION}.dll
+            ${PYTHON_DIR}/python${PYTHON_MAJOR_VERSION}.dll ${PYTHON_EXECUTABLE} ${PYTHONW_EXECUTABLE}
+            DESTINATION bin )
 endif()
diff --git a/Framework/PythonInterface/mantid/api/src/Exports/Projection.cpp b/Framework/PythonInterface/mantid/api/src/Exports/Projection.cpp
index 765b22c131e50371fafc9b388326e8437169baa7..c2cfa615c3d37cb4fa14a2a36702533377f80e19 100644
--- a/Framework/PythonInterface/mantid/api/src/Exports/Projection.cpp
+++ b/Framework/PythonInterface/mantid/api/src/Exports/Projection.cpp
@@ -9,7 +9,6 @@
 #include "MantidAPI/WorkspaceFactory.h"
 #include "MantidKernel/WarningSuppressions.h"
 #include "MantidPythonInterface/core/Converters/PyObjectToV3D.h"
-#include <boost/bind.hpp>
 #include <boost/python/class.hpp>
 #include <boost/python/copy_non_const_reference.hpp>
 #include <boost/python/exec.hpp>
@@ -103,6 +102,7 @@ Projection_sptr projCtor3(const object &d1, const object &d2,
 } // anonymous namespace
 
 void export_Projection() {
+  using namespace std::placeholders;
   class_<Projection>(
       "Projection",
       init<>("Default constructor creates a two dimensional projection"))
@@ -145,7 +145,7 @@ void export_Projection() {
               &Projection::U, return_internal_reference<>(),
               boost::mpl::vector2<Mantid::Kernel::V3D &, Projection &>()),
           make_function(
-              boost::bind(&Projection::setAxis, _1, 0, _2),
+              std::bind(&Projection::setAxis, _1, 0, _2),
               default_call_policies(),
               boost::mpl::vector3<void, Projection &, Mantid::Kernel::V3D>()))
       .add_property(
@@ -154,7 +154,7 @@ void export_Projection() {
               &Projection::V, return_internal_reference<>(),
               boost::mpl::vector2<Mantid::Kernel::V3D &, Projection &>()),
           make_function(
-              boost::bind(&Projection::setAxis, _1, 1, _2),
+              std::bind(&Projection::setAxis, _1, 1, _2),
               default_call_policies(),
               boost::mpl::vector3<void, Projection &, Mantid::Kernel::V3D>()))
       .add_property(
@@ -163,7 +163,7 @@ void export_Projection() {
               &Projection::W, return_internal_reference<>(),
               boost::mpl::vector2<Mantid::Kernel::V3D &, Projection &>()),
           make_function(
-              boost::bind(&Projection::setAxis, _1, 2, _2),
+              std::bind(&Projection::setAxis, _1, 2, _2),
               default_call_policies(),
               boost::mpl::vector3<void, Projection &, Mantid::Kernel::V3D>()))
       .add_property(
@@ -172,7 +172,7 @@ void export_Projection() {
               &Projection::U, return_internal_reference<>(),
               boost::mpl::vector2<Mantid::Kernel::V3D &, Projection &>()),
           make_function(
-              boost::bind(&projSetAxis, _1, 0, _2), default_call_policies(),
+              std::bind(&projSetAxis, _1, 0, _2), default_call_policies(),
               boost::mpl::vector3<void, Projection &, const object &>()))
       .add_property(
           "v",
@@ -180,7 +180,7 @@ void export_Projection() {
               &Projection::V, return_internal_reference<>(),
               boost::mpl::vector2<Mantid::Kernel::V3D &, Projection &>()),
           make_function(
-              boost::bind(&projSetAxis, _1, 1, _2), default_call_policies(),
+              std::bind(&projSetAxis, _1, 1, _2), default_call_policies(),
               boost::mpl::vector3<void, Projection &, const object &>()))
       .add_property(
           "w",
@@ -188,7 +188,7 @@ void export_Projection() {
               &Projection::W, return_internal_reference<>(),
               boost::mpl::vector2<Mantid::Kernel::V3D &, Projection &>()),
           make_function(
-              boost::bind(&projSetAxis, _1, 2, _2), default_call_policies(),
+              std::bind(&projSetAxis, _1, 2, _2), default_call_policies(),
               boost::mpl::vector3<void, Projection &, const object &>()))
       .def("createWorkspace", createWorkspace(),
            "Create a TableWorkspace representing the projection");
diff --git a/Framework/PythonInterface/mantid/fitfunctions.py b/Framework/PythonInterface/mantid/fitfunctions.py
index fd53996acf888f8fbeb16907b8f70db2c4de404b..4ac4bdbb022290036ca5e86a39bd979185e66f97 100644
--- a/Framework/PythonInterface/mantid/fitfunctions.py
+++ b/Framework/PythonInterface/mantid/fitfunctions.py
@@ -370,7 +370,7 @@ class FunctionWrapper(object):
         # to pass InputWorkspace into EvaluateFunction before Function.
         # As a special case has been made for this. This case can be removed
         # with ordered kwargs change in Python 3.6.
-        if name is 'EvaluateFunction':
+        if name == 'EvaluateFunction':
             alg.setProperty('Function', kwargs['Function'])
             del kwargs['Function']
             alg.setProperty('InputWorkspace', kwargs['InputWorkspace'])
diff --git a/Framework/PythonInterface/mantid/kernel/funcinspect.py b/Framework/PythonInterface/mantid/kernel/funcinspect.py
index ff8eac18c91100a0a34c8fe98f670d41fd13f4c1..7232a5e9ea6de8bff7cf4b90e759ee850df24249 100644
--- a/Framework/PythonInterface/mantid/kernel/funcinspect.py
+++ b/Framework/PythonInterface/mantid/kernel/funcinspect.py
@@ -40,11 +40,16 @@ def replace_signature(func, varnames):
     else:
         code_attr = '__code__'
         f = func.__code__
-        c = f.__new__(f.__class__, f.co_argcount, f.co_kwonlyargcount,
-                      f.co_nlocals, f.co_stacksize, f.co_flags, f.co_code, 
-                      f.co_consts, f.co_names, varnames, 
-                      f.co_filename, f.co_name, f.co_firstlineno,
-                      f.co_lnotab, f.co_freevars)
+        new_args = [f.__class__, f.co_argcount, f.co_kwonlyargcount,
+                    f.co_nlocals, f.co_stacksize, f.co_flags, f.co_code, 
+                    f.co_consts, f.co_names, varnames, 
+                    f.co_filename, f.co_name, f.co_firstlineno,
+                    f.co_lnotab, f.co_freevars]
+        # Python 3.8 supports positional-only arguments and has an extra
+        # keyword in the constructor
+        if hasattr(f, 'co_posonlyargcount'):
+            new_args.insert(2, f.co_posonlyargcount)
+        c = f.__new__(*new_args)
     #endif
     setattr(func, code_attr, c)
 
diff --git a/Framework/PythonInterface/mantid/kernel/src/Exports/UnitLabel.cpp b/Framework/PythonInterface/mantid/kernel/src/Exports/UnitLabel.cpp
index 670d2418574ad1af8d9bf527a3c5303354aebd4a..9330af21762d8c25de0a51457c77062c28c09711 100644
--- a/Framework/PythonInterface/mantid/kernel/src/Exports/UnitLabel.cpp
+++ b/Framework/PythonInterface/mantid/kernel/src/Exports/UnitLabel.cpp
@@ -24,11 +24,13 @@ boost::shared_ptr<UnitLabel>
 createLabel(const object &ascii, const object &utf8, const object &latex) {
   using Utf8Char = UnitLabel::Utf8String::value_type;
   if (PyUnicode_Check(utf8.ptr())) {
-    auto length = PyUnicode_GetSize(utf8.ptr());
-    boost::scoped_array<Utf8Char> buffer(new Utf8Char[length]);
 #if PY_MAJOR_VERSION >= 3
+    auto length = PyUnicode_GetLength(utf8.ptr());
+    boost::scoped_array<Utf8Char> buffer(new Utf8Char[length]);
     PyUnicode_AsWideChar(utf8.ptr(), buffer.get(), length);
 #else
+    auto length = PyUnicode_GetSize(utf8.ptr());
+    boost::scoped_array<Utf8Char> buffer(new Utf8Char[length]);
     PyUnicode_AsWideChar(reinterpret_cast<PyUnicodeObject *>(utf8.ptr()),
                          buffer.get(), length);
 #endif
diff --git a/Framework/PythonInterface/mantid/plots/__init__.py b/Framework/PythonInterface/mantid/plots/__init__.py
index 86c9847721583276fe74cf9b441691ae020c0bbc..45c96ede2bc51e6ca0ad7c285369ec85bef3d4d0 100644
--- a/Framework/PythonInterface/mantid/plots/__init__.py
+++ b/Framework/PythonInterface/mantid/plots/__init__.py
@@ -15,7 +15,11 @@ Functionality for unpacking mantid objects for plotting with matplotlib.
 # of the main package.
 from __future__ import (absolute_import, division, print_function)
 
-from collections import Iterable
+try:
+   from collections.abc import Iterable
+except ImportError:
+   # check Python 2 location
+   from collections import Iterable   
 from matplotlib.axes import Axes
 from matplotlib.collections import Collection
 from matplotlib.colors import Colormap
@@ -268,6 +272,8 @@ class MantidAxes(Axes):
             # If wanting to plot a spectrum
             elif MantidAxes.is_axis_of_type(MantidAxType.SPECTRUM, kwargs):
                 return MantidAxes.get_spec_num_from_wksp_index(workspace, kwargs['wkspIndex'])
+        elif kwargs.get('LogName', None) is not None:
+            return None
         elif getattr(workspace, 'getNumberHistograms', lambda: -1)() == 1:
             # If the workspace has one histogram, just plot that
             kwargs['wkspIndex'] = 0
@@ -636,7 +642,8 @@ class MantidAxes(Axes):
 
             with autoscale_on_update(self, autoscale_on):
                 artist = self.track_workspace_artist(workspace,
-                                                     plotfunctions.plot(self, *args, **kwargs),
+                                                     plotfunctions.plot(self, normalize_by_bin_width = is_normalized,
+                                                                        *args, **kwargs),
                                                      _data_update, spec_num, is_normalized,
                                                      MantidAxes.is_axis_of_type(MantidAxType.SPECTRUM, kwargs))
             return artist
diff --git a/Framework/PythonInterface/mantid/plots/helperfunctions.py b/Framework/PythonInterface/mantid/plots/helperfunctions.py
index 2cfcdb642634c0f68ea60f8059a24b86e3802aea..0c1f606b8de6a2065babcbc434a821ecfa69c944 100644
--- a/Framework/PythonInterface/mantid/plots/helperfunctions.py
+++ b/Framework/PythonInterface/mantid/plots/helperfunctions.py
@@ -62,11 +62,13 @@ def get_normalize_by_bin_width(workspace, axes, **kwargs):
     :param workspace: :class:`mantid.api.MatrixWorkspace` workspace being plotted
     :param axes: The axes being plotted on
     """
+    normalize_by_bin_width = kwargs.get('normalize_by_bin_width', None)
+    if normalize_by_bin_width is not None:
+        return normalize_by_bin_width, kwargs
     distribution = kwargs.get('distribution', None)
-    aligned, _ = check_resample_to_regular_grid(workspace, **kwargs)
     if distribution or (hasattr(workspace, 'isDistribution') and workspace.isDistribution()):
         return False, kwargs
-    elif distribution is False or aligned:
+    elif distribution is False:
         return True, kwargs
     else:
         try:
@@ -77,11 +79,13 @@ def get_normalize_by_bin_width(workspace, axes, **kwargs):
         if current_artists:
             current_normalization = any(
                 [artist[0].is_normalized for artist in current_artists])
-            normalize_by_bin_width = current_normalization
+            normalization = current_normalization
         else:
-            normalize_by_bin_width = mantid.kernel.config[
-                                         'graph1d.autodistribution'].lower() == 'on'
-    return normalize_by_bin_width, kwargs
+            if mantid.kernel.config['graph1d.autodistribution'].lower() == 'on':
+                normalization = True
+            else:
+                normalization, _ = check_resample_to_regular_grid(workspace, **kwargs)
+    return normalization, kwargs
 
 
 def get_normalization(md_workspace, **kwargs):
@@ -574,12 +578,12 @@ def get_data_uneven_flag(workspace, **kwargs):
 def check_resample_to_regular_grid(ws, **kwargs):
     if isinstance(ws, MatrixWorkspace):
         aligned = kwargs.pop('axisaligned', False)
-        if not ws.isCommonBins() or aligned:
+        if aligned or not ws.isCommonBins():
             return True, kwargs
 
-        x = ws.dataX(0)
+        x = ws.readX(0)
         difference = np.diff(x)
-        if x.size > 1 and not np.all(np.isclose(difference[:-1], difference[0])):
+        if x.size > 1 and not np.allclose(difference[:-1], difference[0]):
             return True, kwargs
     return False, kwargs
 
diff --git a/Framework/PythonInterface/mantid/plots/plotfunctions.py b/Framework/PythonInterface/mantid/plots/plotfunctions.py
index 248677c96959cf99eb2d14a67d0fdbb09d0bd6ef..a926ebac60386083831049b3b4add6189a5ddcd0 100644
--- a/Framework/PythonInterface/mantid/plots/plotfunctions.py
+++ b/Framework/PythonInterface/mantid/plots/plotfunctions.py
@@ -116,6 +116,7 @@ def _plot_impl(axes, workspace, args, kwargs):
         if kwargs.pop('update_axes_labels', True):
             _setLabels1D(axes, workspace, indices,
                          normalize_by_bin_width=normalize_by_bin_width, axis=axis)
+    kwargs.pop('normalize_by_bin_width', None)
     return x, y, args, kwargs
 
 
@@ -137,6 +138,9 @@ def plot(axes, workspace, *args, **kwargs):
     :param normalization: ``None`` (default) ask the workspace. Applies to MDHisto workspaces. It can override
                           the value from displayNormalizationHisto. It checks only if
                           the normalization is mantid.api.MDNormalization.NumEventsNormalization
+    :param normalize_by_bin_width: ``None`` (default) ask the workspace. It can override
+                          the value from distribution. Is implemented so get_normalize_by_bin_width
+                          only need to be run once.
     :param LogName:   if specified, it will plot the corresponding sample log. The x-axis
                       of the plot is the time difference between the log time and the first
                       value of the `proton_charge` log (if available) or the sample log's
diff --git a/Framework/PythonInterface/plugins/algorithms/ConvertWANDSCDtoQ.py b/Framework/PythonInterface/plugins/algorithms/ConvertWANDSCDtoQ.py
index ed5e07670ead025a9bf8ef5cc5e5aa09f4a5ff47..9e5bfc368774507baa6ed6d0330c1ebc82f27c57 100644
--- a/Framework/PythonInterface/plugins/algorithms/ConvertWANDSCDtoQ.py
+++ b/Framework/PythonInterface/plugins/algorithms/ConvertWANDSCDtoQ.py
@@ -86,7 +86,7 @@ class ConvertWANDSCDtoQ(PythonAlgorithm):
         d2 = inWS.getDimension(2)
         number_of_runs = d2.getNBins()
 
-        if (d0.name is not 'y' or d1.name is not 'x' or d2.name != 'scanIndex'):
+        if (d0.name != 'y' or d1.name != 'x' or d2.name != 'scanIndex'):
             issues["InputWorkspace"] = "InputWorkspace has wrong dimensions"
             return issues
 
diff --git a/Framework/PythonInterface/plugins/algorithms/HB2AReduce.py b/Framework/PythonInterface/plugins/algorithms/HB2AReduce.py
index d28ef500fdcab9d5f660162b90255a0e5e1fb20e..817d81c18601df8f9a3da9b9ed49626478374a43 100644
--- a/Framework/PythonInterface/plugins/algorithms/HB2AReduce.py
+++ b/Framework/PythonInterface/plugins/algorithms/HB2AReduce.py
@@ -78,7 +78,7 @@ class HB2AReduce(PythonAlgorithm):
         if not self.getProperty("Filename").value:
             ipts = self.getProperty("IPTS").value
 
-            if ((ipts == Property.EMPTY_INT) or len(self.getProperty("ScanNumbers").value) is 0):
+            if ((ipts == Property.EMPTY_INT) or len(self.getProperty("ScanNumbers").value) == 0):
                 issues["Filename"] = 'Must specify either Filename or IPTS AND ScanNumbers'
 
             if self.getProperty("Exp").value == Property.EMPTY_INT:
diff --git a/Framework/PythonInterface/plugins/algorithms/LoadWANDSCD.py b/Framework/PythonInterface/plugins/algorithms/LoadWANDSCD.py
index 48877bc1139115027314a1b8ef3356129fdae1a2..d5280d8f583b088078c70a194318e1c2d1211e47 100644
--- a/Framework/PythonInterface/plugins/algorithms/LoadWANDSCD.py
+++ b/Framework/PythonInterface/plugins/algorithms/LoadWANDSCD.py
@@ -43,7 +43,7 @@ class LoadWANDSCD(PythonAlgorithm):
         issues = dict()
 
         if not self.getProperty("Filename").value:
-            if (self.getProperty("IPTS").value == Property.EMPTY_INT) or len(self.getProperty("RunNumbers").value) is 0:
+            if (self.getProperty("IPTS").value == Property.EMPTY_INT) or len(self.getProperty("RunNumbers").value) == 0:
                 issues["Filename"] = 'Must specify either Filename or IPTS AND RunNumbers'
 
         return issues
diff --git a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ISISIndirectDiffractionReduction.py b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ISISIndirectDiffractionReduction.py
index 9a7fc6d8ea34697f660c80c30edac4ac67805ce5..f26e4a6dc15517e11f4f3160596d43135acc62df 100644
--- a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ISISIndirectDiffractionReduction.py
+++ b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ISISIndirectDiffractionReduction.py
@@ -390,7 +390,7 @@ class ISISIndirectDiffractionReduction(DataProcessorAlgorithm):
         Checks to ensure a calibration file has been given
         and if so performs AlignDetectors and DiffractionFocussing.
         """
-        if self._cal_file is not '':
+        if self._cal_file != '':
             for ws_name in self._workspace_names:
                 AlignDetectors(InputWorkspace=ws_name,
                                OutputWorkspace=ws_name,
diff --git a/Framework/SINQ/src/PoldiIndexKnownCompounds.cpp b/Framework/SINQ/src/PoldiIndexKnownCompounds.cpp
index 242f40a4db58c83e47d841b95c2145d2e82bb5f3..894bad112135441a068a5bafcd8031dbb299e446 100644
--- a/Framework/SINQ/src/PoldiIndexKnownCompounds.cpp
+++ b/Framework/SINQ/src/PoldiIndexKnownCompounds.cpp
@@ -14,7 +14,6 @@
 #include "MantidKernel/MandatoryValidator.h"
 #include "MantidSINQ/PoldiUtilities/MillerIndicesIO.h"
 
-#include <boost/bind.hpp>
 #include <numeric>
 
 #include <boost/math/distributions/normal.hpp>
@@ -726,10 +725,9 @@ PoldiPeakCollection_sptr
 PoldiIndexKnownCompounds::getIntensitySortedPeakCollection(
     const PoldiPeakCollection_sptr &peaks) const {
   std::vector<PoldiPeak_sptr> peakVector(peaks->peaks());
-
+  using namespace std::placeholders;
   std::sort(peakVector.begin(), peakVector.end(),
-            boost::bind<bool>(&PoldiPeak::greaterThan, _1, _2,
-                              &PoldiPeak::intensity));
+            std::bind(&PoldiPeak::greaterThan, _1, _2, &PoldiPeak::intensity));
 
   PoldiPeakCollection_sptr sortedPeaks =
       boost::make_shared<PoldiPeakCollection>(peaks->intensityType());
diff --git a/Framework/SINQ/src/PoldiPeakSearch.cpp b/Framework/SINQ/src/PoldiPeakSearch.cpp
index f0a2e6f16dedf29387c966d1455cacce9334112e..abf27d49b0da431b57472010007fc94310eea3d7 100644
--- a/Framework/SINQ/src/PoldiPeakSearch.cpp
+++ b/Framework/SINQ/src/PoldiPeakSearch.cpp
@@ -18,7 +18,6 @@
 #include "MantidDataObjects/TableWorkspace.h"
 #include "MantidDataObjects/Workspace2D.h"
 
-#include "boost/bind.hpp"
 #include <algorithm>
 #include <list>
 #include <numeric>
@@ -634,10 +633,11 @@ void PoldiPeakSearch::exec() {
   }
 
   std::vector<PoldiPeak_sptr> intensityFilteredPeaks(peakCoordinates.size());
+  using namespace std::placeholders;
   auto newEnd = std::remove_copy_if(
       peakCoordinates.begin(), peakCoordinates.end(),
       intensityFilteredPeaks.begin(),
-      boost::bind(&PoldiPeakSearch::isLessThanMinimum, this, _1));
+      std::bind(&PoldiPeakSearch::isLessThanMinimum, this, _1));
   intensityFilteredPeaks.resize(
       std::distance(intensityFilteredPeaks.begin(), newEnd));
 
@@ -646,8 +646,7 @@ void PoldiPeakSearch::exec() {
                       << "): " << intensityFilteredPeaks.size() << '\n';
 
   std::sort(intensityFilteredPeaks.begin(), intensityFilteredPeaks.end(),
-            boost::bind<bool>(&PoldiPeak::greaterThan, _1, _2,
-                              &PoldiPeak::intensity));
+            std::bind(&PoldiPeak::greaterThan, _1, _2, &PoldiPeak::intensity));
 
   for (std::vector<PoldiPeak_sptr>::const_iterator peak =
            intensityFilteredPeaks.begin();
diff --git a/Framework/SINQ/src/PoldiUtilities/PoldiAutoCorrelationCore.cpp b/Framework/SINQ/src/PoldiUtilities/PoldiAutoCorrelationCore.cpp
index 9bfd8237ff9b6e2295d796e630611ddbc64a552c..8f29752f44fcb2bbebb7ae0b5db9f7df622dd9aa 100644
--- a/Framework/SINQ/src/PoldiUtilities/PoldiAutoCorrelationCore.cpp
+++ b/Framework/SINQ/src/PoldiUtilities/PoldiAutoCorrelationCore.cpp
@@ -10,7 +10,6 @@
 #include "MantidAPI/WorkspaceFactory.h"
 #include "MantidKernel/Logger.h"
 #include "MantidKernel/MultiThreaded.h"
-#include "boost/bind.hpp"
 #include <algorithm>
 #include <numeric>
 #include <utility>
@@ -25,6 +24,7 @@ namespace Mantid {
 namespace Poldi {
 
 using namespace API;
+using namespace std::placeholders;
 
 PoldiAutoCorrelationCore::PoldiAutoCorrelationCore(Kernel::Logger &g_log)
     : m_detector(), m_chopper(), m_wavelengthRange(), m_deltaT(), m_deltaD(),
@@ -210,11 +210,10 @@ DataObjects::Workspace2D_sptr PoldiAutoCorrelationCore::calculate(
 
     m_logger.information() << "  Correcting intensities...\n";
     std::vector<double> correctedCorrelatedIntensities(dValues.size());
-    std::transform(rawCorrelatedIntensities.begin(),
-                   rawCorrelatedIntensities.end(), m_weightsForD.begin(),
-                   correctedCorrelatedIntensities.rbegin(),
-                   boost::bind(&PoldiAutoCorrelationCore::correctedIntensity,
-                               this, _1, _2));
+    std::transform(
+        rawCorrelatedIntensities.begin(), rawCorrelatedIntensities.end(),
+        m_weightsForD.begin(), correctedCorrelatedIntensities.rbegin(),
+        std::bind(&PoldiAutoCorrelationCore::correctedIntensity, this, _1, _2));
 
     /* The algorithm performs some finalization. In the default case the
      * spectrum is
@@ -315,8 +314,8 @@ PoldiAutoCorrelationCore::getRawCorrelatedIntensity(double dValue,
        */
       std::vector<UncertainValue> cmess(m_detector->elementCount());
       std::transform(m_indices.begin(), m_indices.end(), cmess.begin(),
-                     boost::bind(&PoldiAutoCorrelationCore::getCMessAndCSigma,
-                                 this, dValue, slitOffset, _1));
+                     std::bind(&PoldiAutoCorrelationCore::getCMessAndCSigma,
+                               this, dValue, slitOffset, _1));
 
       UncertainValue sum =
           std::accumulate(cmess.begin(), cmess.end(), UncertainValue(0.0, 0.0),
@@ -594,7 +593,7 @@ std::vector<double> PoldiAutoCorrelationCore::getTofsFor1Angstrom(
   // Map element indices to 2Theta-Values
   std::vector<double> twoThetas(elements.size());
   std::transform(elements.begin(), elements.end(), twoThetas.begin(),
-                 boost::bind(&PoldiAbstractDetector::twoTheta, m_detector, _1));
+                 std::bind(&PoldiAbstractDetector::twoTheta, m_detector, _1));
 
   // We will need sin(Theta) anyway, so we might just calculate those as well
   std::vector<double> sinThetas;
@@ -612,7 +611,7 @@ std::vector<double> PoldiAutoCorrelationCore::getTofsFor1Angstrom(
   std::vector<double> tofFor1Angstrom(elements.size());
   std::transform(distances.begin(), distances.end(), sinThetas.begin(),
                  tofFor1Angstrom.begin(),
-                 boost::bind(&Conversions::dtoTOF, 1.0, _1, _2));
+                 std::bind(&Conversions::dtoTOF, 1.0, _1, _2));
 
   return tofFor1Angstrom;
 }
diff --git a/Framework/SINQ/src/PoldiUtilities/PoldiBasicChopper.cpp b/Framework/SINQ/src/PoldiUtilities/PoldiBasicChopper.cpp
index 82238841208a0396235fa587f8850a2bbacf28bd..0268730416c44e1ba7ec3037c0f3b62f6012b2be 100644
--- a/Framework/SINQ/src/PoldiUtilities/PoldiBasicChopper.cpp
+++ b/Framework/SINQ/src/PoldiUtilities/PoldiBasicChopper.cpp
@@ -7,7 +7,6 @@
 #include "MantidSINQ/PoldiUtilities/PoldiBasicChopper.h"
 
 #include "MantidGeometry/ICompAssembly.h"
-#include "boost/bind.hpp"
 
 namespace Mantid {
 namespace Poldi {
@@ -80,9 +79,10 @@ void PoldiBasicChopper::initializeVariableParameters(double rotationSpeed) {
   m_zeroOffset = m_rawt0 * m_cycleTime + m_rawt0const;
 
   m_slitTimes.resize(m_slitPositions.size());
+  using namespace std::placeholders;
   std::transform(
       m_slitPositions.begin(), m_slitPositions.end(), m_slitTimes.begin(),
-      boost::bind(&PoldiBasicChopper::slitPositionToTimeFraction, this, _1));
+      std::bind(&PoldiBasicChopper::slitPositionToTimeFraction, this, _1));
 }
 
 double PoldiBasicChopper::slitPositionToTimeFraction(double slitPosition) {
diff --git a/Framework/SINQ/src/PoldiUtilities/PoldiDeadWireDecorator.cpp b/Framework/SINQ/src/PoldiUtilities/PoldiDeadWireDecorator.cpp
index 4995383a2fa21a95b9c0774b25466e59adebe3ab..abdcc3da2fb7859a7928974644644391b849f303 100644
--- a/Framework/SINQ/src/PoldiUtilities/PoldiDeadWireDecorator.cpp
+++ b/Framework/SINQ/src/PoldiUtilities/PoldiDeadWireDecorator.cpp
@@ -7,7 +7,6 @@
 #include "MantidSINQ/PoldiUtilities/PoldiDeadWireDecorator.h"
 #include "MantidGeometry/Instrument/DetectorInfo.h"
 
-#include "boost/bind.hpp"
 #include <algorithm>
 
 namespace Mantid {
@@ -74,9 +73,10 @@ PoldiDeadWireDecorator::getGoodElements(std::vector<int> rawElements) {
     size_t newElementCount = rawElements.size() - m_deadWireSet.size();
 
     std::vector<int> goodElements(newElementCount);
+    using namespace std::placeholders;
     std::remove_copy_if(
         rawElements.begin(), rawElements.end(), goodElements.begin(),
-        boost::bind(&PoldiDeadWireDecorator::isDeadElement, this, _1));
+        std::bind(&PoldiDeadWireDecorator::isDeadElement, this, _1));
 
     return goodElements;
   }
diff --git a/Framework/SINQ/src/PoldiUtilities/PoldiPeak.cpp b/Framework/SINQ/src/PoldiUtilities/PoldiPeak.cpp
index 72f914739e5f3d86bacbf4a978e80b19ba5045ee..c65cab3396d38b68b0d3adf514d81dd4a163e194 100644
--- a/Framework/SINQ/src/PoldiUtilities/PoldiPeak.cpp
+++ b/Framework/SINQ/src/PoldiUtilities/PoldiPeak.cpp
@@ -6,7 +6,6 @@
 // SPDX - License - Identifier: GPL - 3.0 +
 #include "MantidSINQ/PoldiUtilities/PoldiPeak.h"
 
-#include "boost/bind.hpp"
 #include <cmath>
 #include <stdexcept>
 
@@ -132,15 +131,15 @@ PoldiPeak_sptr PoldiPeak::create(MillerIndices hkl, UncertainValue dValue,
 bool PoldiPeak::greaterThan(const PoldiPeak_sptr &first,
                             const PoldiPeak_sptr &second,
                             UncertainValue (PoldiPeak::*function)() const) {
-  return static_cast<double>(boost::bind(function, first.get())()) >
-         static_cast<double>(boost::bind(function, second.get())());
+  return static_cast<double>(std::bind(function, first.get())()) >
+         static_cast<double>(std::bind(function, second.get())());
 }
 
 bool PoldiPeak::lessThan(const PoldiPeak_sptr &first,
                          const PoldiPeak_sptr &second,
                          UncertainValue (PoldiPeak::*function)() const) {
-  return static_cast<double>(boost::bind(function, first.get())()) <
-         static_cast<double>(boost::bind(function, second.get())());
+  return static_cast<double>(std::bind(function, first.get())()) <
+         static_cast<double>(std::bind(function, second.get())());
 }
 
 PoldiPeak::PoldiPeak(UncertainValue d, UncertainValue intensity,
diff --git a/Framework/SINQ/test/PoldiPeakCollectionTest.h b/Framework/SINQ/test/PoldiPeakCollectionTest.h
index 2ed9ec100621aa3477275fdaa1341248f2288c3f..3047ea888b90ef65d91ed7280d36e41f0cf621a7 100644
--- a/Framework/SINQ/test/PoldiPeakCollectionTest.h
+++ b/Framework/SINQ/test/PoldiPeakCollectionTest.h
@@ -21,7 +21,6 @@
 #include "MantidGeometry/Crystal/ReflectionGenerator.h"
 #include "MantidGeometry/Crystal/SpaceGroupFactory.h"
 
-#include <boost/bind.hpp>
 #include <stdexcept>
 
 using namespace Mantid::Poldi;
@@ -29,6 +28,7 @@ using namespace Mantid::API;
 using namespace Mantid::DataObjects;
 using namespace Mantid::Kernel;
 using namespace Mantid::Geometry;
+using namespace std::placeholders;
 
 class PoldiPeakCollectionTest;
 
@@ -359,9 +359,8 @@ public:
     std::vector<PoldiPeak_sptr> poldiPeaks = p.peaks();
 
     // sort peak list and check that all peaks are within the limits
-    std::sort(
-        poldiPeaks.begin(), poldiPeaks.end(),
-        boost::bind<bool>(&PoldiPeak::greaterThan, _1, _2, &PoldiPeak::d));
+    std::sort(poldiPeaks.begin(), poldiPeaks.end(),
+              std::bind(&PoldiPeak::greaterThan, _1, _2, &PoldiPeak::d));
 
     TS_ASSERT_LESS_THAN_EQUALS(poldiPeaks[0]->d(), 5.0);
     TS_ASSERT_LESS_THAN_EQUALS(0.55, poldiPeaks[68]->d());
diff --git a/Framework/SINQ/test/PoldiPeakTest.h b/Framework/SINQ/test/PoldiPeakTest.h
index bf58d9a5e7fe3fcd73d4a88140018ee9e5b91cd0..14dc89ba4733d69c1def2c6fca372ddccda2623f 100644
--- a/Framework/SINQ/test/PoldiPeakTest.h
+++ b/Framework/SINQ/test/PoldiPeakTest.h
@@ -9,11 +9,11 @@
 
 #include "MantidSINQ/PoldiUtilities/MillerIndices.h"
 #include "MantidSINQ/PoldiUtilities/PoldiPeak.h"
-#include "boost/bind.hpp"
 #include <cxxtest/TestSuite.h>
 #include <stdexcept>
 
 using namespace Mantid::Poldi;
+using namespace std::placeholders;
 
 class PoldiPeakTest : public CxxTest::TestSuite {
 public:
@@ -143,16 +143,15 @@ public:
     peaks.emplace_back(PoldiPeak::create(2.0, 20.0));
     peaks.emplace_back(PoldiPeak::create(3.0, 800.0));
 
-    std::sort(
-        peaks.begin(), peaks.end(),
-        boost::bind<bool>(&PoldiPeak::greaterThan, _1, _2, &PoldiPeak::q));
+    std::sort(peaks.begin(), peaks.end(),
+              std::bind(&PoldiPeak::greaterThan, _1, _2, &PoldiPeak::q));
     TS_ASSERT_EQUALS(peaks[0]->q(), 3.0);
     TS_ASSERT_EQUALS(peaks[1]->q(), 2.0);
     TS_ASSERT_EQUALS(peaks[2]->q(), 1.0);
 
-    std::sort(peaks.begin(), peaks.end(),
-              boost::bind<bool>(&PoldiPeak::greaterThan, _1, _2,
-                                &PoldiPeak::intensity));
+    std::sort(
+        peaks.begin(), peaks.end(),
+        std::bind(&PoldiPeak::greaterThan, _1, _2, &PoldiPeak::intensity));
     TS_ASSERT_EQUALS(peaks[0]->q(), 3.0);
     TS_ASSERT_EQUALS(peaks[1]->q(), 1.0);
     TS_ASSERT_EQUALS(peaks[2]->q(), 2.0);
@@ -165,14 +164,13 @@ public:
     peaks.emplace_back(PoldiPeak::create(3.0, 800.0));
 
     std::sort(peaks.begin(), peaks.end(),
-              boost::bind<bool>(&PoldiPeak::lessThan, _1, _2, &PoldiPeak::q));
+              std::bind(&PoldiPeak::lessThan, _1, _2, &PoldiPeak::q));
     TS_ASSERT_EQUALS(peaks[0]->q(), 1.0);
     TS_ASSERT_EQUALS(peaks[1]->q(), 2.0);
     TS_ASSERT_EQUALS(peaks[2]->q(), 3.0);
 
-    std::sort(
-        peaks.begin(), peaks.end(),
-        boost::bind<bool>(&PoldiPeak::lessThan, _1, _2, &PoldiPeak::intensity));
+    std::sort(peaks.begin(), peaks.end(),
+              std::bind(&PoldiPeak::lessThan, _1, _2, &PoldiPeak::intensity));
     TS_ASSERT_EQUALS(peaks[0]->q(), 2.0);
     TS_ASSERT_EQUALS(peaks[1]->q(), 1.0);
     TS_ASSERT_EQUALS(peaks[2]->q(), 3.0);
diff --git a/Framework/WorkflowAlgorithms/src/SofTwoThetaTOF.cpp b/Framework/WorkflowAlgorithms/src/SofTwoThetaTOF.cpp
index 4c2a50fc97a7a7c16dfcfce0a3086da90e6e5219..2bccf31cd4a0eff2404d80760aaf2bf8b573b359 100644
--- a/Framework/WorkflowAlgorithms/src/SofTwoThetaTOF.cpp
+++ b/Framework/WorkflowAlgorithms/src/SofTwoThetaTOF.cpp
@@ -198,13 +198,7 @@ SofTwoThetaTOF::groupByTwoTheta(API::MatrixWorkspace_sptr &ws,
     auto tempPath = boost::filesystem::temp_directory_path();
     tempPath /= boost::filesystem::unique_path(
         "detector-grouping-%%%%-%%%%-%%%%-%%%%.xml");
-#ifdef _WIN32
-    // A dirty way to convert a wstring to string.
-    auto const wfilename = tempPath.native();
-    filename = std::string(wfilename.cbegin(), wfilename.cend());
-#else
-    filename = tempPath.native();
-#endif
+    filename = tempPath.string();
     generateGrouping->setProperty("GenerateParFile", false);
     // Make sure the file gets deleted at scope exit.
     // enable cppcheck-suppress unreadVariable if needed
diff --git a/Framework/WorkflowAlgorithms/test/SofTwoThetaTOFTest.h b/Framework/WorkflowAlgorithms/test/SofTwoThetaTOFTest.h
index 2264c1d80563172a5c6d15ff8eb09ecd002f20b7..2b0504e2f579857c03711a8ea47986bcd797db13 100644
--- a/Framework/WorkflowAlgorithms/test/SofTwoThetaTOFTest.h
+++ b/Framework/WorkflowAlgorithms/test/SofTwoThetaTOFTest.h
@@ -98,12 +98,7 @@ public:
     TS_ASSERT_THROWS_NOTHING(alg.setProperty("AngleStep", angleStep))
     auto tempXml = boost::filesystem::temp_directory_path();
     tempXml /= boost::filesystem::unique_path("SofTwoThetaTest-%%%%%%%%.xml");
-#if _WIN32
-    auto const wfilename = tempXml.native();
-    std::string const filename{wfilename.cbegin(), wfilename.cend()};
-#else
-    std::string const filename{tempXml.native()};
-#endif
+    std::string const filename{tempXml.string()};
     TS_ASSERT_THROWS_NOTHING(alg.setProperty("GroupingFilename", filename))
     TS_ASSERT_THROWS_NOTHING(alg.execute())
     TS_ASSERT(alg.isExecuted())
diff --git a/MantidPlot/ipython_widget/mantid_ipython_widget.py b/MantidPlot/ipython_widget/mantid_ipython_widget.py
index 69c4164872225dc0c68980d134ae7c8afa57f93f..1db19db04451d36f6222875d0e3f21346218eff4 100644
--- a/MantidPlot/ipython_widget/mantid_ipython_widget.py
+++ b/MantidPlot/ipython_widget/mantid_ipython_widget.py
@@ -7,6 +7,7 @@
 from __future__ import (absolute_import, division,
                         print_function)
 
+import sys
 import threading
 import types
 import warnings
@@ -36,6 +37,13 @@ except ImportError:
     from IPython.qt.inprocess import QtInProcessKernelManager
 
 
+if sys.version_info.major >= 3 and sys.platform == 'win32':
+    # Tornado requires WindowsSelectorEventLoop
+    # https://www.tornadoweb.org/en/stable/#installation
+    import asyncio
+    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
+
+
 def our_run_code(self, code_obj, result=None, async_=False):
     """ Method with which we replace the run_code method of IPython's InteractiveShell class.
         It calls the original method (renamed to ipython_run_code) on a separate thread
diff --git a/MantidPlot/src/PythonScripting.cpp b/MantidPlot/src/PythonScripting.cpp
index 6daa948f8febaba6135b305e93840b2d5e308d79..b1f4d80d1759d23f657ec161eb968df199be2e14 100644
--- a/MantidPlot/src/PythonScripting.cpp
+++ b/MantidPlot/src/PythonScripting.cpp
@@ -272,14 +272,22 @@ void PythonScripting::setupSip() {
   // Our use of the IPython console requires that we use the v2 api for these
   // PyQt types. This has to be set before the very first import of PyQt
   // which happens on importing _qti
-  PyObject *sipmod = PyImport_ImportModule("sip");
+  // Some environments now have a private sip module inside PyQt itself. Try
+  // this first.
+  PyObject *sipmod = PyImport_ImportModule("PyQt4.sip");
+  if (!sipmod) {
+    PyErr_Clear();
+    sipmod = PyImport_ImportModule("sip");
+  }
   if (sipmod) {
     constexpr std::array<const char *, 7> v2Types = {
         {"QString", "QVariant", "QDate", "QDateTime", "QTextStream", "QTime",
          "QUrl"}};
     for (const auto &className : v2Types) {
-      PyObject_CallMethod(sipmod, STR_LITERAL("setapi"), STR_LITERAL("(si)"),
-                          className, 2);
+      auto result = PyObject_CallMethod(sipmod, STR_LITERAL("setapi"),
+                                        STR_LITERAL("(si)"), className, 2);
+      if (!result)
+        PyErr_Print();
     }
     Py_DECREF(sipmod);
   }
diff --git a/Testing/SystemTests/lib/systemtests/systemtesting.py b/Testing/SystemTests/lib/systemtests/systemtesting.py
index bdc5a0c7cd8bd73da0c72797f3cc818401381660..8f5a5fe5e2e115798df92de6524c69aa430a292a 100644
--- a/Testing/SystemTests/lib/systemtests/systemtesting.py
+++ b/Testing/SystemTests/lib/systemtests/systemtesting.py
@@ -1036,7 +1036,7 @@ class TestManager(object):
                 mod_attrs = dir(mod)
                 for key in mod_attrs:
                     value = getattr(mod, key)
-                    if key is "MantidSystemTest" or not inspect.isclass(value):
+                    if key == "MantidSystemTest" or not inspect.isclass(value):
                         continue
                     if self.isValidTestClass(value):
                         test_name = key
diff --git a/Testing/SystemTests/tests/analysis/ValidateFacilitiesFile.py b/Testing/SystemTests/tests/analysis/ValidateFacilitiesFile.py
deleted file mode 100644
index df511c193dada8a86ecc32843cacf87d58de6778..0000000000000000000000000000000000000000
--- a/Testing/SystemTests/tests/analysis/ValidateFacilitiesFile.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Mantid Repository : https://github.com/mantidproject/mantid
-#
-# Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
-#     NScD Oak Ridge National Laboratory, European Spallation Source
-#     & Institut Laue - Langevin
-# SPDX - License - Identifier: GPL - 3.0 +
-#pylint: disable=no-init,invalid-name
-from __future__ import (absolute_import, division, print_function)
-from mantid import config
-import os
-import systemtesting
-
-
-EXPECTED_EXT = '.expected'
-
-
-class ValidateFacilitiesFile(systemtesting.MantidSystemTest):
-
-    def skipTests(self):
-        try:
-            import minixsv # noqa
-        except ImportError:
-            return True
-        return False
-
-    def runTest(self):
-        """Main entry point for the test suite"""
-        from minixsv import pyxsval
-        direc = config['instrumentDefinition.directory']
-        filename = os.path.join(direc,'Facilities.xml')
-        xsdFile =  os.path.join(direc,'Schema/Facilities/1.0/','FacilitiesSchema.xsd')
-
-        # run the tests
-        failed = []
-        try:
-            print("----------------------------------------")
-            print("Validating Facilities.xml")
-            pyxsval.parseAndValidateXmlInput(filename, xsdFile=xsdFile, validateSchema=0)
-        except Exception as e:
-            print("VALIDATION OF Facilities.xml FAILED WITH ERROR:")
-            print(e)
-            failed.append(filename)
-
-        # final say on whether or not it 'worked'
-        print("----------------------------------------")
-        if len(failed) != 0:
-            print("SUMMARY OF FAILED FILES")
-            raise RuntimeError("Failed Validation of Facilities.xml")
-        else:
-            print("Successfully Validated Facilities.xml")
diff --git a/Testing/SystemTests/tests/analysis/ValidateGroupingFiles.py b/Testing/SystemTests/tests/analysis/ValidateGroupingFiles.py
deleted file mode 100644
index c1e72fc4e27c3891c04fc6d52f3182ad51e889f8..0000000000000000000000000000000000000000
--- a/Testing/SystemTests/tests/analysis/ValidateGroupingFiles.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Mantid Repository : https://github.com/mantidproject/mantid
-#
-# Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
-#     NScD Oak Ridge National Laboratory, European Spallation Source
-#     & Institut Laue - Langevin
-# SPDX - License - Identifier: GPL - 3.0 +
-#pylint: disable=no-init
-from __future__ import (absolute_import, division, print_function)
-from mantid import config
-import os
-import systemtesting
-import glob
-
-EXPECTED_EXT = '.expected'
-
-
-class ValidateGroupingFiles(systemtesting.MantidSystemTest):
-
-    xsdFile =''
-
-    def skipTests(self):
-        try:
-            import minixsv # noqa
-        except ImportError:
-            return True
-        return False
-
-    def __getDataFileList__(self):
-        # get a list of directories to look in
-        direc = config['instrumentDefinition.directory']
-        direc =  os.path.join(direc,'Grouping')
-        print("Looking for Grouping files in: %s" % direc)
-        cwd = os.getcwd()
-        os.chdir(direc)
-        myFiles = glob.glob("*Grouping*.xml")
-        os.chdir(cwd)
-        files = []
-        for filename in myFiles:
-            files.append(os.path.join(direc, filename))
-        return files
-
-    def runTest(self):
-        """Main entry point for the test suite"""
-        from minixsv import pyxsval
-        direc = config['instrumentDefinition.directory']
-        self.xsdFile =  os.path.join(direc,'Schema/Grouping/1.0/','GroupingSchema.xsd')
-        files = self.__getDataFileList__()
-
-        # run the tests
-        failed = []
-        for filename in files:
-            try:
-                print("----------------------------------------")
-                print("Validating '%s'" % filename)
-                pyxsval.parseAndValidateXmlInput(filename, xsdFile=self.xsdFile, validateSchema=0)
-            except Exception as err:
-                print("VALIDATION OF '%s' FAILED WITH ERROR:" % filename)
-                print(err)
-                failed.append(filename)
-
-        # final say on whether or not it 'worked'
-        print("----------------------------------------")
-        if len(failed) != 0:
-            print("SUMMARY OF FAILED FILES")
-            for filename in failed:
-                print(filename)
-            raise RuntimeError("Failed Validation for %d of %d files"
-                               % (len(failed), len(files)))
-        else:
-            print("Successfully Validated %d files" % len(files))
diff --git a/Testing/SystemTests/tests/analysis/ValidateInstrumentDefinitionFiles.py b/Testing/SystemTests/tests/analysis/ValidateInstrumentDefinitionFiles.py
deleted file mode 100644
index 0f68e5f18086381b618323d457327c6a7b911992..0000000000000000000000000000000000000000
--- a/Testing/SystemTests/tests/analysis/ValidateInstrumentDefinitionFiles.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# Mantid Repository : https://github.com/mantidproject/mantid
-#
-# Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
-#     NScD Oak Ridge National Laboratory, European Spallation Source
-#     & Institut Laue - Langevin
-# SPDX - License - Identifier: GPL - 3.0 +
-#pylint: disable=invalid-name
-#pylint: disable=no-init
-from __future__ import (absolute_import, division, print_function)
-from mantid import config
-import os
-import systemtesting
-import glob
-
-
-EXPECTED_EXT = '.expected'
-
-
-class ValidateInstrumentDefinitionFiles(systemtesting.MantidSystemTest):
-
-    xsdFile=''
-    # Explicitly specify single file to test. If None, test all.
-    theFileToTest=None #"MARI_Definition.xml"
-
-    def skipTests(self):
-        try:
-            from genxmlif import GenXmlIfError # noqa
-            from minixsv import pyxsval # noqa
-        except ImportError:
-            return True
-        return False
-
-    def __getDataFileList__(self):
-        # get a list of directories to look in
-        direc = config['instrumentDefinition.directory']
-        print("Looking for instrument definition files in: %s" % direc)
-        cwd = os.getcwd()
-        os.chdir(direc)
-        myFiles = glob.glob("*Definition*.xml")
-        os.chdir(cwd)
-        files = []
-        for filename in myFiles:
-            files.append(os.path.join(direc, filename))
-        return files
-
-    def runTest(self):
-        """Main entry point for the test suite"""
-        from minixsv import pyxsval
-        # need to extend minixsv library to add method for that forces it to
-        # validate against local schema when the xml file itself has
-        # reference to schema online. The preference is to systemtest against
-        # a local schema file to avoid this systemtest failing is
-        # external url temporariliy not available. Secondary it also avoid
-        # having to worry about proxies.
-
-        #pylint: disable=too-few-public-methods
-        class MyXsValidator(pyxsval.XsValidator):
-            ########################################
-            # force validation of XML input against local file
-            #
-            def validateXmlInputForceReadFile (self, xmlInputFile, inputTreeWrapper, xsdFile):
-                xsdTreeWrapper = self.parse (xsdFile)
-                xsdTreeWrapperList = []
-                xsdTreeWrapperList.append(xsdTreeWrapper)
-                self._validateXmlInput (xmlInputFile, inputTreeWrapper, xsdTreeWrapperList)
-                for xsdTreeWrapper in xsdTreeWrapperList:
-                    xsdTreeWrapper.unlink()
-                return inputTreeWrapper
-
-        def parseAndValidateXmlInputForceReadFile(inputFile, xsdFile=None, **kw):
-            myXsValidator = MyXsValidator(**kw)
-            # parse XML input file
-            inputTreeWrapper = myXsValidator.parse (inputFile)
-            # validate XML input file
-            return myXsValidator.validateXmlInputForceReadFile (inputFile, inputTreeWrapper, xsdFile)
-
-        direc = config['instrumentDefinition.directory']
-        self.xsdFile =  os.path.join(direc,'Schema/IDF/1.0/','IDFSchema.xsd')
-        if self.theFileToTest is None:
-            files = self.__getDataFileList__()
-        else:
-            files = [os.path.join(direc,self.theFileToTest)]
-
-        # run the tests
-        failed = []
-        for filename in files:
-            try:
-                print("----------------------------------------")
-                print("Validating '%s'" % filename)
-                parseAndValidateXmlInputForceReadFile(filename, xsdFile=self.xsdFile)
-            except Exception as e:
-                print("VALIDATION OF '%s' FAILED WITH ERROR:" % filename)
-                print(e)
-                failed.append(filename)
-
-        # final say on whether or not it 'worked'
-        print("----------------------------------------")
-        if len(failed) != 0:
-            print("SUMMARY OF FAILED FILES")
-            for filename in failed:
-                print(filename)
-            raise RuntimeError("Failed Validation for %d of %d files"
-                               % (len(failed), len(files)))
-        else:
-            print("Successfully Validated %d files" % len(files))
-
-
-if __name__ == '__main__':
-
-    valid = ValidateInstrumentDefinitionFiles()
-    # validate specific file
-    #valid.theFileToTest = "MARI_Definition.xml"
-    valid.runTest()
diff --git a/Testing/SystemTests/tests/analysis/ValidateInstrumentDir.py b/Testing/SystemTests/tests/analysis/ValidateInstrumentDir.py
new file mode 100644
index 0000000000000000000000000000000000000000..de86b57a08d5649d5b3fee3d0134587bae298235
--- /dev/null
+++ b/Testing/SystemTests/tests/analysis/ValidateInstrumentDir.py
@@ -0,0 +1,122 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+#pylint: disable=invalid-name
+#pylint: disable=no-init
+from __future__ import (absolute_import, division, print_function)
+
+import glob
+import os
+
+from mantid import config
+import six
+import systemtesting
+
+if six.PY2:
+    from io import open  # noqa
+
+# Constants
+FILE_TO_TEST = None  # "MARI_Definition.xml"
+INSTRUMENT_DIR = config['instrumentDefinition.directory']
+
+
+class ValidateXML(object):
+
+    def skipTests(self):
+        try:
+            import lxml  # noqa
+        except ImportError:
+            return True
+
+        return False
+
+    def runTest(self):
+        """Main entry point for the test suite"""
+        from lxml import etree
+
+        # read local schema
+        xsd_file = open(self.xsdpath(), "r", encoding="utf-8")
+        xsd_doc = etree.parse(xsd_file)
+
+        def validate_definition(filepath):
+            schema = etree.XMLSchema(xsd_doc)
+            with open(filepath, "r", encoding="utf-8") as xml_file:
+                is_valid = schema.validate(etree.XML(xml_file.read().encode("utf-8")))
+            if is_valid:
+                return is_valid, None
+            else:
+                return is_valid, schema.error_log.filter_from_errors()[0]
+
+        if FILE_TO_TEST is None:
+            files = self.filelist()
+        else:
+            files = [os.path.join(INSTRUMENT_DIR, FILE_TO_TEST)]
+
+        # run the tests
+        failed = []
+        for filename in files:
+            print("----------------------------------------")
+            print("Validating '%s'" % filename)
+            valid, errors = validate_definition(filename)
+            if not valid:
+                print("VALIDATION OF '%s' FAILED WITH ERROR:" % filename)
+                print(errors)
+                failed.append(filename)
+
+        # final say on whether or not it 'worked'
+        print("----------------------------------------")
+        if len(failed) != 0:
+            print("SUMMARY OF FAILED FILES")
+            for filename in failed:
+                print(filename)
+            raise RuntimeError("Failed Validation for %d of %d files"
+                               % (len(failed), len(files)))
+        else:
+            print("Successfully Validated %d files" % len(files))
+
+
+class ValidateInstrumentDefinitionFiles(ValidateXML, systemtesting.MantidSystemTest):
+
+    def xsdpath(self):
+        return os.path.join(INSTRUMENT_DIR, "Schema", "IDF", "1.0",
+                            "IDFSchema.xsd")
+
+    def filelist(self):
+        print("Looking for instrument definition files in: %s" % INSTRUMENT_DIR)
+        return glob.glob("{}/*Definition*.xml".format(INSTRUMENT_DIR))
+
+
+class ValidateParameterFiles(ValidateXML, systemtesting.MantidSystemTest):
+
+    def xsdpath(self):
+        return os.path.join(INSTRUMENT_DIR, "Schema", "ParameterFile", "1.0",
+                            "ParameterFileSchema.xsd")
+
+    def filelist(self):
+        print("Looking for instrument definition files in: %s" % INSTRUMENT_DIR)
+        return glob.glob("{}/*Parameters*.xml".format(INSTRUMENT_DIR))
+
+
+class ValidateFacilitiesFile(ValidateXML, systemtesting.MantidSystemTest):
+
+    def xsdpath(self):
+        return os.path.join(INSTRUMENT_DIR, "Schema", "Facilities", "1.0",
+                            "FacilitiesSchema.xsd")
+
+    def filelist(self):
+        return [os.path.join(INSTRUMENT_DIR, 'Facilities.xml')]
+
+
+class ValidateGroupingFiles(ValidateXML, systemtesting.MantidSystemTest):
+
+    def xsdpath(self):
+        return os.path.join(INSTRUMENT_DIR, "Schema", "Grouping", "1.0",
+                            "GroupingSchema.xsd")
+
+    def filelist(self):
+        grouping_dir = os.path.join(INSTRUMENT_DIR, "Grouping")
+        print("Looking for grouping files in: %s" % grouping_dir)
+        return glob.glob("{}/*Grouping*.xml".format(grouping_dir))
diff --git a/Testing/SystemTests/tests/analysis/ValidateParameterFiles.py b/Testing/SystemTests/tests/analysis/ValidateParameterFiles.py
deleted file mode 100644
index 016fb9400aad6fe04f402ace52bf34195c2482a2..0000000000000000000000000000000000000000
--- a/Testing/SystemTests/tests/analysis/ValidateParameterFiles.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# Mantid Repository : https://github.com/mantidproject/mantid
-#
-# Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
-#     NScD Oak Ridge National Laboratory, European Spallation Source
-#     & Institut Laue - Langevin
-# SPDX - License - Identifier: GPL - 3.0 +
-#pylint: disable=no-init,invalid-name
-from __future__ import (absolute_import, division, print_function)
-from mantid import config
-import os
-import systemtesting
-import glob
-
-EXPECTED_EXT = '.expected'
-
-
-class ValidateParameterFiles(systemtesting.MantidSystemTest):
-
-    xsdFile=''
-
-    def skipTests(self):
-        try:
-            from genxmlif import GenXmlIfError # noqa
-            from minixsv import pyxsval # noqa
-        except ImportError:
-            return True
-        return False
-
-    def __getDataFileList__(self):
-        # get a list of directories to look in
-        direc = config['instrumentDefinition.directory']
-        print("Looking for instrument definition files in: %s" % direc)
-        cwd = os.getcwd()
-        os.chdir(direc)
-        myFiles = glob.glob("*Parameters*.xml")
-        os.chdir(cwd)
-        files = []
-        for filename in myFiles:
-            files.append(os.path.join(direc, filename))
-        return files
-
-    def runTest(self):
-        """Main entry point for the test suite"""
-        from minixsv import pyxsval # noqa
-        direc = config['instrumentDefinition.directory']
-        print(direc)
-        self.xsdFile =  os.path.join(direc,'Schema/ParameterFile/1.0/','ParameterFileSchema.xsd')
-        files = self.__getDataFileList__()
-
-        # run the tests
-        failed = []
-        for filename in files:
-            try:
-                print("----------------------------------------")
-                print("Validating '%s'" % filename)
-                pyxsval.parseAndValidateXmlInput(filename, xsdFile=self.xsdFile, validateSchema=0)
-            except Exception as e:
-                print("VALIDATION OF '%s' FAILED WITH ERROR:" % filename)
-                print(e)
-                failed.append(filename)
-
-        # final say on whether or not it 'worked'
-        print("----------------------------------------")
-        if len(failed) != 0:
-            print("SUMMARY OF FAILED FILES")
-            for filename in failed:
-                print(filename)
-            raise RuntimeError("Failed Validation for %d of %d files"
-                               % (len(failed), len(files)))
-        else:
-            print("Successfully Validated %d files" % len(files))
-
-
-if __name__ == '__main__':
-    valid = ValidateParameterFiles()
-    valid.runTest()
diff --git a/buildconfig/CMake/Bootstrap.cmake b/buildconfig/CMake/Bootstrap.cmake
index 12f00143779c1c881e44b43c3a986c2c9ad36976..d6787dabec28cd6be97f477d678649c7f47d2f4b 100644
--- a/buildconfig/CMake/Bootstrap.cmake
+++ b/buildconfig/CMake/Bootstrap.cmake
@@ -10,7 +10,7 @@ if( MSVC )
   include ( ExternalProject )
   set( EXTERNAL_ROOT ${PROJECT_SOURCE_DIR}/external CACHE PATH "Location to clone third party dependencies to" )
   set( THIRD_PARTY_GIT_URL "https://github.com/mantidproject/thirdparty-msvc2015.git" )
-  set ( THIRD_PARTY_GIT_SHA1 622c6d0aa7d4480cd4d338e153f1f09e52b8fb09 )
+  set ( THIRD_PARTY_GIT_SHA1 a7bd18f35c8d67e68c3a965a07057efa266fc7d7 )
   set ( THIRD_PARTY_DIR ${EXTERNAL_ROOT}/src/ThirdParty )
   # Generates a script to do the clone/update in tmp
   set ( _project_name ThirdParty )
@@ -65,8 +65,14 @@ if( MSVC )
   unset ( _tmp_dir )
 
   # Print out where we are looking for 3rd party stuff
-  set ( PYTHON_MAJOR_VERSION 2 )
-  set ( PYTHON_MINOR_VERSION 7 )
+  option ( WITH_PYTHON3 "If true then build against Python 3.8" OFF )
+  if ( WITH_PYTHON3 )
+    set ( PYTHON_MAJOR_VERSION 3 )
+    set ( PYTHON_MINOR_VERSION 8 )
+  else()
+    set ( PYTHON_MAJOR_VERSION 2 )
+    set ( PYTHON_MINOR_VERSION 7 )
+  endif()
   set ( THIRD_PARTY_BIN "${THIRD_PARTY_DIR}/bin;${THIRD_PARTY_DIR}/lib/qt4/bin;${THIRD_PARTY_DIR}/lib/qt5/bin;${THIRD_PARTY_DIR}/lib/python${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}" )
   message ( STATUS "Third party dependencies are in ${THIRD_PARTY_DIR}" )
   # Add to the path so that cmake can configure correctly without the user having to do it
diff --git a/buildconfig/CMake/FindBoostPython.cmake b/buildconfig/CMake/FindBoostPython.cmake
index 06a4957b06274e94036649a1f24bebb03c73c93d..c8c8686aab11e0773c832cf293ae35470eb76e4c 100644
--- a/buildconfig/CMake/FindBoostPython.cmake
+++ b/buildconfig/CMake/FindBoostPython.cmake
@@ -5,7 +5,7 @@
 #  - windows: boost_python (python2), ????? (python3)
 #  - others?
 if ( MSVC )
-  find_package ( Boost ${BOOST_VERSION_REQUIRED} COMPONENTS python27 REQUIRED )
+  find_package ( Boost ${BOOST_VERSION_REQUIRED} COMPONENTS python${PYTHON_MAJOR_VERSION}${PYTHON_MINOR_VERSION} REQUIRED )
 else ()
   if ( PYTHON_VERSION_MAJOR GREATER 2 )
     # Try a known set of suffixes plus a user-defined set
diff --git a/buildconfig/CMake/PyQtFindImpl.cmake b/buildconfig/CMake/PyQtFindImpl.cmake
index b8d637f0f14fd2da542bbebd08f1763b970ff043..3bfcf7a66f6bd20e4afc438f5f0641c21d347bcd 100644
--- a/buildconfig/CMake/PyQtFindImpl.cmake
+++ b/buildconfig/CMake/PyQtFindImpl.cmake
@@ -29,24 +29,28 @@ function (find_pyqt major_version)
   endif()
   execute_process (COMMAND ${PYTHON_EXECUTABLE} ${_find_pyqt_py} ${major_version}
     OUTPUT_VARIABLE _pyqt_config ERROR_VARIABLE _pyqt_config_err)
+  if(CMAKE_HOST_WIN32 AND major_version EQUAL 4 AND _pyqt_config_err MATCHES "Qt: Untested Windows version 10.0 detected!")
+    # Known warning on Windows 10 with Qt4 and Python 3
+    set(_pyqt_config_err "")
+  endif()
   if (_pyqt_config AND NOT _pyqt_config_err)
     string (REGEX MATCH "^pyqt_version:([^\n]+).*$" _dummy ${_pyqt_config})
-    set (PYQT${major_version}_VERSION "${CMAKE_MATCH_1}" CACHE STRING "PyQt${major_version}'s version as a 6-digit hexadecimal number")
+    set (PYQT${major_version}_VERSION "${CMAKE_MATCH_1}" CACHE STRING "PyQt${major_version}'s version as a 6-digit hexadecimal number" FORCE)
 
     string (REGEX MATCH ".*\npyqt_version_str:([^\n]+).*$" _dummy ${_pyqt_config})
-    set (PYQT${major_version}_VERSION_STR "${CMAKE_MATCH_1}" CACHE STRING "PyQt${major_version}'s version as a human-readable string")
+    set (PYQT${major_version}_VERSION_STR "${CMAKE_MATCH_1}" CACHE STRING "PyQt${major_version}'s version as a human-readable string" FORCE)
 
     string (REGEX MATCH ".*\npyqt_version_tag:([^\n]+).*$" _dummy ${_pyqt_config})
-    set (PYQT${major_version}_VERSION_TAG "${CMAKE_MATCH_1}" CACHE STRING "The Qt version tag used by PyQt${major_version}'s .sip files")
+    set (PYQT${major_version}_VERSION_TAG "${CMAKE_MATCH_1}" CACHE STRING "The Qt version tag used by PyQt${major_version}'s .sip files" FORCE)
 
     string (REGEX MATCH ".*\npyqt_sip_dir:([^\n]+).*$" _dummy ${_pyqt_config})
-    set (PYQT${major_version}_SIP_DIR "${CMAKE_MATCH_1}" CACHE PATH "The base directory where PyQt${major_version}'s .sip files are installed")
+    set (PYQT${major_version}_SIP_DIR "${CMAKE_MATCH_1}" CACHE PATH "The base directory where PyQt${major_version}'s .sip files are installed" FORCE)
 
     string (REGEX MATCH ".*\npyqt_sip_flags:([^\n]+).*$" _dummy ${_pyqt_config})
-    set (PYQT${major_version}_SIP_FLAGS "${CMAKE_MATCH_1}" CACHE STRING "The SIP flags used to build PyQt${major_version}")
+    set (PYQT${major_version}_SIP_FLAGS "${CMAKE_MATCH_1}" CACHE STRING "The SIP flags used to build PyQt${major_version}" FORCE)
 
     string (REGEX MATCH ".*\npyqt_pyuic:([^\n]+).*$" _dummy ${_pyqt_config})
-    set (PYQT${major_version}_PYUIC "${CMAKE_MATCH_1}" CACHE STRING "Location of the pyuic script")
+    set (PYQT${major_version}_PYUIC "${CMAKE_MATCH_1}" CACHE STRING "Location of the pyuic script" FORCE)
 
     if (NOT EXISTS "${PYQT${major_version}_SIP_DIR}/QtCore/QtCoremod.sip")
       message (FATAL_ERROR "Unable to find QtCore/QtCoremod.sip in ${PYQT${major_version}_SIP_DIR}. PyQt sip files are missing."
diff --git a/buildconfig/CMake/WindowsNSIS.cmake b/buildconfig/CMake/WindowsNSIS.cmake
index 9e896bb0cb53039908415d44a62a1152cc3bdf0b..400a70737ad1a937bc1a5eb00157ef4071ec6a4f 100644
--- a/buildconfig/CMake/WindowsNSIS.cmake
+++ b/buildconfig/CMake/WindowsNSIS.cmake
@@ -60,11 +60,16 @@ mark_as_advanced(WINDOWS_DEPLOYMENT_TYPE)
 set ( BOOST_DIST_DLLS
     boost_date_time-mt.dll
     boost_filesystem-mt.dll
-    boost_python27-mt.dll
     boost_regex-mt.dll
     boost_serialization-mt.dll
     boost_system-mt.dll
 )
+if ( WITH_PYTHON3 )
+  list( APPEND BOOST_DIST_DLLS boost_python38-mt.dll )
+else ()
+  list( APPEND BOOST_DIST_DLLS boost_python27-mt.dll )
+endif ()
+
 set ( POCO_DIST_DLLS
     PocoCrypto64.dll
     PocoFoundation64.dll
diff --git a/dev-docs/source/Python3.rst b/dev-docs/source/Python3.rst
index 85915a6d2ad75e2d9e1a1055742578ff3d79f80b..248ef49e1e69ff5c4b87e102df0115606d63c6dd 100644
--- a/dev-docs/source/Python3.rst
+++ b/dev-docs/source/Python3.rst
@@ -12,13 +12,28 @@ migration strategy for Mantid.
 Building Against Python 3
 #########################
 
-This is currently only possible on a Linux system with a pre-installed version of python 3 and you will need to have
-the latest version of the `mantid-developer` package installed. Once installed run cmake as standard but with the additional option ``-DPYTHON_EXECUTABLE=/usr/bin/python3``. Please note that
-reconfiguring an existing Python 2 build is not supported - a build in a fresh build directory is required.
+This is currently possible on Ubuntu or Windows.
+Please note that reconfiguring an existing Python 2 build is not supported - a build in a fresh build directory is required.
+
+Ubuntu
+^^^^^^
+
+Install the latest version of the `mantid-developer` package. Once installed run cmake as standard but with the additional option ``-DPYTHON_EXECUTABLE=/usr/bin/python3``.
 
 .. warning::
    Do not install python packages via ``pip``. Install packages only from the system repositories.
 
+Windows
+^^^^^^^
+
+All of the required packages are in the third-party bundle that will be fetched for you.
+
+To build from the command line run cmake as standard but with the additional option ``-DWITH_PYTHON3=ON``.
+
+To build from the GUI ensure the previous cache has been deleted, set the source and build directories as usual
+but before clicking configure click "Add Entry" and add an entry with the name ``WITH_PYTHON3`` of type ``BOOL``
+and ensure the Value is checked. Now proceed to configure and generate as usual.
+
 Supporting Python 2 and 3
 #########################
 
diff --git a/dev-docs/source/index.rst b/dev-docs/source/index.rst
index 8c43f6fb93a35abb7ab04da79d05039f1a43131c..1bd00d7980ca5ab63883dee9915a444f07e9565c 100644
--- a/dev-docs/source/index.rst
+++ b/dev-docs/source/index.rst
@@ -47,7 +47,7 @@ Guides
    Configure a doxygen build locally.
 
 :doc:`Python3`
-   Building with Python 3 (Linux only).
+   Building with Python 3 (Ubuntu/Windows).
 
 `C++ Introduction <https://www.mantidproject.org/New_Starter_C%2B%2B_introduction>`_
    Exercises for learning C++.
@@ -207,7 +207,7 @@ GUI Development
 
 :doc:`ISISReflectometryInterface`
    An example of a complex C++ interface that uses MVP.
-   
+
 =========
 Workbench
 =========
diff --git a/docs/source/algorithms/LoadAscii-v2.rst b/docs/source/algorithms/LoadAscii-v2.rst
index 5ec7650188e4269482534ff5ce3d6d54d794af57..263b65da527fe885f0ade4e0e3c24a3af96dbdc4 100644
--- a/docs/source/algorithms/LoadAscii-v2.rst
+++ b/docs/source/algorithms/LoadAscii-v2.rst
@@ -10,14 +10,14 @@ Description
 -----------
 
 The LoadAscii2 algorithm reads in spectra data from a text file and
-stores it in a :ref:`Workspace2D <Workspace2D>` as data points. The data in
+stores it in a :ref:`Workspace2D <Workspace2D>` as data points, or a Table Workspace if it is table data. The data in
 the file must be organized in columns separated by commas, tabs, spaces,
 colons or semicolons. Only one separator type can be used throughout the
 file; use the "Separator" property to tell the algorithm which to use.
 The algorithm :ref:`SaveAscii2 <algm-SaveAscii-v2>` is normally able to produce
 such a file.
 
-The format must be:
+The format must be (Workspace 2D):
 
 -  A single integer or blank line to denote a new spectra
 -  For each bin, between two and four columns of delimited data in the
@@ -39,6 +39,21 @@ no X error::
     2.00000000,3.00000000,1.00000000 4.00000000,0.00000000,0.00000000 4
     2.00000000,0.00000000,0.00000000 4.00000000,0.00000000,0.00000000
 
+The format must be (Table Workspace):
+
+-  Two commented header lines
+-  The first containing the column names
+-  The second containing the column types (str, int, unit, long64, size_t, float, double, bool, V3D)
+-  The number of column names, types and data items must match
+
+
+The following is an example valid file of two columns::
+
+	# Instrument Name , Run Number 
+	# str , int 
+	MUSR,10245
+	IRIS,8465
+	SANS2D,20462
 
 Usage
 -----
diff --git a/docs/source/algorithms/LoadHFIRSANS-v1.rst b/docs/source/algorithms/LoadHFIRSANS-v1.rst
index 6e9754e70e6ecd3da303ca95cdf19a4e2ea6027d..74c0c7f296d9ee1b3c4d3c64885a685ed69ab35e 100644
--- a/docs/source/algorithms/LoadHFIRSANS-v1.rst
+++ b/docs/source/algorithms/LoadHFIRSANS-v1.rst
@@ -24,11 +24,11 @@ Finds and sets the logs:
 * ``monitor``
 * ``timer``
 * ``sample-thicknes``
-* ``source-aperture-diameter``
-* ``sample-aperture-diameter``
+* ``source-aperture-diameter`` and ``source_aperture_diameter``
+* ``sample-aperture-diameter`` and ``sample-aperture-diameter``
 * ``number-of-guides``
-* ``sample-detector-distance`` and ``sdd``
-* ``source-sample-distance``
+* ``sample-detector-distance``, ``sample_detector_distance``, and ``sdd``
+* ``source-sample-distance`` and ``source-sample-distance``
 * ``beam-diameter``
 
 .. categories::
diff --git a/docs/source/algorithms/SaveAscii-v2.rst b/docs/source/algorithms/SaveAscii-v2.rst
index a35e60f03bf289130b86ec3e87ce427584b81e71..0082f962ec3b9767c62fc4c3c3ee0189c3fb6b8d 100644
--- a/docs/source/algorithms/SaveAscii-v2.rst
+++ b/docs/source/algorithms/SaveAscii-v2.rst
@@ -9,7 +9,9 @@
 Description
 -----------
 
-The workspace data are stored in the file in columns: the first column contains
+The format used differs based on the type of workspace being saved.  For a table workspace the data will contain an optional row of column headers, followed by the row values, with each individual column value seperated by the defined seperator.
+
+For a  matrix workspace the data are stored in the file in columns: the first column contains
 the X-values, followed by pairs of Y and E values. Columns are separated by
 commas. The resulting file can normally be loaded into a workspace by the
 :ref:`algm-LoadAscii` algorithm.
diff --git a/docs/source/release/v4.3.0/direct_geometry.rst b/docs/source/release/v4.3.0/direct_geometry.rst
index 2a4a9b09cfe3d55ddd8decd3430d8215539703de..2250c429fca2c8f8c403172999cd002a925b9a11 100644
--- a/docs/source/release/v4.3.0/direct_geometry.rst
+++ b/docs/source/release/v4.3.0/direct_geometry.rst
@@ -9,4 +9,6 @@ Direct Geometry Changes
     putting new features at the top of the section, followed by
     improvements, followed by bug fixes.
 
-:ref:`Release 4.3.0 <v4.3.0>`
\ No newline at end of file
+* New ``NOW4`` instrument definition for SNS
+
+:ref:`Release 4.3.0 <v4.3.0>`
diff --git a/docs/source/release/v4.3.0/framework.rst b/docs/source/release/v4.3.0/framework.rst
index 9df25b4238994512a2a77704cc902667db2f9565..2f8d5dff4a12d8aab440dc47ece5f5dd01d4253b 100644
--- a/docs/source/release/v4.3.0/framework.rst
+++ b/docs/source/release/v4.3.0/framework.rst
@@ -20,13 +20,20 @@ Improvements
 
 - Fixed a bug in :ref:`LoadNGEM <algm-LoadNGEM>` where precision was lost due to integer arithmetic.
 - Prevent units that are not suitable for :ref:`ConvertUnits <algm-ConvertUnits>` being entered as the target unit.
+- Fixed an uncaught exception when plotting logs on single spectrum workspaces in mantidworkbench
+- Save the units for single value logs in :ref:`SaveNexusProcessed <algm-SaveNexusProcessed>`
 
 Algorithms
 ----------
 
+Improvements
+############
+
+- :ref:`SaveAscii <algm-SaveAscii>` can now save table workspaces, and :ref:`LoadAscii <algm-LoadAscii>` can load them again.
 - :ref:`TotScatCalculateSelfScattering <algm-TotScatCalculateSelfScattering>` will calculate a normalized self scattering correction for foccues total scattering data.
 - :ref:`MatchAndMergeWorkspaces <algm-MatchAndMergeWorkspaces>` will merge workspaces in a workspace group withing weighting from a set of limits for each workspace and using `MatchSpectra <algm-MatchSpectra>`.
 
+
 Data Objects
 ------------
 
diff --git a/docs/source/release/v4.3.0/mantidworkbench.rst b/docs/source/release/v4.3.0/mantidworkbench.rst
index 122e4fa6a789978be27fbffc5184bff96127d7fa..99f60d1a66d63aa88d14b67f0e045abd4cadade6 100644
--- a/docs/source/release/v4.3.0/mantidworkbench.rst
+++ b/docs/source/release/v4.3.0/mantidworkbench.rst
@@ -8,6 +8,8 @@ MantidWorkbench Changes
 Improvements
 ############
 
+- Normalization option have been added to 2d plots.
+- You can now save Table Workspaces to Ascii using the `SaveAscii <algm-SaveAscii>` algorithm, and the Ascii Save option on the workspaces toolbox.
 - Normalization options have been added to 2d plots and sliceviewer.
 - The images tab in figure options no longer forces the max value to be greater than the min value.
 
diff --git a/instrument/CG2_Definition.xml b/instrument/CG2_Definition.xml
index c0dcffab11ca3ccf7bc7ec38405604a38f517a51..fe4266a41ebe661016f5568dbef0f35fe7db8894 100644
--- a/instrument/CG2_Definition.xml
+++ b/instrument/CG2_Definition.xml
@@ -433,7 +433,7 @@
   <component type="double-flat-panel" idlist="pixel_ids" name="detector1">
     <location>
       <parameter name="x">
-        <logfile id="detector_trans" eq="-0.001*value"/>
+        <logfile id="detector_trans_Readback" eq="-0.001*value"/>
       </parameter>
       <parameter name="z">
         <logfile id="sample_detector_distance" eq="value"/>
diff --git a/instrument/Facilities.xml b/instrument/Facilities.xml
index bb12995ac2ebe0ec0d622f328d6b902355ef5ba9..02d0256f645e89714bb49f2e2695b28f93ce015c 100644
--- a/instrument/Facilities.xml
+++ b/instrument/Facilities.xml
@@ -567,6 +567,11 @@
     </livedata>
   </instrument>
 
+  <instrument name="NOW4" shortname="NOW4" beamline="14Q">
+    <technique>Neutron Spectroscopy</technique>
+    <technique>TOF Direct Geometry Spectroscopy</technique>
+  </instrument>
+
   <instrument name="VISION" shortname="VIS" beamline="16B">
     <technique>Neutron Spectroscopy</technique>
     <technique>TOF Indirect Geometry Spectroscopy</technique>
@@ -902,7 +907,7 @@
 <!-- HZB -->
 <facility name="HZB" FileExtensions=".nxs">
    <timezone>Europe/Berlin</timezone>
-   
+
    <instrument name="TEST" shortname="TEST">
 	<zeropadding size="8" />
     <technique>ESS Test Beamline</technique>
@@ -946,14 +951,14 @@
 <!--  Test Facility to allow example usage of Live listeners against "Fake" instrument sources -->
 <facility name="TEST_LIVE" FileExtensions=".nxs,.raw">
   <timezone>UTC</timezone>
-  
+
   <instrument name="LOKI">
     <technique>SANS Test</technique>
     <livedata>
       <connection name="event" address="hinata:9092" listener="KafkaEventListener" />
     </livedata>
   </instrument>
-  
+
   <instrument name="ISIS_Histogram">
     <technique>Test Listener</technique>
     <livedata>
diff --git a/instrument/GPSANS_Definition.xml b/instrument/GPSANS_Definition.xml
index d36b51947298deeeece84b42b6f2c4af95e8e3a3..2182f730158eaf2ca4692f0dcbace4e8c7655b56 100644
--- a/instrument/GPSANS_Definition.xml
+++ b/instrument/GPSANS_Definition.xml
@@ -433,7 +433,7 @@
   <component type="double-flat-panel" idlist="pixel_ids" name="detector1">
     <location>
       <parameter name="x">
-        <logfile id="detector_trans" eq="-0.001*value"/>
+        <logfile id="detector_trans_Readback" eq="-0.001*value"/>
       </parameter>
       <parameter name="z">
         <logfile id="sample_detector_distance" eq="value"/>
diff --git a/instrument/NOW4_Definition.xml b/instrument/NOW4_Definition.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f5606937349a1241cf47f30ac5fcc97ca6085f50
--- /dev/null
+++ b/instrument/NOW4_Definition.xml
@@ -0,0 +1,351 @@
+<?xml version='1.0' encoding='ASCII'?>
+<instrument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.mantidproject.org/IDF/1.0" last-modified="2019-06-25 14:11:19.918208" name="NOW4" valid-from="2019-06-02 00:00:00" valid-to="2100-01-31 23:59:59" xsi:schemaLocation="http://www.mantidproject.org/IDF/1.0 http://schema.mantidproject.org/IDF/1.0/IDFSchema.xsd">
+  <!--Created by Andrei Savici-->
+  <defaults>
+    <length unit="metre"/>
+    <angle unit="degree"/>
+    <reference-frame>
+      <along-beam axis="z"/>
+      <pointing-up axis="y"/>
+      <handedness val="right"/>
+      <theta-sign axis="x"/>
+    </reference-frame>
+  </defaults>
+  <!--SOURCE AND SAMPLE POSITION-->
+  <component type="moderator">
+    <location z="-36.262"/>
+  </component>
+  <type is="Source" name="moderator"/>
+  <component type="sample-position">
+    <location x="0.0" y="0.0" z="0.0"/>
+  </component>
+  <type is="SamplePos" name="sample-position"/>
+  <component idlist="detectors" type="detectors">
+    <location/>
+  </component>
+  <type name="detectors">
+    <component type="bank1">
+      <location/>
+    </component>
+  </type>
+  <type name="bank1">
+    <component type="eightpack">
+      <location x="2.64623477185" y="-0.00904297322071" z="-2.3031829704">
+        <rot axis-x="0" axis-y="1" axis-z="0" val="311.035082035"/>
+      </location>
+    </component>
+  </type>
+  <!--STANDARD 8-PACK-->
+  <type name="eightpack">
+    <properties/>
+    <component type="tube">
+      <location name="tube1" x="-0.096012"/>
+      <location name="tube2" x="-0.06858"/>
+      <location name="tube3" x="-0.041148"/>
+      <location name="tube4" x="-0.013716"/>
+      <location name="tube5" x="0.013716"/>
+      <location name="tube6" x="0.041148"/>
+      <location name="tube7" x="0.06858"/>
+      <location name="tube8" x="0.096012"/>
+    </component>
+  </type>
+  <!--STANDARD 2m 128 PIXEL TUBE-->
+  <type name="tube" outline="yes">
+    <properties/>
+    <component type="pixel">
+      <location name="pixel1" y="-0.2"/>
+      <location name="pixel2" y="-0.1984375"/>
+      <location name="pixel3" y="-0.196875"/>
+      <location name="pixel4" y="-0.1953125"/>
+      <location name="pixel5" y="-0.19375"/>
+      <location name="pixel6" y="-0.1921875"/>
+      <location name="pixel7" y="-0.190625"/>
+      <location name="pixel8" y="-0.1890625"/>
+      <location name="pixel9" y="-0.1875"/>
+      <location name="pixel10" y="-0.1859375"/>
+      <location name="pixel11" y="-0.184375"/>
+      <location name="pixel12" y="-0.1828125"/>
+      <location name="pixel13" y="-0.18125"/>
+      <location name="pixel14" y="-0.1796875"/>
+      <location name="pixel15" y="-0.178125"/>
+      <location name="pixel16" y="-0.1765625"/>
+      <location name="pixel17" y="-0.175"/>
+      <location name="pixel18" y="-0.1734375"/>
+      <location name="pixel19" y="-0.171875"/>
+      <location name="pixel20" y="-0.1703125"/>
+      <location name="pixel21" y="-0.16875"/>
+      <location name="pixel22" y="-0.1671875"/>
+      <location name="pixel23" y="-0.165625"/>
+      <location name="pixel24" y="-0.1640625"/>
+      <location name="pixel25" y="-0.1625"/>
+      <location name="pixel26" y="-0.1609375"/>
+      <location name="pixel27" y="-0.159375"/>
+      <location name="pixel28" y="-0.1578125"/>
+      <location name="pixel29" y="-0.15625"/>
+      <location name="pixel30" y="-0.1546875"/>
+      <location name="pixel31" y="-0.153125"/>
+      <location name="pixel32" y="-0.1515625"/>
+      <location name="pixel33" y="-0.15"/>
+      <location name="pixel34" y="-0.1484375"/>
+      <location name="pixel35" y="-0.146875"/>
+      <location name="pixel36" y="-0.1453125"/>
+      <location name="pixel37" y="-0.14375"/>
+      <location name="pixel38" y="-0.1421875"/>
+      <location name="pixel39" y="-0.140625"/>
+      <location name="pixel40" y="-0.1390625"/>
+      <location name="pixel41" y="-0.1375"/>
+      <location name="pixel42" y="-0.1359375"/>
+      <location name="pixel43" y="-0.134375"/>
+      <location name="pixel44" y="-0.1328125"/>
+      <location name="pixel45" y="-0.13125"/>
+      <location name="pixel46" y="-0.1296875"/>
+      <location name="pixel47" y="-0.128125"/>
+      <location name="pixel48" y="-0.1265625"/>
+      <location name="pixel49" y="-0.125"/>
+      <location name="pixel50" y="-0.1234375"/>
+      <location name="pixel51" y="-0.121875"/>
+      <location name="pixel52" y="-0.1203125"/>
+      <location name="pixel53" y="-0.11875"/>
+      <location name="pixel54" y="-0.1171875"/>
+      <location name="pixel55" y="-0.115625"/>
+      <location name="pixel56" y="-0.1140625"/>
+      <location name="pixel57" y="-0.1125"/>
+      <location name="pixel58" y="-0.1109375"/>
+      <location name="pixel59" y="-0.109375"/>
+      <location name="pixel60" y="-0.1078125"/>
+      <location name="pixel61" y="-0.10625"/>
+      <location name="pixel62" y="-0.1046875"/>
+      <location name="pixel63" y="-0.103125"/>
+      <location name="pixel64" y="-0.1015625"/>
+      <location name="pixel65" y="-0.1"/>
+      <location name="pixel66" y="-0.0984375"/>
+      <location name="pixel67" y="-0.096875"/>
+      <location name="pixel68" y="-0.0953125"/>
+      <location name="pixel69" y="-0.09375"/>
+      <location name="pixel70" y="-0.0921875"/>
+      <location name="pixel71" y="-0.090625"/>
+      <location name="pixel72" y="-0.0890625"/>
+      <location name="pixel73" y="-0.0875"/>
+      <location name="pixel74" y="-0.0859375"/>
+      <location name="pixel75" y="-0.084375"/>
+      <location name="pixel76" y="-0.0828125"/>
+      <location name="pixel77" y="-0.08125"/>
+      <location name="pixel78" y="-0.0796875"/>
+      <location name="pixel79" y="-0.078125"/>
+      <location name="pixel80" y="-0.0765625"/>
+      <location name="pixel81" y="-0.075"/>
+      <location name="pixel82" y="-0.0734375"/>
+      <location name="pixel83" y="-0.071875"/>
+      <location name="pixel84" y="-0.0703125"/>
+      <location name="pixel85" y="-0.06875"/>
+      <location name="pixel86" y="-0.0671875"/>
+      <location name="pixel87" y="-0.065625"/>
+      <location name="pixel88" y="-0.0640625"/>
+      <location name="pixel89" y="-0.0625"/>
+      <location name="pixel90" y="-0.0609375"/>
+      <location name="pixel91" y="-0.059375"/>
+      <location name="pixel92" y="-0.0578125"/>
+      <location name="pixel93" y="-0.05625"/>
+      <location name="pixel94" y="-0.0546875"/>
+      <location name="pixel95" y="-0.053125"/>
+      <location name="pixel96" y="-0.0515625"/>
+      <location name="pixel97" y="-0.05"/>
+      <location name="pixel98" y="-0.0484375"/>
+      <location name="pixel99" y="-0.046875"/>
+      <location name="pixel100" y="-0.0453125"/>
+      <location name="pixel101" y="-0.04375"/>
+      <location name="pixel102" y="-0.0421875"/>
+      <location name="pixel103" y="-0.040625"/>
+      <location name="pixel104" y="-0.0390625"/>
+      <location name="pixel105" y="-0.0375"/>
+      <location name="pixel106" y="-0.0359375"/>
+      <location name="pixel107" y="-0.034375"/>
+      <location name="pixel108" y="-0.0328125"/>
+      <location name="pixel109" y="-0.03125"/>
+      <location name="pixel110" y="-0.0296875"/>
+      <location name="pixel111" y="-0.028125"/>
+      <location name="pixel112" y="-0.0265625"/>
+      <location name="pixel113" y="-0.025"/>
+      <location name="pixel114" y="-0.0234375"/>
+      <location name="pixel115" y="-0.021875"/>
+      <location name="pixel116" y="-0.0203125"/>
+      <location name="pixel117" y="-0.01875"/>
+      <location name="pixel118" y="-0.0171875"/>
+      <location name="pixel119" y="-0.015625"/>
+      <location name="pixel120" y="-0.0140625"/>
+      <location name="pixel121" y="-0.0125"/>
+      <location name="pixel122" y="-0.0109375"/>
+      <location name="pixel123" y="-0.009375"/>
+      <location name="pixel124" y="-0.0078125"/>
+      <location name="pixel125" y="-0.00625"/>
+      <location name="pixel126" y="-0.0046875"/>
+      <location name="pixel127" y="-0.003125"/>
+      <location name="pixel128" y="-0.0015625"/>
+      <location name="pixel129" y="0.0"/>
+      <location name="pixel130" y="0.0015625"/>
+      <location name="pixel131" y="0.003125"/>
+      <location name="pixel132" y="0.0046875"/>
+      <location name="pixel133" y="0.00625"/>
+      <location name="pixel134" y="0.0078125"/>
+      <location name="pixel135" y="0.009375"/>
+      <location name="pixel136" y="0.0109375"/>
+      <location name="pixel137" y="0.0125"/>
+      <location name="pixel138" y="0.0140625"/>
+      <location name="pixel139" y="0.015625"/>
+      <location name="pixel140" y="0.0171875"/>
+      <location name="pixel141" y="0.01875"/>
+      <location name="pixel142" y="0.0203125"/>
+      <location name="pixel143" y="0.021875"/>
+      <location name="pixel144" y="0.0234375"/>
+      <location name="pixel145" y="0.025"/>
+      <location name="pixel146" y="0.0265625"/>
+      <location name="pixel147" y="0.028125"/>
+      <location name="pixel148" y="0.0296875"/>
+      <location name="pixel149" y="0.03125"/>
+      <location name="pixel150" y="0.0328125"/>
+      <location name="pixel151" y="0.034375"/>
+      <location name="pixel152" y="0.0359375"/>
+      <location name="pixel153" y="0.0375"/>
+      <location name="pixel154" y="0.0390625"/>
+      <location name="pixel155" y="0.040625"/>
+      <location name="pixel156" y="0.0421875"/>
+      <location name="pixel157" y="0.04375"/>
+      <location name="pixel158" y="0.0453125"/>
+      <location name="pixel159" y="0.046875"/>
+      <location name="pixel160" y="0.0484375"/>
+      <location name="pixel161" y="0.05"/>
+      <location name="pixel162" y="0.0515625"/>
+      <location name="pixel163" y="0.053125"/>
+      <location name="pixel164" y="0.0546875"/>
+      <location name="pixel165" y="0.05625"/>
+      <location name="pixel166" y="0.0578125"/>
+      <location name="pixel167" y="0.059375"/>
+      <location name="pixel168" y="0.0609375"/>
+      <location name="pixel169" y="0.0625"/>
+      <location name="pixel170" y="0.0640625"/>
+      <location name="pixel171" y="0.065625"/>
+      <location name="pixel172" y="0.0671875"/>
+      <location name="pixel173" y="0.06875"/>
+      <location name="pixel174" y="0.0703125"/>
+      <location name="pixel175" y="0.071875"/>
+      <location name="pixel176" y="0.0734375"/>
+      <location name="pixel177" y="0.075"/>
+      <location name="pixel178" y="0.0765625"/>
+      <location name="pixel179" y="0.078125"/>
+      <location name="pixel180" y="0.0796875"/>
+      <location name="pixel181" y="0.08125"/>
+      <location name="pixel182" y="0.0828125"/>
+      <location name="pixel183" y="0.084375"/>
+      <location name="pixel184" y="0.0859375"/>
+      <location name="pixel185" y="0.0875"/>
+      <location name="pixel186" y="0.0890625"/>
+      <location name="pixel187" y="0.090625"/>
+      <location name="pixel188" y="0.0921875"/>
+      <location name="pixel189" y="0.09375"/>
+      <location name="pixel190" y="0.0953125"/>
+      <location name="pixel191" y="0.096875"/>
+      <location name="pixel192" y="0.0984375"/>
+      <location name="pixel193" y="0.1"/>
+      <location name="pixel194" y="0.1015625"/>
+      <location name="pixel195" y="0.103125"/>
+      <location name="pixel196" y="0.1046875"/>
+      <location name="pixel197" y="0.10625"/>
+      <location name="pixel198" y="0.1078125"/>
+      <location name="pixel199" y="0.109375"/>
+      <location name="pixel200" y="0.1109375"/>
+      <location name="pixel201" y="0.1125"/>
+      <location name="pixel202" y="0.1140625"/>
+      <location name="pixel203" y="0.115625"/>
+      <location name="pixel204" y="0.1171875"/>
+      <location name="pixel205" y="0.11875"/>
+      <location name="pixel206" y="0.1203125"/>
+      <location name="pixel207" y="0.121875"/>
+      <location name="pixel208" y="0.1234375"/>
+      <location name="pixel209" y="0.125"/>
+      <location name="pixel210" y="0.1265625"/>
+      <location name="pixel211" y="0.128125"/>
+      <location name="pixel212" y="0.1296875"/>
+      <location name="pixel213" y="0.13125"/>
+      <location name="pixel214" y="0.1328125"/>
+      <location name="pixel215" y="0.134375"/>
+      <location name="pixel216" y="0.1359375"/>
+      <location name="pixel217" y="0.1375"/>
+      <location name="pixel218" y="0.1390625"/>
+      <location name="pixel219" y="0.140625"/>
+      <location name="pixel220" y="0.1421875"/>
+      <location name="pixel221" y="0.14375"/>
+      <location name="pixel222" y="0.1453125"/>
+      <location name="pixel223" y="0.146875"/>
+      <location name="pixel224" y="0.1484375"/>
+      <location name="pixel225" y="0.15"/>
+      <location name="pixel226" y="0.1515625"/>
+      <location name="pixel227" y="0.153125"/>
+      <location name="pixel228" y="0.1546875"/>
+      <location name="pixel229" y="0.15625"/>
+      <location name="pixel230" y="0.1578125"/>
+      <location name="pixel231" y="0.159375"/>
+      <location name="pixel232" y="0.1609375"/>
+      <location name="pixel233" y="0.1625"/>
+      <location name="pixel234" y="0.1640625"/>
+      <location name="pixel235" y="0.165625"/>
+      <location name="pixel236" y="0.1671875"/>
+      <location name="pixel237" y="0.16875"/>
+      <location name="pixel238" y="0.1703125"/>
+      <location name="pixel239" y="0.171875"/>
+      <location name="pixel240" y="0.1734375"/>
+      <location name="pixel241" y="0.175"/>
+      <location name="pixel242" y="0.1765625"/>
+      <location name="pixel243" y="0.178125"/>
+      <location name="pixel244" y="0.1796875"/>
+      <location name="pixel245" y="0.18125"/>
+      <location name="pixel246" y="0.1828125"/>
+      <location name="pixel247" y="0.184375"/>
+      <location name="pixel248" y="0.1859375"/>
+      <location name="pixel249" y="0.1875"/>
+      <location name="pixel250" y="0.1890625"/>
+      <location name="pixel251" y="0.190625"/>
+      <location name="pixel252" y="0.1921875"/>
+      <location name="pixel253" y="0.19375"/>
+      <location name="pixel254" y="0.1953125"/>
+      <location name="pixel255" y="0.196875"/>
+      <location name="pixel256" y="0.1984375"/>
+    </component>
+  </type>
+  <!--PIXEL FOR STANDARD 2m 128 PIXEL TUBE-->
+  <type is="detector" name="pixel">
+    <cylinder id="cyl-approx">
+      <centre-of-bottom-base p="0.0" r="0.0" t="0.0"/>
+      <axis x="0.0" y="1.0" z="0.0"/>
+      <radius val="0.006"/>
+      <height val="0.0015625"/>
+    </cylinder>
+    <algebra val="cyl-approx"/>
+  </type>
+  <!--MONITOR SHAPE-->
+  <!--FIXME: Do something real here.-->
+  <type is="monitor" name="monitor">
+    <cylinder id="cyl-approx">
+      <centre-of-bottom-base p="0.0" r="0.0" t="0.0"/>
+      <axis x="0.0" y="0.0" z="1.0"/>
+      <radius val="0.01"/>
+      <height val="0.03"/>
+    </cylinder>
+    <algebra val="cyl-approx"/>
+  </type>
+  <!--DETECTOR IDs-->
+  <idlist idname="detectors">
+    <id end="2047" start="0"/>
+  </idlist>
+  <!--DETECTOR PARAMETERS-->
+  <component-link name="detectors">
+    <parameter name="tube_pressure">
+      <value units="atm" val="6.0"/>
+    </parameter>
+    <parameter name="tube_thickness">
+      <value units="metre" val="0.0008"/>
+    </parameter>
+    <parameter name="tube_temperature">
+      <value units="K" val="290.0"/>
+    </parameter>
+  </component-link>
+</instrument>
diff --git a/instrument/NOW4_Parameters.xml b/instrument/NOW4_Parameters.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77935f2bfe0b9173a017b941e8ea3a3003de2c27
--- /dev/null
+++ b/instrument/NOW4_Parameters.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<parameter-file instrument="NOW4" valid-from="2011-10-10T00:00:00">
+
+	<component-link name="NOW4">
+
+		<parameter name="deltaE-mode" type="string">
+			<value val="direct" />
+		</parameter>
+
+		<parameter name="ei-mon1-spec">
+			<value val="2" />
+		</parameter>
+
+		<parameter name="ei-mon2-spec">
+			<value val="3" />
+		</parameter>
+
+		<!-- TODO: Update with real vanadium mass -->
+		<parameter name="vanadium-mass">
+			<value val="-1" />
+		</parameter>
+
+		<parameter name="bkgd-range-min">
+			<value val="30000" />
+		</parameter>
+
+		<parameter name="bkgd-range-max">
+			<value val="31500" />
+		</parameter>
+
+		<parameter name="scale-factor">
+			<value val="1.0" />
+		</parameter>
+
+		<parameter name="monovan-integr-min">
+			<value val="-1" />
+		</parameter>
+
+		<parameter name="monovan-integr-max">
+			<value val="1" />
+		</parameter>
+
+		<!-- Diagnostic test defaults -->
+
+		<!-- Absolute lo threshold for vanadium diag (tiny) -->
+		<parameter name="diag_tiny">
+		  <value val="1e-10"/>
+		</parameter>
+
+		<!-- Absolute hi threshold for vanadium diag (huge) -->
+		<parameter name="diag_huge">
+		  <value val="1e10"/>
+		</parameter>
+
+		<!-- Remove zeroes in background (s_zero)-->
+		<parameter name="diag_samp_zero">
+		  <value val="0.0"/>
+		</parameter>
+
+		<!-- Fraction of median to consider counting low for the white beam diag (sv_lo)-->
+		<parameter name="diag_samp_lo">
+		  <value val="0.0"/>
+		</parameter>
+
+		<!-- Fraction of median to consider counting high for the white beam diag (sv_hi)-->
+		<parameter name="diag_samp_hi">
+		  <value val="5.0"/>
+		</parameter>
+
+		<!-- Error criterion as a multiple of error bar for background (sv_sig) -->
+		<parameter name="diag_samp_sig">
+		  <value val="3.3"/>
+		</parameter>
+
+		<!-- Lower bound defining outliers as fraction of median value (v_out_lo)-->
+		<parameter name="diag_van_out_lo">
+		  <value val="0.01"/>
+		</parameter>
+
+		<!-- Upper bound defining outliers as fraction of median value (v_out_hi)-->
+		<parameter name="diag_van_out_hi">
+		  <value val="100."/>
+		</parameter>
+
+		<!-- Fraction of median to consider counting low for the white beam diag (vv_lo)-->
+		<parameter name="diag_van_lo">
+		  <value val="0.1"/>
+		</parameter>
+
+		<!-- Fraction of median to consider counting high for the white beam diag (vv_hi)-->
+		<parameter name="diag_van_hi">
+		  <value val="1.5"/>
+		</parameter>
+
+		<!-- Error criterion as a multiple of error bar for background (vv_sig) -->
+		<parameter name="diag_van_sig">
+		  <value val="3.3"/>
+		</parameter>
+
+		<!-- True if background is to be checked -->
+		<parameter name="check_background">
+		  <value val="0.0"/>
+		</parameter>
+
+		<!-- True if the bleed tests should be run -->
+		<parameter name="diag_bleed_test">
+		  <value val="0.0"/>
+		</parameter>
+
+		<!-- Variation for ratio test with second white beam -->
+		<parameter name="diag_variation">
+		  <value val="1.1"/>
+		</parameter>
+
+		<!-- Absolute units conversion average -->
+
+		<parameter name="monovan_lo_bound">
+			<value val="0.01" />
+		</parameter>
+
+		<parameter name="monovan_hi_bound">
+			<value val="100" />
+		</parameter>
+
+		<parameter name="monovan_lo_frac">
+			<value val="0.8" />
+		</parameter>
+
+		<parameter name="monovan_hi_frac">
+			<value val="1.2" />
+		</parameter>
+
+		<!-- All the following parameters are taken directly from the MARI definition
+			and are WRONG! They are only here for now to get things working -->
+
+		<parameter name="wb-scale-factor">
+			<value val="1.0" />
+		</parameter>
+
+		<parameter name="wb-integr-min">
+			<value val="0.5" />
+		</parameter>
+
+		<parameter name="wb-integr-max">
+			<value val="80" />
+		</parameter>
+
+		<parameter name="norm-mon1-spec">
+			<value val="-3" />
+		</parameter>
+
+		<parameter name="norm-mon1-min">
+			<value val="1000" />
+		</parameter>
+
+		<parameter name="norm-mon1-max">
+			<value val="2000" />
+		</parameter>
+
+		<parameter name="abs-average-min">
+			<value val="1e-10" />
+		</parameter>
+
+		<parameter name="abs-average-max">
+			<value val="1e10" />
+		</parameter>
+
+		<parameter name="abs-median-lbound">
+			<value val="0.01" />
+		</parameter>
+
+		<parameter name="abs-median-ubound">
+			<value val="100" />
+		</parameter>
+
+		<parameter name="abs-median-lo-frac">
+			<value val="0.8" />
+		</parameter>
+
+		<parameter name="abs-median-hi-frac">
+			<value val="1.2" />
+		</parameter>
+
+		<parameter name="abs-median-signif">
+			<value val="3.3" />
+		</parameter>
+
+		<!--   formula for t0 calculation. See http://muparser.sourceforge.net/mup_features.html#idDef2 for available operators-->
+		<parameter name="t0_formula" type="string">
+			<value val="4.0 + (107.0 / (1.0 + (incidentEnergy / 31.0)^3))" />
+		</parameter>
+
+		<parameter name="treat-background-as-events" type="string">
+			<value val="yes" />
+		</parameter>
+
+	</component-link>
+</parameter-file>
diff --git a/instrument/Schema/IDF/1.0/IDFSchema.xsd b/instrument/Schema/IDF/1.0/IDFSchema.xsd
index c4925ed070949d4fcf04c9ac557660c3b84105ba..4764bda76f826fd2ee68eac4498a97e785b87e0b 100644
--- a/instrument/Schema/IDF/1.0/IDFSchema.xsd
+++ b/instrument/Schema/IDF/1.0/IDFSchema.xsd
@@ -194,7 +194,9 @@
         </xs:complexType>
       </xs:element>
       <xs:element name="description">      
-        <xs:attribute name="is"/>
+        <xs:complexType>
+          <xs:attribute name="is"/>
+        </xs:complexType>
       </xs:element>
       <xs:element name="fixed"/>
       <xs:element name="formula">
diff --git a/qt/CMakeLists.txt b/qt/CMakeLists.txt
index 8ba86e753bc4add79a9a12369a6dca7eb3c07205..258bc792fbd5e5881309d718b296bc0b54b1ba06 100644
--- a/qt/CMakeLists.txt
+++ b/qt/CMakeLists.txt
@@ -16,7 +16,7 @@ if(ENABLE_WORKBENCH AND NOT PYRCC5_CMD)
         ${PYTHON_EXECUTABLE}
         -m
         PyQt5.pyrcc_main
-        CACHE string "Command line to use to run the PyQt5 resource compiler")
+        CACHE STRING "Command line to use to run the PyQt5 resource compiler")
   else()
     find_file(PYRCC5_CMD "pyrcc5")
     if(NOT PYRCC5_CMD)
diff --git a/qt/applications/workbench/workbench/app/mainwindow.py b/qt/applications/workbench/workbench/app/mainwindow.py
index b4dc787f43e1ec4255e31ac1dafcda8fcbdf495c..14fa70eb2c0e588ed3c3339cd460e8c0c854b989 100644
--- a/qt/applications/workbench/workbench/app/mainwindow.py
+++ b/qt/applications/workbench/workbench/app/mainwindow.py
@@ -727,11 +727,19 @@ class MainWindow(QMainWindow):
 
 
 def initialize():
-    """Perform an initialization of the application instance. Most notably
-    this patches sys.exit so that it does nothing.
+    """Perform an initialization of the application instance.
+
+        - Patches sys.exit so that it does nothing.
+        - Uses WindowsSelectorEventLoop required by Tornado
 
     :return: A reference to the existing application instance
     """
+    if sys.version_info.major >= 3 and sys.platform == 'win32':
+        # Tornado requires WindowsSelectorEventLoop
+        # https://www.tornadoweb.org/en/stable/#installation
+        import asyncio
+        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
+
     app = qapplication()
 
     # Monkey patching sys.exit so users can't kill
diff --git a/qt/python/mantidqt/_common.sip b/qt/python/mantidqt/_common.sip
index 0717cc0acd19d6bfabe76c31f3d64803d6eed19c..ffee4cf80aba2f1a764d0eb4b448f101620e70bc 100644
--- a/qt/python/mantidqt/_common.sip
+++ b/qt/python/mantidqt/_common.sip
@@ -887,6 +887,7 @@ public:
     QString getText();
     QString getFirstFilename() const;
     void isForRunFiles(bool /*mode*/);
+    void isForDirectory(bool /*mode*/);
     bool isSearching() const;
     bool isValid();
     void liveButtonSetChecked(bool);
diff --git a/qt/python/mantidqt/project/plotsloader.py b/qt/python/mantidqt/project/plotsloader.py
index ee19bf7431345972275de710401a2f97fd7f6eb3..309998423ad26e10d528cf38546021858f0e1b0e 100644
--- a/qt/python/mantidqt/project/plotsloader.py
+++ b/qt/python/mantidqt/project/plotsloader.py
@@ -239,19 +239,19 @@ class PlotsLoader(object):
 
     def update_axis(self, axis_, properties):
         if isinstance(axis_, matplotlib.axis.XAxis):
-            if properties["position"] is "top":
+            if properties["position"] == "top":
                 axis_.tick_top()
             else:
                 axis_.tick_bottom()
 
         if isinstance(axis_, matplotlib.axis.YAxis):
-            if properties["position"] is "right":
+            if properties["position"] == "right":
                 axis_.tick_right()
             else:
                 axis_.tick_left()
 
         labels = axis_.get_ticklabels()
-        if properties["fontSize"] is not "":
+        if properties["fontSize"] != "":
             for label in labels:
                 label.set_fontsize(properties["fontSize"])
 
@@ -276,17 +276,17 @@ class PlotsLoader(object):
     @staticmethod
     def update_axis_ticks(axis_, properties):
         # Update Major and Minor Locator
-        if properties["majorTickLocator"] is "FixedLocator":
+        if properties["majorTickLocator"] == "FixedLocator":
             axis_.set_major_locator(ticker.FixedLocator(properties["majorTickLocatorValues"]))
 
-        if properties["minorTickLocator"] is "FixedLocator":
+        if properties["minorTickLocator"] == "FixedLocator":
             axis_.set_minor_locator(ticker.FixedLocator(properties["minorTickLocatorValues"]))
 
         # Update Major and Minor Formatter
-        if properties["majorTickFormatter"] is "FixedFormatter":
+        if properties["majorTickFormatter"] == "FixedFormatter":
             axis_.set_major_formatter(ticker.FixedFormatter(properties["majorTickFormat"]))
 
-        if properties["minorTickFormatter"] is "FixedFormatter":
+        if properties["minorTickFormatter"] == "FixedFormatter":
             axis_.set_major_formatter(ticker.FixedLocator(properties["minorTickFormat"]))
 
     @staticmethod
diff --git a/qt/scientific_interfaces/Direct/ALFView_model.cpp b/qt/scientific_interfaces/Direct/ALFCustomInstrumentModel.cpp
similarity index 87%
rename from qt/scientific_interfaces/Direct/ALFView_model.cpp
rename to qt/scientific_interfaces/Direct/ALFCustomInstrumentModel.cpp
index f8bcd2fa4c7e06e39bbfc8886d83856cafa83ae7..f2c58b4ef21f1451801fc795c131c21445b6db8b 100644
--- a/qt/scientific_interfaces/Direct/ALFView_model.cpp
+++ b/qt/scientific_interfaces/Direct/ALFCustomInstrumentModel.cpp
@@ -5,15 +5,13 @@
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
 
-#include "ALFView_model.h"
+#include "ALFCustomInstrumentModel.h"
 #include "MantidAPI/Algorithm.h"
 #include "MantidAPI/AlgorithmManager.h"
 #include "MantidAPI/AnalysisDataService.h"
 #include "MantidAPI/MatrixWorkspace.h"
 #include "MantidAPI/NumericAxis.h"
-
 #include "MantidGeometry/Instrument.h"
-
 #include "MantidKernel/Unit.h"
 
 #include <utility>
@@ -27,7 +25,8 @@ using namespace Mantid::API;
 namespace MantidQt {
 namespace CustomInterfaces {
 
-ALFView_model::ALFView_model() : m_numberOfTubesInAverage(0) {
+ALFCustomInstrumentModel::ALFCustomInstrumentModel()
+    : m_numberOfTubesInAverage(0) {
   m_tmpName = "ALF_tmp";
   m_instrumentName = "ALF";
   m_wsName = "ALFData";
@@ -40,7 +39,8 @@ ALFView_model::ALFView_model() : m_numberOfTubesInAverage(0) {
  * @param name:: string name for ALF data
  * @return std::pair<int,std::string>:: the run number and status
  */
-std::pair<int, std::string> ALFView_model::loadData(const std::string &name) {
+std::pair<int, std::string>
+ALFCustomInstrumentModel::loadData(const std::string &name) {
   auto alg = AlgorithmManager::Instance().create("Load");
   alg->initialize();
   alg->setProperty("Filename", name);
@@ -69,7 +69,7 @@ std::pair<int, std::string> ALFView_model::loadData(const std::string &name) {
  * Loads data, normalise to current and then converts to d spacing
  * @return pair<bool,bool>:: If the instrument is ALF, if it is d-spacing
  */
-std::map<std::string, bool> ALFView_model::isDataValid() {
+std::map<std::string, bool> ALFCustomInstrumentModel::isDataValid() {
   auto ws =
       AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(m_tmpName);
   bool isItALF = false;
@@ -90,7 +90,7 @@ std::map<std::string, bool> ALFView_model::isDataValid() {
  * Transforms ALF data; normalise to current and then converts to d spacing
  * If already d-space does nothing.
  */
-void ALFView_model::transformData() {
+void ALFCustomInstrumentModel::transformData() {
   auto normAlg = AlgorithmManager::Instance().create("NormaliseByCurrent");
   normAlg->initialize();
   normAlg->setProperty("InputWorkspace", m_wsName);
@@ -105,7 +105,7 @@ void ALFView_model::transformData() {
   dSpacingAlg->execute();
 }
 
-void ALFView_model::storeSingleTube(const std::string &name) {
+void ALFCustomInstrumentModel::storeSingleTube(const std::string &name) {
   auto alg = AlgorithmManager::Instance().create("ScaleX");
   alg->initialize();
   alg->setProperty("InputWorkspace", CURVES);
@@ -122,12 +122,12 @@ void ALFView_model::storeSingleTube(const std::string &name) {
   AnalysisDataService::Instance().remove(CURVES);
 }
 
-std::string ALFView_model::WSName() {
+std::string ALFCustomInstrumentModel::WSName() {
   std::string name = m_instrumentName + std::to_string(getCurrentRun());
   return EXTRACTEDWS + name;
 }
 
-void ALFView_model::averageTube() {
+void ALFCustomInstrumentModel::averageTube() {
   const std::string name = m_instrumentName + std::to_string(getCurrentRun());
   const int oldTotalNumber = m_numberOfTubesInAverage;
   // multiply up current average
@@ -160,11 +160,12 @@ void ALFView_model::averageTube() {
   m_numberOfTubesInAverage++;
 }
 
-bool ALFView_model::hasTubeBeenExtracted(const std::string &name) {
+bool ALFCustomInstrumentModel::hasTubeBeenExtracted(const std::string &name) {
   return AnalysisDataService::Instance().doesExist(EXTRACTEDWS + name);
 }
 
-bool ALFView_model::extractTubeConditon(std::map<std::string, bool> tabBools) {
+bool ALFCustomInstrumentModel::extractTubeConditon(
+    std::map<std::string, bool> tabBools) {
   try {
 
     bool ifCurve = (tabBools.find("plotStored")->second ||
@@ -175,7 +176,8 @@ bool ALFView_model::extractTubeConditon(std::map<std::string, bool> tabBools) {
   }
 }
 
-bool ALFView_model::averageTubeConditon(std::map<std::string, bool> tabBools) {
+bool ALFCustomInstrumentModel::averageTubeConditon(
+    std::map<std::string, bool> tabBools) {
   try {
 
     bool ifCurve = (tabBools.find("plotStored")->second ||
@@ -188,12 +190,12 @@ bool ALFView_model::averageTubeConditon(std::map<std::string, bool> tabBools) {
     return false;
   }
 }
-void ALFView_model::extractSingleTube() {
+void ALFCustomInstrumentModel::extractSingleTube() {
   storeSingleTube(m_instrumentName + std::to_string(getCurrentRun()));
   m_numberOfTubesInAverage = 1;
 }
 
-CompositeFunction_sptr ALFView_model::getDefaultFunction() {
+CompositeFunction_sptr ALFCustomInstrumentModel::getDefaultFunction() {
 
   CompositeFunction_sptr composite =
       boost::dynamic_pointer_cast<Mantid::API::CompositeFunction>(
diff --git a/qt/scientific_interfaces/Direct/ALFView_model.h b/qt/scientific_interfaces/Direct/ALFCustomInstrumentModel.h
similarity index 71%
rename from qt/scientific_interfaces/Direct/ALFView_model.h
rename to qt/scientific_interfaces/Direct/ALFCustomInstrumentModel.h
index 63b1f779fd85daf98943adef01ef20a541127ad1..74a357ef1fd0fc32d26d5e709b851884953abf85 100644
--- a/qt/scientific_interfaces/Direct/ALFView_model.h
+++ b/qt/scientific_interfaces/Direct/ALFCustomInstrumentModel.h
@@ -4,12 +4,12 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#ifndef MANTIDQT_CUSTOMINTERFACES_ALFVIEWMODEL_H_
-#define MANTIDQT_CUSTOMINTERFACES_ALFVIEWMODEL_H_
+#ifndef MANTIDQT_CUSTOMINTERFACES_ALFCUSTOMINSTRUMENTMODEL_H_
+#define MANTIDQT_CUSTOMINTERFACES_ALFCUSTOMINSTRUMENTMODEL_H_
 
-#include "BaseInstrumentModel.h"
 #include "MantidAPI/CompositeFunction.h"
 #include "MantidAPI/FunctionFactory.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentModel.h"
 
 #include <map>
 #include <string>
@@ -17,11 +17,12 @@
 namespace MantidQt {
 namespace CustomInterfaces {
 
-class ALFView_model : public BaseInstrumentModel {
+class ALFCustomInstrumentModel
+    : public MantidWidgets::BaseCustomInstrumentModel {
 
 public:
-  ALFView_model();
-  virtual ~ALFView_model(){};
+  ALFCustomInstrumentModel();
+  virtual ~ALFCustomInstrumentModel(){};
   std::pair<int, std::string> loadData(const std::string &name) override;
   std::map<std::string, bool> isDataValid();
   void transformData();
@@ -41,4 +42,4 @@ private:
 } // namespace CustomInterfaces
 } // namespace MantidQt
 
-#endif /* MANTIDQT_CUSTOMINTERFACES_ALFVIEWMODEL_H_ */
+#endif /* MANTIDQT_CUSTOMINTERFACES_ALFCUSTOMINSTRUMENTMODEL_H_ */
diff --git a/qt/scientific_interfaces/Direct/ALFView_presenter.cpp b/qt/scientific_interfaces/Direct/ALFCustomInstrumentPresenter.cpp
similarity index 72%
rename from qt/scientific_interfaces/Direct/ALFView_presenter.cpp
rename to qt/scientific_interfaces/Direct/ALFCustomInstrumentPresenter.cpp
index baf5f8f77816675e5fe072f9e4c0a03d6e2bd5d3..c9f23955d076313a00d7ddb66a27d2ba2446e292 100644
--- a/qt/scientific_interfaces/Direct/ALFView_presenter.cpp
+++ b/qt/scientific_interfaces/Direct/ALFCustomInstrumentPresenter.cpp
@@ -4,11 +4,11 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#include "ALFView_presenter.h"
-#include "ALFView_model.h"
-#include "ALFView_view.h"
-
+#include "ALFCustomInstrumentPresenter.h"
+#include "ALFCustomInstrumentModel.h"
+#include "ALFCustomInstrumentView.h"
 #include "MantidAPI/FileFinder.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPanePresenter.h"
 
 #include <functional>
 #include <tuple>
@@ -16,26 +16,29 @@
 namespace MantidQt {
 namespace CustomInterfaces {
 
-ALFView_presenter::ALFView_presenter(ALFView_view *view, ALFView_model *model,
-                                     PlotFitAnalysisPanePresenter *analysisPane)
-    : BaseInstrumentPresenter(view, model, analysisPane->getView()),
+ALFCustomInstrumentPresenter::ALFCustomInstrumentPresenter(
+    ALFCustomInstrumentView *view, ALFCustomInstrumentModel *model,
+    MantidWidgets::PlotFitAnalysisPanePresenter *analysisPane)
+    : BaseCustomInstrumentPresenter(view, model, analysisPane->getView()),
       m_view(view), m_model(model), m_analysisPane(analysisPane),
       m_extractSingleTubeObserver(nullptr), m_averageTubeObserver(nullptr) {
   addInstrument();
 }
 
-void ALFView_presenter::addInstrument() {
+void ALFCustomInstrumentPresenter::addInstrument() {
   auto setUp = setupALFInstrument();
   initLayout(&setUp);
 }
 
-void ALFView_presenter::setUpInstrumentAnalysisSplitter() {
+void ALFCustomInstrumentPresenter::setUpInstrumentAnalysisSplitter() {
   CompositeFunction_sptr composite = m_model->getDefaultFunction();
   m_analysisPane->addFunction(composite);
   m_view->setupAnalysisPane(m_analysisPane->getView());
 }
 
-void ALFView_presenter::loadSideEffects() { m_analysisPane->clearCurrentWS(); }
+void ALFCustomInstrumentPresenter::loadSideEffects() {
+  m_analysisPane->clearCurrentWS();
+}
 
 typedef std::pair<std::string,
                   std::vector<std::function<bool(std::map<std::string, bool>)>>>
@@ -49,7 +52,7 @@ typedef std::vector<std::tuple<std::string, Observer *>>
     instrumentObserverOptions> : a pair of the conditions and observers
 */
 std::pair<instrumentSetUp, instrumentObserverOptions>
-ALFView_presenter::setupALFInstrument() {
+ALFCustomInstrumentPresenter::setupALFInstrument() {
 
   m_extractSingleTubeObserver = new VoidObserver();
   m_averageTubeObserver = new VoidObserver();
@@ -62,10 +65,10 @@ ALFView_presenter::setupALFInstrument() {
 
   // set up custom context menu conditions
   std::function<bool(std::map<std::string, bool>)> extractConditionBinder =
-      std::bind(&ALFView_model::extractTubeConditon, m_model,
+      std::bind(&ALFCustomInstrumentModel::extractTubeConditon, m_model,
                 std::placeholders::_1);
   std::function<bool(std::map<std::string, bool>)> averageTubeConditonBinder =
-      std::bind(&ALFView_model::averageTubeConditon, m_model,
+      std::bind(&ALFCustomInstrumentModel::averageTubeConditon, m_model,
                 std::placeholders::_1);
 
   binders.emplace_back(extractConditionBinder);
@@ -75,7 +78,8 @@ ALFView_presenter::setupALFInstrument() {
 
   // set up single tube extract
   std::function<void()> extractSingleTubeBinder =
-      std::bind(&ALFView_presenter::extractSingleTube, this); // binder for slot
+      std::bind(&ALFCustomInstrumentPresenter::extractSingleTube,
+                this); // binder for slot
   m_extractSingleTubeObserver->setSlot(
       extractSingleTubeBinder); // add slot to observer
   std::tuple<std::string, Observer *> tmp = std::make_tuple(
@@ -84,7 +88,7 @@ ALFView_presenter::setupALFInstrument() {
 
   // set up average tube
   std::function<void()> averageTubeBinder =
-      std::bind(&ALFView_presenter::averageTube, this);
+      std::bind(&ALFCustomInstrumentPresenter::averageTube, this);
   m_averageTubeObserver->setSlot(averageTubeBinder);
   tmp = std::make_tuple("averageTube", m_averageTubeObserver);
   customInstrumentOptions.emplace_back(tmp);
@@ -92,13 +96,13 @@ ALFView_presenter::setupALFInstrument() {
   return std::make_pair(setUpContextConditions, customInstrumentOptions);
 }
 
-void ALFView_presenter::extractSingleTube() {
+void ALFCustomInstrumentPresenter::extractSingleTube() {
   m_model->extractSingleTube();
   const std::string WSName = m_model->WSName();
   m_analysisPane->addSpectrum(WSName);
 }
 
-void ALFView_presenter::averageTube() {
+void ALFCustomInstrumentPresenter::averageTube() {
   m_model->averageTube();
   const std::string WSName = m_model->WSName();
   m_analysisPane->addSpectrum(WSName);
diff --git a/qt/scientific_interfaces/Direct/ALFView_presenter.h b/qt/scientific_interfaces/Direct/ALFCustomInstrumentPresenter.h
similarity index 53%
rename from qt/scientific_interfaces/Direct/ALFView_presenter.h
rename to qt/scientific_interfaces/Direct/ALFCustomInstrumentPresenter.h
index 0df7153dc00583160557040bfb3b8360e958df58..b32512fdb98b0e309cae39583ae88f731960edb2 100644
--- a/qt/scientific_interfaces/Direct/ALFView_presenter.h
+++ b/qt/scientific_interfaces/Direct/ALFCustomInstrumentPresenter.h
@@ -4,30 +4,31 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#ifndef MANTIDQT_CUSTOMINTERFACES_ALFVIEWPRESENTER_H_
-#define MANTIDQT_CUSTOMINTERFACES_ALFVIEWPRESENTER_H_
+#ifndef MANTIDQT_CUSTOMINTERFACES_ALFCUSTOMINSTRUMENTPRESENTER_H_
+#define MANTIDQT_CUSTOMINTERFACES_ALFCUSTOMINSTRUMENTPRESENTER_H_
 
-#include "BaseInstrumentPresenter.h"
-#include "PlotFitAnalysisPanePresenter.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentPresenter.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPanePresenter.h"
 
-#include "ALFView_model.h"
-#include "ALFView_view.h"
+#include "ALFCustomInstrumentModel.h"
+#include "ALFCustomInstrumentView.h"
 #include "DllConfig.h"
 #include "MantidQtWidgets/Common/ObserverPattern.h"
-#include "MantidQtWidgets/Common/UserSubWindow.h"
 
 #include <string>
 
 namespace MantidQt {
 namespace CustomInterfaces {
 
-class MANTIDQT_DIRECT_DLL ALFView_presenter : public BaseInstrumentPresenter {
+class MANTIDQT_DIRECT_DLL ALFCustomInstrumentPresenter
+    : public MantidWidgets::BaseCustomInstrumentPresenter {
   Q_OBJECT
 
 public:
-  ALFView_presenter(ALFView_view *view, ALFView_model *model,
-                    PlotFitAnalysisPanePresenter *analysisPane);
-  ~ALFView_presenter() {
+  ALFCustomInstrumentPresenter(
+      ALFCustomInstrumentView *view, ALFCustomInstrumentModel *model,
+      MantidWidgets::PlotFitAnalysisPanePresenter *analysisPane);
+  ~ALFCustomInstrumentPresenter() {
     delete m_extractSingleTubeObserver;
     delete m_averageTubeObserver;
     delete m_analysisPane;
@@ -47,13 +48,13 @@ private:
   void extractSingleTube();
   void averageTube();
 
-  ALFView_view *m_view;
-  ALFView_model *m_model;
-  PlotFitAnalysisPanePresenter *m_analysisPane;
+  ALFCustomInstrumentView *m_view;
+  ALFCustomInstrumentModel *m_model;
+  MantidWidgets::PlotFitAnalysisPanePresenter *m_analysisPane;
   VoidObserver *m_extractSingleTubeObserver;
   VoidObserver *m_averageTubeObserver;
 };
 } // namespace CustomInterfaces
 } // namespace MantidQt
 
-#endif /* MANTIDQT_CUSTOMINTERFACES_ALFVIEWPRESENTER_H_ */
+#endif /* MANTIDQT_CUSTOMINTERFACES_ALFCUSTOMINSTRUMENTPRESENTER_H_ */
diff --git a/qt/scientific_interfaces/Direct/ALFView_view.cpp b/qt/scientific_interfaces/Direct/ALFCustomInstrumentView.cpp
similarity index 75%
rename from qt/scientific_interfaces/Direct/ALFView_view.cpp
rename to qt/scientific_interfaces/Direct/ALFCustomInstrumentView.cpp
index 32249d588a5fc244de039e7ccaac165726054eed..5ef3f7d3a3cec1271da1678b396c76b57468190f 100644
--- a/qt/scientific_interfaces/Direct/ALFView_view.cpp
+++ b/qt/scientific_interfaces/Direct/ALFCustomInstrumentView.cpp
@@ -4,7 +4,7 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#include "ALFView_view.h"
+#include "ALFCustomInstrumentView.h"
 #include "MantidQtWidgets/InstrumentView/InstrumentWidgetPickTab.h"
 
 #include <QMessageBox>
@@ -15,15 +15,16 @@
 namespace MantidQt {
 namespace CustomInterfaces {
 
-ALFView_view::ALFView_view(const std::string &instrument, QWidget *parent)
-    : BaseInstrumentView(instrument, parent),
+ALFCustomInstrumentView::ALFCustomInstrumentView(const std::string &instrument,
+                                                 QWidget *parent)
+    : MantidWidgets::BaseCustomInstrumentView(instrument, parent),
       m_extractSingleTubeObservable(nullptr), m_averageTubeObservable(nullptr),
       m_extractAction(nullptr), m_averageAction(nullptr),
       m_analysisPane(nullptr) {
   m_helpPage = "ALF View";
 }
 
-void ALFView_view::setUpInstrument(
+void ALFCustomInstrumentView::setUpInstrument(
     const std::string &fileName,
     std::vector<std::function<bool(std::map<std::string, bool>)>> &binders) {
 
@@ -52,27 +53,28 @@ void ALFView_view::setUpInstrument(
   setInstrumentWidget(instrumentWidget);
 }
 
-void ALFView_view::extractSingleTube() {
+void ALFCustomInstrumentView::extractSingleTube() {
   MantidWidgets::InstrumentWidget *instrumentView = getInstrumentView();
   instrumentView->getPickTab()->savePlotToWorkspace();
 
   m_extractSingleTubeObservable->notify();
 }
 
-void ALFView_view::averageTube() {
+void ALFCustomInstrumentView::averageTube() {
   MantidWidgets::InstrumentWidget *instrumentView = getInstrumentView();
   instrumentView->getPickTab()->savePlotToWorkspace();
   m_averageTubeObservable->notify();
 }
 
-void ALFView_view::observeExtractSingleTube(Observer *listner) {
+void ALFCustomInstrumentView::observeExtractSingleTube(Observer *listner) {
   m_extractSingleTubeObservable->attach(listner);
 }
-void ALFView_view::observeAverageTube(Observer *listner) {
+void ALFCustomInstrumentView::observeAverageTube(Observer *listner) {
   m_averageTubeObservable->attach(listner);
 }
 
-void ALFView_view::addObserver(std::tuple<std::string, Observer *> &listener) {
+void ALFCustomInstrumentView::addObserver(
+    std::tuple<std::string, Observer *> &listener) {
   if (std::get<0>(listener) == "singleTube") {
     observeExtractSingleTube(std::get<1>(listener));
   } else if (std::get<0>(listener) == "averageTube") {
@@ -80,14 +82,15 @@ void ALFView_view::addObserver(std::tuple<std::string, Observer *> &listener) {
   }
 }
 
-void ALFView_view::setupAnalysisPane(PlotFitAnalysisPaneView *analysis) {
+void ALFCustomInstrumentView::setupAnalysisPane(
+    MantidWidgets::PlotFitAnalysisPaneView *analysis) {
   // keep a copy here so we can use a custom class
   m_analysisPane = analysis;
   // just adds it to the view
-  BaseInstrumentView::setupInstrumentAnalysisSplitters(analysis);
+  BaseCustomInstrumentView::setupInstrumentAnalysisSplitters(analysis);
 }
 
-void ALFView_view::addSpectrum(std::string wsName) {
+void ALFCustomInstrumentView::addSpectrum(std::string wsName) {
   m_analysisPane->addSpectrum(wsName);
 }
 
diff --git a/qt/scientific_interfaces/Direct/ALFView_view.h b/qt/scientific_interfaces/Direct/ALFCustomInstrumentView.h
similarity index 64%
rename from qt/scientific_interfaces/Direct/ALFView_view.h
rename to qt/scientific_interfaces/Direct/ALFCustomInstrumentView.h
index e77c1dc68f4a26110acb0314c73d7e570ed133f8..7b86bc56ca51ce479e1e1629548bc5dc4dcc05aa 100644
--- a/qt/scientific_interfaces/Direct/ALFView_view.h
+++ b/qt/scientific_interfaces/Direct/ALFCustomInstrumentView.h
@@ -4,15 +4,14 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#ifndef MANTIDQT_CUSTOMINTERFACES_ALFVIEW_VIEW_H_
-#define MANTIDQT_CUSTOMINTERFACES_ALFVIEW_VIEW_H_
+#ifndef MANTIDQT_CUSTOMINTERFACES_ALFCustomInstrumentView_H_
+#define MANTIDQT_CUSTOMINTERFACES_ALFCustomInstrumentView_H_
 
-#include "BaseInstrumentView.h"
 #include "DllConfig.h"
 #include "MantidQtWidgets/Common/MWRunFiles.h"
 #include "MantidQtWidgets/Common/ObserverPattern.h"
-#include "MantidQtWidgets/InstrumentView/InstrumentWidget.h"
-#include "PlotFitAnalysisPaneView.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentView.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneView.h"
 
 #include <QObject>
 #include <QSplitter>
@@ -22,12 +21,12 @@
 namespace MantidQt {
 namespace CustomInterfaces {
 
-class ALFView_view : public BaseInstrumentView {
+class ALFCustomInstrumentView : public MantidWidgets::BaseCustomInstrumentView {
   Q_OBJECT
 
 public:
-  explicit ALFView_view(const std::string &instrument,
-                        QWidget *parent = nullptr);
+  explicit ALFCustomInstrumentView(const std::string &instrument,
+                                   QWidget *parent = nullptr);
   void observeExtractSingleTube(Observer *listner);
   void observeAverageTube(Observer *listner);
 
@@ -38,7 +37,7 @@ public:
 
   void addObserver(std::tuple<std::string, Observer *> &listener) override;
   void addSpectrum(std::string wsName);
-  void setupAnalysisPane(PlotFitAnalysisPaneView *analysis);
+  void setupAnalysisPane(MantidWidgets::PlotFitAnalysisPaneView *analysis);
 
 public slots:
   void extractSingleTube();
@@ -49,9 +48,9 @@ private:
   Observable *m_averageTubeObservable;
   QAction *m_extractAction;
   QAction *m_averageAction;
-  PlotFitAnalysisPaneView *m_analysisPane;
+  MantidWidgets::PlotFitAnalysisPaneView *m_analysisPane;
 };
 } // namespace CustomInterfaces
 } // namespace MantidQt
 
-#endif /* MANTIDQT_CUSTOMINTERFACES_ALFVIEW_VIEW_H_ */
+#endif /* MANTIDQT_CUSTOMINTERFACES_ALFCustomInstrumentView_H_ */
diff --git a/qt/scientific_interfaces/Direct/ALFView.cpp b/qt/scientific_interfaces/Direct/ALFView.cpp
index 90589ae8d91dd75eab67674124a0416b82c871d5..995675fab20546892f17a037ac155605451712d8 100644
--- a/qt/scientific_interfaces/Direct/ALFView.cpp
+++ b/qt/scientific_interfaces/Direct/ALFView.cpp
@@ -4,20 +4,12 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#include "ALFView_model.h"
-#include "ALFView_presenter.h"
-#include "PlotFitAnalysisPaneModel.h"
-#include "PlotFitAnalysisPaneView.h"
-
-#include "BaseInstrumentModel.h"
-#include "BaseInstrumentView.h"
-// will need these later
-#include "MantidQtWidgets/Common/FunctionBrowser.h"
-#include "MantidQtWidgets/InstrumentView/InstrumentWidget.h"
-#include "MantidQtWidgets/InstrumentView/InstrumentWidgetPickTab.h"
-#include "MantidQtWidgets/Plotting/PreviewPlot.h"
-
 #include "ALFView.h"
+#include "ALFCustomInstrumentModel.h"
+#include "ALFCustomInstrumentPresenter.h"
+
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneModel.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneView.h"
 
 #include <tuple>
 
@@ -32,14 +24,16 @@ Mantid::Kernel::Logger g_log("ALFView");
 ALFView::ALFView(QWidget *parent)
     : UserSubWindow(parent), m_view(nullptr), m_presenter(nullptr),
       m_analysisPane(nullptr) {
-  m_model = new ALFView_model();
-  m_view = new ALFView_view(m_model->getInstrument(), this);
-  auto analysisView = new PlotFitAnalysisPaneView(-15.0, 15.0, m_view);
-  auto analysisModel = new PlotFitAnalysisPaneModel();
-  m_analysisPane =
-      new PlotFitAnalysisPanePresenter(analysisView, analysisModel);
-
-  m_presenter = new ALFView_presenter(m_view, m_model, m_analysisPane);
+  m_model = new ALFCustomInstrumentModel();
+  m_view = new ALFCustomInstrumentView(m_model->getInstrument(), this);
+  auto analysisView =
+      new MantidWidgets::PlotFitAnalysisPaneView(-15.0, 15.0, m_view);
+  auto analysisModel = new MantidWidgets::PlotFitAnalysisPaneModel();
+  m_analysisPane = new MantidWidgets::PlotFitAnalysisPanePresenter(
+      analysisView, analysisModel);
+
+  m_presenter =
+      new ALFCustomInstrumentPresenter(m_view, m_model, m_analysisPane);
 }
 void ALFView::initLayout() { this->setCentralWidget(m_view); }
 
diff --git a/qt/scientific_interfaces/Direct/ALFView.h b/qt/scientific_interfaces/Direct/ALFView.h
index 4b21df8b79d66a5e3c514c4e7c6f7ed5f3b98b86..98fc97308ea4395e3d57c919489c1815e5d47b3b 100644
--- a/qt/scientific_interfaces/Direct/ALFView.h
+++ b/qt/scientific_interfaces/Direct/ALFView.h
@@ -7,15 +7,13 @@
 #ifndef MANTIDQT_CUSTOMINTERFACES_ALFVIEW_H_
 #define MANTIDQT_CUSTOMINTERFACES_ALFVIEW_H_
 
-#include "ALFView_model.h"
-#include "ALFView_presenter.h"
-#include "ALFView_view.h"
+#include "ALFCustomInstrumentModel.h"
+#include "ALFCustomInstrumentPresenter.h"
+#include "ALFCustomInstrumentView.h"
 #include "DllConfig.h"
 #include "MantidQtWidgets/Common/ObserverPattern.h"
 #include "MantidQtWidgets/Common/UserSubWindow.h"
-
-#include "PlotFitAnalysisPanePresenter.h"
-#include "PlotFitAnalysisPaneView.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPanePresenter.h"
 
 namespace MantidQt {
 namespace CustomInterfaces {
@@ -34,10 +32,10 @@ protected:
   void initLayout() override;
 
 private:
-  ALFView_view *m_view;
-  ALFView_model *m_model;
-  ALFView_presenter *m_presenter;
-  PlotFitAnalysisPanePresenter *m_analysisPane;
+  ALFCustomInstrumentView *m_view;
+  ALFCustomInstrumentModel *m_model;
+  ALFCustomInstrumentPresenter *m_presenter;
+  MantidWidgets::PlotFitAnalysisPanePresenter *m_analysisPane;
 };
 } // namespace CustomInterfaces
 } // namespace MantidQt
diff --git a/qt/scientific_interfaces/Direct/CMakeLists.txt b/qt/scientific_interfaces/Direct/CMakeLists.txt
index 95b428bc6b408b706f3bce420f375c496963e958..4cc3d153ea8ec7dbc2e253c7cd34b26794c7f552 100644
--- a/qt/scientific_interfaces/Direct/CMakeLists.txt
+++ b/qt/scientific_interfaces/Direct/CMakeLists.txt
@@ -1,24 +1,13 @@
 set(SRC_FILES
     ALFView.cpp
-    ALFView_view.cpp
-    ALFView_presenter.cpp
-    ALFView_model.cpp
-    BaseInstrumentModel.cpp
-    BaseInstrumentView.cpp
-    BaseInstrumentPresenter.cpp
-    PlotFitAnalysisPaneView.cpp
-    PlotFitAnalysisPanePresenter.cpp
-    PlotFitAnalysisPaneModel.cpp)
+    ALFCustomInstrumentView.cpp
+    ALFCustomInstrumentPresenter.cpp
+    ALFCustomInstrumentModel.cpp)
     
 set(MOC_FILES
     ALFView.h
-    ALFView_view.h
-    ALFView_presenter.h
-    BaseInstrumentView.h
-    BaseInstrumentView.h
-    BaseInstrumentPresenter.h
-    PlotFitAnalysisPaneView.h
-    PlotFitAnalysisPanePresenter.h)
+    ALFCustomInstrumentView.h
+    ALFCustomInstrumentPresenter.h)
     
 set(INC_FILES
     DllConfig.h)
@@ -49,8 +38,8 @@ mtd_add_qt_library(TARGET_NAME MantidScientificInterfacesDirect
                      Qwt5
                    MTD_QT_LINK_LIBS
                      MantidQtWidgetsCommon
-                     MantidQtWidgetsPlotting
                      MantidQtWidgetsInstrumentView
+                     MantidQtWidgetsPlotting
                    INSTALL_DIR_BASE
                      ${PLUGINS_DIR}
                    OSX_INSTALL_RPATH
@@ -84,7 +73,7 @@ mtd_add_qt_library(TARGET_NAME MantidScientificInterfacesDirect
                    MTD_QT_LINK_LIBS
                      MantidQtWidgetsCommon
                      MantidQtWidgetsInstrumentView
-					 MantidQtWidgetsPlotting
+                     MantidQtWidgetsPlotting
                      MantidQtWidgetsMplCpp
                    INSTALL_DIR_BASE
                      ${WORKBENCH_PLUGINS_DIR}
diff --git a/qt/scientific_interfaces/Muon/IO_MuonGrouping.cpp b/qt/scientific_interfaces/Muon/IO_MuonGrouping.cpp
index bd085510cecd1cc6e98ffb4912a078ba16d6509e..774ec8026bbce7fb3f86e85eec25780b013edca8 100644
--- a/qt/scientific_interfaces/Muon/IO_MuonGrouping.cpp
+++ b/qt/scientific_interfaces/Muon/IO_MuonGrouping.cpp
@@ -20,7 +20,6 @@
 #include <Poco/DOM/Text.h>
 #include <Poco/XML/XMLWriter.h>
 
-#include <boost/bind.hpp>
 #include <boost/shared_ptr.hpp>
 #include <fstream>
 
diff --git a/qt/scientific_interfaces/test/ISISReflectometry/Common/CoderCommonTester.h b/qt/scientific_interfaces/test/ISISReflectometry/Common/CoderCommonTester.h
index 3db2c579220ead5a2ee87d6f51e059803cab65c5..80cf962c5170f0bff60e2f02200717a686865a8f 100644
--- a/qt/scientific_interfaces/test/ISISReflectometry/Common/CoderCommonTester.h
+++ b/qt/scientific_interfaces/test/ISISReflectometry/Common/CoderCommonTester.h
@@ -295,7 +295,7 @@ private:
     TS_ASSERT_EQUALS(gui->m_ui.tabRadioButton->isChecked(),
                      map[QString("tabRadioButton")].toBool())
     TS_ASSERT_EQUALS(gui->m_ui.fileFormatComboBox->currentIndex(),
-                     map[QString("fileFormatComboBox")].toBool())
+                     map[QString("fileFormatComboBox")].toInt())
     TS_ASSERT_EQUALS(gui->m_ui.filterEdit->text(),
                      map[QString("filterEdit")].toString())
     TS_ASSERT_EQUALS(gui->m_ui.regexCheckBox->isChecked(),
@@ -332,4 +332,4 @@ private:
 } // namespace CustomInterfaces
 } // namespace MantidQt
 
-#endif /* CODER_COMMON_TESTER_H_ */
\ No newline at end of file
+#endif /* CODER_COMMON_TESTER_H_ */
diff --git a/qt/widgets/instrumentview/CMakeLists.txt b/qt/widgets/instrumentview/CMakeLists.txt
index 5140d63e89e4f4505cf7d995a15d27a8b8305d82..806dea6b7d86ab3524c920868d31511cf23b493b 100644
--- a/qt/widgets/instrumentview/CMakeLists.txt
+++ b/qt/widgets/instrumentview/CMakeLists.txt
@@ -6,6 +6,9 @@ set(
   SRC_FILES
   src/BankRenderingHelpers.cpp
   src/BankTextureBuilder.cpp
+  src/BaseCustomInstrumentModel.cpp
+  src/BaseCustomInstrumentView.cpp
+  src/BaseCustomInstrumentPresenter.cpp
   src/BinDialog.cpp
   src/CollapsiblePanel.cpp
   src/DetXMLFile.cpp
@@ -29,6 +32,9 @@ set(
   src/PanelsSurface.cpp
   src/PeakMarker2D.cpp
   src/PeakOverlay.cpp
+  src/PlotFitAnalysisPaneModel.cpp
+  src/PlotFitAnalysisPanePresenter.cpp
+  src/PlotFitAnalysisPaneView.cpp
   src/Projection3D.cpp
   src/ProjectionSurface.cpp
   src/RectF.cpp
@@ -52,6 +58,8 @@ set(QT5_SRC_FILES src/MiniPlotMpl.cpp)
 set(
   MOC_FILES
   inc/MantidQtWidgets/InstrumentView/BinDialog.h
+  inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentPresenter.h
+  inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentView.h
   inc/MantidQtWidgets/InstrumentView/CollapsiblePanel.h
   inc/MantidQtWidgets/InstrumentView/InstrumentActor.h
   inc/MantidQtWidgets/InstrumentView/InstrumentTreeModel.h
@@ -65,6 +73,8 @@ set(
   inc/MantidQtWidgets/InstrumentView/InstrumentWidgetTreeTab.h
   inc/MantidQtWidgets/InstrumentView/MantidGLWidget.h
   inc/MantidQtWidgets/InstrumentView/PeakOverlay.h
+  inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneView.h
+  inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPanePresenter.h
   inc/MantidQtWidgets/InstrumentView/Projection3D.h
   inc/MantidQtWidgets/InstrumentView/ProjectionSurface.h
   inc/MantidQtWidgets/InstrumentView/Shape2DCollection.h
@@ -81,6 +91,9 @@ set(
   INC_FILES
   inc/MantidQtWidgets/InstrumentView/BankRenderingHelpers.h
   inc/MantidQtWidgets/InstrumentView/BankTextureBuilder.h
+  inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentModel.h
+  inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentPresenter.h
+  inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentView.h
   inc/MantidQtWidgets/InstrumentView/BinDialog.h
   inc/MantidQtWidgets/InstrumentView/CollapsiblePanel.h
   inc/MantidQtWidgets/InstrumentView/ColorMap.h
@@ -108,6 +121,9 @@ set(
   inc/MantidQtWidgets/InstrumentView/PanelsSurface.h
   inc/MantidQtWidgets/InstrumentView/PeakMarker2D.h
   inc/MantidQtWidgets/InstrumentView/PeakOverlay.h
+  inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneModel.h
+  inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPanePresenter.h
+  inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneView.h
   inc/MantidQtWidgets/InstrumentView/Projection3D.h
   inc/MantidQtWidgets/InstrumentView/ProjectionSurface.h
   inc/MantidQtWidgets/InstrumentView/RectF.h
@@ -203,6 +219,7 @@ mtd_add_qt_library(TARGET_NAME MantidQtWidgetsInstrumentView
                      Qt5::OpenGL
                    MTD_QT_LINK_LIBS
                      MantidQtWidgetsCommon
+                     MantidQtWidgetsPlotting
                      MantidQtWidgetsMplCpp
                    INSTALL_DIR
                      ${WORKBENCH_LIB_DIR}
diff --git a/qt/scientific_interfaces/Direct/BaseInstrumentModel.h b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentModel.h
similarity index 69%
rename from qt/scientific_interfaces/Direct/BaseInstrumentModel.h
rename to qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentModel.h
index ddf6c6e0a26e2618bbce1c0384aaf947742a1f48..7669ac7266d7e406c2dc2592df89d6cf3d466138 100644
--- a/qt/scientific_interfaces/Direct/BaseInstrumentModel.h
+++ b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentModel.h
@@ -4,19 +4,22 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#ifndef MANTIDQT_CUSTOMINTERFACES_BASEINSTRUMENTMODEL_H_
-#define MANTIDQT_CUSTOMINTERFACES_BASEINSTRUMENTMODEL_H_
+#ifndef MANTIDQT_INSTRUMENTVIEW_BASECUSTOMINSTRUMENTMODEL_H_
+#define MANTIDQT_INSTRUMENTVIEW_BASECUSTOMINSTRUMENTMODEL_H_
+
+#include "DllOption.h"
+
 #include <map>
 #include <string>
 
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
-class BaseInstrumentModel {
+class EXPORT_OPT_MANTIDQT_INSTRUMENTVIEW BaseCustomInstrumentModel {
 
 public:
-  BaseInstrumentModel();
-  ~BaseInstrumentModel(){};
+  BaseCustomInstrumentModel();
+  ~BaseCustomInstrumentModel(){};
   virtual void loadEmptyInstrument();
   virtual std::pair<int, std::string> loadData(const std::string &name);
   void setCurrentRun(int &run) { m_currentRun = run; };
@@ -35,7 +38,7 @@ protected:
   std::string m_wsName;
 };
 
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
 
-#endif /* MANTIDQT_CUSTOMINTERFACES_BASEINSTRUMENTMODEL_H_ */
+#endif /* MANTIDQT_INSTRUMENTVIEW_BASEINSTRUMENTMODEL_H_ */
diff --git a/qt/scientific_interfaces/Direct/BaseInstrumentPresenter.h b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentPresenter.h
similarity index 60%
rename from qt/scientific_interfaces/Direct/BaseInstrumentPresenter.h
rename to qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentPresenter.h
index b27ff33805cefb1181fcb707de9e64f78b796588..daad1941f388f94a7d55b634cd1ad24f277520b9 100644
--- a/qt/scientific_interfaces/Direct/BaseInstrumentPresenter.h
+++ b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentPresenter.h
@@ -4,30 +4,27 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#ifndef MANTIDQT_CUSTOMINTERFACES_BASEINSTRUMENTPRESENTER_H_
-#define MANTIDQT_CUSTOMINTERFACES_BASEINSTRUMENTPRESENTER_H_
-
-#include "BaseInstrumentModel.h"
-#include "BaseInstrumentView.h"
-#include "PlotFitAnalysisPaneView.h"
-
-#include "ALFView_view.h"
-#include "DllConfig.h"
+#ifndef MANTIDQT_INSTRUMENTVIEW_BASECUSTOMINSTRUMENTPRESENTER_H_
+#define MANTIDQT_INSTRUMENTVIEW_BASECUSTOMINSTRUMENTPRESENTER_H_
+#include "DllOption.h"
 #include "MantidQtWidgets/Common/ObserverPattern.h"
-#include "MantidQtWidgets/Common/UserSubWindow.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentModel.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentView.h"
 
 #include <string>
 
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
-class BaseInstrumentPresenter : public QObject {
+class EXPORT_OPT_MANTIDQT_INSTRUMENTVIEW BaseCustomInstrumentPresenter
+    : public QObject {
   Q_OBJECT
 
 public:
-  BaseInstrumentPresenter(BaseInstrumentView *view, BaseInstrumentModel *model,
-                          QWidget *analysisView);
-  ~BaseInstrumentPresenter() { delete m_loadRunObserver; };
+  BaseCustomInstrumentPresenter(BaseCustomInstrumentView *view,
+                                BaseCustomInstrumentModel *model,
+                                QWidget *analysisView);
+  ~BaseCustomInstrumentPresenter() { delete m_loadRunObserver; };
 
   typedef std::pair<
       std::string,
@@ -53,14 +50,14 @@ private:
   virtual void setUpInstrumentAnalysisSplitter();
   std::pair<instrumentSetUp, instrumentObserverOptions> setupInstrument();
 
-  BaseInstrumentView *m_view;
-  BaseInstrumentModel *m_model;
+  BaseCustomInstrumentView *m_view;
+  BaseCustomInstrumentModel *m_model;
   int m_currentRun;
   std::string m_currentFile;
   VoidObserver *m_loadRunObserver;
   QWidget *m_analysisPaneView;
 };
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
 
-#endif /* MANTIDQT_CUSTOMINTERFACES_BASEINSTRUMENTPRESENTER_H_ */
+#endif /* MANTIDQT_INSTRUMENTVIEW_BaseCustomInstrumentPresenter_H_ */
diff --git a/qt/scientific_interfaces/Direct/BaseInstrumentView.h b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentView.h
similarity index 76%
rename from qt/scientific_interfaces/Direct/BaseInstrumentView.h
rename to qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentView.h
index 6789c6522ac6914537a394e89d7b5b7bdcf1f164..b1ad37f0995c23c9261bd386b2c7ea82f8c3f301 100644
--- a/qt/scientific_interfaces/Direct/BaseInstrumentView.h
+++ b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/BaseCustomInstrumentView.h
@@ -4,15 +4,13 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#ifndef MANTIDQT_CUSTOMINTERFACES_BASEINSTRUMENTVIEW_H_
-#define MANTIDQT_CUSTOMINTERFACES_BASEINSTRUMENTVIEW_H_
+#ifndef MANTIDQT_INSTRUMENTVIEW_BASECUSTOMINSTRUMENTVIEW_H_
+#define MANTIDQT_INSTRUMENTVIEW_BASECUSTOMINSTRUMENTVIEW_H_
 
-#include "DllConfig.h"
-#include "MantidQtWidgets/Common/FunctionBrowser.h"
+#include "DllOption.h"
 #include "MantidQtWidgets/Common/MWRunFiles.h"
 #include "MantidQtWidgets/Common/ObserverPattern.h"
 #include "MantidQtWidgets/InstrumentView/InstrumentWidget.h"
-#include "MantidQtWidgets/Plotting/PreviewPlot.h"
 
 #include <QObject>
 #include <QPushButton>
@@ -21,14 +19,15 @@
 #include <string>
 
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
-class BaseInstrumentView : public QSplitter {
+class EXPORT_OPT_MANTIDQT_INSTRUMENTVIEW BaseCustomInstrumentView
+    : public QSplitter {
   Q_OBJECT
 
 public:
-  explicit BaseInstrumentView(const std::string &instrument,
-                              QWidget *parent = nullptr);
+  explicit BaseCustomInstrumentView(const std::string &instrument,
+                                    QWidget *parent = nullptr);
   std::string getFile();
   void setRunQuietly(const std::string &runNumber);
   void observeLoadRun(Observer *listener) {
@@ -66,7 +65,7 @@ private:
   MantidWidgets::InstrumentWidget *m_instrumentWidget;
   QPushButton *m_help;
 };
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
 
-#endif /* MANTIDQT_CUSTOMINTERFACES_BASEINSTRUMENTVIEW_H_ */
+#endif /* MANTIDQT_INSTRUMENTVIEW_BASECUSTOMINSTRUMENTVIEW_H_ */
diff --git a/qt/scientific_interfaces/Direct/PlotFitAnalysisPaneModel.h b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneModel.h
similarity index 71%
rename from qt/scientific_interfaces/Direct/PlotFitAnalysisPaneModel.h
rename to qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneModel.h
index a3befb87039632a2e5d4c9db4aac5f5f2832800d..83f3a03a0f3085a8ee1e6aad7c3fb6f41c50860d 100644
--- a/qt/scientific_interfaces/Direct/PlotFitAnalysisPaneModel.h
+++ b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneModel.h
@@ -4,8 +4,8 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#ifndef MANTIDQT_CUSTOMINTERFACES_PLOTFITANALYSISPANEMODEL_H_
-#define MANTIDQT_CUSTOMINTERFACES_PLOTFITANALYSISPANEMODEL_H_
+#ifndef MANTIDQT_INSTRUMENTVIEW_PLOTFITANALYSISPANEMODEL_H_
+#define MANTIDQT_INSTRUMENTVIEW_PLOTFITANALYSISPANEMODEL_H_
 
 #include "MantidAPI/IFunction.h"
 
@@ -13,7 +13,7 @@
 #include <string>
 using namespace Mantid::API;
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
 class PlotFitAnalysisPaneModel {
 
@@ -23,7 +23,7 @@ public:
                        const IFunction_sptr func);
 };
 
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
 
-#endif /* MANTIDQT_CUSTOMINTERFACES_PLOTFITANALYSISPANEMODEL_H_ */
+#endif /* MANTIDQT_INSTRUMENTVIEW_PLOTFITANALYSISPANEMODEL_H_ */
diff --git a/qt/scientific_interfaces/Direct/PlotFitAnalysisPanePresenter.h b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPanePresenter.h
similarity index 67%
rename from qt/scientific_interfaces/Direct/PlotFitAnalysisPanePresenter.h
rename to qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPanePresenter.h
index d50a899f33cdf1c91831472ed656cb475ce43f93..58c0d1ae86922f24941db81e6a09b19bcf21e718 100644
--- a/qt/scientific_interfaces/Direct/PlotFitAnalysisPanePresenter.h
+++ b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPanePresenter.h
@@ -4,19 +4,20 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#ifndef MANTIDQT_CUSTOMINTERFACES_PLOTFITANALYSISPANEPRESENTER_H_
-#define MANTIDQT_CUSTOMINTERFACES_PLOTFITANALYSISPANEPRESENTER_H_
-
-#include "PlotFitAnalysisPaneModel.h"
-#include "PlotFitAnalysisPaneView.h"
+#ifndef MANTIDQT_INSTRUMENTVIEW_PLOTFITANALYSISPANEPRESENTER_H_
+#define MANTIDQT_INSTRUMENTVIEW_PLOTFITANALYSISPANEPRESENTER_H_
 
+#include "DllOption.h"
 #include "MantidQtWidgets/Common/ObserverPattern.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneModel.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneView.h"
 #include <string>
 
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
-class PlotFitAnalysisPanePresenter : public QObject {
+class EXPORT_OPT_MANTIDQT_INSTRUMENTVIEW PlotFitAnalysisPanePresenter
+    : public QObject {
   Q_OBJECT
 
 public:
@@ -39,7 +40,7 @@ private:
   PlotFitAnalysisPaneModel *m_model;
   std::string m_currentName;
 };
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
 
-#endif /* MANTIDQT_CUSTOMINTERFACES_PLOTFITANALYSISPANEPRESENTER_H_ */
+#endif /* MANTIDQT_INSTRUMENTVIEW_PLOTFITANALYSISPANEPRESENTER_H_ */
diff --git a/qt/scientific_interfaces/Direct/PlotFitAnalysisPaneView.h b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneView.h
similarity index 83%
rename from qt/scientific_interfaces/Direct/PlotFitAnalysisPaneView.h
rename to qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneView.h
index 8962be77d65df0458f2deb648fa5b6ec0104dd1e..24242f33af38302f4b2517e664a4bf04fce60a3a 100644
--- a/qt/scientific_interfaces/Direct/PlotFitAnalysisPaneView.h
+++ b/qt/widgets/instrumentview/inc/MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneView.h
@@ -4,10 +4,10 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#ifndef MANTIDQT_CUSTOMINTERFACES_PLOTFITPANEVIEW_H_
-#define MANTIDQT_CUSTOMINTERFACES_PLOTFITPANEVIEW_H_
+#ifndef MANTIDQT_INSTRUMENTVIEW_PLOTFITPANEVIEW_H_
+#define MANTIDQT_INSTRUMENTVIEW_PLOTFITPANEVIEW_H_
 
-#include "DllConfig.h"
+#include "DllOption.h"
 #include "MantidQtWidgets/Common/FunctionBrowser.h"
 #include "MantidQtWidgets/Common/ObserverPattern.h"
 #include "MantidQtWidgets/Plotting/PreviewPlot.h"
@@ -21,9 +21,10 @@
 #include <string>
 
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
-class PlotFitAnalysisPaneView : public QWidget {
+class EXPORT_OPT_MANTIDQT_INSTRUMENTVIEW PlotFitAnalysisPaneView
+    : public QWidget {
   Q_OBJECT
 
 public:
@@ -55,7 +56,7 @@ private:
   QPushButton *m_fitButton;
   Observable *m_fitObservable;
 };
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
 
-#endif /* MANTIDQT_CUSTOMINTERFACES_PLOTFITPANEVIEW_H_ */
+#endif /* MANTIDQT_INSTRUMENTVIEW_PLOTFITPANEVIEW_H_ */
diff --git a/qt/scientific_interfaces/Direct/BaseInstrumentModel.cpp b/qt/widgets/instrumentview/src/BaseCustomInstrumentModel.cpp
similarity index 77%
rename from qt/scientific_interfaces/Direct/BaseInstrumentModel.cpp
rename to qt/widgets/instrumentview/src/BaseCustomInstrumentModel.cpp
index 8e3231f9c0fde7ab75fe704ec3d527144f1b127c..9af2790a27671cbc2c6d88fc481a2df31bc5f6ab 100644
--- a/qt/scientific_interfaces/Direct/BaseInstrumentModel.cpp
+++ b/qt/widgets/instrumentview/src/BaseCustomInstrumentModel.cpp
@@ -5,7 +5,7 @@
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
 
-#include "BaseInstrumentModel.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentModel.h"
 #include "MantidAPI/Algorithm.h"
 #include "MantidAPI/AlgorithmManager.h"
 #include "MantidAPI/AnalysisDataService.h"
@@ -22,13 +22,13 @@ const int ERRORCODE = -999;
 
 using namespace Mantid::API;
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
-BaseInstrumentModel::BaseInstrumentModel()
+BaseCustomInstrumentModel::BaseCustomInstrumentModel()
     : m_currentRun(0), m_tmpName("tmp"), m_instrumentName("MUSR"),
       m_wsName("testData") {}
 
-void BaseInstrumentModel::loadEmptyInstrument() {
+void BaseCustomInstrumentModel::loadEmptyInstrument() {
   auto alg =
       Mantid::API::AlgorithmManager::Instance().create("LoadEmptyInstrument");
   alg->initialize();
@@ -43,7 +43,7 @@ void BaseInstrumentModel::loadEmptyInstrument() {
  * @return std::pair<int,std::string>:: the run number and status
  */
 std::pair<int, std::string>
-BaseInstrumentModel::loadData(const std::string &name) {
+BaseCustomInstrumentModel::loadData(const std::string &name) {
   auto alg = AlgorithmManager::Instance().create("Load");
   alg->initialize();
   alg->setProperty("Filename", name);
@@ -58,16 +58,16 @@ BaseInstrumentModel::loadData(const std::string &name) {
   return std::make_pair(runNumber, message);
 }
 
-void BaseInstrumentModel::rename() {
+void BaseCustomInstrumentModel::rename() {
   AnalysisDataService::Instance().rename(m_tmpName, m_wsName);
 }
-void BaseInstrumentModel::remove() {
+void BaseCustomInstrumentModel::remove() {
   AnalysisDataService::Instance().remove(m_tmpName);
 }
 
-std::string BaseInstrumentModel::dataFileName() { return m_wsName; }
+std::string BaseCustomInstrumentModel::dataFileName() { return m_wsName; }
 
-int BaseInstrumentModel::currentRun() {
+int BaseCustomInstrumentModel::currentRun() {
   try {
 
     auto ws =
@@ -78,9 +78,9 @@ int BaseInstrumentModel::currentRun() {
   }
 }
 
-bool BaseInstrumentModel::isErrorCode(const int run) {
+bool BaseCustomInstrumentModel::isErrorCode(const int run) {
   return (run == ERRORCODE);
 }
 
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
diff --git a/qt/scientific_interfaces/Direct/BaseInstrumentPresenter.cpp b/qt/widgets/instrumentview/src/BaseCustomInstrumentPresenter.cpp
similarity index 75%
rename from qt/scientific_interfaces/Direct/BaseInstrumentPresenter.cpp
rename to qt/widgets/instrumentview/src/BaseCustomInstrumentPresenter.cpp
index b964d8b71d7184efcbaf035f323b2c011b736b07..6d667702346bf2e96bb535da32418a1ca360fa08 100644
--- a/qt/scientific_interfaces/Direct/BaseInstrumentPresenter.cpp
+++ b/qt/widgets/instrumentview/src/BaseCustomInstrumentPresenter.cpp
@@ -4,47 +4,49 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#include "BaseInstrumentPresenter.h"
-#include "BaseInstrumentView.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentPresenter.h"
 #include "MantidAPI/FileFinder.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentModel.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentView.h"
 
 #include <functional>
 #include <tuple>
 
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
-BaseInstrumentPresenter::BaseInstrumentPresenter(BaseInstrumentView *view,
-                                                 BaseInstrumentModel *model,
-                                                 QWidget *analysisPaneView)
+BaseCustomInstrumentPresenter::BaseCustomInstrumentPresenter(
+    BaseCustomInstrumentView *view, BaseCustomInstrumentModel *model,
+    QWidget *analysisPaneView)
     : m_view(view), m_model(model), m_currentRun(0), m_currentFile(""),
       m_loadRunObserver(nullptr), m_analysisPaneView(analysisPaneView) {
   m_loadRunObserver = new VoidObserver();
   m_model->loadEmptyInstrument();
 }
 
-void BaseInstrumentPresenter::addInstrument() {
+void BaseCustomInstrumentPresenter::addInstrument() {
   auto setUp = setupInstrument();
   initLayout(&setUp);
 }
 
-void BaseInstrumentPresenter::initLayout(
+void BaseCustomInstrumentPresenter::initLayout(
     std::pair<instrumentSetUp, instrumentObserverOptions> *setUp) {
   // connect to new run
   m_view->observeLoadRun(m_loadRunObserver);
   std::function<void()> loadBinder =
-      std::bind(&BaseInstrumentPresenter::loadRunNumber, this);
+      std::bind(&BaseCustomInstrumentPresenter::loadRunNumber, this);
   m_loadRunObserver->setSlot(loadBinder);
   initInstrument(setUp);
   setUpInstrumentAnalysisSplitter();
   m_view->setupHelp();
 }
 
-void BaseInstrumentPresenter::setUpInstrumentAnalysisSplitter() {
+void BaseCustomInstrumentPresenter::setUpInstrumentAnalysisSplitter() {
   m_view->setupInstrumentAnalysisSplitters(m_analysisPaneView);
 }
 
-void BaseInstrumentPresenter::loadAndAnalysis(const std::string &pathToRun) {
+void BaseCustomInstrumentPresenter::loadAndAnalysis(
+    const std::string &pathToRun) {
   try {
     auto loadedResult = m_model->loadData(pathToRun);
 
@@ -65,7 +67,7 @@ void BaseInstrumentPresenter::loadAndAnalysis(const std::string &pathToRun) {
   }
 }
 
-void BaseInstrumentPresenter::loadRunNumber() {
+void BaseCustomInstrumentPresenter::loadRunNumber() {
   auto pathToRun = m_view->getFile();
   if (pathToRun == "" || m_currentFile == pathToRun) {
     return;
@@ -73,9 +75,7 @@ void BaseInstrumentPresenter::loadRunNumber() {
   loadAndAnalysis(pathToRun);
 }
 
-// All of the below are specific to ALF
-
-void BaseInstrumentPresenter::initInstrument(
+void BaseCustomInstrumentPresenter::initInstrument(
     std::pair<instrumentSetUp, instrumentObserverOptions> *setUp) {
   if (!setUp) {
     return;
@@ -98,7 +98,7 @@ typedef std::vector<std::tuple<std::string, Observer *>>
     instrumentObserverOptions;
 std::pair<instrumentSetUp, instrumentObserverOptions>
 
-BaseInstrumentPresenter::setupInstrument() {
+BaseCustomInstrumentPresenter::setupInstrument() {
   instrumentSetUp setUpContextConditions;
 
   // set up the slots for the custom context menu
@@ -110,5 +110,5 @@ BaseInstrumentPresenter::setupInstrument() {
   return std::make_pair(setUpContextConditions, customInstrumentOptions);
 }
 
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
diff --git a/qt/scientific_interfaces/Direct/BaseInstrumentView.cpp b/qt/widgets/instrumentview/src/BaseCustomInstrumentView.cpp
similarity index 76%
rename from qt/scientific_interfaces/Direct/BaseInstrumentView.cpp
rename to qt/widgets/instrumentview/src/BaseCustomInstrumentView.cpp
index 9f33fb676b92096fa59f855d5b3a36450cfef7ab..b6026356daa4e8e5b81a3b5c7fd8893b1fdc9ce1 100644
--- a/qt/scientific_interfaces/Direct/BaseInstrumentView.cpp
+++ b/qt/widgets/instrumentview/src/BaseCustomInstrumentView.cpp
@@ -4,10 +4,10 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#include "BaseInstrumentView.h"
+#include "MantidQtWidgets/InstrumentView/BaseCustomInstrumentView.h"
 #include "MantidQtWidgets/Common/HelpWindow.h"
 #include "MantidQtWidgets/InstrumentView/InstrumentWidgetPickTab.h"
-
+// change to BaseCustomInstrumentView etc.
 #include <QMessageBox>
 #include <QSizePolicy>
 #include <QSpacerItem>
@@ -15,10 +15,10 @@
 #include <QVBoxLayout>
 
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
-BaseInstrumentView::BaseInstrumentView(const std::string &instrument,
-                                       QWidget *parent)
+BaseCustomInstrumentView::BaseCustomInstrumentView(
+    const std::string &instrument, QWidget *parent)
     : QSplitter(Qt::Vertical, parent), m_helpPage(""),
       m_loadRunObservable(nullptr), m_files(nullptr),
       m_instrument(QString::fromStdString(instrument)),
@@ -27,18 +27,18 @@ BaseInstrumentView::BaseInstrumentView(const std::string &instrument,
   this->addWidget(loadWidget);
 }
 
-void MantidQt::CustomInterfaces::BaseInstrumentView::setUpInstrument(
+void BaseCustomInstrumentView::setUpInstrument(
     const std::string &fileName,
     std::vector<std::function<bool(std::map<std::string, bool>)>> &instrument) {
 
   (void)instrument;
   auto instrumentWidget =
-      new MantidWidgets::InstrumentWidget(QString::fromStdString(fileName));
+      new InstrumentWidget(QString::fromStdString(fileName));
   instrumentWidget->hideHelp();
   setInstrumentWidget(instrumentWidget);
 }
 
-QWidget *BaseInstrumentView::generateLoadWidget() {
+QWidget *BaseCustomInstrumentView::generateLoadWidget() {
   m_loadRunObservable = new Observable();
 
   m_files = new API::MWRunFiles(this);
@@ -60,7 +60,7 @@ QWidget *BaseInstrumentView::generateLoadWidget() {
   return loadWidget;
 }
 
-void BaseInstrumentView::setupInstrumentAnalysisSplitters(
+void BaseCustomInstrumentView::setupInstrumentAnalysisSplitters(
     QWidget *analysisPane) {
   QSplitter *split = new QSplitter(Qt::Horizontal);
   split->addWidget(m_instrumentWidget);
@@ -68,7 +68,7 @@ void BaseInstrumentView::setupInstrumentAnalysisSplitters(
   this->addWidget(split);
 }
 
-void BaseInstrumentView::setupHelp() {
+void BaseCustomInstrumentView::setupHelp() {
   QWidget *helpWidget = new QWidget();
   m_help = new QPushButton("?");
   m_help->setMaximumWidth(25);
@@ -81,7 +81,7 @@ void BaseInstrumentView::setupHelp() {
   connect(m_help, SIGNAL(clicked()), this, SLOT(openHelp()));
 }
 
-void BaseInstrumentView::openHelp() {
+void BaseCustomInstrumentView::openHelp() {
   if (m_helpPage == "") {
     return;
   }
@@ -89,18 +89,18 @@ void BaseInstrumentView::openHelp() {
       nullptr, QString::fromStdString(m_helpPage));
 }
 
-std::string BaseInstrumentView::getFile() {
+std::string BaseCustomInstrumentView::getFile() {
   auto name = m_files->getFilenames();
   if (name.size() > 0)
     return name[0].toStdString();
   return "";
 }
 
-void BaseInstrumentView::setRunQuietly(const std::string &runNumber) {
+void BaseCustomInstrumentView::setRunQuietly(const std::string &runNumber) {
   m_files->setText(QString::fromStdString(runNumber));
 }
 
-void BaseInstrumentView::fileLoaded() {
+void BaseCustomInstrumentView::fileLoaded() {
   if (m_files->getText().isEmpty())
     return;
 
@@ -111,13 +111,13 @@ void BaseInstrumentView::fileLoaded() {
   m_loadRunObservable->notify();
 }
 
-void BaseInstrumentView::warningBox(const std::string &message) {
+void BaseCustomInstrumentView::warningBox(const std::string &message) {
   warningBox(QString::fromStdString(message));
 }
 
-void BaseInstrumentView::warningBox(const QString &message) {
+void BaseCustomInstrumentView::warningBox(const QString &message) {
   QMessageBox::warning(this, m_instrument + " view", message);
 }
 
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
diff --git a/qt/scientific_interfaces/Direct/PlotFitAnalysisPaneModel.cpp b/qt/widgets/instrumentview/src/PlotFitAnalysisPaneModel.cpp
similarity index 88%
rename from qt/scientific_interfaces/Direct/PlotFitAnalysisPaneModel.cpp
rename to qt/widgets/instrumentview/src/PlotFitAnalysisPaneModel.cpp
index c52382b1368cab5e65965ef4be1b8c89a509e460..feb3e076176299796fbe7f41c05e92c8fe8281e4 100644
--- a/qt/scientific_interfaces/Direct/PlotFitAnalysisPaneModel.cpp
+++ b/qt/widgets/instrumentview/src/PlotFitAnalysisPaneModel.cpp
@@ -5,13 +5,13 @@
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
 
-#include "PlotFitAnalysisPaneModel.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneModel.h"
 #include "MantidAPI/Algorithm.h"
 #include "MantidAPI/AlgorithmManager.h"
 
 using namespace Mantid::API;
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
 IFunction_sptr
 PlotFitAnalysisPaneModel::doFit(const std::string &wsName,
@@ -29,5 +29,5 @@ PlotFitAnalysisPaneModel::doFit(const std::string &wsName,
   return alg->getProperty("Function");
 }
 
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
diff --git a/qt/scientific_interfaces/Direct/PlotFitAnalysisPanePresenter.cpp b/qt/widgets/instrumentview/src/PlotFitAnalysisPanePresenter.cpp
similarity index 87%
rename from qt/scientific_interfaces/Direct/PlotFitAnalysisPanePresenter.cpp
rename to qt/widgets/instrumentview/src/PlotFitAnalysisPanePresenter.cpp
index f2a32c1a17cd83c7ab7afcc28a030f6d7e4f4918..a14df8b827d236eb6ad5a6b4f52ee6219b4f0b00 100644
--- a/qt/scientific_interfaces/Direct/PlotFitAnalysisPanePresenter.cpp
+++ b/qt/widgets/instrumentview/src/PlotFitAnalysisPanePresenter.cpp
@@ -4,18 +4,14 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#include "PlotFitAnalysisPanePresenter.h"
-
-#include "MantidAPI/CompositeFunction.h"
-#include "MantidAPI/FileFinder.h"
-#include "MantidAPI/FunctionFactory.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPanePresenter.h"
 
 #include <exception>
 #include <functional>
 #include <tuple>
 
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
 PlotFitAnalysisPanePresenter::PlotFitAnalysisPanePresenter(
     PlotFitAnalysisPaneView *view, PlotFitAnalysisPaneModel *model)
@@ -54,5 +50,5 @@ void PlotFitAnalysisPanePresenter::addSpectrum(const std::string &wsName) {
   m_view->addSpectrum(wsName);
 }
 
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
diff --git a/qt/scientific_interfaces/Direct/PlotFitAnalysisPaneView.cpp b/qt/widgets/instrumentview/src/PlotFitAnalysisPaneView.cpp
similarity index 96%
rename from qt/scientific_interfaces/Direct/PlotFitAnalysisPaneView.cpp
rename to qt/widgets/instrumentview/src/PlotFitAnalysisPaneView.cpp
index 21ca27a7d4c6e4b5e351965811fb2f8d6b7a4b57..db0ff22fbf2599c56ab7d528a3f5af46650e14d5 100644
--- a/qt/scientific_interfaces/Direct/PlotFitAnalysisPaneView.cpp
+++ b/qt/widgets/instrumentview/src/PlotFitAnalysisPaneView.cpp
@@ -4,7 +4,7 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#include "PlotFitAnalysisPaneView.h"
+#include "MantidQtWidgets/InstrumentView/PlotFitAnalysisPaneView.h"
 #include "MantidAPI/CompositeFunction.h"
 #include "MantidAPI/FunctionFactory.h"
 
@@ -16,7 +16,7 @@
 #include <QSplitter>
 #include <QVBoxLayout>
 namespace MantidQt {
-namespace CustomInterfaces {
+namespace MantidWidgets {
 
 PlotFitAnalysisPaneView::PlotFitAnalysisPaneView(const double &start,
                                                  const double &end,
@@ -115,5 +115,5 @@ void PlotFitAnalysisPaneView::fitWarning(const std::string &message) {
   QMessageBox::warning(this, "Fit error", message.c_str());
 }
 
-} // namespace CustomInterfaces
+} // namespace MantidWidgets
 } // namespace MantidQt
diff --git a/qt/widgets/plotting/inc/MantidQtWidgets/Plotting/Qwt/SafeQwtPlot.h b/qt/widgets/plotting/inc/MantidQtWidgets/Plotting/Qwt/SafeQwtPlot.h
index dd481901f488d0fe2a0a759919b7048fcefa4197..d68c5e69b2106289f9119b6b2ac4c62490808e5c 100644
--- a/qt/widgets/plotting/inc/MantidQtWidgets/Plotting/Qwt/SafeQwtPlot.h
+++ b/qt/widgets/plotting/inc/MantidQtWidgets/Plotting/Qwt/SafeQwtPlot.h
@@ -13,7 +13,7 @@
 #include "qwt_text.h"
 MSVC_DIAG_OFF(4244)
 #include <QPainter>
-MSVC_DIAG_ON()
+MSVC_DIAG_ON(4244)
 #include <qwt_plot.h>
 
 namespace MantidQt {
diff --git a/qt/widgets/sliceviewer/inc/MantidQtWidgets/SliceViewer/QPeaksTableModel.h b/qt/widgets/sliceviewer/inc/MantidQtWidgets/SliceViewer/QPeaksTableModel.h
index cd2c41cde04f0f4b49fdc3a682a52f9173fcbff8..bf71b0cf542471c69840f6d0bc82894d3ac5603b 100644
--- a/qt/widgets/sliceviewer/inc/MantidQtWidgets/SliceViewer/QPeaksTableModel.h
+++ b/qt/widgets/sliceviewer/inc/MantidQtWidgets/SliceViewer/QPeaksTableModel.h
@@ -5,7 +5,6 @@
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
 #include "DllOption.h"
-#include "boost/bind.hpp"
 #include "boost/function.hpp"
 #include "boost/tuple/tuple.hpp"
 #include <QAbstractTableModel>
diff --git a/scripts/Diffraction/isis_powder/polaris_routines/polaris_algs.py b/scripts/Diffraction/isis_powder/polaris_routines/polaris_algs.py
index 8cf5287de594446ed236ea15dec0dd359d5139cb..a7ef6c233a362286f168bf14129b927dac3fb969 100644
--- a/scripts/Diffraction/isis_powder/polaris_routines/polaris_algs.py
+++ b/scripts/Diffraction/isis_powder/polaris_routines/polaris_algs.py
@@ -8,6 +8,7 @@ from __future__ import (absolute_import, division, print_function)
 import numpy as np
 
 import mantid.simpleapi as mantid
+from six import string_types
 
 from isis_powder.routines import absorb_corrections, common
 from isis_powder.routines.common_enums import WORKSPACE_UNITS
@@ -145,7 +146,7 @@ def _obtain_focused_run(run_number, focus_file_path):
 
 
 def _load_qlims(q_lims):
-    if type(q_lims) == str or type(q_lims) == unicode:
+    if isinstance(q_lims, string_types):
         q_min = []
         q_max = []
         try:
@@ -157,13 +158,13 @@ def _load_qlims(q_lims):
                     q_max.append(float(value_list[3]))
             q_min = np.array(q_min)
             q_max = np.array(q_max)
-        except IOError:
-            raise RuntimeError("q_lims directory is not valid")
-    elif type(q_lims) == list or type(q_lims) == np.ndarray:
+        except IOError as exc:
+            raise RuntimeError("q_lims path is not valid: {}".format(exc))
+    elif isinstance(q_lims, (list, tuple)) or isinstance(q_lims, np.ndarray):
         q_min = q_lims[0, :]
         q_max = q_lims[1, :]
     else:
-        raise RuntimeError("q_lims type is not valid")
+        raise RuntimeError("q_lims type is not valid. Expected a string filename or an array.")
     return q_min, q_max
 
 
diff --git a/scripts/Diffraction/isis_powder/routines/yaml_parser.py b/scripts/Diffraction/isis_powder/routines/yaml_parser.py
index 0f840d2fd5021ac16ac451f6708bf94080e8509e..f8b54e492c5055c00fc6f5ca77b1950c9a4e0698 100644
--- a/scripts/Diffraction/isis_powder/routines/yaml_parser.py
+++ b/scripts/Diffraction/isis_powder/routines/yaml_parser.py
@@ -42,7 +42,7 @@ def open_yaml_file_as_dictionary(file_path):
 
     with open(file_path, 'r') as input_stream:
         try:
-            read_config = yaml.load(input_stream)
+            read_config = yaml.safe_load(input_stream)
         except yaml.YAMLError as exception:
             print(exception)
             raise RuntimeError("Failed to parse YAML file: " + str(file_path))
diff --git a/scripts/Engineering/gui/CMakeLists.txt b/scripts/Engineering/gui/CMakeLists.txt
index d04e7efbfa29a8b3f80cdfbeacbb2493fa9483a3..62c1f5271a99bb83e2417cbef8c7104fb40003d1 100644
--- a/scripts/Engineering/gui/CMakeLists.txt
+++ b/scripts/Engineering/gui/CMakeLists.txt
@@ -3,6 +3,10 @@
 set(TEST_PY_FILES
     # Common
     engineering_diffraction/tabs/common/test/test_vanadium_corrections.py
+    # Settings
+    engineering_diffraction/settings/test/test_settings_helper.py
+    engineering_diffraction/settings/test/test_settings_model.py
+    engineering_diffraction/settings/test/test_settings_presenter.py
     # Calibration
     engineering_diffraction/tabs/calibration/test/test_calib_model.py
     engineering_diffraction/tabs/calibration/test/test_calib_presenter.py
diff --git a/scripts/Engineering/gui/engineering_diffraction/engineering_diffraction.py b/scripts/Engineering/gui/engineering_diffraction/engineering_diffraction.py
index 3a8dbe99906095ffb77409dd2f222c700fb35310..ba311894e2f91ab1f50a548f22bfb5cef55588a0 100644
--- a/scripts/Engineering/gui/engineering_diffraction/engineering_diffraction.py
+++ b/scripts/Engineering/gui/engineering_diffraction/engineering_diffraction.py
@@ -14,6 +14,10 @@ from .tabs.calibration.presenter import CalibrationPresenter
 from .tabs.focus.model import FocusModel
 from .tabs.focus.view import FocusView
 from .tabs.focus.presenter import FocusPresenter
+from .settings.settings_model import SettingsModel
+from .settings.settings_view import SettingsView
+from .settings.settings_presenter import SettingsPresenter
+from mantidqt.icons import get_icon
 
 from mantidqt.interfacemanager import InterfaceManager
 from mantidqt.utils.qt import load_ui
@@ -35,15 +39,26 @@ class EngineeringDiffractionGui(QtWidgets.QMainWindow, Ui_main_window):
         self.setFocusPolicy(QtCore.Qt.StrongFocus)
         self.calibration_presenter = None
         self.focus_presenter = None
+        self.settings_presenter = None
         self.set_on_help_clicked(self.open_help_window)
 
-        # Setup Tabs
+        self.set_on_settings_clicked(self.open_settings)
+        self.btn_settings.setIcon(get_icon("mdi.settings", "black", 1.2))
+
+        # Setup Elements
+        self.setup_settings()
         self.setup_calibration()
         self.setup_focus()
 
         # Setup notifiers
         self.setup_calibration_notifier()
 
+    def setup_settings(self):
+        model = SettingsModel()
+        view = SettingsView(self)
+        self.settings_presenter = SettingsPresenter(model, view)
+        self.settings_presenter.load_settings_from_file_or_default()
+
     def setup_calibration(self):
         cal_model = CalibrationModel()
         cal_view = CalibrationView(parent=self.tabs)
@@ -67,6 +82,9 @@ class EngineeringDiffractionGui(QtWidgets.QMainWindow, Ui_main_window):
     def set_on_help_clicked(self, slot):
         self.pushButton_help.clicked.connect(slot)
 
+    def set_on_settings_clicked(self, slot):
+        self.btn_settings.clicked.connect(slot)
+
     def set_on_rb_num_changed(self, slot):
         self.lineEdit_RBNumber.textChanged.connect(slot)
 
@@ -76,5 +94,9 @@ class EngineeringDiffractionGui(QtWidgets.QMainWindow, Ui_main_window):
     def open_help_window(self):
         InterfaceManager().showCustomInterfaceHelp(self.doc)
 
+    def open_settings(self):
+        self.settings_presenter.load_existing_settings()
+        self.settings_presenter.show()
+
     def get_rb_no(self):
         return self.lineEdit_RBNumber.text()
diff --git a/scripts/Engineering/gui/engineering_diffraction/main_window.ui b/scripts/Engineering/gui/engineering_diffraction/main_window.ui
index 3f4cac479e962cf435b3197556a061699c45f4d1..6e3565348930ea8a3108e68cb8b0a7d7cafaaa86 100644
--- a/scripts/Engineering/gui/engineering_diffraction/main_window.ui
+++ b/scripts/Engineering/gui/engineering_diffraction/main_window.ui
@@ -91,6 +91,13 @@
         </property>
        </widget>
       </item>
+      <item>
+       <widget class="QToolButton" name="btn_settings">
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
       <item>
        <widget class="QStatusBar" name="statusbar">
         <property name="sizeGripEnabled">
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/__init__.py b/scripts/Engineering/gui/engineering_diffraction/settings/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/settings_helper.py b/scripts/Engineering/gui/engineering_diffraction/settings/settings_helper.py
new file mode 100644
index 0000000000000000000000000000000000000000..020ad2f3032f2d82b3f6a86b7c7bea913d9ca0b4
--- /dev/null
+++ b/scripts/Engineering/gui/engineering_diffraction/settings/settings_helper.py
@@ -0,0 +1,57 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright &copy; 2019 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+
+from __future__ import (absolute_import, division, print_function)
+
+from qtpy.QtCore import QSettings
+
+
+def set_setting(group, prefix, setting_name, value):
+    """
+    Change or add a setting in the mantid .ini file.
+    :param group: Settings group to pull from.
+    :param prefix: Acts like a subgroup.
+    :param setting_name: The key to the setting.
+    :param value: The value of the setting.
+    """
+    settings = QSettings()
+    settings.beginGroup(group)
+    settings.setValue(prefix + setting_name, value)
+    settings.endGroup()
+
+
+def get_setting(group, prefix, setting_name, return_type=str):
+    """
+    Get a setting from the .ini file of mantid settings.
+
+    NOTE: If you specify an int, but the setting contains a bool, you will get 0 for False
+    and 1 for True, without a warning. Specifying bool will raise a TypeError if anything
+    other than a bool or empty string is found in the settings. Not specifying a type will
+    return a string. If nothing is found then an empty string is returned.
+
+    :param group: Settings group to pull from.
+    :param prefix: The prefix of the setting, acts like a subgroup.
+    :param setting_name: Name of the setting.
+    :param return_type: The type of the setting to get.
+    :return: The chosen setting.
+    """
+    settings = QSettings()
+    settings.beginGroup(group)
+    if return_type is bool:
+        setting = settings.value(prefix + setting_name, type=str)
+        if setting == "":
+            pass
+        elif setting == "true":
+            setting = True
+        elif setting == "false":
+            setting = False
+        else:
+            raise TypeError("Unable to convert string into valid bool")
+    else:
+        setting = settings.value(prefix + setting_name, type=return_type)
+    settings.endGroup()
+    return setting
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/settings_model.py b/scripts/Engineering/gui/engineering_diffraction/settings/settings_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..32edb1a5e53230e984cd6a1d543b36bad393a5e7
--- /dev/null
+++ b/scripts/Engineering/gui/engineering_diffraction/settings/settings_model.py
@@ -0,0 +1,32 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright &copy; 2019 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+
+from __future__ import (absolute_import, division, print_function)
+
+from Engineering.gui.engineering_diffraction.settings.settings_helper import get_setting, set_setting
+from Engineering.gui.engineering_diffraction.tabs.common import path_handling
+
+
+class SettingsModel(object):
+    def get_settings_dict(self, names_and_types):
+        settings = {}
+        for setting_name in names_and_types.keys():
+            settings[setting_name] = self.get_setting(setting_name, return_type=names_and_types[setting_name])
+        return settings
+
+    def set_settings_dict(self, settings):
+        for key in settings:
+            self.set_setting(key, settings[key])
+
+    @staticmethod
+    def get_setting(name, return_type=str):
+        return get_setting(path_handling.INTERFACES_SETTINGS_GROUP, path_handling.ENGINEERING_PREFIX, name,
+                           return_type=return_type)
+
+    @staticmethod
+    def set_setting(name, value):
+        set_setting(path_handling.INTERFACES_SETTINGS_GROUP, path_handling.ENGINEERING_PREFIX, name, value)
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/settings_presenter.py b/scripts/Engineering/gui/engineering_diffraction/settings/settings_presenter.py
new file mode 100644
index 0000000000000000000000000000000000000000..3767e462ccf1f7b08ce43edff8f75c96f2a18936
--- /dev/null
+++ b/scripts/Engineering/gui/engineering_diffraction/settings/settings_presenter.py
@@ -0,0 +1,80 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright &copy; 2019 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+# pylint: disable=invalid-name
+from __future__ import (absolute_import, division, print_function)
+
+from os import path
+
+SETTINGS_DICT = {"save_location": str, "full_calibration": str, "recalc_vanadium": bool}
+
+DEFAULT_SETTINGS = {
+    "full_calibration": "",
+    "save_location": path.join(path.expanduser("~"), "Engineering_Mantid"),
+    "recalc_vanadium": False
+}
+
+
+class SettingsPresenter(object):
+    def __init__(self, model, view):
+        self.model = model
+        self.view = view
+        self.settings = {}
+
+        # Connect view signals
+        self.view.set_on_apply_clicked(self.save_new_settings)
+        self.view.set_on_ok_clicked(self.save_and_close_dialog)
+        self.view.set_on_cancel_clicked(self.close_dialog)
+
+    def show(self):
+        self.view.show()
+
+    def load_existing_settings(self):
+        self.load_settings_from_file_or_default()
+        self._show_settings_in_view()
+
+    def close_dialog(self):
+        self.view.close()
+
+    def save_and_close_dialog(self):
+        self.save_new_settings()
+        self.close_dialog()
+
+    def save_new_settings(self):
+        self._collect_new_settings_from_view()
+        self._save_settings_to_file()
+
+    def _collect_new_settings_from_view(self):
+        self.settings["save_location"] = self.view.get_save_location()
+        self.settings["full_calibration"] = self.view.get_full_calibration()
+        self.settings["recalc_vanadium"] = self.view.get_van_recalc()
+
+    def _show_settings_in_view(self):
+        if self._validate_settings(self.settings):
+            self.view.set_save_location(self.settings["save_location"])
+            self.view.set_full_calibration(self.settings["full_calibration"])
+            self.view.set_van_recalc(self.settings["recalc_vanadium"])
+
+    def _save_settings_to_file(self):
+        if self._validate_settings(self.settings):
+            self.model.set_settings_dict(self.settings)
+
+    def load_settings_from_file_or_default(self):
+        self.settings = self.model.get_settings_dict(SETTINGS_DICT)
+        if not self._validate_settings(self.settings):
+            self.settings = DEFAULT_SETTINGS.copy()
+            self._save_settings_to_file()
+
+    @staticmethod
+    def _validate_settings(settings):
+        try:
+            all_keys = settings.keys() == SETTINGS_DICT.keys()
+            save_location = str(settings["save_location"])
+            save_valid = save_location is not "" and save_location is not None
+            recalc_valid = settings["recalc_vanadium"] is not None
+            return all_keys and save_valid and recalc_valid
+        except KeyError:  # Settings contained invalid key.
+            return False
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/settings_view.py b/scripts/Engineering/gui/engineering_diffraction/settings/settings_view.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d94d776b522c8d6aa5b6f5fa2ae3128932bb901
--- /dev/null
+++ b/scripts/Engineering/gui/engineering_diffraction/settings/settings_view.py
@@ -0,0 +1,69 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright &copy; 2019 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+
+from __future__ import (absolute_import, division, print_function)
+from qtpy import QtWidgets
+
+from mantidqt.utils.qt import load_ui
+
+Ui_settings, _ = load_ui(__file__, "settings_widget.ui")
+
+
+class SettingsView(QtWidgets.QDialog, Ui_settings):
+    def __init__(self, parent=None):
+        super(SettingsView, self).__init__(parent)
+        self.setupUi(self)
+        self.setModal(True)
+
+        self.finder_save.setLabelText("Save Location")
+        self.finder_save.isForRunFiles(False)
+        self.finder_save.isForDirectory(True)
+
+        self.finder_fullCalib.setLabelText("Full Calibration")
+        self.finder_fullCalib.isForRunFiles(False)
+        # TODO: Once it becomes possible to load the .csv containing the full calibration into mantid,
+        #  this can be used. Until then, this option is hidden from the user.
+        self.finder_fullCalib.hide()
+
+    # ===============
+    # Slot Connectors
+    # ===============
+
+    def set_on_apply_clicked(self, slot):
+        self.btn_apply.clicked.connect(slot)
+
+    def set_on_ok_clicked(self, slot):
+        self.btn_ok.clicked.connect(slot)
+
+    def set_on_cancel_clicked(self, slot):
+        self.btn_cancel.clicked.connect(slot)
+
+    # =================
+    # Component Getters
+    # =================
+
+    def get_save_location(self):
+        return self.finder_save.getFirstFilename()
+
+    def get_full_calibration(self):
+        return self.finder_fullCalib.getFirstFilename()
+
+    def get_van_recalc(self):
+        return self.check_vanRecalc.isChecked()
+
+    # =================
+    # Component Setters
+    # =================
+
+    def set_save_location(self, text):
+        self.finder_save.setText(text)
+
+    def set_full_calibration(self, text):
+        self.finder_fullCalib.setText(text)
+
+    def set_van_recalc(self, checked):
+        self.check_vanRecalc.setChecked(checked)
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/settings_widget.ui b/scripts/Engineering/gui/engineering_diffraction/settings/settings_widget.ui
new file mode 100644
index 0000000000000000000000000000000000000000..f2093a42150a686110609cb89b195dc38c8f769b
--- /dev/null
+++ b/scripts/Engineering/gui/engineering_diffraction/settings/settings_widget.ui
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>630</width>
+    <height>184</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Engineering Diffraction Analysis</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">QGroupBox {
+border: 1px solid grey;border-radius: 10px;margin-top: 1ex; margin-right: 0ex
+}
+QGroupBox:title {
+                          subcontrol-origin: margin;
+                          subcontrol-position: top center;
+                          padding-top: 0px;
+                          padding-bottom: 0px;
+							  padding-left: 5px;
+                          padding-right: 5px;
+                          color: rgb(56, 56, 56)
+}</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="group_general">
+     <property name="title">
+      <string>General</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="FileFinder" name="finder_save" native="true"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="group_calib">
+     <property name="title">
+      <string>Calibration</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <widget class="QCheckBox" name="check_vanRecalc">
+        <property name="text">
+         <string>Force Vanadium Recalculation</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="FileFinder" name="finder_fullCalib" native="true"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QFrame" name="frame">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::NoFrame</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="btn_apply">
+        <property name="text">
+         <string>Apply</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="btn_ok">
+        <property name="text">
+         <string>OK</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="btn_cancel">
+        <property name="text">
+         <string>Cancel</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>FileFinder</class>
+   <extends>QWidget</extends>
+   <header>mantidqt.widgets.filefinder</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/test/__init__.py b/scripts/Engineering/gui/engineering_diffraction/settings/test/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/test/test_settings_helper.py b/scripts/Engineering/gui/engineering_diffraction/settings/test/test_settings_helper.py
new file mode 100644
index 0000000000000000000000000000000000000000..62a0bf0d145ed963a25d27d06295258523df9bc9
--- /dev/null
+++ b/scripts/Engineering/gui/engineering_diffraction/settings/test/test_settings_helper.py
@@ -0,0 +1,160 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright &copy; 2019 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+
+from __future__ import (absolute_import, division, print_function)
+
+from Engineering.gui.engineering_diffraction.settings.settings_helper import set_setting, get_setting
+
+from qtpy.QtCore import QSettings, QCoreApplication
+
+from shutil import rmtree
+from os.path import dirname
+
+import unittest
+
+GROUP = "CustomInterfaces"
+PREFIX = "EngineeringDiffraction2/"
+
+
+class SettingsHelperTest(unittest.TestCase):
+    def tearDown(self):
+        settings = QSettings()
+        settings.clear()
+        rmtree(dirname(settings.fileName()))
+
+    def setUp(self):
+        settings = QSettings()
+        settings.clear()
+
+    @classmethod
+    def setUpClass(cls):
+        QCoreApplication.setApplicationName("test1")
+        QCoreApplication.setOrganizationName("org1")
+        QSettings.setDefaultFormat(QSettings.IniFormat)
+
+    def test_set_setting_with_string(self):
+        set_setting(GROUP, PREFIX, "something", "value")
+
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        returned = settings.value(PREFIX + "something")
+        settings.endGroup()
+        self.assertEqual(returned, "value")
+
+    def test_set_setting_with_bool_false(self):
+        set_setting(GROUP, PREFIX, "something", False)
+
+        settings = QSettings()
+        settings.beginGroup("CustomInterfaces")
+        returned = settings.value("EngineeringDiffraction2/" + "something", type=bool)
+        settings.endGroup()
+        self.assertEqual(returned, False)
+
+    def test_set_setting_with_bool_true(self):
+        set_setting(GROUP, PREFIX, "something", True)
+
+        settings = QSettings()
+        settings.beginGroup("CustomInterfaces")
+        returned = settings.value("EngineeringDiffraction2/" + "something", type=bool)
+        settings.endGroup()
+        self.assertEqual(returned, True)
+
+    def test_set_setting_with_int(self):
+        set_setting(GROUP, PREFIX, "something", 10)
+
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        returned = settings.value(PREFIX + "something", type=int)
+        settings.endGroup()
+        self.assertEqual(returned, 10)
+
+    def test_get_setting_with_string(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", "value")
+        settings.endGroup()
+
+        self.assertEqual(get_setting(GROUP, PREFIX, "something"), "value")
+
+    def test_get_setting_with_bool_false(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", False)
+        settings.endGroup()
+
+        self.assertEqual(get_setting(GROUP, PREFIX, "something", return_type=bool), False)
+
+    def test_get_setting_with_bool_true(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", True)
+        settings.endGroup()
+
+        self.assertEqual(get_setting(GROUP, PREFIX, "something", return_type=bool), True)
+
+    def test_get_setting_with_int(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", 10)
+        settings.endGroup()
+
+        self.assertEqual(get_setting(GROUP, PREFIX, "something", return_type=int), 10)
+
+    def test_get_setting_with_invalid(self):
+        self.assertEqual(get_setting(GROUP, PREFIX, "something"), "")
+
+    def test_get_setting_int_without_specifying_type(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", 10)
+        settings.endGroup()
+
+        self.assertEqual(get_setting(GROUP, PREFIX, "something"), "10")
+
+    def test_get_setting_bool_without_specifying_type(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", True)
+        settings.endGroup()
+
+        self.assertEqual(get_setting(GROUP, PREFIX, "something"), "true")
+
+    def test_get_setting_bool_specifying_int(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", True)
+        settings.endGroup()
+
+        self.assertEqual(get_setting(GROUP, PREFIX, "something", return_type=int), 1)
+
+    def test_get_setting_int_specifying_bool(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", 10)
+        settings.endGroup()
+
+        self.assertRaises(TypeError, get_setting, GROUP, PREFIX, "something", return_type=bool)
+
+    def test_get_setting_string_specifying_int(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", "some setting")
+        settings.endGroup()
+
+        self.assertRaises(TypeError, get_setting, GROUP, PREFIX, "something", return_type=int)
+
+    def test_get_setting_string_specifying_bool(self):
+        settings = QSettings()
+        settings.beginGroup(GROUP)
+        settings.setValue(PREFIX + "something", "a")
+        settings.endGroup()
+
+        self.assertRaises(TypeError, get_setting, GROUP, PREFIX, "something", return_type=bool)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/test/test_settings_model.py b/scripts/Engineering/gui/engineering_diffraction/settings/test/test_settings_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..3acd388e063e79e16cf256551c8b8aa144ff587e
--- /dev/null
+++ b/scripts/Engineering/gui/engineering_diffraction/settings/test/test_settings_model.py
@@ -0,0 +1,51 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright &copy; 2019 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+
+from __future__ import (absolute_import, division, print_function)
+
+import unittest
+
+from mantid.py3compat.mock import patch
+from Engineering.gui.engineering_diffraction.settings.settings_model import SettingsModel
+
+dir_path = "Engineering.gui.engineering_diffraction.settings."
+
+
+class SettingsModelTest(unittest.TestCase):
+    def setUp(self):
+        self.model = SettingsModel()
+
+    @patch(dir_path + "settings_model.set_setting")
+    def test_set_setting(self, set_setting_mock):
+        self.model.set_setting("name", "value")
+        set_setting_mock.assert_called_with("CustomInterfaces", "EngineeringDiffraction2/", "name", "value")
+
+    @patch(dir_path + "settings_model.get_setting")
+    def test_get_setting(self, get_setting_mock):
+        self.model.get_setting("name")
+        get_setting_mock.assert_called_with("CustomInterfaces", "EngineeringDiffraction2/", "name", return_type=str)
+
+    @patch(dir_path + "settings_model.set_setting")
+    def test_set_settings_dict(self, set_setting_mock):
+        self.model.set_settings_dict({"name": "value", "namebool": False, "namenum": 10})
+        self.assertEqual(set_setting_mock.call_count, 3)
+        set_setting_mock.assert_any_call("CustomInterfaces", "EngineeringDiffraction2/", "name", "value")
+        set_setting_mock.assert_any_call("CustomInterfaces", "EngineeringDiffraction2/", "namebool", False)
+        set_setting_mock.assert_any_call("CustomInterfaces", "EngineeringDiffraction2/", "namenum", 10)
+
+    @patch(dir_path + "settings_model.get_setting")
+    def test_get_settings_dict(self, get_setting_mock):
+        get_setting_mock.return_value = "value"
+        self.assertEqual(self.model.get_settings_dict({"name1": str, "name2": str}),
+                         {'name1': 'value', 'name2': 'value'})
+        self.assertEqual(get_setting_mock.call_count, 2)
+        get_setting_mock.assert_any_call("CustomInterfaces", "EngineeringDiffraction2/", "name1", return_type=str)
+        get_setting_mock.assert_any_call("CustomInterfaces", "EngineeringDiffraction2/", "name2", return_type=str)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/scripts/Engineering/gui/engineering_diffraction/settings/test/test_settings_presenter.py b/scripts/Engineering/gui/engineering_diffraction/settings/test/test_settings_presenter.py
new file mode 100644
index 0000000000000000000000000000000000000000..f08c8d6a901214837dc9c98dbc964b76997075ba
--- /dev/null
+++ b/scripts/Engineering/gui/engineering_diffraction/settings/test/test_settings_presenter.py
@@ -0,0 +1,95 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright &copy; 2019 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+# pylint: disable=invalid-name
+from __future__ import (absolute_import, division, print_function)
+
+import unittest
+
+from mantid.py3compat import mock
+
+from Engineering.gui.engineering_diffraction.settings import settings_model, settings_view, settings_presenter
+
+dir_path = "Engineering.gui.engineering_diffraction.settings."
+
+
+class SettingsPresenterTest(unittest.TestCase):
+    def setUp(self):
+        self.model = mock.create_autospec(settings_model.SettingsModel)
+        self.view = mock.create_autospec(settings_view.SettingsView)
+        self.presenter = settings_presenter.SettingsPresenter(self.model, self.view)
+        self.presenter.settings = {}
+
+    def test_load_existing_settings(self):
+        self.model.get_settings_dict.return_value = {
+            "save_location": "result",
+            "full_calibration": "value",
+            "recalc_vanadium": False
+        }
+
+        self.presenter.load_existing_settings()
+
+        self.assertEqual(self.presenter.settings, {
+            "full_calibration": "value",
+            "save_location": "result",
+            "recalc_vanadium": False
+        })
+        self.assertEqual(self.view.set_save_location.call_count, 1)
+        self.assertEqual(self.view.set_full_calibration.call_count, 1)
+        self.assertEqual(self.view.set_van_recalc.call_count, 1)
+
+    def test_load_invalid_settings(self):
+        self.model.get_settings_dict.return_value = {
+            "foo": "dud",
+            "bar": "result"
+        }
+        self.presenter.load_existing_settings()
+
+        self.view.set_save_location.assert_called_with(settings_presenter.DEFAULT_SETTINGS["save_location"])
+        self.view.set_full_calibration.assert_called_with(settings_presenter.DEFAULT_SETTINGS["full_calibration"])
+        self.view.set_van_recalc.assert_called_with(settings_presenter.DEFAULT_SETTINGS["recalc_vanadium"])
+
+    def test_save_new_settings(self):
+        self.view.get_save_location.return_value = "save"
+        self.view.get_full_calibration.return_value = "cal"
+        self.view.get_van_recalc.return_value = False
+
+        self.presenter.save_new_settings()
+
+        self.assertEqual(self.presenter.settings, {
+            "full_calibration": "cal",
+            "save_location": "save",
+            "recalc_vanadium": False
+        })
+        self.model.set_settings_dict.assert_called_with({
+            "full_calibration": "cal",
+            "save_location": "save",
+            "recalc_vanadium": False
+        })
+        self.assertEqual(self.view.close.call_count, 0)
+
+    def test_save_settings_and_close(self):
+        self.view.get_save_location.return_value = "save"
+        self.view.get_full_calibration.return_value = "cal"
+        self.view.get_van_recalc.return_value = False
+
+        self.presenter.save_and_close_dialog()
+
+        self.assertEqual(self.presenter.settings, {
+            "full_calibration": "cal",
+            "save_location": "save",
+            "recalc_vanadium": False
+        })
+        self.model.set_settings_dict.assert_called_with({
+            "full_calibration": "cal",
+            "save_location": "save",
+            "recalc_vanadium": False
+        })
+        self.assertEqual(self.view.close.call_count, 1)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/scripts/Engineering/gui/engineering_diffraction/tabs/calibration/model.py b/scripts/Engineering/gui/engineering_diffraction/tabs/calibration/model.py
index 6616e2367296727778d173acfd411e730fc61424..24357c27e2aae6f9594e6d75e3eb6cf146cdae74 100644
--- a/scripts/Engineering/gui/engineering_diffraction/tabs/calibration/model.py
+++ b/scripts/Engineering/gui/engineering_diffraction/tabs/calibration/model.py
@@ -13,19 +13,18 @@ import matplotlib.pyplot as plt
 
 from mantid.api import AnalysisDataService as Ads
 from mantid.kernel import logger
-from mantid.simpleapi import Load, EnggCalibrate, DeleteWorkspace, CloneWorkspace, \
+from mantid.simpleapi import EnggCalibrate, DeleteWorkspace, CloneWorkspace, \
     CreateWorkspace, AppendSpectra, CreateEmptyTableWorkspace
 from Engineering.EnggUtils import write_ENGINX_GSAS_iparam_file
 from Engineering.gui.engineering_diffraction.tabs.common import vanadium_corrections
 from Engineering.gui.engineering_diffraction.tabs.common import path_handling
+from Engineering.gui.engineering_diffraction.settings.settings_helper import get_setting
 
 VANADIUM_INPUT_WORKSPACE_NAME = "engggui_vanadium_ws"
 CURVES_WORKSPACE_NAME = "engggui_vanadium_curves"
 INTEGRATED_WORKSPACE_NAME = "engggui_vanadium_integration"
 CALIB_PARAMS_WORKSPACE_NAME = "engggui_calibration_banks_parameters"
 
-CALIBRATION_DIR = path.join(path_handling.OUT_FILES_ROOT_DIR, "Calibration", "")
-
 NORTH_BANK_TEMPLATE_FILE = "template_ENGINX_241391_236516_North_bank.prm"
 SOUTH_BANK_TEMPLATE_FILE = "template_ENGINX_241391_236516_South_bank.prm"
 
@@ -47,8 +46,14 @@ class CalibrationModel(object):
         """
         van_integration, van_curves = vanadium_corrections.fetch_correction_workspaces(
             vanadium_path, instrument, rb_num=rb_num)
-        sample_workspace = self.load_sample(sample_path)
-        output = self.run_calibration(sample_workspace, van_integration, van_curves)
+        sample_workspace = path_handling.load_workspace(sample_path)
+        full_calib_path = get_setting(path_handling.INTERFACES_SETTINGS_GROUP,
+                                      path_handling.ENGINEERING_PREFIX, "full_calibration")
+        if full_calib_path is not None and path.exists(full_calib_path):
+            full_calib = path_handling.load_workspace(full_calib_path)
+            output = self.run_calibration(sample_workspace, van_integration, van_curves, full_calib_ws=full_calib)
+        else:
+            output = self.run_calibration(sample_workspace, van_integration, van_curves)
         if plot_output:
             self._plot_vanadium_curves()
             for i in range(2):
@@ -64,10 +69,10 @@ class CalibrationModel(object):
             params_table.append([i, difc[i], 0.0, tzero[i]])
         self.update_calibration_params_table(params_table)
 
-        self.create_output_files(CALIBRATION_DIR, difc, tzero, sample_path, vanadium_path,
-                                 instrument)
+        calib_dir = path.join(path_handling.get_output_path(), "Calibration", "")
+        self.create_output_files(calib_dir, difc, tzero, sample_path, vanadium_path, instrument)
         if rb_num:
-            user_calib_dir = path.join(path_handling.OUT_FILES_ROOT_DIR, "User", rb_num,
+            user_calib_dir = path.join(path_handling.get_output_path(), "User", rb_num,
                                        "Calibration", "")
             self.create_output_files(user_calib_dir, difc, tzero, sample_path, vanadium_path,
                                      instrument)
@@ -180,33 +185,31 @@ class CalibrationModel(object):
             ax.set_xlabel("Expected Peaks Centre(dSpacing, A)")
         fig.show()
 
-    @staticmethod
-    def load_sample(sample_run_no):
-        try:
-            return Load(Filename=sample_run_no, OutputWorkspace="engggui_calibration_sample_ws")
-        except Exception as e:
-            logger.error("Error while loading calibration sample data. "
-                         "Could not run the algorithm Load successfully for the calibration sample "
-                         "(run number: " + str(sample_run_no) + "). Error description: " + str(e) +
-                         " Please check also the previous log messages for details.")
-            raise RuntimeError
-
-    def run_calibration(self, sample_ws, van_integration, van_curves):
+    def run_calibration(self, sample_ws, van_integration, van_curves, full_calib_ws=None):
         """
         Runs the main Engineering calibration algorithm.
         :param sample_ws: The workspace with the sample data.
         :param van_integration: The integration values from the vanadium corrections
         :param van_curves: The curves from the vanadium corrections.
+        :param full_calib_ws: Full pixel calibration of the detector (optional)
         :return: The output of the algorithm.
         """
         output = [None] * 2
         for i in range(2):
             table_name = self._generate_table_workspace_name(i)
-            output[i] = EnggCalibrate(InputWorkspace=sample_ws,
-                                      VanIntegrationWorkspace=van_integration,
-                                      VanCurvesWorkspace=van_curves,
-                                      Bank=str(i + 1),
-                                      FittedPeaks=table_name)
+            if full_calib_ws is not None:
+                output[i] = EnggCalibrate(InputWorkspace=sample_ws,
+                                          VanIntegrationWorkspace=van_integration,
+                                          VanCurvesWorkspace=van_curves,
+                                          Bank=str(i + 1),
+                                          FittedPeaks=table_name)
+            else:
+                output[i] = EnggCalibrate(InputWorkspace=sample_ws,
+                                          VanIntegrationWorkspace=van_integration,
+                                          VanCurvesWorkspace=van_curves,
+                                          Bank=str(i + 1),
+                                          FittedPeaks=table_name,
+                                          DetectorPositions=full_calib_ws)
         return output
 
     def create_output_files(self, calibration_dir, difc, tzero, sample_path, vanadium_path,
diff --git a/scripts/Engineering/gui/engineering_diffraction/tabs/calibration/test/test_calib_model.py b/scripts/Engineering/gui/engineering_diffraction/tabs/calibration/test/test_calib_model.py
index 60e8d530feb89353e116cd204610f5244169e85b..e5ea4fde9e1c83df09746247076e47c28e0698f1 100644
--- a/scripts/Engineering/gui/engineering_diffraction/tabs/calibration/test/test_calib_model.py
+++ b/scripts/Engineering/gui/engineering_diffraction/tabs/calibration/test/test_calib_model.py
@@ -34,7 +34,7 @@ class CalibrationModelTest(unittest.TestCase):
     @patch(class_path + '.update_calibration_params_table')
     @patch(class_path + '.create_output_files')
     @patch(class_path + '.run_calibration')
-    @patch(class_path + '.load_sample')
+    @patch(file_path + ".path_handling.load_workspace")
     @patch(file_path + '.vanadium_corrections.fetch_correction_workspaces')
     def test_EnggVanadiumCorrections_algorithm_is_called(self, van, load_sample, calib,
                                                          output_files, update_table):
@@ -44,7 +44,7 @@ class CalibrationModelTest(unittest.TestCase):
 
     @patch(class_path + '.update_calibration_params_table')
     @patch(class_path + '.create_output_files')
-    @patch(class_path + '.load_sample')
+    @patch(file_path + ".path_handling.load_workspace")
     @patch(class_path + '.run_calibration')
     @patch(file_path + '.vanadium_corrections.fetch_correction_workspaces')
     def test_fetch_vanadium_is_called(self, van_corr, calibrate_alg, load_sample, output_files,
@@ -53,9 +53,26 @@ class CalibrationModelTest(unittest.TestCase):
         self.model.create_new_calibration(VANADIUM_NUMBER, CERIUM_NUMBER, False, "ENGINX")
         self.assertEqual(van_corr.call_count, 1)
 
+    @patch(file_path + '.path.exists')
+    @patch(file_path + '.get_setting')
     @patch(class_path + '.update_calibration_params_table')
     @patch(class_path + '.create_output_files')
-    @patch(class_path + '.load_sample')
+    @patch(file_path + ".path_handling.load_workspace")
+    @patch(class_path + '.run_calibration')
+    @patch(file_path + '.vanadium_corrections.fetch_correction_workspaces')
+    def test_having_full_calib_set_uses_file(self, van_corr, calibrate_alg, load_workspace, output_files,
+                                             update_table, setting, path):
+        path.return_value = True
+        setting.return_value = "mocked/out/path"
+        van_corr.return_value = ("mocked_integration", "mocked_curves")
+        load_workspace.return_value = "mocked_workspace"
+        self.model.create_new_calibration(VANADIUM_NUMBER, CERIUM_NUMBER, False, "ENGINX")
+        calibrate_alg.assert_called_with("mocked_workspace", "mocked_integration", "mocked_curves",
+                                         full_calib_ws="mocked_workspace")
+
+    @patch(class_path + '.update_calibration_params_table')
+    @patch(class_path + '.create_output_files')
+    @patch(file_path + ".path_handling.load_workspace")
     @patch(file_path + '.vanadium_corrections.fetch_correction_workspaces')
     @patch(class_path + '._plot_vanadium_curves')
     @patch(class_path + '._generate_difc_tzero_workspace')
@@ -75,7 +92,7 @@ class CalibrationModelTest(unittest.TestCase):
 
     @patch(class_path + '.update_calibration_params_table')
     @patch(class_path + '.create_output_files')
-    @patch(class_path + '.load_sample')
+    @patch(file_path + ".path_handling.load_workspace")
     @patch(file_path + '.vanadium_corrections.fetch_correction_workspaces')
     @patch(class_path + '._plot_vanadium_curves')
     @patch(class_path + '._plot_difc_tzero')
@@ -93,7 +110,7 @@ class CalibrationModelTest(unittest.TestCase):
 
     @patch(class_path + '.update_calibration_params_table')
     @patch(class_path + '.create_output_files')
-    @patch(class_path + '.load_sample')
+    @patch(file_path + ".path_handling.load_workspace")
     @patch(file_path + '.vanadium_corrections.fetch_correction_workspaces')
     @patch(class_path + '._plot_vanadium_curves')
     @patch(class_path + '._plot_difc_tzero')
@@ -107,7 +124,7 @@ class CalibrationModelTest(unittest.TestCase):
 
     @patch(class_path + '.update_calibration_params_table')
     @patch(class_path + '.create_output_files')
-    @patch(class_path + '.load_sample')
+    @patch(file_path + ".path_handling.load_workspace")
     @patch(file_path + '.vanadium_corrections.fetch_correction_workspaces')
     @patch(class_path + '.run_calibration')
     def test_calibration_params_table_is_updated(self, calibrate_alg, vanadium_alg, load_sample,
diff --git a/scripts/Engineering/gui/engineering_diffraction/tabs/common/path_handling.py b/scripts/Engineering/gui/engineering_diffraction/tabs/common/path_handling.py
index 35da5482bfb72effedfcd22855f0363533fd28c5..ca37e6d9d6ef57218cba4d7db6bba44b5ae3bb7a 100644
--- a/scripts/Engineering/gui/engineering_diffraction/tabs/common/path_handling.py
+++ b/scripts/Engineering/gui/engineering_diffraction/tabs/common/path_handling.py
@@ -8,9 +8,29 @@
 from __future__ import (absolute_import, division, print_function)
 
 from os import path
+from mantid.kernel import logger
+from mantid.simpleapi import Load
+from Engineering.gui.engineering_diffraction.settings.settings_helper import get_setting
 
-OUT_FILES_ROOT_DIR = path.join(path.expanduser("~"), "Engineering_Mantid")
+INTERFACES_SETTINGS_GROUP = "CustomInterfaces"
+ENGINEERING_PREFIX = "EngineeringDiffraction2/"
 
 
 def get_run_number_from_path(run_path, instrument):
     return path.splitext(path.basename(run_path))[0].replace(instrument, '').lstrip('0')
+
+
+def get_output_path():
+    location = get_setting(INTERFACES_SETTINGS_GROUP, ENGINEERING_PREFIX, "save_location")
+    return location if location is not None else ""
+
+
+def load_workspace(file_path):
+    try:
+        return Load(Filename=file_path, OutputWorkspace="engggui_calibration_sample_ws")
+    except Exception as e:
+        logger.error("Error while loading workspace. "
+                     "Could not run the algorithm Load successfully for the data file "
+                     "(path: " + str(file_path) + "). Error description: " + str(e) +
+                     " Please check also the previous log messages for details.")
+        raise RuntimeError
diff --git a/scripts/Engineering/gui/engineering_diffraction/tabs/common/test/test_vanadium_corrections.py b/scripts/Engineering/gui/engineering_diffraction/tabs/common/test/test_vanadium_corrections.py
index 9fa9503123401c3611d891c5a1816bc513030851..9468b3183a861f4f355a5410f145b36717f7fd2e 100644
--- a/scripts/Engineering/gui/engineering_diffraction/tabs/common/test/test_vanadium_corrections.py
+++ b/scripts/Engineering/gui/engineering_diffraction/tabs/common/test/test_vanadium_corrections.py
@@ -59,17 +59,19 @@ class VanadiumCorrectionsTest(unittest.TestCase):
         self.assertEqual(0, van_correction.call_count)
         self.assertEqual(0, save.call_count)
 
+    @patch(dir_path + ".vanadium_corrections.path_handling.get_output_path")
     @patch(dir_path + ".vanadium_corrections.makedirs")
-    def test_file_path_generation(self, makedirs):
+    def test_file_path_generation(self, makedirs, out_path):
+        out_path.return_value = path.join(path.expanduser("~"), "Test_Directory")
         vanadium_run_number = "1234"
-        engineering_path = path.join(path.expanduser("~"), "Engineering_Mantid")
+        engineering_path = path.join(path.expanduser("~"), "Test_Directory")
         if path.exists(engineering_path):
             rmtree(engineering_path)
         output = vanadium_corrections._generate_saved_workspace_file_paths(vanadium_run_number)
         self.assertEqual(output,
-                         (path.join(path.expanduser("~"), "Engineering_Mantid", "Vanadium_Runs",
+                         (path.join(path.expanduser("~"), "Test_Directory", "Vanadium_Runs",
                                     "1234_precalculated_vanadium_run_integration.nxs"),
-                          path.join(path.expanduser("~"), "Engineering_Mantid", "Vanadium_Runs",
+                          path.join(path.expanduser("~"), "Test_Directory", "Vanadium_Runs",
                                     "1234_precalculated_vanadium_run_bank_curves.nxs")))
         self.assertEqual(1, makedirs.call_count)
 
diff --git a/scripts/Engineering/gui/engineering_diffraction/tabs/common/vanadium_corrections.py b/scripts/Engineering/gui/engineering_diffraction/tabs/common/vanadium_corrections.py
index 2f79c91c4990f585815bb7e6186540be7c01085a..0fa938deb76c981da0d00947a391b6b2882a6e1b 100644
--- a/scripts/Engineering/gui/engineering_diffraction/tabs/common/vanadium_corrections.py
+++ b/scripts/Engineering/gui/engineering_diffraction/tabs/common/vanadium_corrections.py
@@ -14,6 +14,7 @@ from mantid.simpleapi import logger, Load, EnggVanadiumCorrections, SaveNexus
 from mantid.simpleapi import AnalysisDataService as Ads
 
 from Engineering.gui.engineering_diffraction.tabs.common import path_handling
+from Engineering.gui.engineering_diffraction.settings.settings_helper import get_setting
 
 VANADIUM_INPUT_WORKSPACE_NAME = "engggui_vanadium_ws"
 CURVES_WORKSPACE_NAME = "engggui_vanadium_curves"
@@ -35,7 +36,9 @@ def fetch_correction_workspaces(vanadium_path, instrument, rb_num=""):
     """
     vanadium_number = path_handling.get_run_number_from_path(vanadium_path, instrument)
     integ_path, curves_path = _generate_saved_workspace_file_paths(vanadium_number)
-    if path.exists(curves_path) and path.exists(integ_path):  # Check if the cached files exist.
+    force_recalc = get_setting(path_handling.INTERFACES_SETTINGS_GROUP,
+                               path_handling.ENGINEERING_PREFIX, "recalc_vanadium", return_type=bool)
+    if path.exists(curves_path) and path.exists(integ_path) and not force_recalc:  # Check if the cached files exist.
         try:
             integ_workspace = Load(Filename=integ_path, OutputWorkspace=INTEGRATED_WORKSPACE_NAME)
             curves_workspace = Load(Filename=curves_path, OutputWorkspace=CURVES_WORKSPACE_NAME)
@@ -48,7 +51,7 @@ def fetch_correction_workspaces(vanadium_path, instrument, rb_num=""):
             return integ_workspace, curves_workspace
         except RuntimeError as e:
             logger.error(
-                "Problem loading existing vanadium calculations. Creating new cached files. Description: "
+                "Problem loading existing vanadium calculations. Creating new files. Description: "
                 + str(e))
     integ_workspace, curves_workspace = _calculate_vanadium_correction(vanadium_path)
     _save_correction_files(integ_workspace, integ_path, curves_workspace, curves_path)
@@ -113,10 +116,10 @@ def _generate_saved_workspace_file_paths(vanadium_number, rb_num=""):
     integrated_filename = vanadium_number + SAVED_FILE_INTEG_SUFFIX
     curves_filename = vanadium_number + SAVED_FILE_CURVE_SUFFIX
     if rb_num:
-        vanadium_dir = path.join(path_handling.OUT_FILES_ROOT_DIR, "User", rb_num,
+        vanadium_dir = path.join(path_handling.get_output_path(), "User", rb_num,
                                  VANADIUM_DIRECTORY_NAME)
     else:
-        vanadium_dir = path.join(path_handling.OUT_FILES_ROOT_DIR, VANADIUM_DIRECTORY_NAME)
+        vanadium_dir = path.join(path_handling.get_output_path(), VANADIUM_DIRECTORY_NAME)
     if not path.exists(vanadium_dir):
         makedirs(vanadium_dir)
     return path.join(vanadium_dir, integrated_filename), path.join(vanadium_dir, curves_filename)
diff --git a/scripts/Engineering/gui/engineering_diffraction/tabs/focus/model.py b/scripts/Engineering/gui/engineering_diffraction/tabs/focus/model.py
index 9b67f260aba5d3b9110b2f22c71bc8c6509d1b0a..d4cd2e5f713959ab55c51151c63c049c16522bfd 100644
--- a/scripts/Engineering/gui/engineering_diffraction/tabs/focus/model.py
+++ b/scripts/Engineering/gui/engineering_diffraction/tabs/focus/model.py
@@ -12,7 +12,8 @@ from matplotlib import gridspec
 import matplotlib.pyplot as plt
 
 from Engineering.gui.engineering_diffraction.tabs.common import vanadium_corrections, path_handling
-from mantid.simpleapi import EnggFocus, Load, logger, AnalysisDataService as Ads, SaveNexus, SaveGSS, SaveFocusedXYE
+from Engineering.gui.engineering_diffraction.settings.settings_helper import get_setting
+from mantid.simpleapi import EnggFocus, logger, AnalysisDataService as Ads, SaveNexus, SaveGSS, SaveFocusedXYE
 
 SAMPLE_RUN_WORKSPACE_NAME = "engggui_focusing_input_ws"
 FOCUSED_OUTPUT_WORKSPACE_NAME = "engggui_focusing_output_ws_bank_"
@@ -33,12 +34,18 @@ class FocusModel(object):
             return
         integration_workspace = Ads.retrieve(vanadium_corrections.INTEGRATED_WORKSPACE_NAME)
         curves_workspace = Ads.retrieve(vanadium_corrections.CURVES_WORKSPACE_NAME)
-        sample_workspace = self._load_focus_sample_run(sample_path)
+        sample_workspace = path_handling.load_workspace(sample_path)
         output_workspaces = []
+        full_calib_path = get_setting(path_handling.INTERFACES_SETTINGS_GROUP,
+                                      path_handling.ENGINEERING_PREFIX, "full_calibration")
+        if full_calib_path is not None and path.exists(full_calib_path):
+            full_calib_workspace = path_handling.load_workspace(full_calib_path)
+        else:
+            full_calib_workspace = None
         for name in banks:
             output_workspace_name = FOCUSED_OUTPUT_WORKSPACE_NAME + str(name)
             self._run_focus(sample_workspace, output_workspace_name, integration_workspace,
-                            curves_workspace, name)
+                            curves_workspace, name, full_calib_workspace)
             output_workspaces.append(output_workspace_name)
             # Save the output to the file system.
             self._save_output(instrument, sample_path, name, output_workspace_name, rb_num)
@@ -47,30 +54,32 @@ class FocusModel(object):
             self._plot_focused_workspaces(output_workspaces)
 
     @staticmethod
-    def _run_focus(input_workspace, output_workspace, vanadium_integration_ws, vanadium_curves_ws,
-                   bank):
+    def _run_focus(input_workspace,
+                   output_workspace,
+                   vanadium_integration_ws,
+                   vanadium_curves_ws,
+                   bank,
+                   full_calib_ws=None):
         try:
-            return EnggFocus(InputWorkspace=input_workspace,
-                             OutputWorkspace=output_workspace,
-                             VanIntegrationWorkspace=vanadium_integration_ws,
-                             VanCurvesWorkspace=vanadium_curves_ws,
-                             Bank=bank)
+            if full_calib_ws is not None:
+                return EnggFocus(InputWorkspace=input_workspace,
+                                 OutputWorkspace=output_workspace,
+                                 VanIntegrationWorkspace=vanadium_integration_ws,
+                                 VanCurvesWorkspace=vanadium_curves_ws,
+                                 Bank=bank,
+                                 DetectorPositions=full_calib_ws)
+            else:
+                return EnggFocus(InputWorkspace=input_workspace,
+                                 OutputWorkspace=output_workspace,
+                                 VanIntegrationWorkspace=vanadium_integration_ws,
+                                 VanCurvesWorkspace=vanadium_curves_ws,
+                                 Bank=bank)
         except RuntimeError as e:
             logger.error(
                 "Error in focusing, Could not run the EnggFocus algorithm successfully for bank " +
                 str(bank) + ". Error Description: " + str(e))
             raise RuntimeError()
 
-    @staticmethod
-    def _load_focus_sample_run(sample_path):
-        try:
-            return Load(Filename=sample_path, OutputWorkspace=SAMPLE_RUN_WORKSPACE_NAME)
-        except RuntimeError as e:
-            logger.error(
-                "Error while loading sample data for focusing. Could not load the sample with filename: "
-                + sample_path + ". Error Description: " + str(e))
-            raise RuntimeError
-
     @staticmethod
     def _plot_focused_workspaces(focused_workspaces):
         fig = plt.figure()
@@ -104,36 +113,36 @@ class FocusModel(object):
     def _save_focused_output_files_as_gss(self, instrument, sample_path, bank, sample_workspace,
                                           rb_num):
         gss_output_path = path.join(
-            path_handling.OUT_FILES_ROOT_DIR, "Focus",
+            path_handling.get_output_path(), "Focus",
             self._generate_output_file_name(instrument, sample_path, bank, ".gss"))
         SaveGSS(InputWorkspace=sample_workspace, Filename=gss_output_path)
         if rb_num is not None:
             gss_output_path = path.join(
-                path_handling.OUT_FILES_ROOT_DIR, "User", rb_num, "Focus",
+                path_handling.get_output_path(), "User", rb_num, "Focus",
                 self._generate_output_file_name(instrument, sample_path, bank, ".gss"))
             SaveGSS(InputWorkspace=sample_workspace, Filename=gss_output_path)
 
     def _save_focused_output_files_as_nexus(self, instrument, sample_path, bank, sample_workspace,
                                             rb_num):
         nexus_output_path = path.join(
-            path_handling.OUT_FILES_ROOT_DIR, "Focus",
+            path_handling.get_output_path(), "Focus",
             self._generate_output_file_name(instrument, sample_path, bank, ".nxs"))
         SaveNexus(InputWorkspace=sample_workspace, Filename=nexus_output_path)
         if rb_num is not None:
             nexus_output_path = path.join(
-                path_handling.OUT_FILES_ROOT_DIR, "User", rb_num, "Focus",
+                path_handling.get_output_path(), "User", rb_num, "Focus",
                 self._generate_output_file_name(instrument, sample_path, bank, ".nxs"))
             SaveNexus(InputWorkspace=sample_workspace, Filename=nexus_output_path)
 
     def _save_focused_output_files_as_xye(self, instrument, sample_path, bank, sample_workspace,
                                           rb_num):
         xye_output_path = path.join(
-            path_handling.OUT_FILES_ROOT_DIR, "Focus",
+            path_handling.get_output_path(), "Focus",
             self._generate_output_file_name(instrument, sample_path, bank, ".dat"))
         SaveFocusedXYE(InputWorkspace=sample_workspace, Filename=xye_output_path, SplitFiles=False)
         if rb_num is not None:
             xye_output_path = path.join(
-                path_handling.OUT_FILES_ROOT_DIR, "User", rb_num, "Focus",
+                path_handling.get_output_path(), "User", rb_num, "Focus",
                 self._generate_output_file_name(instrument, sample_path, bank, ".dat"))
             SaveFocusedXYE(InputWorkspace=sample_workspace,
                            Filename=xye_output_path,
diff --git a/scripts/Engineering/gui/engineering_diffraction/tabs/focus/test/test_focus_model.py b/scripts/Engineering/gui/engineering_diffraction/tabs/focus/test/test_focus_model.py
index 53b8456052a5e0b8d271ec15a95631b49e75e377..bf476ed3a1ed7958cef5c0fb8f38e0f0aafaf309 100644
--- a/scripts/Engineering/gui/engineering_diffraction/tabs/focus/test/test_focus_model.py
+++ b/scripts/Engineering/gui/engineering_diffraction/tabs/focus/test/test_focus_model.py
@@ -25,7 +25,7 @@ class FocusModelTest(unittest.TestCase):
                                                    sample_path="this_is_mocked_out_too",
                                                    instrument="ENGINX")
 
-    @patch(file_path + ".FocusModel._load_focus_sample_run")
+    @patch(file_path + ".path_handling.load_workspace")
     @patch(file_path + ".vanadium_corrections.Ads.doesExist")
     def test_focus_cancelled_if_van_wsp_missing(self, ads_exist, load):
         ads_exist.return_value = False
@@ -35,7 +35,7 @@ class FocusModelTest(unittest.TestCase):
     @patch(file_path + ".Ads")
     @patch(file_path + ".FocusModel._save_output")
     @patch(file_path + ".FocusModel._run_focus")
-    @patch(file_path + ".FocusModel._load_focus_sample_run")
+    @patch(file_path + ".path_handling.load_workspace")
     def test_focus_run_for_each_bank(self, load_focus, run_focus, output, ads):
         ads.retrieve.return_value = "test_wsp"
         banks = ["1", "2"]
@@ -45,13 +45,13 @@ class FocusModelTest(unittest.TestCase):
         self.assertEqual(len(banks), run_focus.call_count)
         run_focus.assert_called_with("mocked_sample",
                                      model.FOCUSED_OUTPUT_WORKSPACE_NAME + banks[-1], "test_wsp",
-                                     "test_wsp", banks[-1])
+                                     "test_wsp", banks[-1], None)
 
     @patch(file_path + ".Ads")
     @patch(file_path + ".FocusModel._save_output")
     @patch(file_path + ".FocusModel._plot_focused_workspaces")
     @patch(file_path + ".FocusModel._run_focus")
-    @patch(file_path + ".FocusModel._load_focus_sample_run")
+    @patch(file_path + ".path_handling.load_workspace")
     @patch(file_path + ".vanadium_corrections.fetch_correction_workspaces")
     def test_focus_plotted_when_checked(self, fetch_van, load_focus, run_focus, plot_focus, output,
                                         ads):
@@ -67,7 +67,7 @@ class FocusModelTest(unittest.TestCase):
     @patch(file_path + ".FocusModel._save_output")
     @patch(file_path + ".FocusModel._plot_focused_workspaces")
     @patch(file_path + ".FocusModel._run_focus")
-    @patch(file_path + ".FocusModel._load_focus_sample_run")
+    @patch(file_path + ".path_handling.load_workspace")
     @patch(file_path + ".vanadium_corrections.fetch_correction_workspaces")
     def test_focus_not_plotted_when_not_checked(self, fetch_van, load_focus, run_focus, plot_focus,
                                                 output, ads):
@@ -83,7 +83,7 @@ class FocusModelTest(unittest.TestCase):
     @patch(file_path + ".SaveNexus")
     def test_save_output_files_with_no_RB_number(self, nexus, gss, xye):
         mocked_workspace = "mocked-workspace"
-        output_file = path.join(path_handling.OUT_FILES_ROOT_DIR, "Focus",
+        output_file = path.join(path_handling.get_output_path(), "Focus",
                                 "ENGINX_123_bank_North.nxs")
 
         self.model._save_output("ENGINX", "Path/To/ENGINX000123.whatever", "North",
diff --git a/scripts/Inelastic/CrystalField/normalisation.py b/scripts/Inelastic/CrystalField/normalisation.py
index 42c101bb894ab0c3809972101c702926e325ccff..89d9e25c9ff0d062b099976c792348c019164e3b 100644
--- a/scripts/Inelastic/CrystalField/normalisation.py
+++ b/scripts/Inelastic/CrystalField/normalisation.py
@@ -212,7 +212,7 @@ def split2range(*args, **kwargs):
         Nlm[bname] = splitting_factor
     ranges = norm2stev(IonNum=nre, **Nlm)
 
-    if argin['Output'].lower() is 'constraints':
+    if argin['Output'].lower() == 'constraints':
         constr = ''
         for bname in ranges.keys():
             constr += '%.4g<%s<%.4g,' % (-ranges[bname], bname, ranges[bname])
diff --git a/scripts/Inelastic/Direct/PropertiesDescriptors.py b/scripts/Inelastic/Direct/PropertiesDescriptors.py
index 23d18c73955d65f1909f5d938871b7241e947bc4..a22e2e03799c278d05e22420da64287e54218433 100644
--- a/scripts/Inelastic/Direct/PropertiesDescriptors.py
+++ b/scripts/Inelastic/Direct/PropertiesDescriptors.py
@@ -1201,7 +1201,7 @@ class SpectraToMonitorsList(PropDescriptor):
             return None
 
         if isinstance(spectra_list, string_types):
-            if spectra_list.lower() is 'none':
+            if spectra_list.lower() == 'none':
                 result = None
             else:
                 spectra = spectra_list.split(',')
diff --git a/scripts/Inelastic/IndirectImport.py b/scripts/Inelastic/IndirectImport.py
index d3a20fd4b4ddf998ff29c7c1156d5a4e83fb0766..a7bb64a857ba805c5d9c87d4c95c36b10fad1d86 100644
--- a/scripts/Inelastic/IndirectImport.py
+++ b/scripts/Inelastic/IndirectImport.py
@@ -10,9 +10,11 @@ the Indirect scripts depending on platform and numpy package version.
 
 We also deal with importing the mantidplot module outside of MantidPlot here.
 """
-
 from __future__ import (absolute_import, division, print_function)
+
+from contextlib import contextmanager
 import numpy.core.setup_common as numpy_cfg
+import os
 import platform
 import sys
 from mantid import logger
@@ -106,9 +108,23 @@ def import_f2py(lib_base_name):
     # Only proceed if we are indeed on one of the supported platforms.
     assert is_supported_f2py_platform()
 
-    lib_name = lib_base_name + _lib_suffix()
+    @contextmanager
+    def in_syspath(directory):
+        sys.path.insert(0, directory)
+        yield
+        sys.path.pop(0)
 
-    return __import__(lib_name)
+    lib_name = lib_base_name + _lib_suffix()
+    # In Python 3 f2py produces a filename properly tagged with the ABI compatability
+    # information and Python can import this without issue but it will take an untagged
+    # filename in preference so we cannot keep the Python2/Python3 ones in the same
+    # directory. We manipulate the sys.path temporarily to get the correct library.
+    version = sys.version_info
+    if version.major >= 3:
+        return __import__(lib_name)
+    else:
+        with in_syspath(os.path.join(os.path.dirname(__file__), 'cp27')):
+            return __import__(lib_name)
 
 
 def run_f2py_compatibility_test():
diff --git a/scripts/Inelastic/QLdata_win64.cp38-win_amd64.pyd b/scripts/Inelastic/QLdata_win64.cp38-win_amd64.pyd
new file mode 100644
index 0000000000000000000000000000000000000000..68170025432c02fcf2e4375c7e8b808d121c18c0
Binary files /dev/null and b/scripts/Inelastic/QLdata_win64.cp38-win_amd64.pyd differ
diff --git a/scripts/Inelastic/QLres_win64.cp38-win_amd64.pyd b/scripts/Inelastic/QLres_win64.cp38-win_amd64.pyd
new file mode 100644
index 0000000000000000000000000000000000000000..a05effad32b68e5f8337836553e1ff9aea0ad4c7
Binary files /dev/null and b/scripts/Inelastic/QLres_win64.cp38-win_amd64.pyd differ
diff --git a/scripts/Inelastic/QLse_win64.cp38-win_amd64.pyd b/scripts/Inelastic/QLse_win64.cp38-win_amd64.pyd
new file mode 100644
index 0000000000000000000000000000000000000000..f26afeee8cf8c299bfdf934b0bc2a3a597c56b55
Binary files /dev/null and b/scripts/Inelastic/QLse_win64.cp38-win_amd64.pyd differ
diff --git a/scripts/Inelastic/Quest_win64.cp38-win_amd64.pyd b/scripts/Inelastic/Quest_win64.cp38-win_amd64.pyd
new file mode 100644
index 0000000000000000000000000000000000000000..7c02c7a842f4911c3279a8e0dbb9c929e4071d92
Binary files /dev/null and b/scripts/Inelastic/Quest_win64.cp38-win_amd64.pyd differ
diff --git a/scripts/Inelastic/ResNorm_win64.cp38-win_amd64.pyd b/scripts/Inelastic/ResNorm_win64.cp38-win_amd64.pyd
new file mode 100644
index 0000000000000000000000000000000000000000..7daae32de8642e428ca5deecee245a8632d1e4b4
Binary files /dev/null and b/scripts/Inelastic/ResNorm_win64.cp38-win_amd64.pyd differ
diff --git a/scripts/Inelastic/QLdata_win64.pyd b/scripts/Inelastic/cp27/QLdata_win64.pyd
similarity index 100%
rename from scripts/Inelastic/QLdata_win64.pyd
rename to scripts/Inelastic/cp27/QLdata_win64.pyd
diff --git a/scripts/Inelastic/QLres_win64.pyd b/scripts/Inelastic/cp27/QLres_win64.pyd
similarity index 100%
rename from scripts/Inelastic/QLres_win64.pyd
rename to scripts/Inelastic/cp27/QLres_win64.pyd
diff --git a/scripts/Inelastic/QLse_win64.pyd b/scripts/Inelastic/cp27/QLse_win64.pyd
similarity index 100%
rename from scripts/Inelastic/QLse_win64.pyd
rename to scripts/Inelastic/cp27/QLse_win64.pyd
diff --git a/scripts/Inelastic/Quest_win64.pyd b/scripts/Inelastic/cp27/Quest_win64.pyd
similarity index 100%
rename from scripts/Inelastic/Quest_win64.pyd
rename to scripts/Inelastic/cp27/Quest_win64.pyd
diff --git a/scripts/Inelastic/ResNorm_win64.pyd b/scripts/Inelastic/cp27/ResNorm_win64.pyd
similarity index 100%
rename from scripts/Inelastic/ResNorm_win64.pyd
rename to scripts/Inelastic/cp27/ResNorm_win64.pyd
diff --git a/scripts/Inelastic/cylabs_win64.pyd b/scripts/Inelastic/cp27/cylabs_win64.pyd
similarity index 100%
rename from scripts/Inelastic/cylabs_win64.pyd
rename to scripts/Inelastic/cp27/cylabs_win64.pyd
diff --git a/scripts/Inelastic/muscat_win64.pyd b/scripts/Inelastic/cp27/muscat_win64.pyd
similarity index 100%
rename from scripts/Inelastic/muscat_win64.pyd
rename to scripts/Inelastic/cp27/muscat_win64.pyd
diff --git a/scripts/Inelastic/cylabs_win64.cp38-win_amd64.pyd b/scripts/Inelastic/cylabs_win64.cp38-win_amd64.pyd
new file mode 100644
index 0000000000000000000000000000000000000000..49f51382e30f7c123199b4f0509278381c81834a
Binary files /dev/null and b/scripts/Inelastic/cylabs_win64.cp38-win_amd64.pyd differ
diff --git a/scripts/Inelastic/muscat_win64.cp38-win_amd64.pyd b/scripts/Inelastic/muscat_win64.cp38-win_amd64.pyd
new file mode 100644
index 0000000000000000000000000000000000000000..7eeaf0122037daccf6b6212635df82bb91306d58
Binary files /dev/null and b/scripts/Inelastic/muscat_win64.cp38-win_amd64.pyd differ
diff --git a/scripts/LargeScaleStructures/geometry_writer.py b/scripts/LargeScaleStructures/geometry_writer.py
index 031bf1bda74447cf0d0cfdd370e1aaef54aeee40..a74d8f854d200f7c969e88aef6e4a8c578e3ca66 100644
--- a/scripts/LargeScaleStructures/geometry_writer.py
+++ b/scripts/LargeScaleStructures/geometry_writer.py
@@ -105,12 +105,12 @@ class MantidGeom(object):
         if location is None:
             self._append_child("location", sample, x="0.0", y="0.0", z="0.0")
         else:
-            if coord_type is "cartesian":
+            if coord_type == "cartesian":
                 self._append_child("location", sample,
                                    x=location[0],
                                    y=location[1],
                                    z=location[2])
-            if coord_type is "spherical":
+            if coord_type == "spherical":
                 self._append_child("location", sample,
                                    r=location[0],
                                    t=location[1],
diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_presenter.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_presenter.py
index 4429ca99e33c78d1e09569b30eda5b252e6336fe..e7a06d561adcfae05d702a5d3728d362726ada3f 100644
--- a/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_presenter.py
+++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_presenter.py
@@ -54,7 +54,7 @@ class MaxEntPresenter(object):
         else:
             self.view.setRun("")
 
-        if run is not "None":
+        if run != "None":
             final_options.append(run)
         self.view.addItems(final_options)
         start = int(
diff --git a/scripts/test/DirectReductionHelpersTest.py b/scripts/test/DirectReductionHelpersTest.py
index 6ab18eb09f38426d8b2412cbc614ab0954ec4a7f..13fa61a6b0c6e228d9682987dcbc68f7b1e58cdd 100644
--- a/scripts/test/DirectReductionHelpersTest.py
+++ b/scripts/test/DirectReductionHelpersTest.py
@@ -290,7 +290,7 @@ class DirectReductionHelpersTest(unittest.TestCase):
                     return attr
                 else:
                     attr_dic = object.__getattribute__(self,'__dict__')
-                    if name is '__dict__':
+                    if name == '__dict__':
                         return attr_dic
                     else:
                         return helpers.gen_getter(attr_dic,name)
@@ -346,7 +346,7 @@ class DirectReductionHelpersTest(unittest.TestCase):
             some_descriptor = SomeDescriptor()
 
             def __setattr__(self,name,val):
-                if name is 'special':
+                if name == 'special':
                     return
                 elif name in self.__class__.__dict__:
                     fp = self.__class__.__dict__[name]
@@ -356,7 +356,7 @@ class DirectReductionHelpersTest(unittest.TestCase):
 
 
             def __getattr__(self,name):
-                if name is 'special':
+                if name == 'special':
                     return self.__special
                 else:
                     tDict = object.__getattribute__(self,'__dict__')
diff --git a/tools/sip/sipwrapper.py b/tools/sip/sipwrapper.py
index 1ae794a8dcebdad1fd262e09fe97d617018b5c6c..fd72b1202f2f8468ca0328915523ce81eb5c7b61 100755
--- a/tools/sip/sipwrapper.py
+++ b/tools/sip/sipwrapper.py
@@ -66,7 +66,7 @@ def parse_arguments(argv):
     known_args, _ = parser.parse_known_args(argv)
     sip_cmd_line = argv[1:]
     if sys.platform == 'win32':
-        sip_cmd_line = map(lambda s: s.replace('\\', '\\\\'), sip_cmd_line)
+        sip_cmd_line = list(map(lambda s: s.replace('\\', '\\\\'), sip_cmd_line))
         # the executable may need .exe appending to be run with the cmd
         # processor
         sip_exe = sip_cmd_line[0] + '.exe'