diff --git a/Framework/DataHandling/CMakeLists.txt b/Framework/DataHandling/CMakeLists.txt
index 2c388a5b6a0d33d8ac24cfdd7a54acb4e21c3c2b..bb0ec2b4dcf031d3a5b131b3370a6395ae167eea 100644
--- a/Framework/DataHandling/CMakeLists.txt
+++ b/Framework/DataHandling/CMakeLists.txt
@@ -56,6 +56,7 @@
 	src/LoadEventPreNexus2.cpp
 	src/LoadFITS.cpp
 	src/LoadFullprofResolution.cpp
+  src/LoadGeometry.cpp
 	src/LoadGSASInstrumentFile.cpp
 	src/LoadGSS.cpp
 	src/LoadHelper.cpp
@@ -64,7 +65,7 @@
 	src/LoadILLIndirect2.cpp
 	src/LoadILLPolarizationFactors.cpp
 	src/LoadILLReflectometry.cpp
-    	src/LoadILLSANS.cpp
+  src/LoadILLSANS.cpp
 	src/LoadILLTOF2.cpp
 	src/LoadISISNexus2.cpp
 	src/LoadISISPolarizationEfficiencies.cpp
@@ -139,7 +140,7 @@
 	src/RotateInstrumentComponent.cpp
 	src/RotateSource.cpp
 	src/SNSDataArchive.cpp
-    	src/SaveANSTOAscii.cpp
+  src/SaveANSTOAscii.cpp
 	src/SaveAscii.cpp
 	src/SaveAscii2.cpp
 	src/SaveBankScatteringAngles.cpp
@@ -161,7 +162,7 @@
 	src/SaveILLCosmosAscii.cpp
 	src/SaveISISNexus.cpp
 	src/SaveIsawDetCal.cpp
-    	src/SaveMask.cpp
+  src/SaveMask.cpp
 	src/SaveNISTDAT.cpp
 	src/SaveNXSPE.cpp
 	src/SaveNXTomo.cpp
@@ -174,7 +175,7 @@
 	src/SavePHX.cpp
 	src/SaveParameterFile.cpp
 	src/SaveRKH.cpp
-        src/SaveReflectometryAscii.cpp
+  src/SaveReflectometryAscii.cpp
 	src/SaveReflCustomAscii.cpp
 	src/SaveReflThreeColumnAscii.cpp
 	src/SaveSESANS.cpp
