def test_get_display_indices_with_two_dimensions(self): indices = WorkspaceInfo.display_indices(slicepoint=(None, 0, None), transpose=False) self.assertEqual(indices, (0, 2)) indices = WorkspaceInfo.display_indices(slicepoint=(None, None, 0), transpose=False) self.assertEqual(indices, (0, 1)) # Currently display_indices only looks for the first two None values indices = WorkspaceInfo.display_indices(slicepoint=(None, None, None), transpose=False) self.assertEqual(indices, (0, 1))
def dimensions_changed(self): """Indicates that the dimensions have changed""" data_view = self._data_view sliceinfo = self.get_sliceinfo() if data_view.nonorthogonal_mode: if sliceinfo.can_support_nonorthogonal_axes(): # axes need to be recreated to have the correct transform associated data_view.create_axes_nonorthogonal(sliceinfo.get_northogonal_transform()) else: data_view.disable_tool_button(ToolItemText.NONORTHOGONAL_AXES) data_view.create_axes_orthogonal() else: if sliceinfo.can_support_nonorthogonal_axes(): data_view.enable_tool_button(ToolItemText.NONORTHOGONAL_AXES) else: data_view.disable_tool_button(ToolItemText.NONORTHOGONAL_AXES) ws_type = WorkspaceInfo.get_ws_type(self.model.ws) if ws_type == WS_TYPE.MDH or ws_type == WS_TYPE.MDE: if self.model.get_number_dimensions() > 2 and \ sliceinfo.slicepoint[data_view.dimensions.get_previous_states().index(None)] is None: # The dimension of the slicepoint has changed self.new_plot(dimensions_changing=True) else: self.new_plot(dimensions_transposing=True) else: self.new_plot() self._call_cutviewer_presenter_if_created("on_dimension_changed")
def test_can_support_dynamic_rebinning_for_MDE_workspace(self): with mock.patch.object(WorkspaceInfo, "get_ws_type") as mock_get_ws_type: mock_get_ws_type.return_value = WS_TYPE.MDE mock_ws = mock.NonCallableMock() self.assertTrue( WorkspaceInfo.can_support_dynamic_rebinning(mock_ws)) mock_get_ws_type.assert_called_once_with(mock_ws)
def get_dim_info(workspace, n: int) -> dict: """ returns dict of (minimum :float, maximum :float, number_of_bins :int, width :float, name :str, units :str, type :str, can_rebin: bool, qdim: bool) for dimension n """ dim = workspace.getDimension(n) return { 'minimum': dim.getMinimum(), 'maximum': dim.getMaximum(), 'number_of_bins': dim.getNBins(), 'width': dim.getBinWidth(), 'name': dim.name, 'units': dim.getUnits(), 'type': WorkspaceInfo.get_ws_type(workspace).name, 'can_rebin': WorkspaceInfo.can_support_dynamic_rebinning(workspace), 'qdim': dim.getMDFrame().isQ() }
def show_all_data_clicked(self): """Instructs the view to show all data""" if WorkspaceInfo.is_ragged_matrix_workspace(self.model.ws): # get limits from full extent of image (which was calculated by looping over all spectra excl. monitors) x0, x1, y0, y1 = self._data_view.get_full_extent() limits = ((x0, x1), (y0, y1)) else: # otherwise query data model based on slice info and transpose limits = self.get_data_limits() self.set_axes_limits(*limits)
def test_cannot_support_dynamic_rebinning_for_MDH_workspace_with_different_dims( self): with mock.patch.object(WorkspaceInfo, "get_ws_type") as mock_get_ws_type: mock_get_ws_type.return_value = WS_TYPE.MDH mock_ws = mock.NonCallableMock() mock_ws.hasOriginalWorkspace.return_value = True self.assertFalse( WorkspaceInfo.can_support_dynamic_rebinning(mock_ws)) mock_get_ws_type.assert_called_once_with(mock_ws)
def test_cannot_support_dynamic_rebinning_with_non_MD_workspace_types( self): for in_type in [WS_TYPE.MATRIX, None]: with mock.patch.object(WorkspaceInfo, "get_ws_type") as mock_get_ws_type: mock_get_ws_type.return_value = in_type mock_ws = mock.NonCallableMock() self.assertFalse( WorkspaceInfo.can_support_dynamic_rebinning(mock_ws)) mock_get_ws_type.assert_called_once_with(mock_ws)
def get_dim_limits(workspace, slicepoint, transpose): """ Return a xlim, ylim) for the display dimensions where xlim, ylim are tuples :param slicepoint: Sequence containing either a float or None where None indicates a display dimension :param transpose: A boolean flag indicating if the display dimensions are transposed """ xindex, yindex = WorkspaceInfo.display_indices(slicepoint, transpose) xdim, ydim = workspace.getDimension(xindex), workspace.getDimension( yindex) return (xdim.getMinimum(), xdim.getMaximum()), (ydim.getMinimum(), ydim.getMaximum())
def new_plot_MDH(self, dimensions_transposing=False, dimensions_changing=False): """ Tell the view to display a new plot of an MDHistoWorkspace """ data_view = self.view.data_view limits = data_view.get_axes_limits() if limits is None or not WorkspaceInfo.can_support_dynamic_rebinning(self.model.ws): data_view.plot_MDH(self.model.get_ws(), slicepoint=self.get_slicepoint()) self._call_peaks_presenter_if_created("notify", PeaksViewerPresenter.Event.OverlayPeaks) else: self.new_plot_MDE(dimensions_transposing, dimensions_changing)
def __init__(self, ws, parent=None, window_flags=Qt.Window, model=None, view=None, conf=None): """ Create a presenter for controlling the slice display for a workspace :param ws: Workspace containing data to display and slice :param parent: An optional parent widget :param window_flags: An optional set of window flags :param model: A model to define slicing operations. If None uses SliceViewerModel :param view: A view to display the operations. If None uses SliceViewerView """ model: SliceViewerModel = model if model else SliceViewerModel(ws) self.view = view if view else SliceViewerView(self, Dimensions.get_dimensions_info(ws), model.can_normalize_workspace(), parent, window_flags, conf) super().__init__(ws, self.view.data_view, model) self._logger = Logger("SliceViewer") self._peaks_presenter: PeaksViewerCollectionPresenter = None self._cutviewer_presenter = None self.conf = conf # Acts as a 'time capsule' to the properties of the model at this # point in the execution. By the time the ADS observer calls self.replace_workspace, # the workspace associated with self.model has already been changed. self.initial_model_properties = model.get_properties() self._new_plot_method, self.update_plot_data = self._decide_plot_update_methods() self.view.setWindowTitle(self.model.get_title()) self.view.data_view.create_axes_orthogonal( redraw_on_zoom=not WorkspaceInfo.can_support_dynamic_rebinning(self.model.ws)) if self.model.can_normalize_workspace(): self.view.data_view.set_normalization(ws) self.view.data_view.norm_opts.currentTextChanged.connect(self.normalization_changed) if not self.model.can_support_peaks_overlays(): self.view.data_view.disable_tool_button(ToolItemText.OVERLAY_PEAKS) # check whether to enable non-orthog view # don't know whether can always assume init with display indices (0,1) - so get sliceinfo sliceinfo = self.get_sliceinfo() if not sliceinfo.can_support_nonorthogonal_axes(): self.view.data_view.disable_tool_button(ToolItemText.NONORTHOGONAL_AXES) if not self.model.can_support_non_axis_cuts(): self.view.data_view.disable_tool_button(ToolItemText.NONAXISALIGNEDCUTS) self.view.data_view.help_button.clicked.connect(self.action_open_help_window) self.refresh_view() # Start the GUI with zoom selected. self.view.data_view.activate_tool(ToolItemText.ZOOM) self.ads_observer = SliceViewerADSObserver(self.replace_workspace, self.rename_workspace, self.ADS_cleared, self.delete_workspace)
def test_cannot_support_dynamic_rebinning_for_MDH_workspace_without_original_workspace( self): with mock.patch.object(WorkspaceInfo, "get_ws_type") as mock_get_ws_type: mock_get_ws_type.return_value = WS_TYPE.MDH mock_ws = mock.NonCallableMock() mock_ws.hasOriginalWorkspace.return_value = False mock_ws.getOriginalWorkspace.return_value.getNumDims.return_value = mock_ws.getNumDims.return_value self.assertFalse( WorkspaceInfo.can_support_dynamic_rebinning(mock_ws)) self.assertEqual(mock_get_ws_type.call_count, 2) mock_get_ws_type.assert_has_calls(2 * [mock.call(mock_ws)])
def _decide_plot_update_methods(self) -> Tuple[Callable, Callable]: """ Checks the type of workspace in self.model and decides which of the new_plot and update_plot_data methods to use :return: the new_plot method to use """ # TODO get rid of private access here ws_type = WorkspaceInfo.get_ws_type(self.model.ws) if ws_type == WS_TYPE.MDH: return self.new_plot_MDH, self.update_plot_data_MDH elif ws_type == WS_TYPE.MDE: return self.new_plot_MDE, self.update_plot_data_MDE else: return self.new_plot_matrix, self.update_plot_data_matrix
def test_get_display_indices_with_transpose(self): indices = WorkspaceInfo.display_indices(slicepoint=(None, 0, None), transpose=True) self.assertEqual(indices, (2, 0))
def test_get_ws_type_with_MDEventWorkspace(self): mock_ws = mock.Mock(spec=MultipleExperimentInfos) mock_ws.isMDHistoWorkspace = mock.Mock(return_value=False) self.assertEqual(WS_TYPE.MDE, WorkspaceInfo.get_ws_type(mock_ws))
def test_get_ws_type_with_MatrixWorkspace(self): mock_ws = mock.Mock(spec=MatrixWorkspace) self.assertEqual(WS_TYPE.MATRIX, WorkspaceInfo.get_ws_type(mock_ws))
def data_limits_changed(self): """Notify data limits on image axes have changed""" if WorkspaceInfo.can_support_dynamic_rebinning(self.model.ws): self.new_plot() # automatically uses current display limits else: self._data_view.draw_plot()