def test_workspace_selection_changed_multiple_selected_empty_options_success(self): slice_widget_presenter = SliceWidgetPresenter(self.slice_view) slice_widget_presenter.register_master(self.main_presenter) workspace = "a" self.main_presenter.get_selected_workspaces = mock.Mock(return_value=[workspace,workspace]) slice_widget_presenter.workspace_selection_changed() assert(self.slice_view.clear_input_fields.called)
def test_notify_presenter_clears_error(self): presenter = SliceWidgetPresenter(self.slice_view) presenter.register_master(self.main_presenter) self.slice_view.clear_displayed_error = mock.Mock() # This unit test will verify that notifying cut presenter will cause the error to be cleared on the view. # The actual subsequent procedure will fail, however this irrelevant to this. Hence the try, except blocks for command in [x for x in dir(Command) if x[0] != "_"]: try: presenter.notify(command) except ValueError: pass self.slice_view.clear_displayed_error.assert_called() self.slice_view.reset_mock()
def test_workspace_selection_changed(self, is_sliceable_mock, get_axis_range_mock, get_available_axes_mock, get_ws_handle_mock, get_ws_handle_mock2): slice_widget_presenter = SliceWidgetPresenter(self.slice_view) slice_widget_presenter.register_master(self.main_presenter) workspace = 'workspace' self.main_presenter.get_selected_workspaces = mock.Mock( return_value=[workspace]) ws_mock = mock.Mock() get_ws_handle_mock.return_value = ws_mock get_ws_handle_mock2.return_value = ws_mock is_sliceable_mock.return_value = True dims = ['dim1', 'dim2'] get_available_axes_mock.return_value = dims get_axis_range_mock.return_value = (0, 1, 0.1) slice_widget_presenter.workspace_selection_changed() assert (self.slice_view.populate_slice_x_options.called) assert (self.slice_view.populate_slice_y_options.called) assert (get_available_axes_mock.called) assert (get_axis_range_mock.called) # Test error handling get_axis_range_mock.side_effect = KeyError slice_widget_presenter.workspace_selection_changed() assert (self.slice_view.clear_input_fields.called)
def test_plot_slice_successful(self): slice_widget_presenter = SliceWidgetPresenter(self.slice_view) slice_widget_presenter.register_master(self.main_presenter) slice_widget_presenter.set_slice_plotter_presenter( self.slice_plotter_presenter) x = Axis('x', '0', '10', '1') y = Axis('y', '2', '8', '3') intensity_start = '7' intensity_end = '8' norm_to_one = False colourmap = 'colormap' selected_workspace = 'workspace1' self.main_presenter.get_selected_workspaces.return_value = [ selected_workspace ] self.slice_view.get_slice_x_axis.return_value = x.units self.slice_view.get_slice_x_start.return_value = x.start self.slice_view.get_slice_x_end.return_value = x.end self.slice_view.get_slice_x_step.return_value = x.step self.slice_view.get_slice_y_axis.return_value = y.units self.slice_view.get_slice_y_start.return_value = y.start self.slice_view.get_slice_y_end.return_value = y.end self.slice_view.get_slice_y_step.return_value = y.step self.slice_view.get_slice_intensity_start.return_value = intensity_start self.slice_view.get_slice_intensity_end.return_value = intensity_end self.slice_view.get_slice_is_norm_to_one.return_value = norm_to_one self.slice_view.get_slice_colourmap.return_value = colourmap plot_info = ("plot_data", "boundaries", "colormap", "norm") self.slice_plotter_presenter.plot_slice = mock.Mock( return_value=plot_info) self.slice_plotter_presenter.validate_intensity = mock.Mock( return_value=(7.0, 8.0)) slice_widget_presenter.notify(Command.DisplaySlice) self.main_presenter.get_selected_workspaces.assert_called_once_with() self.slice_view.get_slice_x_axis.assert_called_once_with() self.slice_view.get_slice_x_start.assert_called_once_with() self.slice_view.get_slice_x_end.assert_called_once_with() self.slice_view.get_slice_x_step.assert_called_once_with() self.slice_view.get_slice_y_axis.assert_called_once_with() self.slice_view.get_slice_y_start.assert_called_once_with() self.slice_view.get_slice_y_end.assert_called_once_with() self.slice_view.get_slice_y_step.assert_called_once_with() self.slice_view.get_slice_intensity_start.assert_called_once_with() self.slice_view.get_slice_intensity_end.assert_called_once_with() self.slice_view.get_slice_is_norm_to_one.assert_called_once_with() self.slice_view.get_slice_colourmap.assert_called_once_with() self.slice_plotter_presenter.validate_intensity.assert_called_once_with( '7', '8') self.slice_plotter_presenter.plot_slice.assert_called_with( selected_workspace, Axis('x', 0, 10, 1), Axis('y', 2, 8, 3), float(intensity_start), float(intensity_end), norm_to_one, colourmap)
def __init__(self, parent=None, *args, **kwargs): """This Widget provides basic control over displaying slices. This widget is NOT USABLE without a main window The main window must implement MainView""" QWidget.__init__(self, parent, *args, **kwargs) load_ui(__file__, 'slice.ui', self) self.btnSliceDisplay.clicked.connect(self._btn_clicked) self.display_errors_to_statusbar = True self._presenter = SliceWidgetPresenter(self) # Each time the fields are populated, set a minimum step size self._minimumStep = {} self.lneSliceXStep.editingFinished.connect( lambda: self._step_edited('x', self.lneSliceXStep)) self.lneSliceYStep.editingFinished.connect( lambda: self._step_edited('y', self.lneSliceYStep)) self.enable_units_choice(False) self.cmbSliceXAxis.currentIndexChanged.connect( lambda ind: self._change_axes(1, ind)) self.cmbSliceYAxis.currentIndexChanged.connect( lambda ind: self._change_axes(2, ind)) self.set_validators()
def test_workspace_selection_changed_multiple_selected_empty_options_success( self): slice_widget_presenter = SliceWidgetPresenter(self.slice_view) slice_widget_presenter.register_master(self.main_presenter) workspace = "a" self.main_presenter.get_selected_workspaces = mock.Mock( return_value=[workspace, workspace]) slice_widget_presenter.workspace_selection_changed() assert (self.slice_view.clear_input_fields.called)
def test_plot_slice_successful(self): slice_widget_presenter = SliceWidgetPresenter(self.slice_view) slice_widget_presenter.register_master(self.main_presenter) slice_widget_presenter.set_slice_plotter_presenter(self.slice_plotter_presenter) x = Axis('x', '0', '10' ,'1') y = Axis('y', '2', '8', '3') intensity_start = '7' intensity_end = '8' norm_to_one = False colourmap = 'colormap' selected_workspace = 'workspace1' self.main_presenter.get_selected_workspaces.return_value = [selected_workspace] self.slice_view.get_slice_x_axis.return_value = x.units self.slice_view.get_slice_x_start.return_value = x.start self.slice_view.get_slice_x_end.return_value = x.end self.slice_view.get_slice_x_step.return_value = x.step self.slice_view.get_slice_y_axis.return_value = y.units self.slice_view.get_slice_y_start.return_value = y.start self.slice_view.get_slice_y_end.return_value = y.end self.slice_view.get_slice_y_step.return_value = y.step self.slice_view.get_slice_intensity_start.return_value = intensity_start self.slice_view.get_slice_intensity_end.return_value = intensity_end self.slice_view.get_slice_is_norm_to_one.return_value = norm_to_one self.slice_view.get_slice_colourmap.return_value = colourmap self.slice_view.get_units.return_value = 'meV' plot_info = ("plot_data", "boundaries", "colormap", "norm") self.slice_plotter_presenter.plot_slice = mock.Mock(return_value=plot_info) self.slice_plotter_presenter.validate_intensity = mock.Mock(return_value=(7.0, 8.0)) slice_widget_presenter.notify(Command.DisplaySlice) self.main_presenter.get_selected_workspaces.assert_called_once_with() self.slice_view.get_slice_x_axis.assert_called_once_with() self.slice_view.get_slice_x_start.assert_called_once_with() self.slice_view.get_slice_x_end.assert_called_once_with() self.slice_view.get_slice_x_step.assert_called_once_with() self.slice_view.get_slice_y_axis.assert_called_once_with() self.slice_view.get_slice_y_start.assert_called_once_with() self.slice_view.get_slice_y_end.assert_called_once_with() self.slice_view.get_slice_y_step.assert_called_once_with() self.slice_view.get_slice_intensity_start.assert_called_once_with() self.slice_view.get_slice_intensity_end.assert_called_once_with() self.slice_view.get_slice_is_norm_to_one.assert_called_once_with() self.slice_view.get_slice_colourmap.assert_called_once_with() self.slice_plotter_presenter.validate_intensity.assert_called_once_with('7', '8') self.slice_plotter_presenter.plot_slice.assert_called_with(selected_workspace, Axis('x', 0, 10, 1), Axis('y', 2, 8, 3), float(intensity_start), float(intensity_end), norm_to_one, colourmap)
def __init__(self, parent=None, *args, **kwargs): """This Widget provides basic control over displaying slices. This widget is NOT USABLE without a main window The main window must implement MainView""" QWidget.__init__(self, parent, *args, **kwargs) load_ui(__file__, 'slice.ui', self) self.btnSliceDisplay.clicked.connect(self._btn_clicked) self.display_errors_to_statusbar = True self._presenter = SliceWidgetPresenter(self) # Each time the fields are populated, set a minimum step size self._minimumStep = {} self.lneSliceXStep.editingFinished.connect(lambda: self._step_edited('x', self.lneSliceXStep)) self.lneSliceYStep.editingFinished.connect(lambda: self._step_edited('y', self.lneSliceYStep)) self.cmbSliceXAxis.currentIndexChanged.connect(lambda ind: self._change_axes(1, ind)) self.cmbSliceYAxis.currentIndexChanged.connect(lambda ind: self._change_axes(2, ind)) self.cmbSliceUnits.currentIndexChanged.connect(self._change_unit) self.set_validators() self._old_en = EnergyUnits('meV') self._en_default = 'meV'
def test_register_master_success(self): slice_presenter = SliceWidgetPresenter(self.slice_view) slice_presenter.register_master(self.main_presenter) self.main_presenter.subscribe_to_workspace_selection_monitor.assert_called_once_with(slice_presenter)
class SliceWidget(SliceView, QWidget): error_occurred = Signal('QString') busy = Signal(bool) def __init__(self, parent=None, *args, **kwargs): """This Widget provides basic control over displaying slices. This widget is NOT USABLE without a main window The main window must implement MainView""" QWidget.__init__(self, parent, *args, **kwargs) load_ui(__file__, 'slice.ui', self) self.btnSliceDisplay.clicked.connect(self._btn_clicked) self.display_errors_to_statusbar = True self._presenter = SliceWidgetPresenter(self) # Each time the fields are populated, set a minimum step size self._minimumStep = {} self.lneSliceXStep.editingFinished.connect( lambda: self._step_edited('x', self.lneSliceXStep)) self.lneSliceYStep.editingFinished.connect( lambda: self._step_edited('y', self.lneSliceYStep)) self.enable_units_choice(False) self.cmbSliceXAxis.currentIndexChanged.connect( lambda ind: self._change_axes(1, ind)) self.cmbSliceYAxis.currentIndexChanged.connect( lambda ind: self._change_axes(2, ind)) self.set_validators() def get_presenter(self): return self._presenter def _btn_clicked(self): if self._step_edited('x', self.lneSliceXStep) and self._step_edited( 'y', self.lneSliceXStep): self._presenter.notify(Command.DisplaySlice) def _step_edited(self, idx, lineEdit): """Checks that user inputted step size is not too small.""" if self._minimumStep: try: value = float(lineEdit.text()) except ValueError: value = 0 self._display_error( 'Invalid step parameter. Using default value.') if value == 0: lineEdit.setText(str(self._minimumStep[idx])) self._display_error('Setting step size to default.') elif value < (self._minimumStep[idx] / 100.): self._display_error('Step size too small!') return False return True def _change_axes(self, axis, idx): """Makes sure u1 and u2 are always different, and updates default limits/steps values.""" curr_axis = axis - 1 other_axis = axis % 2 axes_handle = [self.cmbSliceXAxis, self.cmbSliceYAxis] num_items = axes_handle[other_axis].count() if num_items < 2: return axes = [ self.cmbSliceXAxis.currentText(), self.cmbSliceYAxis.currentText() ] index = [ self.cmbSliceXAxis.currentIndex(), self.cmbSliceYAxis.currentIndex() ] axes_set = [ self.cmbSliceXAxis.setCurrentIndex, self.cmbSliceYAxis.setCurrentIndex ] if axes[curr_axis] == axes[other_axis]: new_index = (index[other_axis] + 1) % num_items axes_set[other_axis](new_index) self._presenter.populate_slice_params() def _display_error(self, error_string): self.error_occurred.emit(error_string) def enable_units_choice(self, enabled): if enabled: # TODO implement conversion from meV to cm-1 pass #self.cmbSliceUnits.show() #self.label_16.show() else: self.cmbSliceUnits.hide() self.label_16.hide() def get_units(self): return self.cmbSliceUnits.currentText() def get_slice_x_axis(self): return str(self.cmbSliceXAxis.currentText()) def get_slice_y_axis(self): return str(self.cmbSliceYAxis.currentText()) def get_slice_is_norm_to_one(self): return self.rdoSliceNormToOne.isChecked() def get_slice_smoothing(self): return str(self.lneSliceSmoothing.text()) def get_slice_x_start(self): return str(self.lneSliceXStart.text()) def get_slice_x_end(self): return str(self.lneSliceXEnd.text()) def get_slice_x_step(self): return str(self.lneSliceXStep.text()) def get_slice_y_start(self): return str(self.lneSliceYStart.text()) def get_slice_y_end(self): return str(self.lneSliceYEnd.text()) def get_slice_y_step(self): return str(self.lneSliceYStep.text()) def get_slice_colourmap(self): return str(self.cmbSliceColormap.currentText()) def get_slice_intensity_start(self): return str(self.lneSliceIntensityStart.text()) def get_slice_intensity_end(self): return str(self.lneSliceIntensityEnd.text()) def populate_colormap_options(self, colormaps): self.cmbSliceColormap.clear() for colormap in colormaps: self.cmbSliceColormap.addItem(colormap) def populate_slice_x_options(self, options): self.cmbSliceXAxis.clear() for option in options: self.cmbSliceXAxis.addItem(option) def populate_slice_y_options(self, options): self.cmbSliceYAxis.clear() for option in options: self.cmbSliceYAxis.addItem(option) def error_select_one_workspace(self): self._display_error('Please select a workspace to slice') def error_invalid_x_params(self): self._display_error('Invalid parameters for the x axis of the slice') def error_invalid_intensity_params(self): self._display_error( 'Invalid parameters for the intensity of the slice') def error_invalid_plot_parameters(self): self._display_error('Invalid parameters for the slice') def error_invalid_smoothing_params(self): self._display_error('Invalid value for smoothing') def error_invalid_y_units(self): self._display_error('Invalid selection of the y axis') def error_invalid_y_params(self): self._display_error('Invalid parameters for the y axis of the slice') def error_invalid_x_units(self): self._display_error('Invalid selection of the x axis') def error(self, string): self._display_error(string) def populate_slice_x_params(self, x_start, x_end, x_step): self.lneSliceXStart.setText(x_start) self.lneSliceXEnd.setText(x_end) self.lneSliceXStep.setText(x_step) if x_step: self._minimumStep['x'] = float(x_step) def populate_slice_y_params(self, y_start, y_end, y_step): self.lneSliceYStart.setText(y_start) self.lneSliceYEnd.setText(y_end) self.lneSliceYStep.setText(y_step) if y_step: self._minimumStep['y'] = float(y_step) def clear_input_fields(self): self.populate_slice_x_options([]) self.populate_slice_y_options([]) self.populate_slice_x_params("", "", "") self.populate_slice_y_params("", "", "") self.lneSliceIntensityStart.setText("") self.lneSliceIntensityEnd.setText("") self.rdoSliceNormToOne.setChecked(0) self._minimumStep = {} def disable(self): self.cmbSliceXAxis.setEnabled(False) self.cmbSliceYAxis.setEnabled(False) self.lneSliceXStart.setEnabled(False) self.lneSliceXEnd.setEnabled(False) self.lneSliceXStep.setEnabled(False) self.lneSliceYStart.setEnabled(False) self.lneSliceYEnd.setEnabled(False) self.lneSliceYStep.setEnabled(False) self.lneSliceIntensityStart.setEnabled(False) self.lneSliceIntensityEnd.setEnabled(False) self.rdoSliceNormToOne.setEnabled(False) self.btnSliceDisplay.setEnabled(False) self.cmbSliceColormap.setEnabled(False) def enable(self): self.cmbSliceXAxis.setEnabled(True) self.cmbSliceYAxis.setEnabled(True) self.lneSliceXStart.setEnabled(True) self.lneSliceXEnd.setEnabled(True) self.lneSliceXStep.setEnabled(True) self.lneSliceYStart.setEnabled(True) self.lneSliceYEnd.setEnabled(True) self.lneSliceYStep.setEnabled(True) self.lneSliceIntensityStart.setEnabled(True) self.lneSliceIntensityEnd.setEnabled(True) self.rdoSliceNormToOne.setEnabled(True) self.btnSliceDisplay.setEnabled(True) self.cmbSliceColormap.setEnabled(True) def set_validators(self): line_edits = [ self.lneSliceXStart, self.lneSliceXEnd, self.lneSliceXStep, self.lneSliceYStart, self.lneSliceYEnd, self.lneSliceYStep, self.lneSliceIntensityStart, self.lneSliceIntensityEnd ] for line_edit in line_edits: line_edit.setValidator(QDoubleValidator()) def clear_displayed_error(self): self._display_error("")
def test_plot_slice_error_handling(self): slice_widget_presenter = SliceWidgetPresenter(self.slice_view) slice_widget_presenter.register_master(self.main_presenter) slice_widget_presenter.set_slice_plotter_presenter( self.slice_plotter_presenter) x = Axis('x', '0', '10', '1') y = Axis('y', '2', '8', '3') intensity_start = '7' intensity_end = '8' norm_to_one = False smoothing = '10' colourmap = 'colormap' selected_workspace = 'workspace1' self.slice_view.get_slice_x_axis.return_value = x.units self.slice_view.get_slice_x_start.return_value = x.start self.slice_view.get_slice_x_end.return_value = x.end self.slice_view.get_slice_x_step.return_value = x.step self.slice_view.get_slice_y_axis.return_value = y.units self.slice_view.get_slice_y_start.return_value = y.start self.slice_view.get_slice_y_end.return_value = y.end self.slice_view.get_slice_y_step.return_value = y.step self.slice_view.get_slice_intensity_start.return_value = intensity_start self.slice_view.get_slice_intensity_end.return_value = intensity_end self.slice_view.get_slice_is_norm_to_one.return_value = norm_to_one self.slice_view.get_slice_smoothing.return_value = smoothing self.slice_view.get_slice_colourmap.return_value = colourmap plot_info = ("plot_data", "boundaries", "colormap", "norm") self.slice_plotter_presenter.plot_slice = mock.Mock( return_value=plot_info) self.slice_plotter_presenter.validate_intensity = mock.Mock( return_value=(7.0, 8.0)) # Test empty workspace, multiple workspaces self.main_presenter.get_selected_workspaces.return_value = [] slice_widget_presenter.notify(Command.DisplaySlice) assert self.slice_view.error_select_one_workspace.called self.main_presenter.get_selected_workspaces.return_value = [ selected_workspace, selected_workspace ] self.slice_view.error_select_one_workspace.reset_mock() slice_widget_presenter.notify(Command.DisplaySlice) assert self.slice_view.error_select_one_workspace.called # Test invalid axes self.main_presenter.get_selected_workspaces.return_value = [ selected_workspace ] self.slice_view.get_slice_y_axis.return_value = x.units slice_widget_presenter.notify(Command.DisplaySlice) assert self.slice_view.error_invalid_plot_parameters.called # Simulate matplotlib error self.slice_plotter_presenter.plot_slice = mock.Mock( side_effect=ValueError( 'minvalue must be less than or equal to maxvalue')) self.slice_view.get_slice_y_axis.return_value = y.units slice_widget_presenter.notify(Command.DisplaySlice) assert self.slice_view.error_invalid_intensity_params.called self.slice_plotter_presenter.plot_slice = mock.Mock( side_effect=ValueError('something bad')) self.assertRaises(ValueError, slice_widget_presenter.notify, Command.DisplaySlice)
def test_set_energy_default(self): slice_presenter = SliceWidgetPresenter(self.slice_view) slice_presenter.set_energy_default("meV") self.slice_view.set_units.assert_called_once() self.slice_view.set_energy_default.assert_called_once()
def test_register_master_invalid_master_fail(self): slice_presenter = SliceWidgetPresenter(self.slice_view) with self.assertRaises(AssertionError): slice_presenter.register_master(3)
def test_register_master_success(self): slice_presenter = SliceWidgetPresenter(self.slice_view) slice_presenter.register_master(self.main_presenter) self.main_presenter.subscribe_to_workspace_selection_monitor.assert_called_once_with( slice_presenter)
def test_notify_presenter_unknown_command_raise_exception_failure(self): slice_widget_presenter = SliceWidgetPresenter(self.slice_view) slice_widget_presenter.register_master(self.main_presenter) unknown_command = -1 with self.assertRaises(ValueError): slice_widget_presenter.notify(unknown_command)
def test_constructor_invalid_slice_view_failure(self): with self.assertRaises(TypeError): SliceWidgetPresenter(self.slice_plotter_presenter)
def test_constructor_success(self): self.slice_plotter_presenter = SliceWidgetPresenter(self.slice_view)
def test_workspace_selection_changed(self, is_sliceable_mock, get_axis_range_mock, get_available_axes_mock, get_ws_handle_mock, get_ws_handle_mock2): slice_widget_presenter = SliceWidgetPresenter(self.slice_view) slice_widget_presenter.register_master(self.main_presenter) workspace = 'workspace' self.main_presenter.get_selected_workspaces = mock.Mock(return_value=[workspace]) ws_mock = mock.Mock() get_ws_handle_mock.return_value = ws_mock get_ws_handle_mock2.return_value = ws_mock is_sliceable_mock.return_value = True dims = ['dim1', 'dim2'] get_available_axes_mock.return_value = dims get_axis_range_mock.return_value = (0, 1, 0.1) self.slice_view.get_units = mock.Mock(side_effect=['meV', 'cm-1', 'cm-1']) slice_widget_presenter.workspace_selection_changed() assert (self.slice_view.get_slice_x_axis.call_count == 1) assert (self.slice_view.populate_slice_x_options.called) assert (self.slice_view.populate_slice_y_options.called) assert (get_available_axes_mock.called) assert (get_axis_range_mock.called) # Test energy unit conversion is different for second call slice_widget_presenter.workspace_selection_changed() self.slice_view.get_slice_x_axis.assert_called() self.slice_view.get_slice_x_axis.return_value = 'DeltaE' slice_widget_presenter.workspace_selection_changed() assert (self.slice_view.get_slice_x_axis.call_count == 5) # Test error handling get_axis_range_mock.side_effect = KeyError slice_widget_presenter.workspace_selection_changed() assert (self.slice_view.clear_input_fields.called)
class SliceWidget(SliceView, QWidget): error_occurred = Signal('QString') busy = Signal(bool) def __init__(self, parent=None, *args, **kwargs): """This Widget provides basic control over displaying slices. This widget is NOT USABLE without a main window The main window must implement MainView""" QWidget.__init__(self, parent, *args, **kwargs) load_ui(__file__, 'slice.ui', self) self.btnSliceDisplay.clicked.connect(self._btn_clicked) self.display_errors_to_statusbar = True self._presenter = SliceWidgetPresenter(self) # Each time the fields are populated, set a minimum step size self._minimumStep = {} self.lneSliceXStep.editingFinished.connect(lambda: self._step_edited('x', self.lneSliceXStep)) self.lneSliceYStep.editingFinished.connect(lambda: self._step_edited('y', self.lneSliceYStep)) self.cmbSliceXAxis.currentIndexChanged.connect(lambda ind: self._change_axes(1, ind)) self.cmbSliceYAxis.currentIndexChanged.connect(lambda ind: self._change_axes(2, ind)) self.cmbSliceUnits.currentIndexChanged.connect(self._change_unit) self.set_validators() self._old_en = EnergyUnits('meV') self._en_default = 'meV' def get_presenter(self): return self._presenter def _btn_clicked(self): if self._step_edited('x', self.lneSliceXStep) and self._step_edited('y', self.lneSliceXStep): self._presenter.notify(Command.DisplaySlice) def _step_edited(self, idx, lineEdit): """Checks that user inputted step size is not too small.""" if self._minimumStep: try: value = float(lineEdit.text()) except ValueError: value = 0 self._display_error('Invalid step parameter. Using default value.') if value == 0: lineEdit.setText(str(self._minimumStep[idx])) self._display_error('Setting step size to default.') elif value < (self._minimumStep[idx] / 100.): self._display_error('Step size too small!') return False return True def _change_axes(self, axis, idx): """Makes sure u1 and u2 are always different, and updates default limits/steps values.""" curr_axis = axis - 1 other_axis = axis % 2 axes_handle = [self.cmbSliceXAxis, self.cmbSliceYAxis] num_items = axes_handle[other_axis].count() if num_items < 2: return axes = [self.cmbSliceXAxis.currentText(), self.cmbSliceYAxis.currentText()] index = [self.cmbSliceXAxis.currentIndex(), self.cmbSliceYAxis.currentIndex()] axes_set = [self.cmbSliceXAxis.setCurrentIndex, self.cmbSliceYAxis.setCurrentIndex] if axes[curr_axis] == axes[other_axis]: new_index = (index[other_axis] + 1) % num_items axes_set[other_axis](new_index) self._presenter.populate_slice_params() def _change_unit(self): new_unit = self.get_units() if self._old_en.factor_to(new_unit) != 1.: if 'DeltaE' in self.get_slice_x_axis(): x_start, x_end, x_step = self.get_slice_x_start(), self.get_slice_x_end(), self.get_slice_x_step() x_start, x_end, x_step = self._old_en.convert_to(new_unit, x_start, x_end, x_step) self.populate_slice_x_params(x_start, x_end, x_step) elif 'DeltaE' in self.get_slice_y_axis(): y_start, y_end, y_step = self.get_slice_y_start(), self.get_slice_y_end(), self.get_slice_y_step() y_start, y_end, y_step = self._old_en.convert_to(new_unit, y_start, y_end, y_step) self.populate_slice_y_params(y_start, y_end, y_step) self._old_en = EnergyUnits(new_unit) def _display_error(self, error_string): self.error_occurred.emit(error_string) def get_units(self): return self.cmbSliceUnits.currentText() def set_units(self, en_unit): self.cmbSliceUnits.setCurrentIndex(EnergyUnits.get_index(en_unit)) def get_slice_x_axis(self): return str(self.cmbSliceXAxis.currentText()) def get_slice_y_axis(self): return str(self.cmbSliceYAxis.currentText()) def get_slice_is_norm_to_one(self): return self.rdoSliceNormToOne.isChecked() def get_slice_smoothing(self): return str(self.lneSliceSmoothing.text()) def get_slice_x_start(self): return str(self.lneSliceXStart.text()) def get_slice_x_end(self): return str(self.lneSliceXEnd.text()) def get_slice_x_step(self): return str(self.lneSliceXStep.text()) def get_slice_y_start(self): return str(self.lneSliceYStart.text()) def get_slice_y_end(self): return str(self.lneSliceYEnd.text()) def get_slice_y_step(self): return str(self.lneSliceYStep.text()) def get_slice_colourmap(self): return str(self.cmbSliceColormap.currentText()) def get_slice_intensity_start(self): return str(self.lneSliceIntensityStart.text()) def get_slice_intensity_end(self): return str(self.lneSliceIntensityEnd.text()) def populate_colormap_options(self, colormaps): self.cmbSliceColormap.clear() for colormap in colormaps: self.cmbSliceColormap.addItem(colormap) def populate_slice_x_options(self, options): self.cmbSliceXAxis.clear() for option in options: self.cmbSliceXAxis.addItem(option) def populate_slice_y_options(self, options): self.cmbSliceYAxis.clear() for option in options: self.cmbSliceYAxis.addItem(option) def error_select_one_workspace(self): self._display_error('Please select a workspace to slice') def error_invalid_x_params(self): self._display_error('Invalid parameters for the x axis of the slice') def error_invalid_intensity_params(self): self._display_error('Invalid parameters for the intensity of the slice') def error_invalid_plot_parameters(self): self._display_error('Invalid parameters for the slice') def error_invalid_smoothing_params(self): self._display_error('Invalid value for smoothing') def error_invalid_y_units(self): self._display_error('Invalid selection of the y axis') def error_invalid_y_params(self): self._display_error('Invalid parameters for the y axis of the slice') def error_invalid_x_units(self): self._display_error('Invalid selection of the x axis') def error(self, string): self._display_error(string) def populate_slice_x_params(self, x_start, x_end, x_step): self.lneSliceXStart.setText(x_start) self.lneSliceXEnd.setText(x_end) self.lneSliceXStep.setText(x_step) if x_step: self._minimumStep['x'] = float(x_step) def populate_slice_y_params(self, y_start, y_end, y_step): self.lneSliceYStart.setText(y_start) self.lneSliceYEnd.setText(y_end) self.lneSliceYStep.setText(y_step) if y_step: self._minimumStep['y'] = float(y_step) def clear_input_fields(self): self.populate_slice_x_options([]) self.populate_slice_y_options([]) self.populate_slice_x_params("", "", "") self.populate_slice_y_params("", "", "") self.lneSliceIntensityStart.setText("") self.lneSliceIntensityEnd.setText("") self.rdoSliceNormToOne.setChecked(0) self.cmbSliceUnits.setCurrentIndex(EnergyUnits.get_index(self._en_default)) self._minimumStep = {} def disable(self): self.cmbSliceXAxis.setEnabled(False) self.cmbSliceYAxis.setEnabled(False) self.lneSliceXStart.setEnabled(False) self.lneSliceXEnd.setEnabled(False) self.lneSliceXStep.setEnabled(False) self.lneSliceYStart.setEnabled(False) self.lneSliceYEnd.setEnabled(False) self.lneSliceYStep.setEnabled(False) self.lneSliceIntensityStart.setEnabled(False) self.lneSliceIntensityEnd.setEnabled(False) self.rdoSliceNormToOne.setEnabled(False) self.btnSliceDisplay.setEnabled(False) self.cmbSliceColormap.setEnabled(False) self.cmbSliceUnits.setEnabled(False) def enable(self): self.cmbSliceXAxis.setEnabled(True) self.cmbSliceYAxis.setEnabled(True) self.lneSliceXStart.setEnabled(True) self.lneSliceXEnd.setEnabled(True) self.lneSliceXStep.setEnabled(True) self.lneSliceYStart.setEnabled(True) self.lneSliceYEnd.setEnabled(True) self.lneSliceYStep.setEnabled(True) self.lneSliceIntensityStart.setEnabled(True) self.lneSliceIntensityEnd.setEnabled(True) self.rdoSliceNormToOne.setEnabled(True) self.btnSliceDisplay.setEnabled(True) self.cmbSliceColormap.setEnabled(True) self.cmbSliceUnits.setEnabled(True) def set_validators(self): line_edits = [self.lneSliceXStart, self.lneSliceXEnd, self.lneSliceXStep, self.lneSliceYStart, self.lneSliceYEnd, self.lneSliceYStep, self.lneSliceIntensityStart, self.lneSliceIntensityEnd] for line_edit in line_edits: line_edit.setValidator(QDoubleValidator()) def set_energy_default(self, en_default): self._en_default = en_default def clear_displayed_error(self): self._display_error("")
def test_plot_slice_error_handling(self): slice_widget_presenter = SliceWidgetPresenter(self.slice_view) slice_widget_presenter.register_master(self.main_presenter) slice_widget_presenter.set_slice_plotter_presenter(self.slice_plotter_presenter) x = Axis('x', '0', '10', '1') y = Axis('y', '2', '8', '3') intensity_start = '7' intensity_end = '8' norm_to_one = False smoothing = '10' colourmap = 'colormap' selected_workspace = 'workspace1' self.slice_view.get_slice_x_axis.return_value = x.units self.slice_view.get_slice_x_start.return_value = x.start self.slice_view.get_slice_x_end.return_value = x.end self.slice_view.get_slice_x_step.return_value = x.step self.slice_view.get_slice_y_axis.return_value = y.units self.slice_view.get_slice_y_start.return_value = y.start self.slice_view.get_slice_y_end.return_value = y.end self.slice_view.get_slice_y_step.return_value = y.step self.slice_view.get_slice_intensity_start.return_value = intensity_start self.slice_view.get_slice_intensity_end.return_value = intensity_end self.slice_view.get_slice_is_norm_to_one.return_value = norm_to_one self.slice_view.get_slice_smoothing.return_value = smoothing self.slice_view.get_slice_colourmap.return_value = colourmap self.slice_view.get_units.return_value = 'meV' plot_info = ("plot_data", "boundaries", "colormap", "norm") self.slice_plotter_presenter.plot_slice = mock.Mock(return_value=plot_info) self.slice_plotter_presenter.validate_intensity = mock.Mock(return_value=(7.0, 8.0)) # Test empty workspace, multiple workspaces self.main_presenter.get_selected_workspaces.return_value = [] slice_widget_presenter.notify(Command.DisplaySlice) assert self.slice_view.error_select_one_workspace.called self.main_presenter.get_selected_workspaces.return_value = [selected_workspace, selected_workspace] self.slice_view.error_select_one_workspace.reset_mock() slice_widget_presenter.notify(Command.DisplaySlice) assert self.slice_view.error_select_one_workspace.called # Test invalid axes self.main_presenter.get_selected_workspaces.return_value = [selected_workspace] self.slice_view.get_slice_y_axis.return_value = x.units slice_widget_presenter.notify(Command.DisplaySlice) assert self.slice_view.error_invalid_plot_parameters.called # Simulate matplotlib error self.slice_plotter_presenter.plot_slice = mock.Mock( side_effect=ValueError('minvalue must be less than or equal to maxvalue')) self.slice_view.get_slice_y_axis.return_value = y.units slice_widget_presenter.notify(Command.DisplaySlice) assert self.slice_view.error_invalid_intensity_params.called self.slice_plotter_presenter.plot_slice = mock.Mock(side_effect=ValueError('something bad')) self.assertRaises(ValueError, slice_widget_presenter.notify, Command.DisplaySlice)