@@ -251,6 +252,7 @@ set ( INC_FILES
 	inc/MantidDataHandling/LoadEventPreNexus2.h
 	inc/MantidDataHandling/LoadFITS.h
 	inc/MantidDataHandling/LoadFullprofResolution.h
+  inc/MantidDataHandling/LoadGeometry.h
 	inc/MantidDataHandling/LoadGSASInstrumentFile.h
 	inc/MantidDataHandling/LoadGSS.h
 	inc/MantidDataHandling/LoadHelper.h
@@ -365,7 +367,7 @@ set ( INC_FILES
 	inc/MantidDataHandling/SavePHX.h
 	inc/MantidDataHandling/SaveParameterFile.h
 	inc/MantidDataHandling/SaveRKH.h
-        inc/MantidDataHandling/SaveReflectometryAscii.h
+  inc/MantidDataHandling/SaveReflectometryAscii.h
 	inc/MantidDataHandling/SaveReflCustomAscii.h
 	inc/MantidDataHandling/SaveReflThreeColumnAscii.h
 	inc/MantidDataHandling/SaveSESANS.h
@@ -544,7 +546,7 @@ set ( TEST_FILES
 	SavePHXTest.h
 	SaveParameterFileTest.h
 	SaveRKHTest.h
-        SaveReflectometryAsciiTest.h
+  SaveReflectometryAsciiTest.h
 	SaveReflCustomAsciiTest.h
 	SaveReflThreeColumnAsciiTest.h
 	SaveSESANSTest.h
diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadGeometry.h b/Framework/DataHandling/inc/MantidDataHandling/LoadGeometry.h
new file mode 100644
index 0000000000000000000000000000000000000000..e01e4d07e460c275a3bfe4daad71dfa30347b07f
--- /dev/null
+++ b/Framework/DataHandling/inc/MantidDataHandling/LoadGeometry.h
@@ -0,0 +1,52 @@
+// Mantid Repository : https://github.com/mantidproject/mantid
+//
+// Copyright © 2007 ISIS Rutherford Appleton Laboratory UKRI,
+//     NScD Oak Ridge National Laboratory, European Spallation Source
+//     & Institut Laue - Langevin
+// SPDX - License - Identifier: GPL - 3.0 +
+#ifndef MANTID_DATAHANDLING_LOADGEOMETRY_H_
+#define MANTID_DATAHANDLING_LOADGEOMETRY_H_
+
+#include <string>
+
+namespace Mantid {
+namespace DataHandling {
+/**
+Loads an instrument definition file into a workspace, with the purpose of being
+able to visualise an instrument without requiring to read in a ISIS raw datafile
+first.
+The name of the algorithm refers to the fact that an instrument
+is loaded into a workspace but without any real data - hence the reason for
+referring to
+it as an 'empty' instrument.
+
+Required Properties:
+<UL>
+<LI> Filename - The name of an instrument definition file </LI>
+<LI> OutputWorkspace - The name of the workspace in which to store the imported
+instrument</LI>
+</UL>
+
+Optional Properties: (note that these options are not available if reading a
+multiperiod file)
+<UL>
+<LI> detector_value  - This value affect the colour of the detectorss in the
+instrument display window</LI>
+<LI> monitor_value  - This value affect the colour of the monitors in the
+instrument display window</LI>
+</UL>
+
+@author Anders Markvardsen, ISIS, RAL
+@date 31/10/2008
+*/
+namespace LoadGeometry {
+
+bool isIDF(const std::string &filename, const std::string &instrumentname);
+bool isNexus(const std::string &filename);
+
+} // namespace LoadGeometry
+
+} // namespace DataHandling
+} // namespace Mantid
+
+#endif /*MANTID_DATAHANDLING_LOADGEOMETRY_H_*/
diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadInstrument.h b/Framework/DataHandling/inc/MantidDataHandling/LoadInstrument.h
index d8e24ed3d32046875cc5c140d9900dc623457f2b..3edfe0ab89a420b6b0aa8dc001d1f188ecd9d934 100644
--- a/Framework/DataHandling/inc/MantidDataHandling/LoadInstrument.h
+++ b/Framework/DataHandling/inc/MantidDataHandling/LoadInstrument.h
@@ -78,6 +78,12 @@ public:
   const std::string category() const override {
     return "DataHandling\\Instrument";
   }
+  /// Load instrument from IDF XML file
+  void IDFInstrumentLoader();
+  /// Load instrument from Nexus file
+  void NexusInstrumentLoader();
+  /// Retrieve file name if undefined
+  void checkAndRetrieveInstrumentFilename();
 
 private:
   void init() override;
diff --git a/Framework/DataHandling/src/LoadEmptyInstrument.cpp b/Framework/DataHandling/src/LoadEmptyInstrument.cpp
index a145d5f1362239c08af2b1443c2270b1adcc6eef..bad262ec93ac968d4a82c0d7e0a5f866eb9e5021 100644
--- a/Framework/DataHandling/src/LoadEmptyInstrument.cpp
+++ b/Framework/DataHandling/src/LoadEmptyInstrument.cpp
@@ -5,6 +5,7 @@
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
 #include "MantidDataHandling/LoadEmptyInstrument.h"
+#include "MantidDataHandling/LoadGeometry.h"
 #include "MantidAPI/FileProperty.h"
 #include "MantidAPI/RegisterFileLoader.h"
 #include "MantidAPI/SpectrumInfo.h"
@@ -16,8 +17,8 @@
 #include "MantidIndexing/IndexInfo.h"
 #include "MantidKernel/BoundedValidator.h"
 #include "MantidKernel/ConfigService.h"
-#include "MantidKernel/FileDescriptor.h"
-#include "MantidKernel/NexusDescriptor.h"
+// #include "MantidKernel/FileDescriptor.h"
+// #include "MantidKernel/NexusDescriptor.h"
 #include "MantidKernel/OptionalBool.h"
 #include "MantidNexusGeometry/NexusGeometryParser.h"
 
@@ -32,25 +33,25 @@ using namespace Geometry;
 using namespace DataObjects;
 using namespace HistogramData;
 
-namespace {
-bool isIDF(const std::string &filename, const std::string &instrumentname) {
-  if (!filename.empty()) {
-    FileDescriptor descriptor(filename);
-    return ((descriptor.isAscii() && descriptor.extension() == ".xml"));
-  }
-  return !instrumentname.empty();
-}
-
-bool isNexus(const std::string &filename) {
-  if (!filename.empty() && !FileDescriptor(filename).isAscii(filename)) {
-    NexusDescriptor descriptor(filename);
-    return descriptor.isHDF(filename) &&
-           (descriptor.classTypeExists("NXcylindrical_geometry") ||
-            descriptor.classTypeExists("NXoff_geometry"));
-  }
-  return false;
-}
-} // namespace
+// namespace {
+// bool isIDF(const std::string &filename, const std::string &instrumentname) {
+//   if (!filename.empty()) {
+//     FileDescriptor descriptor(filename);
+//     return ((descriptor.isAscii() && descriptor.extension() == ".xml"));
+//   }
+//   return !instrumentname.empty();
+// }
+//
+// bool isNexus(const std::string &filename) {
+//   if (!filename.empty() && !FileDescriptor(filename).isAscii(filename)) {
+//     NexusDescriptor descriptor(filename);
+//     return descriptor.isHDF(filename) &&
+//            (descriptor.classTypeExists("NXcylindrical_geometry") ||
+//             descriptor.classTypeExists("NXoff_geometry"));
+//   }
+//   return false;
+// }
+// } // namespace
 
 /**
  * Return the confidence with with this algorithm can load the file
@@ -132,10 +133,10 @@ void LoadEmptyInstrument::exec() {
   const std::string instrumentname = getPropertyValue("InstrumentName");
   Instrument_const_sptr instrument;
   Progress prog(this, 0.0, 1.0, 10);
-  if (isNexus(filename)) {
+  if (LoadGeometry::isNexus(filename)) {
     prog.reportIncrement(0, "Loading geometry from file");
     instrument = NexusGeometry::NexusGeometryParser::createInstrument(filename);
-  } else if (isIDF(filename, instrumentname)) {
+  } else if (LoadGeometry::isIDF(filename, instrumentname)) {
     MatrixWorkspace_sptr ws = this->runLoadInstrument(filename, instrumentname);
     instrument = ws->getInstrument();
   } else {
diff --git a/Framework/DataHandling/src/LoadGeometry.cpp b/Framework/DataHandling/src/LoadGeometry.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d9f18d8bd8a3f725b32812f294d6ad7d1707cdea
--- /dev/null
+++ b/Framework/DataHandling/src/LoadGeometry.cpp
@@ -0,0 +1,33 @@
+// 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 +
+#include "MantidDataHandling/LoadGeometry.h"
+#include "MantidKernel/FileDescriptor.h"
+#include "MantidKernel/NexusDescriptor.h"
+
+namespace Mantid {
+namespace DataHandling {
+
+bool LoadGeometry::isIDF(const std::string &filename, const std::string &instrumentname) {
+  if (!filename.empty()) {
+    Mantid::Kernel::FileDescriptor descriptor(filename);
+    return ((descriptor.isAscii() && descriptor.extension() == ".xml"));
+  }
+  return !instrumentname.empty();
+}
+
+bool LoadGeometry::isNexus(const std::string &filename) {
+  if (!filename.empty() && !Mantid::Kernel::FileDescriptor(filename).isAscii(filename)) {
+    Mantid::Kernel::NexusDescriptor descriptor(filename);
+    return descriptor.isHDF(filename) &&
+           (descriptor.classTypeExists("NXcylindrical_geometry") ||
+            descriptor.classTypeExists("NXoff_geometry"));
+  }
+  return false;
+}
+
+} // namespace DataHandling
+} // namespace Mantid
diff --git a/Framework/DataHandling/src/LoadInstrument.cpp b/Framework/DataHandling/src/LoadInstrument.cpp
index dd956e8c9b381016765f4bb7f792a8cc71ba3de0..b6c5d21167cdd87ae69f89428eccdd15c2a0b0ae 100644
--- a/Framework/DataHandling/src/LoadInstrument.cpp
+++ b/Framework/DataHandling/src/LoadInstrument.cpp
@@ -4,19 +4,20 @@
 //     NScD Oak Ridge National Laboratory, European Spallation Source
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
-#include "MantidDataHandling/LoadInstrument.h"
 #include "MantidAPI/FileProperty.h"
 #include "MantidAPI/InstrumentDataService.h"
 #include "MantidAPI/MatrixWorkspace.h"
 #include "MantidAPI/Progress.h"
+#include "MantidDataHandling/LoadGeometry.h"
+#include "MantidDataHandling/LoadInstrument.h"
 #include "MantidGeometry/Instrument.h"
+#include "MantidGeometry/Instrument/InstrumentDefinitionParser.h"
 #include "MantidKernel/ArrayProperty.h"
 #include "MantidKernel/ConfigService.h"
 #include "MantidKernel/MandatoryValidator.h"
 #include "MantidKernel/OptionalBool.h"
 #include "MantidKernel/Strings.h"
-
-#include "MantidGeometry/Instrument/InstrumentDefinitionParser.h"
+#include "MantidNexusGeometry/NexusGeometryParser.h"
 #include <Poco/DOM/DOMParser.h>
 #include <Poco/DOM/Document.h>
 #include <Poco/DOM/Element.h>
@@ -28,6 +29,7 @@
 #include <Poco/Path.h>
 #include <fstream>
 #include <sstream>
+#include <iostream>
 
 namespace Mantid {
 namespace DataHandling {
@@ -48,12 +50,14 @@ void LoadInstrument::init() {
                       "Workspace", "Anonymous", Direction::InOut),
                   "The name of the workspace to load the instrument definition "
                   "into. Any existing instrument will be replaced.");
+  const std::vector<std::string> extensions{".xml", ".nxs", ".hdf5"};
   declareProperty(
       make_unique<FileProperty>("Filename", "", FileProperty::OptionalLoad,
-                                ".xml"),
+                                extensions),
       "The filename (including its full or relative path) of an instrument "
       "definition file. The file extension must either be .xml or .XML when "
-      "specifying an instrument definition file. Note Filename or "
+      "specifying an instrument definition file. Files can also be .hdf5 or "
+      ".nxs for usage with NeXus Geometry files. Note Filename or "
       "InstrumentName must be specified but not both.");
   declareProperty(
       make_unique<ArrayProperty<detid_t>>("MonitorList", Direction::Output),
@@ -99,6 +103,29 @@ void LoadInstrument::exec() {
   m_filename = getPropertyValue("Filename");
   m_instName = getPropertyValue("InstrumentName");
 
+  // Decide whether to use Nexus or IDF loading
+  if (LoadGeometry::isIDF(m_filename, m_instName))
+    IDFInstrumentLoader();
+  else if (LoadGeometry::isNexus(m_filename))
+    NexusInstrumentLoader();
+  else
+    throw Kernel::Exception::FileError("Instrument input cannot be read",m_filename);
+
+  // Set the monitors output property
+  // auto instr = m_workspace->getInstrument();
+  setProperty("MonitorList", (m_workspace->getInstrument())->getMonitors());
+
+  // Rebuild the spectra map for this workspace so that it matches the
+  // instrument
+  // if required
+  const OptionalBool RewriteSpectraMap = getProperty("RewriteSpectraMap");
+  if (RewriteSpectraMap == OptionalBool::True)
+    m_workspace->rebuildSpectraMapping();
+}
+
+/// Load instrument from IDF XML file
+void LoadInstrument::IDFInstrumentLoader() {
+
   // We will parse the XML using the InstrumentDefinitionParser
   InstrumentDefinitionParser parser;
 
@@ -129,28 +156,7 @@ void LoadInstrument::exec() {
   }
   // otherwise we need either Filename or InstrumentName to be set
   else {
-    // Retrieve the filename from the properties
-    if (m_filename.empty()) {
-      // look to see if an Instrument name provided in which case create
-      // IDF filename on the fly
-      if (m_instName.empty()) {
-        g_log.error("Either the InstrumentName or Filename property of "
-                    "LoadInstrument most be specified");
-        throw Kernel::Exception::FileError(
-            "Either the InstrumentName or Filename property of LoadInstrument "
-            "most be specified to load an IDF",
-            m_filename);
-      } else {
-        const std::string date = m_workspace->getWorkspaceStartDate();
-        m_filename = ExperimentInfo::getInstrumentFilename(m_instName, date);
-      }
-    }
-
-    if (m_filename.empty()) {
-      throw Exception::NotFoundError(
-          "Unable to find an Instrument Definition File for", m_instName);
-    }
-
+    checkAndRetrieveInstrumentFilename();
     // Remove the path from the filename for use with the InstrumentDataService
     const std::string::size_type stripPath = m_filename.find_last_of("\\/");
     std::string instrumentFile =
@@ -201,16 +207,39 @@ void LoadInstrument::exec() {
     if (!m_filename.empty())
       runLoadParameterFile();
   }
+}
 
-  // Set the monitors output property
-  setProperty("MonitorList", instrument->getMonitors());
+void LoadInstrument::NexusInstrumentLoader() {
+  checkAndRetrieveInstrumentFilename();
+  m_filename = ExperimentInfo::getInstrumentFilename(m_instName,
+               m_workspace->getWorkspaceStartDate());
+  Instrument_const_sptr instrument = NexusGeometry::NexusGeometryParser::createInstrument(m_filename);
+  m_workspace->setInstrument(instrument);
+  m_workspace->populateInstrumentParameters();
+}
 
-  // Rebuild the spectra map for this workspace so that it matches the
-  // instrument
-  // if required
-  const OptionalBool RewriteSpectraMap = getProperty("RewriteSpectraMap");
-  if (RewriteSpectraMap == OptionalBool::True)
-    m_workspace->rebuildSpectraMapping();
+/// Get the file name from the instrument name if it is not defined
+void LoadInstrument::checkAndRetrieveInstrumentFilename() {
+  // Retrieve the filename from the properties
+  if (m_filename.empty()) {
+    // look to see if an Instrument name provided in which case create
+    // filename on the fly
+    if (m_instName.empty()) {
+      g_log.error("Either the InstrumentName or Filename property of "
+                  "LoadInstrument most be specified");
+      throw Kernel::Exception::FileError(
+          "Either the InstrumentName or Filename property of LoadInstrument "
+          "most be specified to load an IDF",
+          m_filename);
+    } else {
+      m_filename = ExperimentInfo::getInstrumentFilename(m_instName,
+                   m_workspace->getWorkspaceStartDate());
+    }
+  }
+  if (m_filename.empty()) {
+    throw Exception::NotFoundError(
+        "Unable to find an Instrument Definition File for", m_instName);
+  }
 }
 
 //-----------------------------------------------------------------------------------------------------------------------
diff --git a/Framework/NexusGeometry/src/InstrumentBuilder.cpp b/Framework/NexusGeometry/src/InstrumentBuilder.cpp
index 8fa6a6dd4ce7687a862e5bfa3bd82bde8d6e8428..734356547c02d68782eca7018146fe234755d50b 100644
--- a/Framework/NexusGeometry/src/InstrumentBuilder.cpp
+++ b/Framework/NexusGeometry/src/InstrumentBuilder.cpp
@@ -171,6 +171,7 @@ InstrumentBuilder::createInstrument() {
       m_instrument->getName());
   auto *product = m_instrument.release();
   m_instrument = std::move(temp);
+  product->parseTreeAndCacheBeamline();
   // Some older compilers (Apple clang 7) don't support copy construction
   // std::unique_ptr<const T>(const std::ptr<T>&)
   return std::unique_ptr<const Geometry::Instrument>(product);