From 5a3205b4bb56634550dd9b968cdd00eff92e4260 Mon Sep 17 00:00:00 2001
From: Marina Ganeva <m.ganeva@fz-juelich.de>
Date: Fri, 9 Oct 2015 11:26:44 +0200
Subject: [PATCH] TOFTOF Crop workspace algorithm.

---
 .../plugins/algorithms/TOFTOFCropWorkspace.py | 67 +++++++++++++++++++
 .../python/plugins/algorithms/CMakeLists.txt  |  1 +
 .../algorithms/TOFTOFCropWorkspaceTest.py     | 59 ++++++++++++++++
 .../algorithms/TOFTOFCropWorkspace-v1.rst     | 59 ++++++++++++++++
 4 files changed, 186 insertions(+)
 create mode 100644 Framework/PythonInterface/plugins/algorithms/TOFTOFCropWorkspace.py
 create mode 100644 Framework/PythonInterface/test/python/plugins/algorithms/TOFTOFCropWorkspaceTest.py
 create mode 100644 docs/source/algorithms/TOFTOFCropWorkspace-v1.rst

diff --git a/Framework/PythonInterface/plugins/algorithms/TOFTOFCropWorkspace.py b/Framework/PythonInterface/plugins/algorithms/TOFTOFCropWorkspace.py
new file mode 100644
index 00000000000..2bbf6ffb910
--- /dev/null
+++ b/Framework/PythonInterface/plugins/algorithms/TOFTOFCropWorkspace.py
@@ -0,0 +1,67 @@
+from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty    # , WorkspaceUnitValidator
+from mantid.kernel import Direction
+from mantid.simpleapi import CropWorkspace
+
+
+class TOFTOFCropWorkspace(PythonAlgorithm):
+    """ Crop empty time channels
+    """
+    def __init__(self):
+        PythonAlgorithm.__init__(self)
+
+    def category(self):
+        """ Return category
+        """
+        return "PythonAlgorithms\\MLZ\\TOFTOF;Utility"
+
+    def name(self):
+        """ Return summary
+        """
+        return "TOFTOFCropWorkspace"
+
+    def summary(self):
+        return "Crop empty time channels."
+
+    def PyInit(self):
+        """ Declare properties
+        """
+        # better would be to use the validator, but it fails if WorkspaceGroup is given as an input
+        # self.declareProperty(WorkspaceProperty("InputWorkspace", "", direction=Direction.Input,
+        #                                       validator=WorkspaceUnitValidator('TOF')),
+        #                     doc="Input workspace.")
+        self.declareProperty(WorkspaceProperty("InputWorkspace", "", direction=Direction.Input),
+                             doc="Input workspace.")
+        self.declareProperty(WorkspaceProperty("OutputWorkspace", "", direction=Direction.Output),
+                             doc="Name of the workspace that will contain the results")
+        return
+
+    def PyExec(self):
+        """ Main execution body
+        """
+        inputws = self.getProperty("InputWorkspace").value
+        # check X units, will be not needed if validator will work
+        xunit = inputws.getAxis(0).getUnit().unitID()
+        if xunit != 'TOF':
+            message = "Workspace " + inputws.getName() + " has invalid X axis units " + str(xunit) +\
+                ". X axis units must be TOF."
+            self.log().error(message)
+            raise ValueError(message)
+
+        outputws = self.getProperty("OutputWorkspace").value
+
+        # check for required properties
+        run = inputws.getRun()
+        if run.hasProperty('channel_width') and run.hasProperty('full_channels'):
+            channel_width = float(run.getLogData('channel_width').value)
+            full_channels = float(run.getLogData('full_channels').value)
+        else:
+            message = "Workspace " + inputws.getName() + " does not contain required sample logs. Cannot crop."
+            self.log().error("message")
+            raise RuntimeError(message)
+
+        outputws = CropWorkspace(inputws, XMin=0., XMax=full_channels*channel_width, OutputWorkspace=outputws)
+        self.setProperty("OutputWorkspace", outputws)
+
+
+# Register algorithm with Mantid.
+AlgorithmFactory.subscribe(TOFTOFCropWorkspace)
diff --git a/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt
index bb68b040a2e..de4e7b03fe0 100644
--- a/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt
+++ b/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt
@@ -75,6 +75,7 @@ set ( TEST_PY_FILES
   UpdatePeakParameterTableValueTest.py
   SANSSubtractTest.py
   TimeSliceTest.py
+  TOFTOFCropWorkspaceTest.py
   TOSCABankCorrectionTest.py
   TransformToIqtTest.py
   ExportSampleLogsToCSVFileTest.py
diff --git a/Framework/PythonInterface/test/python/plugins/algorithms/TOFTOFCropWorkspaceTest.py b/Framework/PythonInterface/test/python/plugins/algorithms/TOFTOFCropWorkspaceTest.py
new file mode 100644
index 00000000000..14651813e29
--- /dev/null
+++ b/Framework/PythonInterface/test/python/plugins/algorithms/TOFTOFCropWorkspaceTest.py
@@ -0,0 +1,59 @@
+import unittest
+from mantid.simpleapi import Load, DeleteWorkspace, GroupWorkspaces, TOFTOFCropWorkspace
+from testhelpers import run_algorithm
+from mantid.api import AnalysisDataService
+
+
+class TOFTOFCropWorkspaceTest(unittest.TestCase):
+
+    _input_ws = None
+    _cropped_ws = None
+
+    def setUp(self):
+        input_ws = Load(Filename="TOFTOFTestdata.nxs")
+        self._input_ws = input_ws
+
+    def test_basicrun(self):
+        OutputWorkspaceName = "cropped_ws"
+        alg_test = run_algorithm("TOFTOFCropWorkspace",
+                                 InputWorkspace=self._input_ws,
+                                 OutputWorkspace=OutputWorkspaceName)
+        self.assertTrue(alg_test.isExecuted())
+        self._cropped_ws = AnalysisDataService.retrieve(OutputWorkspaceName)
+
+        run = self._cropped_ws.getRun()
+        # check existence of required entries in logs
+        self.assertTrue('full_channels' in run.keys())
+        self.assertTrue('channel_width' in run.keys())
+        # check their values
+        full_channels = float(run.getLogData('full_channels').value)
+        channel_width = float(run.getLogData('channel_width').value)
+        self.assertTrue(full_channels > 0.)
+        self.assertTrue(channel_width > 0.)
+        # check unit horizontal axis
+        self.assertEqual(self._cropped_ws.getAxis(0).getUnit().unitID(), 'TOF')
+        # check length of cropped ws
+        self.assertEqual(len(self._cropped_ws.readX(0)), int(full_channels))
+
+    def test_inputgroup(self):
+        group = GroupWorkspaces([self._input_ws])
+        OutputWorkspaceName = "cropped_ws"
+        alg_test = run_algorithm("TOFTOFCropWorkspace",
+                                 InputWorkspace=group,
+                                 OutputWorkspace=OutputWorkspaceName)
+        self.assertTrue(alg_test.isExecuted())
+
+    def test_invalid_xunits(self):
+        self._input_ws.getAxis(0).setUnit('Wavelength')
+        OutputWorkspaceName = "cropped_ws"
+        self.assertRaises(RuntimeError, TOFTOFCropWorkspace, InputWorkspace=self._input_ws,
+                          OutputWorkspace=OutputWorkspaceName)
+
+    def cleanUp(self):
+        if AnalysisDataService.doesExist(self._input_ws):
+            DeleteWorkspace(self._input_ws)
+        if AnalysisDataService.doesExist(self._cropped_ws):
+            DeleteWorkspace(self._cropped_ws)
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/docs/source/algorithms/TOFTOFCropWorkspace-v1.rst b/docs/source/algorithms/TOFTOFCropWorkspace-v1.rst
new file mode 100644
index 00000000000..2a390bc98a7
--- /dev/null
+++ b/docs/source/algorithms/TOFTOFCropWorkspace-v1.rst
@@ -0,0 +1,59 @@
+.. algorithm::
+
+.. summary::
+
+.. alias::
+
+.. properties::
+
+Description
+-----------
+
+Applies algorithm :ref:`algm-Cropworkspace` to an input workspace or a group of workspaces to crop the empty time channels. Boundaries are calculated as follows:
+
+    :math:`X_{min} = 0`
+
+    :math:`X_{max} = N_{fc}\times\Delta t`
+
+where :math:`N_{fc}` is the number of full time channels defined in the *full_channels* sample log and :math:`\Delta t` is the channel width defined in the *channel_width* sample log.
+
+
+Restrictions on the input workspace
+###################################
+
+-  The unit of the X-axis must be **Time-of-flight**.
+-  Workspace must contain *channel_width* and *full_channels* sample logs.
+
+
+Usage
+-----
+
+**Example**
+
+.. testcode:: ExTOFTOFCropWorkspace
+
+    # Load data
+    ws=Load(Filename='TOFTOFTestdata.nxs')
+
+    print "Input workspace"
+    print "Total number of time channels: ",  len(ws.readX(0))
+    print  "Number of filled time channels: ", ws.getRun().getLogData('full_channels').value
+
+    wscropped = TOFTOFCropWorkspace(ws)
+
+    print "Output workspace"
+    print "Total number of time channels: ",  len(wscropped.readX(0))    
+
+Output:
+
+.. testoutput:: ExTOFTOFCropWorkspace
+
+    Input workspace
+    Total number of time channels:  1025
+    Number of filled time channels:  1020.0
+    Output workspace
+    Total number of time channels:  1020
+    
+.. categories::
+
+.. sourcelink::
-- 
GitLab