diff --git a/Framework/PythonInterface/plugins/algorithms/TOFTOFCropWorkspace.py b/Framework/PythonInterface/plugins/algorithms/TOFTOFCropWorkspace.py new file mode 100644 index 0000000000000000000000000000000000000000..2bbf6ffb910fd0d8324f5559fde21183c686d705 --- /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 bb68b040a2e73b551095e18bf876be0abb92e83b..de4e7b03fe0ea0b3a6254c43932631235a9777d0 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 0000000000000000000000000000000000000000..14651813e297fe91d44d8e8006bfc41db7655bbb --- /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 0000000000000000000000000000000000000000..2a390bc98a778ae33750d5aaaa43175e39501f3b --- /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::