diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CMakeLists.txt
index 57b1f1b8c6bf6608895199784738317b1bf253a6..0c6113c925d996ce744e70a2fafbfb75f7c9abf3 100644
--- a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CMakeLists.txt
+++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CMakeLists.txt
@@ -10,6 +10,7 @@ set ( TEST_PY_FILES
   AnalysisDataServiceTest.py
   AxisTest.py
   CatalogManagerTest.py
+  CutMDTest.py
   DataProcessorAlgorithmTest.py
   DeprecatedAlgorithmCheckerTest.py
   ExperimentInfoTest.py
diff --git a/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CutMDTest.py b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CutMDTest.py
new file mode 100644
index 0000000000000000000000000000000000000000..203ed1ecb0b930ebf9cc5f7e9b5ec199fd41d1e0
--- /dev/null
+++ b/Code/Mantid/Framework/PythonInterface/test/python/mantid/api/CutMDTest.py
@@ -0,0 +1,232 @@
+import unittest
+import testhelpers
+import numpy as np
+from mantid.simpleapi import *
+from mantid.api import IMDHistoWorkspace, IMDEventWorkspace
+
+
+class CutMDTest(unittest.TestCase):
+    
+
+    def setUp(self):
+        # Create a workspace
+        data_ws = CreateMDWorkspace(Dimensions=3, Extents=[-10,10,-10,10,-10,10], Names="A,B,C", Units="U,U,U")
+        # Mark the workspace as being in HKL
+        SetSpecialCoordinates(InputWorkspace=data_ws, SpecialCoordinates='HKL')
+        # Set the UB
+        SetUB(Workspace=data_ws, a = 1, b = 1, c = 1, alpha =90, beta=90, gamma = 90)
+        # Add some data to the workspace
+        FakeMDEventData(InputWorkspace=data_ws, PeakParams=[10000,0,0,0,1])
+        self.__in_md  = data_ws
+        
+    def tearDown(self):
+        DeleteWorkspace(self.__in_md )
+
+    def test_exec_throws_if_giving_4th_binning_parameter_when_workspace_is_3D(self):
+        test_md = CreateMDWorkspace(Dimensions=3, Extents=[-10,10,-10,10,-10,10], Names="H,K,L", Units="U,U,U")
+        # Explicitly set the coordinate system to lab Q.
+        SetSpecialCoordinates(InputWorkspace=test_md, SpecialCoordinates='HKL')
+        self.assertRaises(RuntimeError, CutMD, InputWorkspace=test_md, OutputWorkspace="out_ws", P1Bin=[0.1], P2Bin=[0.1], P3Bin=[0.1], P4Bin=[0.1])
+        
+    def test_slice_to_original(self):
+        out_md = CutMD(self.__in_md, P1Bin=[0.1], P2Bin=[0.1], P3Bin=[0.1], CheckAxes=False)
+        self.assertTrue(isinstance(out_md, IMDEventWorkspace), "Should default to producing an IMDEventWorkspace.")
+        # No rotation. Basis vectors should have been left the same, so no extent changes.
+        self.assertEquals(self.__in_md.getDimension(0).getMinimum(), out_md.getDimension(0).getMinimum())
+        self.assertEquals(self.__in_md.getDimension(0).getMaximum(), out_md.getDimension(0).getMaximum())
+        self.assertEquals(self.__in_md.getDimension(1).getMinimum(), out_md.getDimension(1).getMinimum())
+        self.assertEquals(self.__in_md.getDimension(1).getMaximum(), out_md.getDimension(1).getMaximum())
+        self.assertEquals(self.__in_md.getDimension(2).getMinimum(), out_md.getDimension(2).getMinimum())
+        self.assertEquals(self.__in_md.getDimension(2).getMaximum(), out_md.getDimension(2).getMaximum())
+        self.assertEquals("['zeta', 0, 0]",  out_md.getDimension(0).getName() )
+        self.assertEquals("[0, 'eta', 0]",  out_md.getDimension(1).getName() )
+        self.assertEquals("[0, 0, 'xi']",  out_md.getDimension(2).getName() )
+        self.assertTrue(isinstance(out_md, IMDEventWorkspace), "nopix defaults to True. Should get an IMDEventWorkspace")
+        
+    def test_recalculate_extents_with_3_bin_arguments(self):
+        out_md = CutMD(self.__in_md, P1Bin=[0, 0.3, 0.8], P2Bin=[0.1], P3Bin=[0.1], CheckAxes=False, NoPix=True)
+        dim = out_md.getDimension(0)
+        self.assertAlmostEqual(0, dim.getMinimum(), 6, "Wrong minimum")
+        self.assertEqual(2, dim.getNBins(), "Wrong calculated number of bins")
+        self.assertAlmostEqual(0.6, dim.getMaximum(), 6, "Wrong calculated maximum")
+        
+    def test_truncate_extents(self):
+        out_md = CutMD(self.__in_md, P1Bin=[0, 1.1, 1], P2Bin=[21], P3Bin=[0.1], CheckAxes=False, NoPix=True)
+  
+        self.assertEqual(1, out_md.getDimension(0).getNBins(), "Step is beyond range. Should just be integrated")
+        self.assertEqual(1, out_md.getDimension(1).getNBins(), "Step is beyond range. Should just be integrated")
+        
+    def test_wrong_projection_workspace_format_wrong_column_numbers(self):
+        projection = CreateEmptyTableWorkspace()
+        projection.addColumn("str", "name")
+        # missing other columns
+        self.assertRaises(RuntimeError, CutMD, InputWorkspace=self.__in_md, Projection=projection, OutputWorkspace="out_ws", P1Bin=[0.1], P2Bin=[0.1], P3Bin=[0.1], CheckAxes=False)
+        
+    def test_wrong_table_workspace_format_wrong_row_numbers(self):
+        projection = CreateEmptyTableWorkspace()
+        # Correct number of columns, and names
+        projection.addColumn("str", "name")
+        projection.addColumn("str", "value")
+        projection.addColumn("double", "offset")
+        projection.addColumn("str", "type")
+        # Incorrect number of rows i.e. zero in this case as none added.
+        self.assertRaises(RuntimeError, CutMD, InputWorkspace=self.__in_md, Projection=projection, OutputWorkspace="out_ws", P1Bin=[0.1], P2Bin=[0.1], P3Bin=[0.1], CheckAxes=False)
+        
+    def test_orthogonal_slice_with_scaling(self):
+        # We create a fake workspace and check to see that the extents get scaled with the new coordinate system when sliced
+        to_cut = CreateMDWorkspace(Dimensions=3, Extents=[-1,1,-1,1,-1,1], Names='H,K,L', Units='U,U,U')
+        # Set the UB
+        SetUB(Workspace=to_cut, a = 1, b = 1, c = 1, alpha =90, beta=90, gamma = 90)
+        
+        SetSpecialCoordinates(InputWorkspace=to_cut, SpecialCoordinates='HKL')
+        
+        scale_x = 2.0
+        scale_y = 2.0
+                    
+        projection = CreateEmptyTableWorkspace()
+        # Correct number of columns, and names
+        projection.addColumn("str", "name")
+        projection.addColumn("str", "value")
+        projection.addColumn("double", "offset")
+        projection.addColumn("str", "type")
+
+        projection.addRow(["u", "%s,0,0" % scale_x, 0, "r"])
+        projection.addRow(["v", "0,%s,0" % scale_y, 0, "r"])
+
+        u = map(float,projection.cell(0,1).split(","))
+        v = map(float,projection.cell(1,1).split(","))
+        scale_z = np.cross(v,u)[-1]
+        projection.addRow(["w", "0,0,%s" % scale_z, 0, "r"])
+                    
+        out_md = CutMD(to_cut, Projection=projection, P1Bin=[0.1], P2Bin=[0.1], P3Bin=[0.1])
+        
+        '''
+        Here we check that the corners in HKL end up in the expected positions when transformed into the new scaled basis
+        provided by the W transform (projection table)
+        '''
+        self.assertEquals(-(1/scale_x), out_md.getDimension(0).getMinimum()) 
+        self.assertEquals((1/scale_x), out_md.getDimension(0).getMaximum())
+        self.assertEquals(-(1/scale_y), out_md.getDimension(1).getMinimum())
+        self.assertEquals((1/scale_y), out_md.getDimension(1).getMaximum())
+        self.assertEquals((1/scale_z), out_md.getDimension(2).getMinimum())
+        self.assertEquals(-(1/scale_z), out_md.getDimension(2).getMaximum())
+        self.assertEquals("['2.00zeta', 0, 0]",  out_md.getDimension(0).getName() )
+        self.assertEquals("[0, '2.00eta', 0]",  out_md.getDimension(1).getName() )
+        self.assertEquals("[0, 0, '-4.00xi']",  out_md.getDimension(2).getName() )
+        
+        
+    def test_non_orthogonal_slice(self):
+         # We create a fake workspace and check to see that the extents get transformed to the new coordinate system.
+        to_cut = CreateMDWorkspace(Dimensions=3, Extents=[-1,1,-1,1,-1,1], Names='H,K,L', Units='U,U,U')
+        # Set the UB
+        SetUB(Workspace=to_cut, a = 1, b = 1, c = 1, alpha =90, beta=90, gamma = 90)
+        SetSpecialCoordinates(InputWorkspace=to_cut, SpecialCoordinates='HKL')
+        
+        projection = CreateEmptyTableWorkspace()
+        # Correct number of columns, and names
+        projection.addColumn("str", "name")
+        projection.addColumn("str", "value")
+        projection.addColumn("double", "offset")
+        projection.addColumn("str", "type")
+
+        projection.addRow(["u", "1,1,0", 0.0, "r"])
+        projection.addRow(["v","-1,1,0", 0.0, "r"])
+        projection.addRow(["w", "0,0,1", 0.0, "r"])
+                    
+        out_md = CutMD(to_cut, Projection=projection, P1Bin=[0.1], P2Bin=[0.1], P3Bin=[0.1], NoPix=True)
+        
+        '''
+        Here we check that the corners in HKL end up in the expected positions when transformed into the new scaled basis
+        provided by the W transform (projection table)
+        '''
+        self.assertEquals(-1, out_md.getDimension(0).getMinimum()) 
+        self.assertEquals(1, out_md.getDimension(0).getMaximum())
+        self.assertEquals(-1, out_md.getDimension(1).getMinimum())
+        self.assertEquals(1, out_md.getDimension(1).getMaximum())
+        self.assertEquals(-1, out_md.getDimension(2).getMinimum())
+        self.assertEquals(1, out_md.getDimension(2).getMaximum())
+        self.assertEquals("['zeta', 'zeta', 0]",  out_md.getDimension(0).getName() )
+        self.assertEquals("['-eta', 'eta', 0]",  out_md.getDimension(1).getName() )
+        self.assertEquals("[0, 0, 'xi']",  out_md.getDimension(2).getName() )
+        
+        self.assertTrue(isinstance(out_md, IMDHistoWorkspace), "Expect that the output was an IMDHistoWorkspace given the NoPix flag.")
+        
+    def test_orthogonal_slice_with_cropping(self):
+         # We create a fake workspace and check to see that using bin inputs for cropping works
+        to_cut = CreateMDWorkspace(Dimensions=3, Extents=[-1,1,-1,1,-1,1], Names='H,K,L', Units='U,U,U')
+        # Set the UB
+        SetUB(Workspace=to_cut, a = 1, b = 1, c = 1, alpha =90, beta=90, gamma = 90)
+        SetSpecialCoordinates(InputWorkspace=to_cut, SpecialCoordinates='HKL')
+        
+        projection = CreateEmptyTableWorkspace()
+        # Correct number of columns, and names
+        projection.addColumn("str", "name")
+        projection.addColumn("str", "value")
+        projection.addColumn("double", "offset")
+        projection.addColumn("str", "type")
+
+        projection.addRow(["u", "1,0,0", 0, "r"])
+        projection.addRow(["v", "0,1,0", 0, "r"])
+        projection.addRow(["w", "0,0,1", 0, "r"])
+                    
+        '''
+        Specify the cropping boundaries as part of the bin inputs.
+        '''
+        out_md = CutMD(to_cut, Projection=projection, P1Bin=[-0.5,0.5], P2Bin=[-0.1,0.1], P3Bin=[-0.3,0.3], NoPix=True)
+        
+        '''
+        Here we check that the corners in HKL end up in the expected positions when transformed into the new scaled basis
+        provided by the W transform (projection table)
+        '''
+        self.assertAlmostEqual(-0.5, out_md.getDimension(0).getMinimum(), 6) 
+        self.assertAlmostEqual(0.5, out_md.getDimension(0).getMaximum(), 6) 
+        self.assertAlmostEqual(-0.1, out_md.getDimension(1).getMinimum(), 6) 
+        self.assertAlmostEqual(0.1, out_md.getDimension(1).getMaximum(), 6) 
+        self.assertAlmostEqual(-0.3, out_md.getDimension(2).getMinimum(), 6) 
+        self.assertAlmostEqual(0.3, out_md.getDimension(2).getMaximum(), 6) 
+        self.assertEquals("['zeta', 0, 0]",  out_md.getDimension(0).getName() )
+        self.assertEquals("[0, 'eta', 0]",  out_md.getDimension(1).getName() )
+        self.assertEquals("[0, 0, 'xi']",  out_md.getDimension(2).getName() )
+        
+        self.assertTrue(isinstance(out_md, IMDHistoWorkspace), "Expect that the output was an IMDHistoWorkspace given the NoPix flag.")
+        
+    def test_orthogonal_slice_4D(self):
+         # We create a fake 4-D workspace and check to see that using bin inputs for cropping works
+        to_cut = CreateMDWorkspace(Dimensions=4, Extents=[-1,1,-1,1,-1,1,-10,10], Names='H,K,L,E', Units='U,U,U,V')
+        # Set the UB
+        SetUB(Workspace=to_cut, a = 1, b = 1, c = 1, alpha =90, beta=90, gamma = 90)
+        SetSpecialCoordinates(InputWorkspace=to_cut, SpecialCoordinates='HKL')
+        
+        '''
+        Process the 4D workspace
+        '''
+        out_md = CutMD(to_cut, P1Bin=[-0.5,0.5], P2Bin=[-0.1,0.1], P3Bin=[-0.3,0.3], P4Bin=[1],  NoPix=True)
+        
+        
+        self.assertAlmostEqual(-0.5, out_md.getDimension(0).getMinimum(), 6) 
+        self.assertAlmostEqual(0.5, out_md.getDimension(0).getMaximum(), 6) 
+        self.assertAlmostEqual(-0.1, out_md.getDimension(1).getMinimum(), 6) 
+        self.assertAlmostEqual(0.1, out_md.getDimension(1).getMaximum(), 6) 
+        self.assertAlmostEqual(-0.3, out_md.getDimension(2).getMinimum(), 6) 
+        self.assertAlmostEqual(0.3, out_md.getDimension(2).getMaximum(), 6)
+        self.assertAlmostEqual(-10, out_md.getDimension(3).getMinimum(), 6) 
+        self.assertAlmostEqual(10, out_md.getDimension(3).getMaximum(), 6)
+        self.assertEqual(20, out_md.getDimension(3).getNBins())
+        
+        self.assertEquals("['zeta', 0, 0]",  out_md.getDimension(0).getName() )
+        self.assertEquals("[0, 'eta', 0]",  out_md.getDimension(1).getName() )
+        self.assertEquals("[0, 0, 'xi']",  out_md.getDimension(2).getName() )
+        self.assertEquals("E",  out_md.getDimension(3).getName() )
+        
+        self.assertTrue(isinstance(out_md, IMDHistoWorkspace), "Expect that the output was an IMDHistoWorkspace given the NoPix flag.")
+                
+        '''
+        Process the 4D workspace again, this time with different binning
+        '''
+        out_md = CutMD(to_cut, P1Bin=[-0.5,0.5], P2Bin=[-0.1,0.1], P3Bin=[-0.3,0.3], P4Bin=[-8,1,8],  NoPix=True) 
+        self.assertEqual(16, out_md.getDimension(3).getNBins())
+        self.assertTrue(isinstance(out_md, IMDHistoWorkspace), "Expect that the output was an IMDHistoWorkspace given the NoPix flag.")
+                
+
+if __name__ == '__main__':
+    unittest.main()