def __init__(self, parent_presenter, WorkHandler, BeamCentreModel, SANSCentreFinder): self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS") self._beam_centre_model = BeamCentreModel(SANSCentreFinder)
def __init__(self, parent_presenter): super(BeamCentrePresenter, self).__init__() self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS") self._beam_centre_model = BeamCentreModel()
def __init__(self): super(TableModel, self).__init__() self._user_file = "" self._batch_file = "" self._table_entries = [] self.work_handler = WorkHandler() self._subscriber_list = [] self._id_count = 0
def __init__(self, parent_presenter, WorkHandler, run_integral, create_state, facility): super(DiagnosticsPagePresenter, self).__init__() self._view = None self._facility = facility self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self.run_integral = run_integral self._logger = Logger("SANS") self._create_state = create_state
def __init__(self, parent_presenter, SANSCentreFinder, work_handler=None, beam_centre_model=None): self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler( ) if not work_handler else work_handler self._logger = Logger("SANS") self._beam_centre_model = BeamCentreModel( SANSCentreFinder) if not beam_centre_model else beam_centre_model
def __init__(self, facility, view=None): super(RunTabPresenter, self).__init__() self._facility = facility # Logger self.sans_logger = Logger("SANS") # Name of grpah to output to self.output_graph = 'SANS-Latest' self.progress = 0 # Models that are being used by the presenter self._state_model = None self._table_model = TableModel() # Presenter needs to have a handle on the view since it delegates it self._view = None self.set_view(view) self._processing = False self.work_handler = WorkHandler() self.batch_process_runner = BatchProcessRunner(self.notify_progress, self.on_processing_finished, self.on_processing_error) # File information for the first input self._file_information = None self._clipboard = [] # Settings diagnostic tab presenter self._settings_diagnostic_tab_presenter = SettingsDiagnosticPresenter(self) # Masking table presenter self._masking_table_presenter = MaskingTablePresenter(self) # Beam centre presenter self._beam_centre_presenter = BeamCentrePresenter(self, WorkHandler, BeamCentreModel, SANSCentreFinder) # Workspace Diagnostic page presenter self._workspace_diagnostic_presenter = DiagnosticsPagePresenter(self, WorkHandler, run_integral, create_state, self._facility)
def __init__(self, parent_presenter, WorkHandler, BeamCentreModel, SANSCentreFinder): super(BeamCentrePresenter, self).__init__() self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS") self._beam_centre_model = BeamCentreModel(SANSCentreFinder)
def __init__(self, parent_presenter, WorkHandler, run_integral, create_state, facility): self._view = None self._facility = facility self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self.run_integral = run_integral self._logger = Logger("SANS") self._create_state = create_state
def __init__(self): super(TableModel, self).__init__() self._user_file = "" self._batch_file = "" self._table_entries = [] self.work_handler = WorkHandler() self._subscriber_list = [] self._id_count = 0
class CreateFileInformationTest(unittest.TestCase): def setUp(self): self.success_callback = mock.MagicMock() self.success_callback_1 = mock.MagicMock() self.error_callback = mock.MagicMock() self.work_handler = WorkHandler() self.qApp = QCoreApplication(['test_app']) def test_retieves_file_information_and_passes_to_callback(self): create_file_information('LOQ74044', self.error_callback, self.success_callback, self.work_handler, 0) self.work_handler.wait_for_done() self.qApp.processEvents() self.assertEqual(self.success_callback.call_count, 1) self.assertEqual(self.error_callback.call_count, 0) def test_that_retrieved_file_information_is_correct(self): create_file_information('LOQ74044', self.error_callback, self.success_callback, self.work_handler, 0) self.work_handler.wait_for_done() self.qApp.processEvents() file_information = self.success_callback.call_args[0][0] self.assertEqual(file_information.is_event_mode(), False) self.assertEqual(file_information.get_run_number(), 74044) self.assertEqual(file_information.get_thickness(), 1.0) def test_that_multiple_threading_calls_at_once_are_handled_cleanly(self): create_file_information('LOQ74044', self.error_callback, self.success_callback, self.work_handler, 0) create_file_information('LOQ74044', self.error_callback, self.success_callback_1, self.work_handler, 0) create_file_information('LOQ74044', self.error_callback, self.success_callback_1, self.work_handler, 1) create_file_information('LOQ74044', self.error_callback, self.success_callback_1, self.work_handler, 0) create_file_information('LOQ74044', self.error_callback, self.success_callback_1, self.work_handler, 2) self.work_handler.wait_for_done() self.qApp.processEvents() self.assertEqual(self.success_callback.call_count, 0) self.assertEqual(self.success_callback_1.call_count, 3) self.assertEqual(self.error_callback.call_count, 0) @mock.patch('sans.gui_logic.presenter.create_file_information.SANSFileInformationFactory') def test_that_error_callback_is_called_on_error_with_correct_message(self, file_information_factory_mock): file_information_factory_instance = mock.MagicMock() file_information_factory_instance.create_sans_file_information.side_effect = RuntimeError('File Error') file_information_factory_mock.return_value = file_information_factory_instance create_file_information('LOQ74044', self.error_callback, self.success_callback, self.work_handler, 0) self.work_handler.wait_for_done() self.qApp.processEvents() self.success_callback.assert_called_once_with(None) self.assertEqual(self.error_callback.call_count, 1) self.assertEqual(str(self.error_callback.call_args[0][0][1]), 'File Error')
class CreateFileInformationTest(unittest.TestCase): def setUp(self): self.success_callback = mock.MagicMock() self.success_callback_1 = mock.MagicMock() self.error_callback = mock.MagicMock() self.work_handler = WorkHandler() self.qApp = QCoreApplication(['test_app']) def test_retieves_file_information_and_passes_to_callback(self): create_file_information('LOQ74044', self.error_callback, self.success_callback, self.work_handler, 0) self.work_handler.wait_for_done() self.qApp.processEvents() self.assertEqual(self.success_callback.call_count, 1) self.assertEqual(self.error_callback.call_count, 0) def test_that_retrieved_file_information_is_correct(self): create_file_information('LOQ74044', self.error_callback, self.success_callback, self.work_handler, 0) self.work_handler.wait_for_done() self.qApp.processEvents() file_information = self.success_callback.call_args[0][0] self.assertEqual(file_information.is_event_mode(), False) self.assertEqual(file_information.get_run_number(), 74044) self.assertEqual(file_information.get_thickness(), 1.0) def test_that_multiple_threading_calls_at_once_are_handled_cleanly(self): create_file_information('LOQ74044', self.error_callback, self.success_callback, self.work_handler, 0) create_file_information('LOQ74044', self.error_callback, self.success_callback_1, self.work_handler, 0) create_file_information('LOQ74044', self.error_callback, self.success_callback_1, self.work_handler, 1) create_file_information('LOQ74044', self.error_callback, self.success_callback_1, self.work_handler, 0) create_file_information('LOQ74044', self.error_callback, self.success_callback_1, self.work_handler, 2) self.work_handler.wait_for_done() self.qApp.processEvents() self.assertEqual(self.success_callback.call_count, 0) self.assertEqual(self.success_callback_1.call_count, 3) self.assertEqual(self.error_callback.call_count, 0) @mock.patch('sans.gui_logic.presenter.create_file_information.SANSFileInformationFactory') def test_that_error_callback_is_called_on_error_with_correct_message(self, file_information_factory_mock): file_information_factory_instance = mock.MagicMock() file_information_factory_instance.create_sans_file_information.side_effect = RuntimeError('File Error') file_information_factory_mock.return_value = file_information_factory_instance create_file_information('LOQ74044', self.error_callback, self.success_callback, self.work_handler, 0) self.work_handler.wait_for_done() self.qApp.processEvents() self.success_callback.assert_called_once_with(None) self.assertEqual(self.error_callback.call_count, 1) self.assertEqual(str(self.error_callback.call_args[0][0][1]), 'File Error')
def __init__(self, parent_presenter): super(MaskingTablePresenter, self).__init__() self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS")
class MaskingTablePresenter(object): DISPLAY_WORKSPACE_NAME = "__sans_mask_display_dummy_workspace" class ConcreteMaskingTableListener(MaskingTable.MaskingTableListener): def __init__(self, presenter): super(MaskingTablePresenter.ConcreteMaskingTableListener, self).__init__() self._presenter = presenter def on_row_changed(self): self._presenter.on_row_changed() def on_update_rows(self): self._presenter.on_update_rows() def on_display(self): self._presenter.on_display() class DisplayMaskListener(WorkHandler.WorkListener): def __init__(self, presenter): super(MaskingTablePresenter.DisplayMaskListener, self).__init__() self._presenter = presenter def on_processing_finished(self, result): self._presenter.on_processing_finished_masking_display(result) def on_processing_error(self, error): self._presenter.on_processing_error_masking_display(error) def __init__(self, parent_presenter): super(MaskingTablePresenter, self).__init__() self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS") def on_row_changed(self): row_index = self._view.get_current_row() state = self.get_state(row_index) if state: self.display_masking_information(state) def on_display(self): # Get the state information for the selected row. row_index = self._view.get_current_row() state = self.get_state(row_index) if not state: self._logger.information( "You can only show a masked workspace if a user file has been loaded and there" "valid sample scatter entry has been provided in the selected row." ) return # Disable the button self._view.set_display_mask_button_to_processing() # Run the task listener = MaskingTablePresenter.DisplayMaskListener(self) state_copy = copy.copy(state) self._work_handler.process(listener, load_and_mask_workspace, state_copy, self.DISPLAY_WORKSPACE_NAME) def on_processing_finished_masking_display(self, result): # Enable button self._view.set_display_mask_button_to_normal() # Display masked workspace self._display(result) def on_processing_error_masking_display(self, error): self._logger.warning( "There has been an error. See more: {}".format(error)) def on_processing_error(self, error): pass def on_update_rows(self): """ Update the row selection in the combobox """ current_row_index = self._view.get_current_row() valid_row_indices = self._parent_presenter.get_row_indices() new_row_index = -1 if current_row_index in valid_row_indices: new_row_index = current_row_index elif len(valid_row_indices) > 0: new_row_index = valid_row_indices[0] self._view.update_rows(valid_row_indices) if new_row_index != -1: self.set_row(new_row_index) self.on_row_changed() def set_row(self, index): self._view.set_row(index) def set_view(self, view): if view: self._view = view # Set up row selection listener listener = MaskingTablePresenter.ConcreteMaskingTableListener(self) self._view.add_listener(listener) # Set the default gui self._set_default_gui() def _set_default_gui(self): self._view.update_rows([]) self.display_masking_information(state=None) def get_state(self, index): return self._parent_presenter.get_state_for_row(index) @staticmethod def _append_single_spectrum_mask(spectrum_mask, container, detector_name, prefix): if spectrum_mask: for item in spectrum_mask: detail = prefix + str(item) container.append( masking_information(first="Spectrum", second=detector_name, third=detail)) @staticmethod def _append_strip_spectrum_mask(strip_mask_start, strip_mask_stop, container, detector_name, prefix): if strip_mask_start and strip_mask_stop: for start, stop in zip(strip_mask_start, strip_mask_stop): detail = prefix + str(start) + ">" + prefix + str(stop) container.append( masking_information(first="Strip", second=detector_name, third=detail)) @staticmethod def _append_block_spectrum_mask(horizontal_mask_start, horizontal_mask_stop, vertical_mask_start, vertical_mask_stop, container, detector_name): if horizontal_mask_start and horizontal_mask_stop and vertical_mask_start and vertical_mask_stop: for h_start, h_stop, v_start, v_stop in zip( horizontal_mask_start, horizontal_mask_stop, vertical_mask_start, vertical_mask_stop): detail = "H{}>H{}+V{}>V{}".format(h_start, h_stop, v_start, v_stop) container.append( masking_information(first="Strip", second=detector_name, third=detail)) @staticmethod def _append_spectrum_block_cross_mask(horizontal_mask, vertical_mask, container, detector_name): if horizontal_mask and vertical_mask: for h, v in zip(horizontal_mask, vertical_mask): detail = "H{}+V{}".format(h, v) container.append( masking_information(first="Strip", second=detector_name, third=detail)) @staticmethod def _get_spectrum_masks(mask_detector_info): detector_name = mask_detector_info.detector_name spectrum_masks = [] # ------------------------------- # Get the vertical spectrum masks # ------------------------------- single_vertical_strip_mask = mask_detector_info.single_vertical_strip_mask MaskingTablePresenter._append_single_spectrum_mask( single_vertical_strip_mask, spectrum_masks, detector_name, "V") range_vertical_strip_start = mask_detector_info.range_vertical_strip_start range_vertical_strip_stop = mask_detector_info.range_vertical_strip_stop MaskingTablePresenter._append_strip_spectrum_mask( range_vertical_strip_start, range_vertical_strip_stop, spectrum_masks, detector_name, "V") # --------------------------------- # Get the horizontal spectrum masks # --------------------------------- single_horizontal_strip_mask = mask_detector_info.single_horizontal_strip_mask MaskingTablePresenter._append_single_spectrum_mask( single_horizontal_strip_mask, spectrum_masks, detector_name, "H") range_horizontal_strip_start = mask_detector_info.range_horizontal_strip_start range_horizontal_strip_stop = mask_detector_info.range_horizontal_strip_stop MaskingTablePresenter._append_strip_spectrum_mask( range_horizontal_strip_start, range_horizontal_strip_stop, spectrum_masks, detector_name, "H") # --------------------------------- # Get the block masks # --------------------------------- block_horizontal_start = mask_detector_info.block_horizontal_start block_horizontal_stop = mask_detector_info.block_horizontal_stop block_vertical_start = mask_detector_info.block_vertical_start block_vertical_stop = mask_detector_info.block_vertical_stop MaskingTablePresenter._append_block_spectrum_mask( block_horizontal_start, block_horizontal_stop, block_vertical_start, block_vertical_stop, spectrum_masks, detector_name) block_cross_horizontal = mask_detector_info.block_cross_horizontal block_cross_vertical = mask_detector_info.block_cross_vertical MaskingTablePresenter._append_spectrum_block_cross_mask( block_cross_horizontal, block_cross_vertical, spectrum_masks, detector_name) # --------------------------------- # Get spectrum masks # --------------------------------- single_spectra = mask_detector_info.single_spectra MaskingTablePresenter._append_single_spectrum_mask( single_spectra, spectrum_masks, detector_name, "S") spectrum_range_start = mask_detector_info.spectrum_range_start spectrum_range_stop = mask_detector_info.spectrum_range_stop MaskingTablePresenter._append_strip_spectrum_mask( spectrum_range_start, spectrum_range_stop, spectrum_masks, detector_name, "S") return spectrum_masks @staticmethod def _get_time_masks_general(mask_info): container = [] bin_mask_general_start = mask_info.bin_mask_general_start bin_mask_general_stop = mask_info.bin_mask_general_stop if bin_mask_general_start and bin_mask_general_stop: for start, stop in zip(bin_mask_general_start, bin_mask_general_stop): detail = "{}-{}".format(start, stop) container.append( masking_information(first="Time", second="", third=detail)) return container @staticmethod def _get_time_masks(mask_info): container = [] bin_mask_start = mask_info.bin_mask_start bin_mask_stop = mask_info.bin_mask_stop detector_name = mask_info.detector_name if bin_mask_start and bin_mask_stop: for start, stop in zip(bin_mask_start, bin_mask_stop): detail = "{}-{}".format(start, stop) container.append( masking_information(first="Time", second=detector_name, third=detail)) return container @staticmethod def _get_arm_mask(mask_info): container = [] beam_stop_arm_width = mask_info.beam_stop_arm_width beam_stop_arm_angle = mask_info.beam_stop_arm_angle beam_stop_arm_pos1 = mask_info.beam_stop_arm_pos1 if mask_info.beam_stop_arm_pos1 else 0. beam_stop_arm_pos2 = mask_info.beam_stop_arm_pos2 if mask_info.beam_stop_arm_pos2 else 0. if beam_stop_arm_width and beam_stop_arm_angle: detail = "LINE {}, {}, {}, {}".format(beam_stop_arm_width, beam_stop_arm_angle, beam_stop_arm_pos1, beam_stop_arm_pos2) container.append( masking_information(first="Arm", second="", third=detail)) return container @staticmethod def _get_phi_mask(mask_info): container = [] phi_min = mask_info.phi_min phi_max = mask_info.phi_max use_mask_phi_mirror = mask_info.use_mask_phi_mirror if phi_min and phi_max: if use_mask_phi_mirror: detail = "L/PHI {} {}".format(phi_min, phi_max) else: detail = "L/PHI/NOMIRROR{} {}".format(phi_min, phi_max) container.append( masking_information(first="Phi", second="", third=detail)) return container @staticmethod def _get_mask_files(mask_info): container = [] mask_files = mask_info.mask_files if mask_files: for mask_file in mask_files: container.append( masking_information(first="Mask file", second="", third=mask_file)) return container @staticmethod def _get_radius(mask_info): container = [] radius_min = mask_info.radius_min radius_max = mask_info.radius_max if radius_min: detail = "infinite-cylinder, r = {}".format(radius_min) container.append( masking_information(first="Beam stop", second="", third=detail)) if radius_max: detail = "infinite-cylinder, r = {}".format(radius_max) container.append( masking_information(first="Corners", second="", third=detail)) return container def _generate_masking_information(self, state): if state is None: return [] mask_info = state.mask masks = [] mask_info_lab = mask_info.detectors[DetectorType.to_string( DetectorType.LAB)] mask_info_hab = mask_info.detectors[DetectorType.to_string( DetectorType.HAB)] if DetectorType.to_string( DetectorType.HAB) in mask_info.detectors else None # noqa # Add the radius mask radius_mask = self._get_radius(mask_info) masks.extend(radius_mask) # Add the spectrum masks for LAB spectrum_masks_lab = self._get_spectrum_masks(mask_info_lab) masks.extend(spectrum_masks_lab) # Add the spectrum masks for HAB if mask_info_hab: spectrum_masks_hab = self._get_spectrum_masks(mask_info_hab) masks.extend(spectrum_masks_hab) # Add the general time mask time_masks_general = self._get_time_masks_general(mask_info) masks.extend(time_masks_general) # Add the time masks for LAB time_masks_lab = self._get_time_masks(mask_info_lab) masks.extend(time_masks_lab) # Add the time masks for HAB if mask_info_hab: time_masks_hab = self._get_time_masks(mask_info_hab) masks.extend(time_masks_hab) # Add arm mask arm_mask = self._get_arm_mask(mask_info) masks.extend(arm_mask) # Add phi mask phi_mask = self._get_phi_mask(mask_info) masks.extend(phi_mask) # Add mask files mask_files = self._get_mask_files(mask_info) masks.extend(mask_files) return masks def get_masking_information(self, state): table_entries = [] if state is not None: table_entries = self._generate_masking_information(state) return table_entries def display_masking_information(self, state): table_entries = self.get_masking_information(state) self._view.set_table(table_entries) @staticmethod def _display(masked_workspace): if masked_workspace and AnalysisDataService.doesExist( masked_workspace.name()): instrument_win = mantidplot.getInstrumentView( masked_workspace.name()) instrument_win.show()
def __init__(self, parent_presenter): super(MaskingTablePresenter, self).__init__() self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS")
class MaskingTablePresenter(object): DISPLAY_WORKSPACE_NAME = "__sans_mask_display_dummy_workspace" class ConcreteMaskingTableListener(MaskingTable.MaskingTableListener): def __init__(self, presenter): super(MaskingTablePresenter.ConcreteMaskingTableListener, self).__init__() self._presenter = presenter def on_row_changed(self): self._presenter.on_row_changed() def on_update_rows(self): self._presenter.on_update_rows() def on_display(self): self._presenter.on_display() class DisplayMaskListener(WorkHandler.WorkListener): def __init__(self, presenter): super(MaskingTablePresenter.DisplayMaskListener, self).__init__() self._presenter = presenter def on_processing_finished(self, result): self._presenter.on_processing_finished_masking_display(result) def on_processing_error(self, error): self._presenter.on_processing_error_masking_display(error) def __init__(self, parent_presenter): super(MaskingTablePresenter, self).__init__() self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS") def on_row_changed(self): row_index = self._view.get_current_row() state = self.get_state(row_index, file_lookup=False) if state: self.display_masking_information(state) def on_display(self): # Get the state information for the selected row. # Disable the button self._view.set_display_mask_button_to_processing() try: row_index = self._view.get_current_row() state = self.get_state(row_index) except Exception as e: self.on_processing_error_masking_display(e) raise Exception(str(e)) # propagate errors for run_tab_presenter to deal with else: if not state: self._logger.information("You can only show a masked workspace if a user file has been loaded and there" "valid sample scatter entry has been provided in the selected row.") return # Run the task listener = MaskingTablePresenter.DisplayMaskListener(self) state_copy = copy.copy(state) self._work_handler.process(listener, load_and_mask_workspace, 0, state_copy, self.DISPLAY_WORKSPACE_NAME) def on_processing_finished_masking_display(self, result): # Enable button self._view.set_display_mask_button_to_normal() # Display masked workspace self._display(result) def on_processing_error_masking_display(self, error): self._logger.warning("There has been an error. See more: {}".format(error)) # Enable button self._view.set_display_mask_button_to_normal() def on_processing_error(self, error): pass def on_update_rows(self): """ Update the row selection in the combobox """ current_row_index = self._view.get_current_row() valid_row_indices = self._parent_presenter.get_row_indices() new_row_index = -1 if current_row_index in valid_row_indices: new_row_index = current_row_index elif len(valid_row_indices) > 0: new_row_index = valid_row_indices[0] self._view.update_rows(valid_row_indices) if new_row_index != -1: self.set_row(new_row_index) self.on_row_changed() def set_row(self, index): self._view.set_row(index) def set_view(self, view): if view: self._view = view # Set up row selection listener listener = MaskingTablePresenter.ConcreteMaskingTableListener(self) self._view.add_listener(listener) # Set the default gui self._set_default_gui() def _set_default_gui(self): self._view.update_rows([]) self.display_masking_information(state=None) def get_state(self, index, file_lookup=True): return self._parent_presenter.get_state_for_row(index, file_lookup=file_lookup) @staticmethod def _append_single_spectrum_mask(spectrum_mask, container, detector_name, prefix): if spectrum_mask: for item in spectrum_mask: detail = prefix + str(item) container.append(masking_information(first="Spectrum", second=detector_name, third=detail)) @staticmethod def _append_strip_spectrum_mask(strip_mask_start, strip_mask_stop, container, detector_name, prefix): if strip_mask_start and strip_mask_stop: for start, stop in zip(strip_mask_start, strip_mask_stop): detail = prefix + str(start) + ">" + prefix + str(stop) container.append(masking_information(first="Strip", second=detector_name, third=detail)) @staticmethod def _append_block_spectrum_mask(horizontal_mask_start, horizontal_mask_stop, vertical_mask_start, vertical_mask_stop, container, detector_name): if horizontal_mask_start and horizontal_mask_stop and vertical_mask_start and vertical_mask_stop: for h_start, h_stop, v_start, v_stop in zip(horizontal_mask_start, horizontal_mask_stop, vertical_mask_start, vertical_mask_stop): detail = "H{}>H{}+V{}>V{}".format(h_start, h_stop, v_start, v_stop) container.append(masking_information(first="Strip", second=detector_name, third=detail)) @staticmethod def _append_spectrum_block_cross_mask(horizontal_mask, vertical_mask, container, detector_name): if horizontal_mask and vertical_mask: for h, v in zip(horizontal_mask, vertical_mask): detail = "H{}+V{}".format(h, v) container.append(masking_information(first="Strip", second=detector_name, third=detail)) @staticmethod def _get_spectrum_masks(mask_detector_info): detector_name = mask_detector_info.detector_name spectrum_masks = [] # ------------------------------- # Get the vertical spectrum masks # ------------------------------- single_vertical_strip_mask = mask_detector_info.single_vertical_strip_mask MaskingTablePresenter._append_single_spectrum_mask(single_vertical_strip_mask, spectrum_masks, detector_name, "V") range_vertical_strip_start = mask_detector_info.range_vertical_strip_start range_vertical_strip_stop = mask_detector_info.range_vertical_strip_stop MaskingTablePresenter._append_strip_spectrum_mask(range_vertical_strip_start, range_vertical_strip_stop, spectrum_masks, detector_name, "V") # --------------------------------- # Get the horizontal spectrum masks # --------------------------------- single_horizontal_strip_mask = mask_detector_info.single_horizontal_strip_mask MaskingTablePresenter._append_single_spectrum_mask(single_horizontal_strip_mask, spectrum_masks, detector_name, "H") range_horizontal_strip_start = mask_detector_info.range_horizontal_strip_start range_horizontal_strip_stop = mask_detector_info.range_horizontal_strip_stop MaskingTablePresenter._append_strip_spectrum_mask(range_horizontal_strip_start, range_horizontal_strip_stop, spectrum_masks, detector_name, "H") # --------------------------------- # Get the block masks # --------------------------------- block_horizontal_start = mask_detector_info.block_horizontal_start block_horizontal_stop = mask_detector_info.block_horizontal_stop block_vertical_start = mask_detector_info.block_vertical_start block_vertical_stop = mask_detector_info.block_vertical_stop MaskingTablePresenter._append_block_spectrum_mask(block_horizontal_start, block_horizontal_stop, block_vertical_start, block_vertical_stop, spectrum_masks, detector_name) block_cross_horizontal = mask_detector_info.block_cross_horizontal block_cross_vertical = mask_detector_info.block_cross_vertical MaskingTablePresenter._append_spectrum_block_cross_mask(block_cross_horizontal, block_cross_vertical, spectrum_masks, detector_name) # --------------------------------- # Get spectrum masks # --------------------------------- single_spectra = mask_detector_info.single_spectra MaskingTablePresenter._append_single_spectrum_mask(single_spectra, spectrum_masks, detector_name, "S") spectrum_range_start = mask_detector_info.spectrum_range_start spectrum_range_stop = mask_detector_info.spectrum_range_stop MaskingTablePresenter._append_strip_spectrum_mask(spectrum_range_start, spectrum_range_stop, spectrum_masks, detector_name, "S") return spectrum_masks @staticmethod def _get_time_masks_general(mask_info): container = [] bin_mask_general_start = mask_info.bin_mask_general_start bin_mask_general_stop = mask_info.bin_mask_general_stop if bin_mask_general_start and bin_mask_general_stop: for start, stop in zip(bin_mask_general_start, bin_mask_general_stop): detail = "{}-{}".format(start, stop) container.append(masking_information(first="Time", second="", third=detail)) return container @staticmethod def _get_time_masks(mask_info): container = [] bin_mask_start = mask_info.bin_mask_start bin_mask_stop = mask_info.bin_mask_stop detector_name = mask_info.detector_name if bin_mask_start and bin_mask_stop: for start, stop in zip(bin_mask_start, bin_mask_stop): detail = "{}-{}".format(start, stop) container.append(masking_information(first="Time", second=detector_name, third=detail)) return container @staticmethod def _get_arm_mask(mask_info): container = [] beam_stop_arm_width = mask_info.beam_stop_arm_width beam_stop_arm_angle = mask_info.beam_stop_arm_angle beam_stop_arm_pos1 = mask_info.beam_stop_arm_pos1 if mask_info.beam_stop_arm_pos1 else 0. beam_stop_arm_pos2 = mask_info.beam_stop_arm_pos2 if mask_info.beam_stop_arm_pos2 else 0. if beam_stop_arm_width and beam_stop_arm_angle: detail = "LINE {}, {}, {}, {}".format(beam_stop_arm_width, beam_stop_arm_angle, beam_stop_arm_pos1, beam_stop_arm_pos2) container.append(masking_information(first="Arm", second="", third=detail)) return container @staticmethod def _get_phi_mask(mask_info): container = [] phi_min = mask_info.phi_min phi_max = mask_info.phi_max use_mask_phi_mirror = mask_info.use_mask_phi_mirror if phi_min and phi_max: if use_mask_phi_mirror: detail = "L/PHI {} {}".format(phi_min, phi_max) else: detail = "L/PHI/NOMIRROR{} {}".format(phi_min, phi_max) container.append(masking_information(first="Phi", second="", third=detail)) return container @staticmethod def _get_mask_files(mask_info): container = [] mask_files = mask_info.mask_files if mask_files: for mask_file in mask_files: container.append(masking_information(first="Mask file", second="", third=mask_file)) return container @staticmethod def _get_radius(mask_info): container = [] radius_min = mask_info.radius_min radius_max = mask_info.radius_max if radius_min: detail = "infinite-cylinder, r = {}".format(radius_min) container.append(masking_information(first="Beam stop", second="", third=detail)) if radius_max: detail = "infinite-cylinder, r = {}".format(radius_max) container.append(masking_information(first="Corners", second="", third=detail)) return container def _generate_masking_information(self, state): if state is None: return [] mask_info = state.mask masks = [] mask_info_lab = mask_info.detectors[DetectorType.to_string(DetectorType.LAB)] mask_info_hab = mask_info.detectors[DetectorType.to_string(DetectorType.HAB)] if DetectorType.to_string(DetectorType.HAB) in mask_info.detectors else None # noqa # Add the radius mask radius_mask = self._get_radius(mask_info) masks.extend(radius_mask) # Add the spectrum masks for LAB spectrum_masks_lab = self._get_spectrum_masks(mask_info_lab) masks.extend(spectrum_masks_lab) # Add the spectrum masks for HAB if mask_info_hab: spectrum_masks_hab = self._get_spectrum_masks(mask_info_hab) masks.extend(spectrum_masks_hab) # Add the general time mask time_masks_general = self._get_time_masks_general(mask_info) masks.extend(time_masks_general) # Add the time masks for LAB time_masks_lab = self._get_time_masks(mask_info_lab) masks.extend(time_masks_lab) # Add the time masks for HAB if mask_info_hab: time_masks_hab = self._get_time_masks(mask_info_hab) masks.extend(time_masks_hab) # Add arm mask arm_mask = self._get_arm_mask(mask_info) masks.extend(arm_mask) # Add phi mask phi_mask = self._get_phi_mask(mask_info) masks.extend(phi_mask) # Add mask files mask_files = self._get_mask_files(mask_info) masks.extend(mask_files) return masks def get_masking_information(self, state): table_entries = [] if state is not None: table_entries = self._generate_masking_information(state) return table_entries def display_masking_information(self, state): table_entries = self.get_masking_information(state) self._view.set_table(table_entries) @staticmethod def _display(masked_workspace): if masked_workspace and AnalysisDataService.doesExist(masked_workspace.name()): instrument_win = mantidplot.getInstrumentView(masked_workspace.name()) instrument_win.show()
class DiagnosticsPagePresenter(object): class ConcreteDiagnosticsPageListener(DiagnosticsPage.DiagnosticsPageListener): def __init__(self, presenter): self._presenter = presenter def on_browse_clicked(self): pass def on_horizontal_clicked(self): self._presenter.on_horizontal_clicked() def on_vertical_clicked(self): self._presenter.on_vertical_clicked() def on_time_clicked(self): self._presenter.on_time_clicked() class IntegralListener(WorkHandler.WorkListener): def __init__(self, presenter): super(DiagnosticsPagePresenter.IntegralListener, self).__init__() self._presenter = presenter def on_processing_finished(self, result): self._presenter.on_processing_finished_integral(result) def on_processing_error(self, error): self._presenter.on_processing_error_integral(error) def __init__(self, parent_presenter, WorkHandler, run_integral, create_state, facility): self._view = None self._facility = facility self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self.run_integral = run_integral self._logger = Logger("SANS") self._create_state = create_state def set_view(self, view, instrument): if view: self._view = view # Set up run listener listener = DiagnosticsPagePresenter.ConcreteDiagnosticsPageListener(self) self._view.add_listener(listener) # Set up combo box self.set_instrument_settings(instrument) def set_instrument_settings(self, instrument=None): detector_list = get_detector_strings_for_diagnostic_page(instrument) self._view.set_detectors(detector_list) def on_user_file_load(self, user_file): self._view.user_file_name = user_file def on_horizontal_clicked(self): self._view.disable_integrals() input_file = self._view.run_input period = self._view.period state_model_with_view_update = self._parent_presenter._get_state_model_with_view_update() state = self._create_state(state_model_with_view_update, input_file, period, self._facility) mask = self._view.horizontal_mask range = self._view.horizontal_range listener = DiagnosticsPagePresenter.IntegralListener(self) detector = get_detector_from_gui_selection(self._view.detector) self._work_handler.process(listener, self.run_integral, 0, range, mask, IntegralEnum.Horizontal, detector, state) def on_vertical_clicked(self): self._view.disable_integrals() input_file = self._view.run_input period = self._view.period state_model_with_view_update = self._parent_presenter._get_state_model_with_view_update() state = self._create_state(state_model_with_view_update, input_file, period, self._facility) mask = self._view.vertical_mask range = self._view.vertical_range listener = DiagnosticsPagePresenter.IntegralListener(self) detector = get_detector_from_gui_selection(self._view.detector) self._work_handler.process(listener, self.run_integral, 0, range, mask, IntegralEnum.Vertical, detector, state) def on_time_clicked(self): self._view.disable_integrals() input_file = self._view.run_input period = self._view.period state_model_with_view_update = self._parent_presenter._get_state_model_with_view_update() state = self._create_state(state_model_with_view_update, input_file, period, self._facility) mask = self._view.time_mask range = self._view.time_range listener = DiagnosticsPagePresenter.IntegralListener(self) detector = get_detector_from_gui_selection(self._view.detector) self._work_handler.process(listener, self.run_integral, 0, range, mask, IntegralEnum.Time, detector, state) def on_processing_finished_integral(self, result): self._view.enable_integrals() def on_processing_error_integral(self, error): self._view.enable_integrals()
class BeamCentrePresenter(object): class ConcreteBeamCentreListener(BeamCentre.BeamCentreListener): def __init__(self, presenter): self._presenter = presenter def on_run_clicked(self): self._presenter.on_run_clicked() class CentreFinderListener(WorkHandler.WorkListener): def __init__(self, presenter): super(BeamCentrePresenter.CentreFinderListener, self).__init__() self._presenter = presenter def on_processing_finished(self, result): self._presenter.on_processing_finished_centre_finder(result) def on_processing_error(self, error): self._presenter.on_processing_error_centre_finder(error) def __init__(self, parent_presenter, SANSCentreFinder, work_handler=None, beam_centre_model=None): self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler( ) if not work_handler else work_handler self._logger = Logger("SANS") self._beam_centre_model = BeamCentreModel( SANSCentreFinder) if not beam_centre_model else beam_centre_model def set_view(self, view): if view: self._view = view # Set up run listener listener = BeamCentrePresenter.ConcreteBeamCentreListener(self) self._view.add_listener(listener) # Set the default gui self._view.set_options(self._beam_centre_model) # Connect view signals self.connect_signals() def connect_signals(self): self._view.r_min_line_edit.textChanged.connect( self._validate_radius_values) self._view.r_max_line_edit.textChanged.connect( self._validate_radius_values) def on_update_instrument(self, instrument): self._beam_centre_model.set_scaling(instrument) self._view.on_update_instrument(instrument) def on_update_rows(self): self._beam_centre_model.reset_inst_defaults( self._parent_presenter.instrument) def on_processing_finished_centre_finder(self, result): # Enable button self._view.set_run_button_to_normal() # Update Centre Positions in model and GUI if self._beam_centre_model.update_lab: self._beam_centre_model.lab_pos_1 = result['pos1'] self._beam_centre_model.lab_pos_2 = result['pos2'] self._view.lab_pos_1 = self._beam_centre_model.lab_pos_1 * self._beam_centre_model.scale_1 self._view.lab_pos_2 = self._beam_centre_model.lab_pos_2 * self._beam_centre_model.scale_2 if self._beam_centre_model.update_hab: self._beam_centre_model.hab_pos_1 = result['pos1'] self._beam_centre_model.hab_pos_2 = result['pos2'] self._view.hab_pos_1 = self._beam_centre_model.hab_pos_1 * self._beam_centre_model.scale_1 self._view.hab_pos_2 = self._beam_centre_model.hab_pos_2 * self._beam_centre_model.scale_2 def on_processing_error_centre_finder(self, error): self._logger.warning( "There has been an error. See more: {}".format(error)) self._view.set_run_button_to_normal() def on_processing_error(self, error): self._view.set_run_button_to_normal() def on_run_clicked(self): self._work_handler.wait_for_done() # Get the state information for the first row. state = self._parent_presenter.get_state_for_row(0) if not state: self._logger.information( "You can only calculate the beam centre if a user file has been loaded and there" "valid sample scatter entry has been provided in the selected row." ) return # Disable the button self._view.set_run_button_to_processing() #Update model self._update_beam_model_from_view() # Run the task listener = BeamCentrePresenter.CentreFinderListener(self) state_copy = copy.copy(state) self._work_handler.process(listener, self._beam_centre_model.find_beam_centre, 0, state_copy) def _update_beam_model_from_view(self): self._beam_centre_model.r_min = self._view.r_min self._beam_centre_model.r_max = self._view.r_max self._beam_centre_model.max_iterations = self._view.max_iterations self._beam_centre_model.tolerance = self._view.tolerance self._beam_centre_model.left_right = self._view.left_right self._beam_centre_model.verbose = self._view.verbose self._beam_centre_model.COM = self._view.COM self._beam_centre_model.up_down = self._view.up_down self._beam_centre_model.lab_pos_1 = self._view.lab_pos_1 / self._beam_centre_model.scale_1 self._beam_centre_model.lab_pos_2 = self._view.lab_pos_2 / self._beam_centre_model.scale_2 self._beam_centre_model.hab_pos_1 = self._view.hab_pos_1 / self._beam_centre_model.scale_1 self._beam_centre_model.hab_pos_2 = self._view.hab_pos_2 / self._beam_centre_model.scale_2 self._beam_centre_model.q_min = self._view.q_min self._beam_centre_model.q_max = self._view.q_max self._beam_centre_model.component = self._view.component self._beam_centre_model.update_hab = self._view.update_hab self._beam_centre_model.update_lab = self._view.update_lab def update_centre_positions(self, state_model): lab_pos_1 = getattr(state_model, 'lab_pos_1') lab_pos_2 = getattr(state_model, 'lab_pos_2') hab_pos_1 = getattr(state_model, 'hab_pos_1') if getattr( state_model, 'hab_pos_1') else lab_pos_1 hab_pos_2 = getattr(state_model, 'hab_pos_2') if getattr( state_model, 'hab_pos_2') else lab_pos_2 self._view.lab_pos_1 = lab_pos_1 self._view.lab_pos_2 = lab_pos_2 self._view.hab_pos_1 = hab_pos_1 self._view.hab_pos_2 = hab_pos_2 def update_hab_selected(self): self._beam_centre_model.update_hab = True self._beam_centre_model.update_lab = False # HAB is selected, so ensure update HAB is enabled and checked self._view.enable_update_hab(True) # Disable and deselect update LAB self._view.enable_update_lab(False) def update_lab_selected(self): self._beam_centre_model.update_hab = False self._beam_centre_model.update_lab = True # LAB is selected, so ensure update LAB is enabled and checked self._view.enable_update_lab(True) # Disable and deselect update HAB self._view.enable_update_hab(False) def update_all_selected(self): self._beam_centre_model.update_hab = True self._beam_centre_model.update_lab = True self._view.enable_update_hab(True) self._view.enable_update_lab(True) def set_on_state_model(self, attribute_name, state_model): attribute = getattr(self._view, attribute_name) if attribute or isinstance(attribute, bool): setattr(state_model, attribute_name, attribute) def set_on_view(self, attribute_name, state_model): attribute = getattr(state_model, attribute_name) if attribute or isinstance( attribute, bool ): # We need to be careful here. We don't want to set empty strings, or None, but we want to set boolean values. # noqa setattr(self._view, attribute_name, attribute) def _validate_radius_values(self): min_value = getattr(self._view, "r_min_line_edit").text() max_value = getattr(self._view, "r_max_line_edit").text() try: min_value = float(min_value) max_value = float(max_value) except ValueError: # one of the values is empty pass else: if min_value == max_value == 0: self._view.run_button.setEnabled(False) return if min_value >= max_value: if self._view.run_button.isEnabled(): # Only post to logger once per disabling self._logger.notice( "Minimum radius is larger than maximum radius. " "Cannot find beam centre with current settings.") self._view.run_button.setEnabled(False) else: self._view.run_button.setEnabled(True)
def setUp(self): self.success_callback = mock.MagicMock() self.success_callback_1 = mock.MagicMock() self.error_callback = mock.MagicMock() self.work_handler = WorkHandler() self.qApp = QCoreApplication(['test_app'])
def __init__(self, parent_presenter): self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS")
class BeamCentrePresenter(object): class ConcreteBeamCentreListener(BeamCentre.BeamCentreListener): def __init__(self, presenter): self._presenter = presenter def on_run_clicked(self): self._presenter.on_run_clicked() class CentreFinderListener(WorkHandler.WorkListener): def __init__(self, presenter): super(BeamCentrePresenter.CentreFinderListener, self).__init__() self._presenter = presenter def on_processing_finished(self, result): self._presenter.on_processing_finished_centre_finder(result) def on_processing_error(self, error): self._presenter.on_processing_error_centre_finder(error) def __init__(self, parent_presenter, WorkHandler, BeamCentreModel, SANSCentreFinder): super(BeamCentrePresenter, self).__init__() self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS") self._beam_centre_model = BeamCentreModel(SANSCentreFinder) def set_view(self, view): if view: self._view = view # Set up run listener listener = BeamCentrePresenter.ConcreteBeamCentreListener(self) self._view.add_listener(listener) # Set the default gui self._view.set_options(self._beam_centre_model) def on_update_instrument(self, instrument): self._beam_centre_model.set_scaling(instrument) self._view.on_update_instrument(instrument) def on_update_rows(self): file_information = self._parent_presenter._table_model.get_file_information_for_row(0) if file_information: self._beam_centre_model.reset_to_defaults_for_instrument(file_information=file_information) self._view.set_options(self._beam_centre_model) def on_processing_finished_centre_finder(self, result): # Enable button self._view.set_run_button_to_normal() # Update Centre Positions in model and GUI if self._beam_centre_model.update_lab: self._beam_centre_model.lab_pos_1 = result['pos1'] self._beam_centre_model.lab_pos_2 = result['pos2'] self._view.lab_pos_1 = self._beam_centre_model.lab_pos_1 * self._beam_centre_model.scale_1 self._view.lab_pos_2 = self._beam_centre_model.lab_pos_2 * self._beam_centre_model.scale_2 if self._beam_centre_model.update_hab: self._beam_centre_model.hab_pos_1 = result['pos1'] self._beam_centre_model.hab_pos_2 = result['pos2'] self._view.hab_pos_1 = self._beam_centre_model.hab_pos_1 * self._beam_centre_model.scale_1 self._view.hab_pos_2 = self._beam_centre_model.hab_pos_2 * self._beam_centre_model.scale_2 def on_processing_error_centre_finder(self, error): self._logger.warning("There has been an error. See more: {}".format(error)) self._view.set_run_button_to_normal() def on_processing_error(self, error): self._view.set_run_button_to_normal() def on_run_clicked(self): # Get the state information for the first row. state = self._parent_presenter.get_state_for_row(0) if not state: self._logger.information("You can only calculate the beam centre if a user file has been loaded and there" "valid sample scatter entry has been provided in the selected row.") return # Disable the button self._view.set_run_button_to_processing() #Update model self._update_beam_model_from_view() # Run the task listener = BeamCentrePresenter.CentreFinderListener(self) state_copy = copy.copy(state) self._work_handler.process(listener, self._beam_centre_model.find_beam_centre, 0, state_copy) def _update_beam_model_from_view(self): self._beam_centre_model.r_min = self._view.r_min self._beam_centre_model.r_max = self._view.r_max self._beam_centre_model.max_iterations = self._view.max_iterations self._beam_centre_model.tolerance = self._view.tolerance self._beam_centre_model.left_right = self._view.left_right self._beam_centre_model.verbose = self._view.verbose self._beam_centre_model.COM = self._view.COM self._beam_centre_model.up_down = self._view.up_down self._beam_centre_model.lab_pos_1 = self._view.lab_pos_1 / self._beam_centre_model.scale_1 self._beam_centre_model.lab_pos_2 = self._view.lab_pos_2 / self._beam_centre_model.scale_2 self._beam_centre_model.hab_pos_1 = self._view.hab_pos_1 / self._beam_centre_model.scale_1 self._beam_centre_model.hab_pos_2 = self._view.hab_pos_2 / self._beam_centre_model.scale_2 self._beam_centre_model.q_min = self._view.q_min self._beam_centre_model.q_max = self._view.q_max self._beam_centre_model.component = self._view.component self._beam_centre_model.update_hab = self._view.update_hab self._beam_centre_model.update_lab = self._view.update_lab def update_centre_positions(self, state_model): lab_pos_1 = getattr(state_model, 'lab_pos_1') lab_pos_2 = getattr(state_model, 'lab_pos_2') hab_pos_1 = getattr(state_model, 'hab_pos_1') if getattr(state_model, 'hab_pos_1') else lab_pos_1 hab_pos_2 = getattr(state_model, 'hab_pos_2') if getattr(state_model, 'hab_pos_2') else lab_pos_2 self._view.lab_pos_1 = lab_pos_1 self._view.lab_pos_2 = lab_pos_2 self._view.hab_pos_1 = hab_pos_1 self._view.hab_pos_2 = hab_pos_2 def set_on_state_model(self, attribute_name, state_model): attribute = getattr(self._view, attribute_name) if attribute or isinstance(attribute, bool): setattr(state_model, attribute_name, attribute) def set_on_view(self, attribute_name, state_model): attribute = getattr(state_model, attribute_name) if attribute or isinstance(attribute, bool): # We need to be careful here. We don't want to set empty strings, or None, but we want to set boolean values. # noqa setattr(self._view, attribute_name, attribute)
class BeamCentrePresenter(object): class ConcreteBeamCentreListener(BeamCentre.BeamCentreListener): def __init__(self, presenter): self._presenter = presenter def on_run_clicked(self): self._presenter.on_run_clicked() class CentreFinderListener(WorkHandler.WorkListener): def __init__(self, presenter): super(BeamCentrePresenter.CentreFinderListener, self).__init__() self._presenter = presenter def on_processing_finished(self, result): self._presenter.on_processing_finished_centre_finder(result) def on_processing_error(self, error): self._presenter.on_processing_error_centre_finder(error) def __init__(self, parent_presenter, WorkHandler, BeamCentreModel, SANSCentreFinder): super(BeamCentrePresenter, self).__init__() self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS") self._beam_centre_model = BeamCentreModel(SANSCentreFinder) def set_view(self, view): if view: self._view = view # Set up run listener listener = BeamCentrePresenter.ConcreteBeamCentreListener(self) self._view.add_listener(listener) # Set the default gui self._view.set_options(self._beam_centre_model) def on_update_instrument(self, instrument): self._beam_centre_model.set_scaling(instrument) self._view.on_update_instrument(instrument) def on_update_rows(self): self._view.set_options(self._beam_centre_model) state = self._parent_presenter.get_state_for_row(0) if state: self._beam_centre_model.reset_to_defaults_for_instrument(state_data=state.data) def on_processing_finished_centre_finder(self, result): # Enable button self._view.set_run_button_to_normal() # Update Centre Positions in model and GUI if self._beam_centre_model.update_lab: self._beam_centre_model.lab_pos_1 = result['pos1'] self._beam_centre_model.lab_pos_2 = result['pos2'] self._view.lab_pos_1 = self._beam_centre_model.lab_pos_1 * self._beam_centre_model.scale_1 self._view.lab_pos_2 = self._beam_centre_model.lab_pos_2 * self._beam_centre_model.scale_2 if self._beam_centre_model.update_hab: self._beam_centre_model.hab_pos_1 = result['pos1'] self._beam_centre_model.hab_pos_2 = result['pos2'] self._view.hab_pos_1 = self._beam_centre_model.hab_pos_1 * self._beam_centre_model.scale_1 self._view.hab_pos_2 = self._beam_centre_model.hab_pos_2 * self._beam_centre_model.scale_2 def on_processing_error_centre_finder(self, error): self._logger.warning("There has been an error. See more: {}".format(error)) self._view.set_run_button_to_normal() def on_processing_error(self, error): self._view.set_run_button_to_normal() def on_run_clicked(self): # Get the state information for the first row. state = self._parent_presenter.get_state_for_row(0) if not state: self._logger.information("You can only calculate the beam centre if a user file has been loaded and there" "valid sample scatter entry has been provided in the selected row.") return # Disable the button self._view.set_run_button_to_processing() #Update model self._update_beam_model_from_view() # Run the task listener = BeamCentrePresenter.CentreFinderListener(self) state_copy = copy.copy(state) self._work_handler.process(listener, self._beam_centre_model.find_beam_centre, state_copy) def _update_beam_model_from_view(self): self._beam_centre_model.r_min = self._view.r_min self._beam_centre_model.r_max = self._view.r_max self._beam_centre_model.max_iterations = self._view.max_iterations self._beam_centre_model.tolerance = self._view.tolerance self._beam_centre_model.left_right = self._view.left_right self._beam_centre_model.verbose = self._view.verbose self._beam_centre_model.COM = self._view.COM self._beam_centre_model.up_down = self._view.up_down self._beam_centre_model.lab_pos_1 = self._view.lab_pos_1 / self._beam_centre_model.scale_1 self._beam_centre_model.lab_pos_2 = self._view.lab_pos_2 / self._beam_centre_model.scale_2 self._beam_centre_model.hab_pos_1 = self._view.hab_pos_1 / self._beam_centre_model.scale_1 self._beam_centre_model.hab_pos_2 = self._view.hab_pos_2 / self._beam_centre_model.scale_2 self._beam_centre_model.q_min = self._view.q_min self._beam_centre_model.q_max = self._view.q_max self._beam_centre_model.component = self._view.component self._beam_centre_model.update_hab = self._view.update_hab self._beam_centre_model.update_lab = self._view.update_lab def update_centre_positions(self, state_model): lab_pos_1 = getattr(state_model, 'lab_pos_1') lab_pos_2 = getattr(state_model, 'lab_pos_2') hab_pos_1 = getattr(state_model, 'hab_pos_1') if getattr(state_model, 'hab_pos_1') else lab_pos_1 hab_pos_2 = getattr(state_model, 'hab_pos_2') if getattr(state_model, 'hab_pos_2') else lab_pos_2 self._view.lab_pos_1 = lab_pos_1 self._view.lab_pos_2 = lab_pos_2 self._view.hab_pos_1 = hab_pos_1 self._view.hab_pos_2 = hab_pos_2 def set_on_state_model(self, attribute_name, state_model): attribute = getattr(self._view, attribute_name) if attribute or isinstance(attribute, bool): setattr(state_model, attribute_name, attribute) def set_on_view(self, attribute_name, state_model): attribute = getattr(state_model, attribute_name) if attribute or isinstance(attribute, bool): # We need to be careful here. We don't want to set empty strings, or None, but we want to set boolean values. # noqa setattr(self._view, attribute_name, attribute)
class TableModel(object): column_name_converter = ["sample_scatter", "sample_scatter_period", "sample_transmission", "sample_transmission_period", "sample_direct", "sample_direct_period", "can_scatter", "can_scatter_period", "can_transmission", "can_transmission_period", "can_direct", "can_direct_period", "output_name", "user_file", "sample_thickness", "sample_height", "sample_width", "sample_shape", "options_column_model"] THICKNESS_ROW = 14 def __init__(self): super(TableModel, self).__init__() self._user_file = "" self._batch_file = "" self._table_entries = [] self.work_handler = WorkHandler() self._subscriber_list = [] self._id_count = 0 @staticmethod def _validate_file_name(file_name): if not file_name: return if not os.path.exists(file_name): raise ValueError("The file {} does not seem to exist.".format(file_name)) @property def user_file(self): return self._user_file @user_file.setter def user_file(self, value): self._user_file = value def get_row_user_file(self, row_index): if row_index < len(self._table_entries): return self._table_entries[row_index].user_file else: raise IndexError("The row {} does not exist.".format(row_index)) @property def batch_file(self): return self._batch_file @batch_file.setter def batch_file(self, value): self._batch_file = value def get_table_entry(self, index): return self._table_entries[index] def add_table_entry(self, row, table_index_model): table_index_model.id = self._id_count self._id_count += 1 self._table_entries.insert(row, table_index_model) if row >= self.get_number_of_rows(): row = self.get_number_of_rows() - 1 self.get_thickness_for_rows([row]) self.notify_subscribers() def append_table_entry(self, table_index_model): table_index_model.id = self._id_count self._id_count += 1 self._table_entries.append(table_index_model) self.get_thickness_for_rows([self.get_number_of_rows() - 1]) self.notify_subscribers() def remove_table_entries(self, rows): # For speed rows should be a Set here but don't think it matters for the list sizes involved. self._table_entries[:] = [item for i,item in enumerate(self._table_entries) if i not in rows] if not self._table_entries: row_index_model = self.create_empty_row() self.append_table_entry(row_index_model) else: self.notify_subscribers() def replace_table_entries(self, row_to_replace_index, rows_to_insert): self.remove_table_entries(row_to_replace_index) for row_entry in reversed(rows_to_insert): self.add_table_entry(row_to_replace_index[0], row_entry) def clear_table_entries(self): self._table_entries = [] row_index_model = self.create_empty_row() self.append_table_entry(row_index_model) def get_number_of_rows(self): return len(self._table_entries) def update_table_entry(self, row, column, value): self._table_entries[row].update_attribute(self.column_name_converter[column], value) self._table_entries[row].update_attribute('row_state', RowState.Unprocessed) self._table_entries[row].update_attribute('tool_tip', '') if column == 0: self.get_thickness_for_rows([row]) self.notify_subscribers() def is_empty_row(self, row): return self._table_entries[row].is_empty() @staticmethod def create_empty_row(): row = [''] * 16 return TableIndexModel(*row) def get_options_hint_strategy(self): return OptionsColumnModel.get_hint_strategy() def set_row_to_processed(self, row, tool_tip): self._table_entries[row].update_attribute('row_state', RowState.Processed) self._table_entries[row].update_attribute('tool_tip', tool_tip) self.notify_subscribers() def reset_row_state(self, row): self._table_entries[row].update_attribute('row_state', RowState.Unprocessed) self._table_entries[row].update_attribute('tool_tip', '') self.notify_subscribers() def set_row_to_error(self, row, tool_tip): self._table_entries[row].update_attribute('row_state', RowState.Error) self._table_entries[row].update_attribute('tool_tip', tool_tip) self.notify_subscribers() def get_thickness_for_rows(self, rows=None): """ Read in the sample thickness for the given rows from the file and set it in the table. :param rows: list of table rows """ if not rows: rows = range(len(self._table_entries)) for row in rows: entry = self._table_entries[row] if entry.is_empty(): continue entry.file_finding = True success_callback = functools.partial(self.update_thickness_from_file_information, entry.id) error_callback = functools.partial(self.failure_handler, entry.id) create_file_information(entry.sample_scatter, error_callback, success_callback, self.work_handler, entry.id) def failure_handler(self, id, error): row = self.get_row_from_id(id) self._table_entries[row].update_attribute('file_information', '') self._table_entries[row].update_attribute('sample_thickness', '') self._table_entries[row].update_attribute('sample_height', '') self._table_entries[row].update_attribute('sample_width', '') self._table_entries[row].update_attribute('sample_shape', '') self._table_entries[row].file_finding = False self.set_row_to_error(row, str(error[1])) def update_thickness_from_file_information(self, id, file_information): row = self.get_row_from_id(id) if file_information: rounded_file_thickness = round(file_information.get_thickness(), 2) rounded_file_height = round(file_information.get_height(), 2) rounded_file_width = round(file_information.get_width(), 2) self._table_entries[row].update_attribute('file_information', file_information) self._table_entries[row].update_attribute('sample_thickness', rounded_file_thickness) self._table_entries[row].update_attribute('sample_height', rounded_file_height) self._table_entries[row].update_attribute('sample_width', rounded_file_width) self._table_entries[row].update_attribute('sample_shape', file_information.get_shape()) self._table_entries[row].file_finding = False self.reset_row_state(row) def subscribe_to_model_changes(self, subscriber): self._subscriber_list.append(subscriber) def notify_subscribers(self): for subscriber in self._subscriber_list: subscriber.on_update_rows() def get_file_information_for_row(self, row): return self._table_entries[row].file_information def get_row_from_id(self, id): for row, entry in enumerate(self._table_entries): if entry.id == id: return row return None def wait_for_file_finding_done(self): self.work_handler.wait_for_done() def wait_for_file_information(self, row): if self._table_entries[row].file_finding: self.wait_for_file_finding_done() def add_table_entry_no_thread_or_signal(self, row, table_index_model): table_index_model.id = self._id_count self._id_count += 1 self._table_entries.insert(row, table_index_model) if row >= self.get_number_of_rows(): row = self.get_number_of_rows() - 1 entry = self._table_entries[row] file_information_factory = SANSFileInformationFactory() file_information = file_information_factory.create_sans_file_information(entry.sample_scatter) self.update_thickness_from_file_information(entry.id, file_information) def set_option(self, row, key, value): self._table_entries[row].options_column_model.set_option(key, value) def __eq__(self, other): return self.equal_dicts(self.__dict__, other.__dict__, ['work_handler']) def __ne__(self, other): return not self.equal_dicts(self.__dict__, other.__dict__, ['work_handler']) @staticmethod def equal_dicts(d1, d2, ignore_keys): d1_filtered = dict((k, v) for k, v in d1.items() if k not in ignore_keys) d2_filtered = dict((k, v) for k, v in d2.items() if k not in ignore_keys) return d1_filtered == d2_filtered
class TableModel(object): column_name_converter = [ "sample_scatter", "sample_scatter_period", "sample_transmission", "sample_transmission_period", "sample_direct", "sample_direct_period", "can_scatter", "can_scatter_period", "can_transmission", "can_transmission_period", "can_direct", "can_direct_period", "output_name", "user_file", "sample_thickness", "sample_height", "sample_width", "sample_shape", "options_column_model" ] THICKNESS_ROW = 14 def __init__(self): super(TableModel, self).__init__() self._user_file = "" self._batch_file = "" self._table_entries = [] self.work_handler = WorkHandler() self._subscriber_list = [] self._id_count = 0 @staticmethod def _validate_file_name(file_name): if not file_name: return if not os.path.exists(file_name): raise ValueError( "The file {} does not seem to exist.".format(file_name)) @property def user_file(self): return self._user_file @user_file.setter def user_file(self, value): self._user_file = value def get_row_user_file(self, row_index): if row_index < len(self._table_entries): return self._table_entries[row_index].user_file else: raise IndexError("The row {} does not exist.".format(row_index)) @property def batch_file(self): return self._batch_file @batch_file.setter def batch_file(self, value): self._batch_file = value def get_table_entry(self, index): return self._table_entries[index] def add_table_entry(self, row, table_index_model): table_index_model.id = self._id_count self._id_count += 1 self._table_entries.insert(row, table_index_model) if row >= self.get_number_of_rows(): row = self.get_number_of_rows() - 1 self.get_thickness_for_rows([row]) self.notify_subscribers() def append_table_entry(self, table_index_model): table_index_model.id = self._id_count self._id_count += 1 self._table_entries.append(table_index_model) self.get_thickness_for_rows([self.get_number_of_rows() - 1]) self.notify_subscribers() def remove_table_entries(self, rows): # For speed rows should be a Set here but don't think it matters for the list sizes involved. self._table_entries[:] = [ item for i, item in enumerate(self._table_entries) if i not in rows ] if not self._table_entries: row_index_model = self.create_empty_row() self.append_table_entry(row_index_model) else: self.notify_subscribers() def replace_table_entries(self, row_to_replace_index, rows_to_insert): self.remove_table_entries(row_to_replace_index) for row_entry in reversed(rows_to_insert): self.add_table_entry(row_to_replace_index[0], row_entry) def clear_table_entries(self): self._table_entries = [] row_index_model = self.create_empty_row() self.append_table_entry(row_index_model) def get_number_of_rows(self): return len(self._table_entries) def update_table_entry(self, row, column, value): self._table_entries[row].update_attribute( self.column_name_converter[column], value) self._table_entries[row].update_attribute('row_state', RowState.Unprocessed) self._table_entries[row].update_attribute('tool_tip', '') if column == 0: self.get_thickness_for_rows([row]) self.notify_subscribers() def is_empty_row(self, row): return self._table_entries[row].is_empty() @staticmethod def create_empty_row(): row = [''] * 16 return TableIndexModel(*row) def get_non_empty_rows(self, rows): return list( filter(lambda x: not self.get_table_entry(x).is_empty(), rows)) def get_options_hint_strategy(self): return OptionsColumnModel.get_hint_strategy() def get_sample_shape_hint_strategy(self): return SampleShapeColumnModel.get_hint_strategy() def set_row_to_processed(self, row, tool_tip): self._table_entries[row].update_attribute('row_state', RowState.Processed) self._table_entries[row].update_attribute('tool_tip', tool_tip) self.notify_subscribers() def reset_row_state(self, row): self._table_entries[row].update_attribute('row_state', RowState.Unprocessed) self._table_entries[row].update_attribute('tool_tip', '') self.notify_subscribers() def set_row_to_error(self, row, tool_tip): self._table_entries[row].update_attribute('row_state', RowState.Error) self._table_entries[row].update_attribute('tool_tip', tool_tip) self.notify_subscribers() def get_thickness_for_rows(self, rows=None): """ Read in the sample thickness for the given rows from the file and set it in the table. :param rows: list of table rows """ if not rows: rows = range(len(self._table_entries)) for row in rows: entry = self._table_entries[row] if entry.is_empty(): continue entry.file_finding = True success_callback = functools.partial( self.update_thickness_from_file_information, entry.id) error_callback = functools.partial(self.failure_handler, entry.id) create_file_information(entry.sample_scatter, error_callback, success_callback, self.work_handler, entry.id) def failure_handler(self, id, error): row = self.get_row_from_id(id) self._table_entries[row].update_attribute('file_information', '') self._table_entries[row].update_attribute('sample_thickness', '') self._table_entries[row].update_attribute('sample_height', '') self._table_entries[row].update_attribute('sample_width', '') self._table_entries[row].update_attribute('sample_shape', '') self._table_entries[row].file_finding = False self.set_row_to_error(row, str(error[1])) def update_thickness_from_file_information(self, id, file_information): row = self.get_row_from_id(id) if file_information: rounded_file_thickness = round(file_information.get_thickness(), 2) rounded_file_height = round(file_information.get_height(), 2) rounded_file_width = round(file_information.get_width(), 2) self._table_entries[row].update_attribute('file_information', file_information) self._table_entries[row].update_attribute('sample_thickness', rounded_file_thickness) self._table_entries[row].update_attribute('sample_height', rounded_file_height) self._table_entries[row].update_attribute('sample_width', rounded_file_width) if self._table_entries[row].sample_shape_string == "": self._table_entries[row].update_attribute( 'sample_shape', file_information.get_shape()) self._table_entries[row].file_finding = False self.reset_row_state(row) def subscribe_to_model_changes(self, subscriber): self._subscriber_list.append(subscriber) def notify_subscribers(self): for subscriber in self._subscriber_list: subscriber.on_update_rows() def get_file_information_for_row(self, row): return self._table_entries[row].file_information def get_row_from_id(self, id): for row, entry in enumerate(self._table_entries): if entry.id == id: return row return None def wait_for_file_finding_done(self): self.work_handler.wait_for_done() def wait_for_file_information(self, row): if self._table_entries[row].file_finding: self.wait_for_file_finding_done() def add_table_entry_no_thread_or_signal(self, row, table_index_model): table_index_model.id = self._id_count self._id_count += 1 self._table_entries.insert(row, table_index_model) if row >= self.get_number_of_rows(): row = self.get_number_of_rows() - 1 entry = self._table_entries[row] file_information_factory = SANSFileInformationFactory() file_information = file_information_factory.create_sans_file_information( entry.sample_scatter) self.update_thickness_from_file_information(entry.id, file_information) def set_option(self, row, key, value): self._table_entries[row].options_column_model.set_option(key, value) def __eq__(self, other): return self.equal_dicts(self.__dict__, other.__dict__, ['work_handler']) def __ne__(self, other): return not self.equal_dicts(self.__dict__, other.__dict__, ['work_handler']) @staticmethod def equal_dicts(d1, d2, ignore_keys): d1_filtered = dict( (k, v) for k, v in d1.items() if k not in ignore_keys) d2_filtered = dict( (k, v) for k, v in d2.items() if k not in ignore_keys) return d1_filtered == d2_filtered
def setUp(self): self.success_callback = mock.MagicMock() self.success_callback_1 = mock.MagicMock() self.error_callback = mock.MagicMock() self.work_handler = WorkHandler() self.qApp = QCoreApplication(['test_app'])
class DiagnosticsPagePresenter(object): class ConcreteDiagnosticsPageListener(DiagnosticsPage.DiagnosticsPageListener): def __init__(self, presenter): self._presenter = presenter def on_browse_clicked(self): pass def on_horizontal_clicked(self): self._presenter.on_horizontal_clicked() def on_vertical_clicked(self): self._presenter.on_vertical_clicked() def on_time_clicked(self): self._presenter.on_time_clicked() class IntegralListener(WorkHandler.WorkListener): def __init__(self, presenter): super(DiagnosticsPagePresenter.IntegralListener, self).__init__() self._presenter = presenter def on_processing_finished(self, result): self._presenter.on_processing_finished_integral(result) def on_processing_error(self, error): self._presenter.on_processing_error_integral(error) def __init__(self, parent_presenter, WorkHandler, run_integral, create_state, facility): super(DiagnosticsPagePresenter, self).__init__() self._view = None self._facility = facility self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self.run_integral = run_integral self._logger = Logger("SANS") self._create_state = create_state def set_view(self, view, instrument): if view: self._view = view # Set up run listener listener = DiagnosticsPagePresenter.ConcreteDiagnosticsPageListener(self) self._view.add_listener(listener) # Set up combo box self.set_instrument_settings(instrument) def set_instrument_settings(self, instrument=None): detector_list = get_detector_strings_for_diagnostic_page(instrument) self._view.set_detectors(detector_list) def on_user_file_load(self, user_file): self._view.user_file_name = user_file def on_horizontal_clicked(self): input_file = self._view.run_input period = self._view.period state_model_with_view_update = self._parent_presenter._get_state_model_with_view_update() state = self._create_state(state_model_with_view_update, input_file, period, self._facility) mask = self._view.horizontal_mask range = self._view.horizontal_range listener = DiagnosticsPagePresenter.IntegralListener(self) detector = get_detector_from_gui_selection(self._view.detector) self._work_handler.process(listener, self.run_integral, range, mask, IntegralEnum.Horizontal, detector, state) def on_vertical_clicked(self): input_file = self._view.run_input period = self._view.period state_model_with_view_update = self._parent_presenter._get_state_model_with_view_update() state = self._create_state(state_model_with_view_update, input_file, period, self._facility) mask = self._view.vertical_mask range = self._view.vertical_range listener = DiagnosticsPagePresenter.IntegralListener(self) detector = get_detector_from_gui_selection(self._view.detector) self._work_handler.process(listener, self.run_integral, range, mask, IntegralEnum.Vertical, detector, state) def on_time_clicked(self): input_file = self._view.run_input period = self._view.period state_model_with_view_update = self._parent_presenter._get_state_model_with_view_update() state = self._create_state(state_model_with_view_update, input_file, period, self._facility) mask = self._view.time_mask range = self._view.time_range listener = DiagnosticsPagePresenter.IntegralListener(self) detector = get_detector_from_gui_selection(self._view.detector) self._work_handler.process(listener, self.run_integral, range, mask, IntegralEnum.Time, detector, state) def on_processing_finished_integral(self, result): pass def on_processing_error_integral(self, error): pass
def __init__(self, parent_presenter): self._view = None self._parent_presenter = parent_presenter self._work_handler = WorkHandler() self._logger = Logger("SANS")