From 43d483c483ac77a6c38d23f9f711aa1f3d91c83d Mon Sep 17 00:00:00 2001
From: Michael Reuter <reuterma@ornl.gov>
Date: Fri, 2 Dec 2011 16:08:04 -0500
Subject: [PATCH] Refs #4240. Adding new presented for MDHistoWorkspace.

I've added two new presenters for the MDHistoWorkspace that follow closely
from the ones for the MDEventWorkspace. One of the main differences is the
non-reliance on recursion depth for the MDHistoWorkspace.
---
 Code/Mantid/Vates/VatesAPI/CMakeLists.txt     |   6 +
 .../MDHWInMemoryLoadingPresenter.h            |  59 ++++++
 .../inc/MantidVatesAPI/MDHWLoadingPresenter.h |  68 +++++++
 .../src/MDHWInMemoryLoadingPresenter.cpp      | 119 +++++++++++
 .../VatesAPI/src/MDHWLoadingPresenter.cpp     | 183 +++++++++++++++++
 .../test/MDHWInMemoryLoadingPresenterTest.h   | 192 ++++++++++++++++++
 .../VatesAPI/test/MDHWLoadingPresenterTest.h  | 124 +++++++++++
 7 files changed, 751 insertions(+)
 create mode 100644 Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MDHWInMemoryLoadingPresenter.h
 create mode 100644 Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MDHWLoadingPresenter.h
 create mode 100644 Code/Mantid/Vates/VatesAPI/src/MDHWInMemoryLoadingPresenter.cpp
 create mode 100644 Code/Mantid/Vates/VatesAPI/src/MDHWLoadingPresenter.cpp
 create mode 100644 Code/Mantid/Vates/VatesAPI/test/MDHWInMemoryLoadingPresenterTest.h
 create mode 100644 Code/Mantid/Vates/VatesAPI/test/MDHWLoadingPresenterTest.h

diff --git a/Code/Mantid/Vates/VatesAPI/CMakeLists.txt b/Code/Mantid/Vates/VatesAPI/CMakeLists.txt
index 4d2e6e5967b..42bc5493ad5 100644
--- a/Code/Mantid/Vates/VatesAPI/CMakeLists.txt
+++ b/Code/Mantid/Vates/VatesAPI/CMakeLists.txt
@@ -17,6 +17,8 @@ src/MDEWEventNexusLoadingPresenter.cpp
 src/MDEWRebinningPresenter.cpp
 src/MDEWLoadingPresenter.cpp
 src/MDEWInMemoryLoadingPresenter.cpp
+src/MDHWInMemoryLoadingPresenter.cpp
+src/MDHWLoadingPresenter.cpp
 src/MedianAndBelowThresholdRange.cpp
 src/MetadataToFieldData.cpp
 src/NoThresholdRange.cpp
@@ -62,6 +64,8 @@ inc/MantidVatesAPI/MDEWEventNexusLoadingPresenter.h
 inc/MantidVatesAPI/MDEWLoadingPresenter.h
 inc/MantidVatesAPI/MDEWInMemoryLoadingPresenter.h
 inc/MantidVatesAPI/MDEWRebinningPresenter.h
+inc/MantidVatesAPI/MDHWInMemoryLoadingPresenter.h
+inc/MantidVatesAPI/MDHWLoadingPresenter.h
 inc/MantidVatesAPI/MDLoadingPresenter.h
 inc/MantidVatesAPI/MDLoadingView.h
 inc/MantidVatesAPI/MDLoadingViewAdapter.h
@@ -127,6 +131,8 @@ test/MDEWEventNexusLoadingPresenterTest.h
 test/MDEWInMemoryLoadingPresenterTest.h
 test/MDEWLoadingPresenterTest.h
 test/MDEWRebinningPresenterTest.h
+test/MDHWInMemoryLoadingPresenterTest.h
+test/MDHWLoadingPresenterTest.h
 test/NullRebinningPresenterTest.h
 test/MetadataToFieldDataTest.h
 test/RebinningKnowledgeSerializerTest.h
diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MDHWInMemoryLoadingPresenter.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MDHWInMemoryLoadingPresenter.h
new file mode 100644
index 00000000000..ed6578cadff
--- /dev/null
+++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MDHWInMemoryLoadingPresenter.h
@@ -0,0 +1,59 @@
+#ifndef MANTID_VATES_MDHW_IN_MEMORY_LOADING_PRESENTER
+#define MANTID_VATES_MDHW_IN_MEMORY_LOADING_PRESENTER
+
+#include "MantidVatesAPI/MDHWLoadingPresenter.h"
+#include <boost/scoped_ptr.hpp>
+
+class vtkDataSet;
+namespace Mantid
+{
+  namespace VATES
+  {
+    /** 
+    @class MDHWInMemoryLoadingPresenter. Presenter for loading MDHWs directly from the ADS, does not touch the disk.
+    @date 02/12/2011
+
+    Copyright &copy; 2011 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+    */
+
+    class MDLoadingView;
+    class WorkspaceProvider;
+    class vtkDataSetFactory;
+    class DLLExport MDHWInMemoryLoadingPresenter : public MDHWLoadingPresenter
+    {
+    public:
+      MDHWInMemoryLoadingPresenter(MDLoadingView* view, WorkspaceProvider* repository, std::string wsName);
+      virtual vtkDataSet* execute(vtkDataSetFactory* factory, ProgressAction& eventHandler);
+      virtual void executeLoadMetadata();
+      virtual ~MDHWInMemoryLoadingPresenter();
+      virtual bool canReadFile() const;
+      virtual std::string getWorkspaceTypeName();
+    private:
+      /// Repository for accessing workspaces. At this level, does not specify how or where from.
+      boost::scoped_ptr<WorkspaceProvider> m_repository;
+      /// The name of the workspace.
+      const std::string m_wsName;
+      std::string m_wsTypeName;
+    };
+  }
+}
+
+#endif
diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MDHWLoadingPresenter.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MDHWLoadingPresenter.h
new file mode 100644
index 00000000000..adfba3f2b6b
--- /dev/null
+++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/MDHWLoadingPresenter.h
@@ -0,0 +1,68 @@
+#ifndef MANTID_VATES_MDHW_LOADING_PRESENTER
+#define MANTID_VATES_MDHW_LOADING_PRESENTER
+
+#include "MantidVatesAPI/MDLoadingPresenter.h"
+#include "MantidGeometry/MDGeometry/MDGeometryXMLBuilder.h"
+#include "MantidGeometry/MDGeometry/IMDDimension.h"
+#include "MantidAPI/IMDHistoWorkspace.h"
+
+namespace Mantid
+{
+  namespace VATES
+  {
+
+    /** 
+    @class MDHWLoadingPresenter, Abstract presenter encapsulating common operations used by all MDHW type loading. Reduces template bloat.
+    @author Owen Arnold, Tessella plc
+    @date 16/08/2011
+
+    Copyright &copy; 2011 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+    */
+    class MDLoadingView;
+    class DLLExport MDHWLoadingPresenter : public MDLoadingPresenter
+    {
+    public:
+      MDHWLoadingPresenter(MDLoadingView* view);
+      const std::string& getGeometryXML() const;
+      virtual bool hasTDimensionAvailable() const;
+      virtual std::vector<double> getTimeStepValues() const;
+      virtual ~MDHWLoadingPresenter();
+    protected:
+      /*---------------------------------------------------------------------------
+      Common/shared operations and members for all MDHW file-type loading.
+      ---------------------------------------------------------------------------*/
+      MDLoadingView* m_view;
+      
+      Mantid::Geometry::MDGeometryBuilderXML<Mantid::Geometry::StrictDimensionPolicy> xmlBuilder;
+      Mantid::Geometry::IMDDimension_sptr tDimension;
+      virtual void appendMetadata(vtkDataSet* visualDataSet, const std::string& wsName) ;
+      virtual void extractMetadata(Mantid::API::IMDHistoWorkspace_sptr histoWs);
+      virtual bool shouldLoad();
+      bool m_isSetup;
+      double m_time;
+      bool m_loadInMemory;
+      bool m_firstLoad;
+    };
+
+  }
+}
+
+#endif
diff --git a/Code/Mantid/Vates/VatesAPI/src/MDHWInMemoryLoadingPresenter.cpp b/Code/Mantid/Vates/VatesAPI/src/MDHWInMemoryLoadingPresenter.cpp
new file mode 100644
index 00000000000..9a85afc3770
--- /dev/null
+++ b/Code/Mantid/Vates/VatesAPI/src/MDHWInMemoryLoadingPresenter.cpp
@@ -0,0 +1,119 @@
+#include "MantidVatesAPI/MDHWInMemoryLoadingPresenter.h"
+#include "MantidVatesAPI/MDLoadingView.h"
+#include "MantidVatesAPI/ProgressAction.h"
+#include "MantidVatesAPI/vtkDataSetFactory.h"
+#include "MantidVatesAPI/WorkspaceProvider.h"
+#include "MantidGeometry/MDGeometry/MDGeometryXMLBuilder.h"
+#include <vtkUnstructuredGrid.h>
+
+namespace Mantid
+{
+  namespace VATES
+  {
+
+    /*
+    Constructor
+    @param view : MVP view
+    @param repository : Object for accessing the workspaces
+    @param wsName : Name of the workspace to use.
+    @throw invalid_argument if the workspace name is empty
+    @throw invalid_argument if the repository is null
+    @throw invalid_arument if view is null
+    */
+    MDHWInMemoryLoadingPresenter::MDHWInMemoryLoadingPresenter(MDLoadingView* view, WorkspaceProvider* repository, std::string wsName) : MDHWLoadingPresenter(view), m_repository(repository), m_wsName(wsName), m_wsTypeName("")
+    {
+      if(m_wsName.empty())
+      {
+        throw std::invalid_argument("The workspace name is empty.");
+      }
+      if(NULL == repository)
+      {
+        throw std::invalid_argument("The repository is NULL");
+      }
+      if(NULL == m_view)
+      {
+        throw std::invalid_argument("View is NULL.");
+      }
+    }
+
+     /*
+    Indicates whether this presenter is capable of handling the type of file that is attempted to be loaded.
+    @return false if the file cannot be read.
+    */
+    bool MDHWInMemoryLoadingPresenter::canReadFile() const
+    {
+      bool bCanReadIt = true;
+      if(!m_repository->canProvideWorkspace(m_wsName))
+      {
+        //The workspace does not exist.
+        bCanReadIt = false;
+      }
+      else if(NULL == boost::dynamic_pointer_cast<Mantid::API::IMDHistoWorkspace>(m_repository->fetchWorkspace(m_wsName)).get())
+      {
+        //The workspace can be found, but is not an IMDHistoWorkspace.
+        bCanReadIt = false;
+      }
+      else
+      {
+        //The workspace is present, and is of the correct type.
+        bCanReadIt = true;
+      }
+      return bCanReadIt;
+    }
+
+    /*
+    Executes the underlying algorithm to create the MVP model.
+    @param factory : visualisation factory to use.
+    @param eventHandler : object that encapuslates the direction of the gui change as the algorithm progresses.
+    */
+    vtkDataSet* MDHWInMemoryLoadingPresenter::execute(vtkDataSetFactory* factory, ProgressAction&)
+    {
+      using namespace Mantid::API;
+      using namespace Mantid::Geometry;
+
+      Workspace_sptr ws = m_repository->fetchWorkspace(m_wsName);
+      IMDHistoWorkspace_sptr histoWs = boost::dynamic_pointer_cast<Mantid::API::IMDHistoWorkspace>(ws);
+
+      //factory->setRecursionDepth(this->m_view->getRecursionDepth());
+      factory->initialize(histoWs);
+      vtkDataSet* visualDataSet = factory->create();
+      
+      /*extractMetaData needs to be re-run here because the first execution of this from ::executeLoadMetadata will not have ensured that all dimensions
+        have proper range extents set.
+      */
+      this->extractMetadata(histoWs);
+
+      this->appendMetadata(visualDataSet, histoWs->getName());
+      return visualDataSet;
+    }
+
+    /**
+     Executes any meta-data loading required.
+    */
+    void MDHWInMemoryLoadingPresenter::executeLoadMetadata()
+    {
+      using namespace Mantid::API;
+
+      Workspace_sptr ws = m_repository->fetchWorkspace(m_wsName);
+      IMDHistoWorkspace_sptr histoWs = boost::dynamic_pointer_cast<Mantid::API::IMDHistoWorkspace>(ws);
+      m_wsTypeName = typeid(*histoWs).name(); //Cache workspace type name
+      //Call base-class extraction method.
+      this->extractMetadata(histoWs);
+    }
+
+    ///Destructor
+    MDHWInMemoryLoadingPresenter::~MDHWInMemoryLoadingPresenter()
+    {
+      delete m_view;
+    }
+
+     /*
+      Getter for the workspace type name.
+      @return Workspace Type Name
+    */
+    std::string MDHWInMemoryLoadingPresenter::getWorkspaceTypeName()
+    {
+      return m_wsTypeName;
+    }
+  }
+}
diff --git a/Code/Mantid/Vates/VatesAPI/src/MDHWLoadingPresenter.cpp b/Code/Mantid/Vates/VatesAPI/src/MDHWLoadingPresenter.cpp
new file mode 100644
index 00000000000..6560e53bb91
--- /dev/null
+++ b/Code/Mantid/Vates/VatesAPI/src/MDHWLoadingPresenter.cpp
@@ -0,0 +1,183 @@
+#include "MantidVatesAPI/MDHWLoadingPresenter.h"
+#include "MantidVatesAPI/MDLoadingView.h"
+#include "MantidAPI/FrameworkManager.h"
+
+#include "MantidGeometry/MDGeometry/MDHistoDimension.h"
+#include "MantidMDAlgorithms/NullImplicitFunction.h"
+#include "MantidVatesAPI/RebinningKnowledgeSerializer.h"
+#include "MantidVatesAPI/MetadataToFieldData.h"
+#include "MantidVatesAPI/RebinningCutterXMLDefinitions.h"
+
+
+#include <vtkFieldData.h>
+#include <vtkDataSet.h>
+
+namespace Mantid
+{
+  namespace VATES
+  {
+    /// Constructor
+    MDHWLoadingPresenter::MDHWLoadingPresenter(MDLoadingView* view) : 
+    m_view(view), 
+    m_isSetup(false), 
+    m_time(-1),
+    m_loadInMemory(false),
+    m_firstLoad(true)
+    {
+      Mantid::API::FrameworkManager::Instance();
+    }
+
+    /// Destructor
+    MDHWLoadingPresenter::~MDHWLoadingPresenter()
+    {
+    }
+
+     /*
+    Extract the geometry and function information 
+    @param histoWs : histogram workspace to get the information from.
+    */
+    void MDHWLoadingPresenter::extractMetadata(Mantid::API::IMDHistoWorkspace_sptr histoWs)
+    {
+      using namespace Mantid::Geometry;
+      MDGeometryBuilderXML<StrictDimensionPolicy> refresh;
+      xmlBuilder= refresh; //Reassign.
+      std::vector<IMDDimension_sptr> dimensions;
+      size_t nDimensions = histoWs->getNumDims();
+      for (size_t d=0; d<nDimensions; d++)
+      {
+        IMDDimension_const_sptr inDim = histoWs->getDimension(d);
+        double min = inDim->getMinimum();
+        double max = inDim->getMaximum();
+        if (min > max)
+        {
+          min = 0.0;
+          max = 1.0;
+        }
+        //std::cout << "dim " << d << min << " to " <<  max << std::endl;
+        MDHistoDimension_sptr dim(new MDHistoDimension(inDim->getName(), inDim->getName(), inDim->getUnits(), min, max, size_t(10)));
+        dimensions.push_back(dim);
+      }
+
+      //Configuring the geometry xml builder allows the object panel associated with this reader to later
+      //determine how to display all geometry related properties.
+      if(nDimensions > 0)
+      {
+        xmlBuilder.addXDimension( dimensions[0] );
+      }
+      if(nDimensions > 1)
+      {
+        xmlBuilder.addYDimension( dimensions[1] );
+      }
+      if(nDimensions > 2)
+      {
+        xmlBuilder.addZDimension( dimensions[2]  );
+      }
+      if(nDimensions > 3)
+      {
+        tDimension = dimensions[3];
+        xmlBuilder.addTDimension(tDimension);
+      }
+      m_isSetup = true;
+    }
+
+    /**
+    Method determines whether loading/re-loading is necessary.
+    */
+    bool MDHWLoadingPresenter::shouldLoad()
+    {
+      double viewTime = m_view->getTime();
+      bool viewLoadInMemory = m_view->getLoadInMemory();
+
+      bool bExecute = false;
+      if(m_time != viewTime)
+      {
+        bExecute = false; //Time has changed. This DOES NOT require reloading.
+      }
+      if(m_loadInMemory != viewLoadInMemory)
+      {
+        bExecute = true; //Must reload with memory/file option.
+      }
+      if(m_firstLoad)
+      {
+        bExecute = true; //First time round. should execute underlying algorithm.
+      }
+
+      // Save state.
+      m_time = viewTime;
+      m_loadInMemory = viewLoadInMemory;
+      m_firstLoad = false;
+      //Return decision.
+      return bExecute;
+    }
+    
+    /*
+    Append the geometry and function information onto the outgoing vtkDataSet.
+    @param visualDataSet : outgoing dataset on which to append metadata.
+    @param wsName : name of the workspace.
+    */
+    void MDHWLoadingPresenter::appendMetadata(vtkDataSet* visualDataSet, const std::string& wsName)
+    {
+      using namespace Mantid::API;
+
+      vtkFieldData* outputFD = vtkFieldData::New();
+      
+      //Serialize metadata
+      RebinningKnowledgeSerializer serializer(LocationNotRequired);
+      serializer.setWorkspaceName(wsName);
+      serializer.setGeometryXML(xmlBuilder.create());
+      serializer.setImplicitFunction( Mantid::Geometry::MDImplicitFunction_sptr(new Mantid::MDAlgorithms::NullImplicitFunction()));
+      std::string xmlString = serializer.createXMLString();
+
+      //Add metadata to dataset.
+      MetadataToFieldData convert;
+      convert(outputFD, xmlString, XMLDefinitions::metaDataId().c_str());
+      visualDataSet->SetFieldData(outputFD);
+      outputFD->Delete();
+    }
+
+    /**
+    Gets the geometry in a string format.
+    @return geometry string ref.
+    @throw runtime_error if execute has not been run first.
+    */
+    const std::string& MDHWLoadingPresenter::getGeometryXML() const
+    {
+      if(!m_isSetup)
+      {
+        throw std::runtime_error("Have not yet run extractMetaData!");
+      }
+      return xmlBuilder.create();
+    }
+
+            /**
+    @return boolean indicating whether the T dimension is available.
+    @throw runtime_error if execute has not been run first.
+    */
+    bool MDHWLoadingPresenter::hasTDimensionAvailable() const
+    {
+      if(!m_isSetup)
+      {
+        throw std::runtime_error("Have not yet run ::extractMetaData!");
+      }
+      return xmlBuilder.hasTDimension();
+    }
+
+       /*
+    @return timestep values.
+    @throw runtime_error if execute has not been run first.
+    */
+    std::vector<double> MDHWLoadingPresenter::getTimeStepValues() const
+    {
+      if(!m_isSetup)
+      {
+        throw std::runtime_error("Have not yet run ::extractMetaData!");
+      }
+      std::vector<double> result;
+      for(size_t i = 0; i < tDimension->getNBins(); i++)
+      {
+        result.push_back(tDimension->getX(i));
+      }
+      return result;
+    }
+  }
+}
diff --git a/Code/Mantid/Vates/VatesAPI/test/MDHWInMemoryLoadingPresenterTest.h b/Code/Mantid/Vates/VatesAPI/test/MDHWInMemoryLoadingPresenterTest.h
new file mode 100644
index 00000000000..e813643bbd8
--- /dev/null
+++ b/Code/Mantid/Vates/VatesAPI/test/MDHWInMemoryLoadingPresenterTest.h
@@ -0,0 +1,192 @@
+#ifndef MDHW_IN_MEMORY_LOADING_PRESENTER_TEST_H 
+#define MDHW_IN_MEMORY_LOADING_PRESENTER_TEST_H
+
+#include <cxxtest/TestSuite.h>
+#include "MockObjects.h"
+
+#include "MantidAPI/AnalysisDataService.h"
+#include "MantidTestHelpers/MDEventsTestHelper.h"
+#include "MantidVatesAPI/FilteringUpdateProgressAction.h"
+#include "MantidVatesAPI/MDHWInMemoryLoadingPresenter.h"
+#include <vtkUnstructuredGrid.h>
+
+using namespace Mantid::VATES;
+using namespace Mantid::API;
+using namespace testing;
+using Mantid::MDEvents::MDEventsTestHelper::makeFakeMDHistoWorkspace;
+
+class MDHWInMemoryLoadingPresenterTest: public CxxTest::TestSuite
+{
+
+private:
+
+  // Helper type. Mocks a Workspace Provider.
+  class MockWorkspaceProvider : public Mantid::VATES::WorkspaceProvider
+  {
+  public:
+    MOCK_CONST_METHOD1(canProvideWorkspace, bool(std::string));
+    MOCK_CONST_METHOD1(fetchWorkspace, Mantid::API::Workspace_sptr(std::string));
+    MOCK_CONST_METHOD1(disposeWorkspace, void(std::string));
+  };
+
+  // Helper method. Generates and returns a valid IMDHistoWorkspace
+  static Mantid::API::Workspace_sptr getGoodWorkspace()
+  {
+    Mantid::MDEvents::MDHistoWorkspace_sptr ws = makeFakeMDHistoWorkspace(1.0, 4, 5, 1.0, 0.1);
+    ws->setName("MD_HISTO_WS");
+    return ws;
+  }
+
+  // Helper method. Generates a non-IMDHistoWorkspace.
+  static Mantid::API::Workspace_sptr getBadWorkspace()
+  {
+    //Return a table workspace.
+    return WorkspaceFactory::Instance().createTable();
+  }
+
+public:
+
+  void testConstructWithNullViewThrows()
+  {
+    MockMDLoadingView* pNullView = NULL;
+    TSM_ASSERT_THROWS("Should throw with empty Workspace name.", MDHWInMemoryLoadingPresenter(pNullView, new MockWorkspaceProvider, "_"), std::invalid_argument);
+  }
+
+  void testConstructWithNullRepositoryThrows()
+  {
+    MockWorkspaceProvider* pNullRepository = NULL;
+    TSM_ASSERT_THROWS("Should throw with empty Workspace name.", MDHWInMemoryLoadingPresenter(new MockMDLoadingView, pNullRepository, "_"), std::invalid_argument);
+  } 
+
+  void testConstructWithEmptyWsNameThrows()
+  {
+    std::string emptyName = "";
+    TSM_ASSERT_THROWS("Should throw with empty Workspace name.", MDHWInMemoryLoadingPresenter(new MockMDLoadingView, new MockWorkspaceProvider, emptyName), std::invalid_argument);
+  }
+
+  void testConstruction()
+  {
+    TS_ASSERT_THROWS_NOTHING(MDHWInMemoryLoadingPresenter(new MockMDLoadingView, new MockWorkspaceProvider, "_"));
+  }
+
+  void testCanLoadWithInvalidName()
+  {
+    MockWorkspaceProvider* repository = new MockWorkspaceProvider;
+    EXPECT_CALL(*repository, canProvideWorkspace(_)).WillOnce(Return(false)); //No matter what the argument, always returns false.
+
+    //Give a dummy name corresponding to the workspace.
+    MDHWInMemoryLoadingPresenter presenter(new MockMDLoadingView, repository, "_");
+
+    TSM_ASSERT("Should indicate that the workspace cannot be read-out since the name is not in the Repository.", !presenter.canReadFile());
+  }
+
+  void testCanLoadWithWrongWsType()
+  {
+    MockWorkspaceProvider* repository = new MockWorkspaceProvider;
+    Mantid::API::Workspace_sptr badWs = getBadWorkspace(); // Not an IMDHistoWorkspace.
+    EXPECT_CALL(*repository, canProvideWorkspace(_)).WillOnce(Return(true)); //No matter what the argument, always returns true.
+    EXPECT_CALL(*repository, fetchWorkspace(_)).WillOnce(Return(badWs)); 
+
+    //Give a dummy name corresponding to the workspace.
+    MDHWInMemoryLoadingPresenter presenter(new MockMDLoadingView, repository, "_");
+
+    TSM_ASSERT("Should indicate that the workspace cannot be read-out since it is not of the right type.", !presenter.canReadFile());
+  }
+
+  void testCanLoadSucceeds()
+  {
+    MockWorkspaceProvider* repository = new MockWorkspaceProvider;
+    Mantid::API::Workspace_sptr goodWs = getGoodWorkspace();
+    EXPECT_CALL(*repository, canProvideWorkspace(_)).WillOnce(Return(true)); //No matter what the argument, always returns true.
+    EXPECT_CALL(*repository, fetchWorkspace(_)).WillOnce(Return(goodWs)); 
+
+    //Give a dummy name corresponding to the workspace.
+    MDHWInMemoryLoadingPresenter presenter(new MockMDLoadingView, repository, "_");
+
+    TSM_ASSERT("Should have worked! Workspace is of correct type and repository says ws is present.!", presenter.canReadFile());
+  }
+
+  void testExtractMetadata()
+  {
+    //Setup view
+    MockMDLoadingView* view = new MockMDLoadingView;
+
+    MockWorkspaceProvider* repository = new MockWorkspaceProvider;
+    Mantid::API::Workspace_sptr ws = getGoodWorkspace();
+    EXPECT_CALL(*repository, fetchWorkspace(_)).Times(1).WillRepeatedly(Return(ws));
+
+    MDHWInMemoryLoadingPresenter presenter(view, repository, "_");
+    
+    //Test that it doesn't work when not setup.
+    TSM_ASSERT_THROWS("::executeLoadMetadata is critical to setup, should throw if not run first.", presenter.getGeometryXML(), std::runtime_error);
+    
+    //Test that it does work when setup.
+    presenter.executeLoadMetadata();
+    TSM_ASSERT("Should export geometry xml metadata on request.", !presenter.getGeometryXML().empty())
+  }
+
+  void testExecution()
+  {
+    //Setup view
+    MockMDLoadingView* view = new MockMDLoadingView;
+    EXPECT_CALL(*view, getRecursionDepth()).Times(0);
+    EXPECT_CALL(*view, getLoadInMemory()).Times(0); //Not a question that needs asking for this presenter type.
+    EXPECT_CALL(*view, updateAlgorithmProgress(_)).Times(AnyNumber());
+
+    //Setup rendering factory
+    MockvtkDataSetFactory factory;
+    EXPECT_CALL(factory, initialize(_)).Times(1);
+    EXPECT_CALL(factory, create()).WillOnce(Return(vtkUnstructuredGrid::New()));
+
+    MockWorkspaceProvider* repository = new MockWorkspaceProvider;
+    Mantid::API::Workspace_sptr ws = getGoodWorkspace();
+    EXPECT_CALL(*repository, fetchWorkspace(_)).Times(2).WillRepeatedly(Return(ws));
+
+    //Setup progress updates object
+    FilterUpdateProgressAction<MockMDLoadingView> progressAction(view);
+
+    //Create the presenter and run it!
+    MDHWInMemoryLoadingPresenter presenter(view, repository, "_");
+    presenter.executeLoadMetadata();
+    vtkDataSet* product = presenter.execute(&factory, progressAction);
+
+    TSM_ASSERT("Should have generated a vtkDataSet", NULL != product);
+    TSM_ASSERT_EQUALS("Wrong type of output generated", "vtkUnstructuredGrid", std::string(product->GetClassName()));
+    TSM_ASSERT("No field data!", NULL != product->GetFieldData());
+    TSM_ASSERT_EQUALS("One array expected on field data!", 1, product->GetFieldData()->GetNumberOfArrays());
+    TS_ASSERT_THROWS_NOTHING(presenter.hasTDimensionAvailable());
+    TS_ASSERT_THROWS_NOTHING(presenter.getGeometryXML());
+    TS_ASSERT(!presenter.getWorkspaceTypeName().empty());
+    TS_ASSERT(Mock::VerifyAndClearExpectations(view));
+    TS_ASSERT(Mock::VerifyAndClearExpectations(&factory));
+
+    product->Delete();
+  }
+
+  void testCallHasTDimThrows()
+  {
+    MDHWInMemoryLoadingPresenter presenter(new MockMDLoadingView, new MockWorkspaceProvider, "_");
+    TSM_ASSERT_THROWS("Should throw. Execute not yet run.", presenter.hasTDimensionAvailable(), std::runtime_error);
+  }
+
+  void testCallGetTDimensionValuesThrows()
+  {
+    MDHWInMemoryLoadingPresenter presenter(new MockMDLoadingView, new MockWorkspaceProvider, "_");
+    TSM_ASSERT_THROWS("Should throw. Execute not yet run.", presenter.getTimeStepValues(), std::runtime_error);
+  }
+
+  void testCallGetGeometryThrows()
+  {
+    MDHWInMemoryLoadingPresenter presenter(new MockMDLoadingView, new MockWorkspaceProvider, "_");
+    TSM_ASSERT_THROWS("Should throw. Execute not yet run.", presenter.getGeometryXML(), std::runtime_error);
+  }
+
+  void testGetWorkspaceTypeName()
+  {
+    MDHWInMemoryLoadingPresenter presenter(new MockMDLoadingView, new MockWorkspaceProvider, "_");
+    TSM_ASSERT_EQUALS("Characterisation Test Failed", "", presenter.getWorkspaceTypeName());
+  }
+
+};
+
+#endif
diff --git a/Code/Mantid/Vates/VatesAPI/test/MDHWLoadingPresenterTest.h b/Code/Mantid/Vates/VatesAPI/test/MDHWLoadingPresenterTest.h
new file mode 100644
index 00000000000..deab22575c2
--- /dev/null
+++ b/Code/Mantid/Vates/VatesAPI/test/MDHWLoadingPresenterTest.h
@@ -0,0 +1,124 @@
+#ifndef MDHW_LOADING_PRESENTER_TEST_H_
+#define MDHW_LOADING_PRESENTER_TEST_H_ 
+
+#include <cxxtest/TestSuite.h>
+#include <vtkUnstructuredGrid.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "MantidVatesAPI/MDHWLoadingPresenter.h"
+#include "MantidVatesAPI/MDLoadingView.h"
+
+using namespace testing;
+using namespace Mantid::VATES;
+
+//=====================================================================================
+// Functional tests
+//=====================================================================================
+class MDHWLoadingPresenterTest : public CxxTest::TestSuite
+{
+
+private: 
+
+  class MockMDLoadingView : public Mantid::VATES::MDLoadingView
+  {
+  public:
+    MOCK_CONST_METHOD0(getTime, double());
+    MOCK_CONST_METHOD0(getRecursionDepth, size_t());
+    MOCK_CONST_METHOD0(getLoadInMemory, bool());
+    MOCK_METHOD1(updateAlgorithmProgress, void(double));
+    ~MockMDLoadingView(){}
+  };
+
+  /*
+  Helper class allows the behaviour of the abstract base type to be tested. Derives from target abstract class providing 
+  dummy implemenations of pure virtual methods.
+  */
+  class ConcreteMDHWLoadingPresenter : public MDHWLoadingPresenter
+  {
+  private:
+    typedef MDHWLoadingPresenter BaseClass;
+  public:
+    ConcreteMDHWLoadingPresenter(MockMDLoadingView* view) : MDHWLoadingPresenter(view)
+    {
+    }
+
+    virtual vtkDataSet* execute(vtkDataSetFactory*, ProgressAction&)
+    {
+      return vtkUnstructuredGrid::New(); 
+    }
+    
+    virtual void executeLoadMetadata()
+    {
+    }
+
+    virtual bool canReadFile() const
+    {
+      return true;
+    }
+
+    virtual bool shouldLoad()
+    {
+      //Forwarding method
+      return BaseClass::shouldLoad();
+    }
+
+    ~ConcreteMDHWLoadingPresenter(){}
+  };
+
+
+public:
+
+void testShouldLoadFirstTimeRound()
+{
+  MockMDLoadingView view;
+  EXPECT_CALL(view, getRecursionDepth()).Times(0);
+  EXPECT_CALL(view, getLoadInMemory()).Times(2); 
+  EXPECT_CALL(view, getTime()).Times(2);
+  EXPECT_CALL(view, updateAlgorithmProgress(_)).Times(0);
+
+  ConcreteMDHWLoadingPresenter presenter(&view);
+  TSM_ASSERT("Should request load on first usage.", presenter.shouldLoad());
+  TSM_ASSERT("Should NOT request load on second usage. Should have it's state syncrhonised with view and the view hasn't changed!", !presenter.shouldLoad());
+  
+  TSM_ASSERT("View not used as expected.", Mock::VerifyAndClearExpectations(&view));
+}
+
+void testTimeChanged()
+{
+  MockMDLoadingView view;
+  EXPECT_CALL(view, getRecursionDepth()).Times(0);
+  EXPECT_CALL(view, getLoadInMemory()).Times(2); 
+  EXPECT_CALL(view, getTime()).Times(2)
+    .WillOnce(Return(0)) 
+    .WillOnce(Return(1));// Time has changed on 2nd call
+  EXPECT_CALL(view, updateAlgorithmProgress(_)).Times(0);
+
+  ConcreteMDHWLoadingPresenter presenter(&view);
+  TSM_ASSERT("Should request load on first usage.", presenter.shouldLoad());
+  TSM_ASSERT("Time has changed, but that shouldn't trigger load", !presenter.shouldLoad());
+  
+  TSM_ASSERT("View not used as expected.", Mock::VerifyAndClearExpectations(&view));
+}
+
+void testLoadInMemoryChanged()
+{
+  MockMDLoadingView view;
+  EXPECT_CALL(view, getRecursionDepth()).Times(0);
+  EXPECT_CALL(view, getLoadInMemory()).Times(2)
+    .WillOnce(Return(true)) 
+    .WillOnce(Return(false)); // Load in memory changed
+  EXPECT_CALL(view, getTime()).Times(2);
+  EXPECT_CALL(view, updateAlgorithmProgress(_)).Times(0);
+
+  ConcreteMDHWLoadingPresenter presenter(&view);
+  TSM_ASSERT("Should request load on first usage.", presenter.shouldLoad());
+  TSM_ASSERT("Load in memory changed. this SHOULD trigger re-load", presenter.shouldLoad());
+  
+  TSM_ASSERT("View not used as expected.", Mock::VerifyAndClearExpectations(&view));
+}
+
+};
+
+#endif
-- 
GitLab