diff --git a/Framework/PythonInterface/plugins/algorithms/SaveReflections.py b/Framework/PythonInterface/plugins/algorithms/SaveReflections.py index d2b28cb2661b2562400a6c1cc19aabbdbd8735bd..265743f523cd280445a818967269f4e57c642a11 100644 --- a/Framework/PythonInterface/plugins/algorithms/SaveReflections.py +++ b/Framework/PythonInterface/plugins/algorithms/SaveReflections.py @@ -6,7 +6,7 @@ # SPDX - License - Identifier: GPL - 3.0 + import re import numpy as np -from mantid.api import AlgorithmFactory, FileProperty, FileAction, PythonAlgorithm, ITableWorkspaceProperty +from mantid.api import AlgorithmFactory, FileProperty, FileAction, PythonAlgorithm, ITableWorkspaceProperty, IPeaksWorkspace from mantid.kernel import StringListValidator, Direction from mantid.simpleapi import SaveHKL @@ -168,9 +168,6 @@ class JanaFormat(object): :param file_name: the file name to output data to. :param workspace: the PeaksWorkspace to write to file. """ - if has_modulated_indexing(workspace): - raise NotImplementedError("Cannot currently save modulated structures to Jana format") - self._cache_instrument_params(workspace) with open(file_name, 'w') as f_handle: self.write_header(f_handle, workspace) self.write_peaks(f_handle, workspace) @@ -181,11 +178,13 @@ class JanaFormat(object): :param f_handle: handle to the file to write to. :param workspace: the PeaksWorkspace to save to file. """ - sample = workspace.sample() - lattice = sample.getOrientedLattice() - lattice_params = [lattice.a(), lattice.b(), lattice.c(), lattice.alpha(), lattice.beta(), lattice.gamma()] - lattice_params = "".join(["{: >10.4f}".format(value) for value in lattice_params]) - f_handle.write("# Lattice parameters {}\n".format(lattice_params)) + if isinstance(workspace, IPeaksWorkspace): + sample = workspace.sample() + lattice = sample.getOrientedLattice() + lattice_params = [lattice.a(), lattice.b(), lattice.c(), lattice.alpha(), lattice.beta(), lattice.gamma()] + lattice_params = "".join(["{: >10.4f}".format(value) for value in lattice_params]) + f_handle.write("# Lattice parameters {}\n".format(lattice_params)) + f_handle.write("(3i5,2f12.2,i5,4f10.4)\n") def write_peaks(self, f_handle, workspace): @@ -219,29 +218,21 @@ class JanaFormat(object): f_handle.write("{SigInt: >12.2f}".format(**peak)) f_handle.write("{: >5.0f}".format(1)) f_handle.write("{Wavelength: >10.4f}".format(**peak)) - f_handle.write("{: >10.4f}".format(self._get_two_theta(peak['DetID']))) + f_handle.write("{: >10.4f}".format(self._get_two_theta(peak))) f_handle.write("{: >10.4f}{: >10.4f}{: >10.4f}".format(1.0, 0.0, 0.0)) f_handle.write("\n") - def _get_two_theta(self, det_id): - """Get the two theta value for this peak - :param det_id: the detector ID of this Peak - """ - det = self._instrument.getDetector(det_id) - return np.degrees(det.getTwoTheta(self._instrument.getPos(), self._z_axis)) - - def _cache_instrument_params(self, workspace): - """Cache some parameters about the instrument - - This stores some of the instrument parameters at the start - of execution so we can quickly access them later. + def _get_two_theta(self, peak): + """Get the two theta value for this peak. - :param workspace: the PeaksWorkspace to cache instrument data from. + This is just Bragg's law relating wavelength to scattering angle. + :param peak: peak object to get the scattering angle for. + :returns: the scattering angle for the peak. """ - self._instrument = workspace.getInstrument() - frame = self._instrument.getReferenceFrame() - self._z_axis = frame.vecPointingAlongBeam() - + d = peak['DSpacing'] + wavelength = peak['Wavelength'] + theta = 2.*np.arcsin(0.5*(wavelength / d)) + return np.rad2deg(theta) # ------------------------------------------------------------------------------------------------------ diff --git a/Framework/PythonInterface/test/python/plugins/algorithms/SaveReflectionsTest.py b/Framework/PythonInterface/test/python/plugins/algorithms/SaveReflectionsTest.py index 63af0dd771be8b0a6355a4007c892dbcd1a03f70..403019976a8cba6b9396f805df8ddfb55c9ce7e2 100644 --- a/Framework/PythonInterface/test/python/plugins/algorithms/SaveReflectionsTest.py +++ b/Framework/PythonInterface/test/python/plugins/algorithms/SaveReflectionsTest.py @@ -140,11 +140,15 @@ class SaveReflectionsTest(unittest.TestCase): def test_save_jana_format_modulated(self): # Arrange workspace = self._create_modulated_peak_table() + reference_result = self._get_reference_result("jana_format_modulated.hkl") file_name = os.path.join(self._test_dir, "test_jana_modulated.hkl") output_format = "Jana" # Act - self.assertRaises(RuntimeError, SaveReflections, InputWorkspace=workspace, Filename=file_name, Format=output_format) + SaveReflections(InputWorkspace=workspace, Filename=file_name, Format=output_format) + + # Assert + self.assertTrue(compare_file(reference_result, file_name)) def test_save_GSAS_format(self): # Arrange diff --git a/Testing/Data/UnitTest/jana_format_modulated.hkl.md5 b/Testing/Data/UnitTest/jana_format_modulated.hkl.md5 new file mode 100644 index 0000000000000000000000000000000000000000..148d77dbf3face53dbe97926d2ec6c09a56131c0 --- /dev/null +++ b/Testing/Data/UnitTest/jana_format_modulated.hkl.md5 @@ -0,0 +1 @@ +96c8aa0e0a91f2c537ec06f0170d7d25 diff --git a/docs/source/release/v3.14.0/diffraction.rst b/docs/source/release/v3.14.0/diffraction.rst index 30df5d2faaeccedec9d20d8361829f72f8978756..6e3734d6d242d3b5bd6418b6ad43e7728a6f1e60 100644 --- a/docs/source/release/v3.14.0/diffraction.rst +++ b/docs/source/release/v3.14.0/diffraction.rst @@ -77,6 +77,7 @@ Improvements - Focus on Pearl now saves out xye_tof files. - :ref:`PDLoadCharacterizations <algm-PDLoadCharacterizations>` now sets the same run numbers for all rows when using an ``exp.ini`` file. - Focus now checks if the vanadium for a run is already loaded before loading it in to prevent reloading the same vanadium multiple times. +- :ref:`SaveReflections <algm-SaveReflections>` now supports saving indexed modulated peaks in the Jana format. Bugfixes