From 6100698b6cf415b6436596d31ac7a86284fbcdd4 Mon Sep 17 00:00:00 2001 From: Duc Le Date: Fri, 6 Oct 2023 14:38:21 +0100 Subject: [PATCH 1/3] Fix slice plot data save bug #947 --- .../workspacemanager/workspace_algorithms.py | 18 +++--------------- .../plot_window/plot_figure_manager.py | 5 ++++- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/mslice/models/workspacemanager/workspace_algorithms.py b/src/mslice/models/workspacemanager/workspace_algorithms.py index 942bb1a36..c0488567b 100644 --- a/src/mslice/models/workspacemanager/workspace_algorithms.py +++ b/src/mslice/models/workspacemanager/workspace_algorithms.py @@ -20,7 +20,7 @@ from mslice.models.axis import Axis from mslice.util.mantid.algorithm_wrapper import add_to_ads -from mslice.models.workspacemanager.workspace_provider import get_workspace_handle, get_workspace_name, delete_workspace +from mslice.models.workspacemanager.workspace_provider import get_workspace_handle, delete_workspace from mslice.util.mantid.mantid_algorithms import Load, MergeMD, MergeRuns, Scale, Minus, ConvertUnits, Rebose from mslice.workspace.pixel_workspace import PixelWorkspace from mslice.workspace.histogram_workspace import HistogramWorkspace @@ -282,23 +282,11 @@ def export_workspace_to_ads(workspace): def _save_single_ws(workspace, save_name, save_method, path, extension, slice_nonpsd): save_as = save_name if save_name is not None else str(workspace) + extension full_path = os.path.join(str(path), save_as) - workspace = get_workspace_handle(workspace) - if workspace.is_slice: - workspace = _get_slice_mdhisto(workspace, get_workspace_name(workspace)) + if isinstance(workspace, str): + workspace = get_workspace_handle(workspace) save_method(workspace, full_path) -def _get_slice_mdhisto(workspace, ws_name): - from mslice.models.slice.slice_functions import compute_slice - try: - return get_workspace_handle('__' + ws_name) - except KeyError: - x_axis = get_axis_from_dimension(workspace, 0) - y_axis = get_axis_from_dimension(workspace, 1) - compute_slice(ws_name, x_axis, y_axis, False) - return get_workspace_handle('__' + ws_name) - - def get_axis_from_dimension(workspace, id): dim = workspace.raw_ws.getDimension(id).name min, max, step = workspace.limits[dim] diff --git a/src/mslice/plotting/plot_window/plot_figure_manager.py b/src/mslice/plotting/plot_window/plot_figure_manager.py index 2a54ff32d..a47a5b2a4 100644 --- a/src/mslice/plotting/plot_window/plot_figure_manager.py +++ b/src/mslice/plotting/plot_window/plot_figure_manager.py @@ -217,7 +217,10 @@ def save_plot(self): if hasattr(self.plot_handler, 'ws_list'): workspaces = self.plot_handler.ws_list else: - workspaces = [self.plot_handler.ws_name] + if isinstance(self.plot_handler, SlicePlot): + workspaces = [self.plot_handler.get_slice_cache().scattering_function] + else: + workspaces = [self.plot_handler.ws_name] try: save_workspaces(workspaces, file_path, From 198379ec692d67be3bbbf912b6059b1876df8942 Mon Sep 17 00:00:00 2001 From: Duc Le Date: Mon, 9 Oct 2023 04:14:34 +0100 Subject: [PATCH 2/3] Fix slice save for intensity types #947. Add test. --- .../workspacemanager/workspace_algorithms.py | 2 +- .../plot_window/plot_figure_manager.py | 2 +- src/mslice/plotting/plot_window/slice_plot.py | 4 ++ .../presenters/slice_plotter_presenter.py | 8 +++ src/mslice/util/intensity_correction.py | 12 ++++ tests/plot_figure_test.py | 67 +++++++++++++++++++ 6 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 tests/plot_figure_test.py diff --git a/src/mslice/models/workspacemanager/workspace_algorithms.py b/src/mslice/models/workspacemanager/workspace_algorithms.py index c0488567b..a298b082c 100644 --- a/src/mslice/models/workspacemanager/workspace_algorithms.py +++ b/src/mslice/models/workspacemanager/workspace_algorithms.py @@ -282,7 +282,7 @@ def export_workspace_to_ads(workspace): def _save_single_ws(workspace, save_name, save_method, path, extension, slice_nonpsd): save_as = save_name if save_name is not None else str(workspace) + extension full_path = os.path.join(str(path), save_as) - if isinstance(workspace, str): + if isinstance(workspace, string_types): workspace = get_workspace_handle(workspace) save_method(workspace, full_path) diff --git a/src/mslice/plotting/plot_window/plot_figure_manager.py b/src/mslice/plotting/plot_window/plot_figure_manager.py index a47a5b2a4..0d30b5e68 100644 --- a/src/mslice/plotting/plot_window/plot_figure_manager.py +++ b/src/mslice/plotting/plot_window/plot_figure_manager.py @@ -218,7 +218,7 @@ def save_plot(self): workspaces = self.plot_handler.ws_list else: if isinstance(self.plot_handler, SlicePlot): - workspaces = [self.plot_handler.get_slice_cache().scattering_function] + workspaces = [self.plot_handler.get_cached_workspace()] else: workspaces = [self.plot_handler.ws_name] try: diff --git a/src/mslice/plotting/plot_window/slice_plot.py b/src/mslice/plotting/plot_window/slice_plot.py index 780115fdf..820aedea6 100644 --- a/src/mslice/plotting/plot_window/slice_plot.py +++ b/src/mslice/plotting/plot_window/slice_plot.py @@ -436,6 +436,10 @@ def flip_icut(self): def get_slice_cache(self): return self._slice_plotter_presenter.get_slice_cache(self.ws_name) + def get_cached_workspace(self): + cached_slice = self.get_slice_cache() + return getattr(cached_slice, IntensityCache.get_slice_type(self.intensity_type)) + def update_workspaces(self): self._slice_plotter_presenter.update_displayed_workspaces() diff --git a/src/mslice/presenters/slice_plotter_presenter.py b/src/mslice/presenters/slice_plotter_presenter.py index 118338244..d9200b534 100644 --- a/src/mslice/presenters/slice_plotter_presenter.py +++ b/src/mslice/presenters/slice_plotter_presenter.py @@ -19,6 +19,7 @@ class SlicePlotterPresenter(PresenterUtility): def __init__(self): self._main_presenter = None self._slice_cache = {} + self._cache_intensity_correction_methods() def plot_slice(self, selected_ws, x_axis, y_axis, intensity_start, intensity_end, norm_to_one, colourmap): workspace = get_workspace_handle(selected_ws) @@ -123,3 +124,10 @@ def _cache_intensity_correction_methods(self): self.show_dynamical_susceptibility_magnetic) IntensityCache.cache_method(cat, IntensityType.D2SIGMA, self.show_d2sigma) IntensityCache.cache_method(cat, IntensityType.SYMMETRISED, self.show_symmetrised) + IntensityCache.cache_method(cat, IntensityType.GDOS, self.show_gdos) + IntensityCache.cache_slice_type(IntensityType.SCATTERING_FUNCTION, "scattering_function") + IntensityCache.cache_slice_type(IntensityType.CHI, "chi") + IntensityCache.cache_slice_type(IntensityType.CHI_MAGNETIC, "chi_magnetic") + IntensityCache.cache_slice_type(IntensityType.D2SIGMA, "d2sigma") + IntensityCache.cache_slice_type(IntensityType.SYMMETRISED, "symmetrised") + IntensityCache.cache_slice_type(IntensityType.GDOS, "gdos") diff --git a/src/mslice/util/intensity_correction.py b/src/mslice/util/intensity_correction.py index 288cb4fd4..55c3200aa 100644 --- a/src/mslice/util/intensity_correction.py +++ b/src/mslice/util/intensity_correction.py @@ -15,6 +15,7 @@ class IntensityCache: __action_dict = {} __method_dict_cut = {} __method_dict_slice = {} + __slice_cache_type = {} __description_dict = {IntensityType.SCATTERING_FUNCTION: "scattering_function", IntensityType.CHI: "dynamical_susceptibility", IntensityType.CHI_MAGNETIC: "dynamical_susceptibility_magnetic", @@ -62,6 +63,17 @@ def get_method(cls, category, intensity_correction_type): else: raise KeyError("method related to the intensity correction type not found") + @classmethod + def cache_slice_type(cls, intensity_correction_type, name): + if intensity_correction_type not in cls.__slice_cache_type: + cls.__slice_cache_type[intensity_correction_type] = name + + @classmethod + def get_slice_type(cls, intensity_correction_type): + if intensity_correction_type not in cls.__slice_cache_type: + raise KeyError("intensity correction cached type not found") + return cls.__slice_cache_type[intensity_correction_type] + @classmethod def get_intensity_type_from_desc(cls, description): if description in cls._IntensityCache__description_dict.values(): diff --git a/tests/plot_figure_test.py b/tests/plot_figure_test.py new file mode 100644 index 000000000..6c6d3decc --- /dev/null +++ b/tests/plot_figure_test.py @@ -0,0 +1,67 @@ +from __future__ import (absolute_import, division, print_function) +import unittest +from unittest import mock +from unittest.mock import patch + +from mslice.presenters.slice_plotter_presenter import SlicePlotterPresenter +from mslice.presenters.cut_plotter_presenter import CutPlotterPresenter +from mslice.util.intensity_correction import IntensityType + +FORCE_METHOD_CALLS_TO_QAPP_THREAD = 'mslice.plotting.plot_window.plot_figure_manager.force_method_calls_to_qapp_thread' + + +class PlotFigureTest(unittest.TestCase): + + def setUp(self): + self.mock_force_qapp = mock.patch( + FORCE_METHOD_CALLS_TO_QAPP_THREAD).start() + # make it a noop + self.mock_force_qapp.side_effect = lambda arg: arg + from mslice.plotting.plot_window.plot_figure_manager import new_plot_figure_manager + self.new_plot_figure_manager = new_plot_figure_manager + self.slice_plotter_presenter = SlicePlotterPresenter() + self.cut_plotter_presenter = CutPlotterPresenter() + + def tearDown(self): + self.mock_force_qapp.stop() + + def test_save_slice_nexus_sofqe(self): + gman = mock.Mock() + workspace = 'testworkspace' + file_name = ('', 'test.nxs', '.nxs') + fg = self.new_plot_figure_manager(num=1, global_manager=gman) + fg.add_slice_plot(self.slice_plotter_presenter, workspace=workspace) + + with patch('mslice.plotting.plot_window.plot_figure_manager.get_save_directory') as get_save_dir, \ + patch('mslice.models.workspacemanager.workspace_algorithms.save_nexus') as save_nexus, \ + patch('mslice.models.workspacemanager.workspace_algorithms.get_workspace_handle') as get_handle, \ + patch.object(SlicePlotterPresenter, 'get_slice_cache') as get_slice_cache: + get_save_dir.return_value = file_name + slice_cache = mock.Mock() + slice_cache.scattering_function = workspace + get_slice_cache.return_value = slice_cache + get_handle.return_value = workspace + fg.save_plot() + save_nexus.assert_called_once_with(workspace, file_name[1]) + get_slice_cache.assert_called_once() + + def test_save_slice_matlab_gdos(self): + gman = mock.Mock() + workspace = 'testworkspace' + file_name = ('', 'test.mat', '.mat') + fg = self.new_plot_figure_manager(num=1, global_manager=gman) + fg.add_slice_plot(self.slice_plotter_presenter, workspace=workspace) + + with patch('mslice.plotting.plot_window.plot_figure_manager.get_save_directory') as get_save_dir, \ + patch('mslice.models.workspacemanager.workspace_algorithms.save_matlab') as save_matlab, \ + patch('mslice.models.workspacemanager.workspace_algorithms.get_workspace_handle') as get_handle, \ + patch.object(SlicePlotterPresenter, 'get_slice_cache') as get_slice_cache: + get_save_dir.return_value = file_name + slice_cache = mock.Mock() + slice_cache.gdos = workspace + get_slice_cache.return_value = slice_cache + get_handle.return_value = workspace + fg.plot_handler.intensity_type = IntensityType.GDOS + fg.save_plot() + save_matlab.assert_called_once_with(workspace, file_name[1]) + get_slice_cache.assert_called_once() From 722550b00418101a26c3900700c9766d11f3cd54 Mon Sep 17 00:00:00 2001 From: MialLewis <95620982+MialLewis@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:27:20 +0100 Subject: [PATCH 3/3] remove redundant code and use enum name --- src/mslice/plotting/plot_window/slice_plot.py | 2 +- .../presenters/slice_plotter_presenter.py | 19 ------------------- src/mslice/util/intensity_correction.py | 12 ------------ 3 files changed, 1 insertion(+), 32 deletions(-) diff --git a/src/mslice/plotting/plot_window/slice_plot.py b/src/mslice/plotting/plot_window/slice_plot.py index 820aedea6..a5e377caa 100644 --- a/src/mslice/plotting/plot_window/slice_plot.py +++ b/src/mslice/plotting/plot_window/slice_plot.py @@ -438,7 +438,7 @@ def get_slice_cache(self): def get_cached_workspace(self): cached_slice = self.get_slice_cache() - return getattr(cached_slice, IntensityCache.get_slice_type(self.intensity_type)) + return getattr(cached_slice, self.intensity_type.name.lower()) def update_workspaces(self): self._slice_plotter_presenter.update_displayed_workspaces() diff --git a/src/mslice/presenters/slice_plotter_presenter.py b/src/mslice/presenters/slice_plotter_presenter.py index d9200b534..a796dd849 100644 --- a/src/mslice/presenters/slice_plotter_presenter.py +++ b/src/mslice/presenters/slice_plotter_presenter.py @@ -10,8 +10,6 @@ from mslice.models.workspacemanager.workspace_provider import get_workspace_handle from mslice.plotting.plot_window.overplot_interface import plot_overplot_line, remove_line from mslice.presenters.presenter_utility import PresenterUtility -from mslice.plotting.pyplot import CATEGORY_SLICE -from mslice.util.intensity_correction import IntensityType, IntensityCache class SlicePlotterPresenter(PresenterUtility): @@ -19,7 +17,6 @@ class SlicePlotterPresenter(PresenterUtility): def __init__(self): self._main_presenter = None self._slice_cache = {} - self._cache_intensity_correction_methods() def plot_slice(self, selected_ws, x_axis, y_axis, intensity_start, intensity_end, norm_to_one, colourmap): workspace = get_workspace_handle(selected_ws) @@ -115,19 +112,3 @@ def set_sample_temperature(self, workspace_name, temp): def workspace_selection_changed(self): pass - - def _cache_intensity_correction_methods(self): - cat = CATEGORY_SLICE - IntensityCache.cache_method(cat, IntensityType.SCATTERING_FUNCTION, self.show_scattering_function) - IntensityCache.cache_method(cat, IntensityType.CHI, self.show_dynamical_susceptibility) - IntensityCache.cache_method(cat, IntensityType.CHI_MAGNETIC, - self.show_dynamical_susceptibility_magnetic) - IntensityCache.cache_method(cat, IntensityType.D2SIGMA, self.show_d2sigma) - IntensityCache.cache_method(cat, IntensityType.SYMMETRISED, self.show_symmetrised) - IntensityCache.cache_method(cat, IntensityType.GDOS, self.show_gdos) - IntensityCache.cache_slice_type(IntensityType.SCATTERING_FUNCTION, "scattering_function") - IntensityCache.cache_slice_type(IntensityType.CHI, "chi") - IntensityCache.cache_slice_type(IntensityType.CHI_MAGNETIC, "chi_magnetic") - IntensityCache.cache_slice_type(IntensityType.D2SIGMA, "d2sigma") - IntensityCache.cache_slice_type(IntensityType.SYMMETRISED, "symmetrised") - IntensityCache.cache_slice_type(IntensityType.GDOS, "gdos") diff --git a/src/mslice/util/intensity_correction.py b/src/mslice/util/intensity_correction.py index 55c3200aa..288cb4fd4 100644 --- a/src/mslice/util/intensity_correction.py +++ b/src/mslice/util/intensity_correction.py @@ -15,7 +15,6 @@ class IntensityCache: __action_dict = {} __method_dict_cut = {} __method_dict_slice = {} - __slice_cache_type = {} __description_dict = {IntensityType.SCATTERING_FUNCTION: "scattering_function", IntensityType.CHI: "dynamical_susceptibility", IntensityType.CHI_MAGNETIC: "dynamical_susceptibility_magnetic", @@ -63,17 +62,6 @@ def get_method(cls, category, intensity_correction_type): else: raise KeyError("method related to the intensity correction type not found") - @classmethod - def cache_slice_type(cls, intensity_correction_type, name): - if intensity_correction_type not in cls.__slice_cache_type: - cls.__slice_cache_type[intensity_correction_type] = name - - @classmethod - def get_slice_type(cls, intensity_correction_type): - if intensity_correction_type not in cls.__slice_cache_type: - raise KeyError("intensity correction cached type not found") - return cls.__slice_cache_type[intensity_correction_type] - @classmethod def get_intensity_type_from_desc(cls, description): if description in cls._IntensityCache__description_dict.values():