def test_that_enable_observer_calls_on_view_when_triggered(self): presenter = ResultsTabPresenter(self.mock_view, self.mock_model) enable_notifier = GenericObservable() enable_notifier.add_subscriber(presenter.enable_tab_observer) enable_notifier._notify_subscribers_impl(arg=None) self.mock_view.setEnabled.assert_called_once_with(True)
def test_that_disable_observer_calls_on_view_when_triggered(self): disable_notifier = GenericObservable() disable_notifier.add_subscriber(self.presenter.disable_tab_observer) self.view.setEnabled = mock.MagicMock() disable_notifier.notify_subscribers() self.view.setEnabled.assert_called_once_with(False)
def test_that_enable_observer_will_disable_the_view_when_there_is_zero_datasets(self): mock_model_number_of_datasets = mock.PropertyMock(return_value=0) type(self.model).number_of_datasets = mock_model_number_of_datasets enable_notifier = GenericObservable() enable_notifier.add_subscriber(self.presenter.enable_tab_observer) self.view.setEnabled = mock.MagicMock() enable_notifier.notify_subscribers() mock_model_number_of_datasets.assert_called_once_with() self.view.setEnabled.assert_called_once_with(False)
def test_that_enable_observer_calls_on_view_when_triggered(self): self.view.setEnabled(True) self.view.disable_widget() for widget in self.view.children(): if str(widget.objectName()) in ['cancel_calculate_phase_table_button']: continue self.assertFalse(widget.isEnabled()) enable_notifier = GenericObservable() enable_notifier.add_subscriber(self.presenter.enable_tab_observer) enable_notifier.notify_subscribers() for widget in self.view.children(): if str(widget.objectName()) in ['cancel_calculate_phase_table_button']: continue self.assertTrue(widget.isEnabled())
class FocusPresenter(object): def __init__(self, model, view): self.model = model self.view = view self.worker = None self.calibration_observer = CalibrationObserver(self) # Observable Setup self.focus_run_notifier = GenericObservable() # Connect view signals to local methods. self.view.set_on_focus_clicked(self.on_focus_clicked) self.view.set_enable_controls_connection( self.set_focus_controls_enabled) # Variables from other GUI tabs. self.current_calibration = CalibrationInfo() self.instrument = "ENGINX" self.rb_num = None last_van_path = get_setting(output_settings.INTERFACES_SETTINGS_GROUP, output_settings.ENGINEERING_PREFIX, "last_vanadium_run") if last_van_path: self.view.set_van_file_text_with_search(last_van_path) def add_focus_subscriber(self, obs): self.focus_run_notifier.add_subscriber(obs) def on_focus_clicked(self): if not self._validate(): return regions_dict = self.current_calibration.create_focus_roi_dictionary() focus_paths = self.view.get_focus_filenames() van_path = self.view.get_vanadium_filename() if self._number_of_files_warning(focus_paths): self.start_focus_worker(focus_paths, van_path, self.view.get_plot_output(), self.rb_num, regions_dict) van_run = self.view.get_vanadium_run() set_setting(output_settings.INTERFACES_SETTINGS_GROUP, output_settings.ENGINEERING_PREFIX, "last_vanadium_run", van_run) def start_focus_worker(self, focus_paths: list, van_path: str, plot_output: bool, rb_num: str, regions_dict: dict) -> None: """ Focus data in a separate thread to stop the main GUI from hanging. :param focus_paths: List of paths to the files containing the data to focus. :param plot_output: True if the output should be plotted. :param rb_num: The RB Number from the main window (often an experiment id) :param regions_dict: Dictionary containing the regions to focus over, mapping region_name -> grouping_ws_name """ self.worker = AsyncTask(self.model.focus_run, (focus_paths, van_path, plot_output, self.instrument, rb_num, regions_dict), error_cb=self._on_worker_error, finished_cb=self._on_worker_success) self.set_focus_controls_enabled(False) self.worker.start() def _on_worker_success(self): self.emit_enable_button_signal() self.focus_run_notifier.notify_subscribers( self.model.get_last_focused_files()) def set_instrument_override(self, instrument): instrument = INSTRUMENT_DICT[instrument] self.view.set_instrument_override(instrument) self.instrument = instrument def set_rb_num(self, rb_num): self.rb_num = rb_num def _validate(self): """ Ensure that the worker is ready to be started. :return: True if the worker can be started safely. """ if self.view.is_searching(): create_error_message( self.view, "Mantid is searching for data files. Please wait.") return False if not self.view.get_focus_valid(): create_error_message(self.view, "Check run numbers/path is valid.") return False if not self.view.get_vanadium_valid(): create_error_message(self.view, "Check vanadium run number/path is valid.") return False if not self.current_calibration.is_valid(): create_error_message( self.view, "Create or Load a calibration via the Calibration tab before focusing." ) return False if self.current_calibration.get_instrument() != self.instrument: create_error_message( self.view, "Please make sure the selected instrument matches instrument for the current calibration.\n" "The instrument for the current calibration is: " + self.current_calibration.get_instrument()) return False return True def _number_of_files_warning(self, paths): if len( paths ) > 10: # Just a guess on the warning for now. May change in future. response = QMessageBox.warning( self.view, 'Engineering Diffraction - Warning', 'You are attempting to focus {} workspaces. This may take some time.\n\n Would you like to continue?' .format(len(paths)), QMessageBox.Ok | QMessageBox.Cancel) return response == QMessageBox.Ok else: return True def _on_worker_error(self, error_info): logger.error(str(error_info)) self.emit_enable_button_signal() def set_focus_controls_enabled(self, enabled): self.view.set_focus_button_enabled(enabled) self.view.set_plot_output_enabled(enabled) def emit_enable_button_signal(self): self.view.sig_enable_controls.emit(True) def update_calibration(self, calibration): """ Update the current calibration following an call from a CalibrationNotifier :param calibration: The new current calibration. """ self.current_calibration = calibration region_text = calibration.get_roi_text() self.view.set_region_display_text(region_text)
class FrequencyAnalysisGui(QtWidgets.QMainWindow): """ The Frequency Domain Analaysis 2.0 interface. """ @staticmethod def warning_popup(message): message_box.warning(str(message)) def __init__(self, parent=None, window_flags=None): super(FrequencyAnalysisGui, self).__init__(parent) if window_flags: self.setWindowFlags(window_flags) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setFocusPolicy(QtCore.Qt.StrongFocus) try: check_facility() except AttributeError as error: self.warning_popup(error.args[0]) # load the feature flags feature_dict = load_features() # initialise the data storing classes of the interface self.loaded_data = MuonLoadData() self.data_context = MuonDataContext('Frequency Domain Data', self.loaded_data) self.gui_context = MuonGuiContext() self.plot_panes_context = PlotPanesContext() self.group_pair_context = MuonGroupPairContext( self.data_context.check_group_contains_valid_detectors) self.corrections_context = CorrectionsContext(self.loaded_data) self.phase_context = PhaseTableContext() self.fitting_context = BasicFittingContext( allow_double_pulse_fitting=True) self.results_context = ResultsContext() self.model_fitting_context = ModelFittingContext( allow_double_pulse_fitting=False) self.frequency_context = FrequencyContext() self.context = FrequencyDomainAnalysisContext( muon_data_context=self.data_context, muon_gui_context=self.gui_context, muon_group_context=self.group_pair_context, corrections_context=self.corrections_context, muon_phase_context=self.phase_context, plot_panes_context=self.plot_panes_context, fitting_context=self.fitting_context, results_context=self.results_context, model_fitting_context=self.model_fitting_context, frequency_context=self.frequency_context) # create the dockable widget self.plot_widget = FrequencyAnalysisPlotWidget(self.context, parent=self) self.dockable_plot_widget_window = PlottingDockWidget( parent=self, plotting_widget=self.plot_widget.view) self.dockable_plot_widget_window.setMinimumWidth(575) # Add dock widget to main Muon analysis window self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockable_plot_widget_window) # Need this line to stop the bug where the dock window snaps back to its original size after resizing. # 0 argument is arbitrary and has no effect on fit widget size # This is a qt bug reported at (https://bugreports.qt.io/browse/QTBUG-65592) if QT_VERSION >= LooseVersion("5.6"): self.resizeDocks({self.dockable_plot_widget_window}, {1}, QtCore.Qt.Horizontal) # construct all the widgets. self.load_widget = LoadWidget(self.loaded_data, self.context, self) self.grouping_tab_widget = GroupingTabWidget(self.context, parent) self.corrections_tab = CorrectionsTabWidget(self.context, self) self.home_tab = HomeTabWidget(self.context, self) self.phase_tab = PhaseTabWidget(self.context, self) self.transform = TransformWidget(self.context, FFTWidget, MaxEntWidget, parent=self) self.fitting_tab = FittingTabWidget(self.context, self) self.seq_fitting_tab = SeqFittingTabWidget( self.context, self.fitting_tab.fitting_tab_model, self) self.results_tab = ResultsTabWidget(self.context.fitting_context, self.context, self) self.add_model_analysis = AddModelAnalysis(self, feature_dict) self.add_raw_plots = AddRawPlots(self, feature_dict) self.add_fitting = AddFitting(self, feature_dict) setup_group_ws = AddGroupingWorkspaces(self, feature_dict) self.setup_tabs() self.plot_widget.insert_plot_panes() self.help_widget = HelpWidget(self.context.window_title) central_widget = QtWidgets.QWidget() vertical_layout = QtWidgets.QVBoxLayout() vertical_layout.addWidget(self.load_widget.load_widget_view) vertical_layout.addWidget(self.tabs) vertical_layout.addWidget(self.help_widget.view) central_widget.setLayout(vertical_layout) central_widget.setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)) self.disable_notifier = GenericObservable() self.disable_observer = GenericObserver( self.disable_notifier.notify_subscribers) self.enable_notifier = GenericObservable() self.enable_observer = GenericObserver( self.enable_notifier.notify_subscribers) self.setup_disable_notifier() self.setup_enable_notifier() self.setCentralWidget(central_widget) self.setWindowTitle(self.context.window_title) self.setup_load_observers() self.setup_gui_variable_observers() self.setup_grouping_changed_observers() self.setup_corrections_changed_observers() self.setup_instrument_changed_notifier() self.setup_group_calculation_enable_notifier() self.setup_group_calculation_disabler_notifier() self.setup_on_load_enabler() self.setup_on_load_disabler() self.setup_phase_quad_changed_notifier() self.setup_phase_table_changed_notifier() self.setup_fitting_notifier() self.setup_counts_calculation_finished_notifier() self.setup_asymmetry_pair_and_diff_calculations_finished_notifier() self.setup_transform() self.context.data_context.message_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.message_observer) self.add_model_analysis.add_observers_to_feature(self) self.add_model_analysis.set_feature_observables(self) self.add_raw_plots.add_observers_to_feature(self) setup_group_ws.add_observers_to_feature(self) def setup_transform(self): self.transform.set_up_calculation_observers( self.fitting_tab.fitting_tab_view.enable_tab_observer, self.fitting_tab.fitting_tab_view.disable_tab_observer) self.transform.new_data_observer(self.transform_finished_observer) self.transform._maxent._presenter.calculation_finished_notifier.add_subscriber( self.plot_widget.maxent_mode.new_data_observer) self.transform._maxent._presenter.new_reconstructed_data.add_subscriber( self.plot_widget.maxent_mode.reconstructed_data_observer) self.transform._maxent._presenter.method_changed.add_subscriber( self.plot_widget.maxent_mode.method_changed) self.transform._maxent._presenter.period_changed.add_subscriber( self.plot_widget.maxent_mode.period_changed) self.context.data_context.instrumentNotifier.add_subscriber( self.plot_widget.maxent_mode.instrument_observer) self.update_fits_observer = GenericObserver(self.handle_units_changed) self.plot_widget.update_freq_units_add_subscriber( self.update_fits_observer) def setup_tabs(self): """ Set up the tabbing structure; the tabs work similarly to conventional web browsers. """ self.tabs = DetachableTabWidget(self) self.tabs.addTabWithOrder(self.home_tab.home_tab_view, 'Home') self.tabs.addTabWithOrder(self.grouping_tab_widget.group_tab_view, 'Grouping') self.tabs.addTabWithOrder(self.corrections_tab.corrections_tab_view, "Corrections") self.tabs.addTabWithOrder(self.phase_tab.phase_table_view, 'Phase Table') self.tabs.addTabWithOrder(self.transform.widget, 'Transform') self.tabs.addTabWithOrder(self.fitting_tab.fitting_tab_view, 'Fitting') self.tabs.addTabWithOrder(self.seq_fitting_tab.seq_fitting_tab_view, 'Sequential Fitting') self.tabs.addTabWithOrder(self.results_tab.results_tab_view, 'Results') self.add_model_analysis.add_to_tab(self) self.transform_finished_observer = GenericObserverWithArgPassing( self.handle_transform_performed) self.tabs.set_slot_for_tab_changed(self.handle_tab_changed) self.tabs.setElideMode(QtCore.Qt.ElideNone) self.tabs.setUsesScrollButtons(False) def handle_tab_changed(self): index = self.tabs.currentIndex() if TAB_ORDER[index] in [ "Home", "Grouping", "Corrections", "Phase Table" ]: # Plot all the selected data plot_mode = self.plot_widget.data_index elif TAB_ORDER[index] in [ "Fitting", "Sequential Fitting", "Transform" ]: # Plot the displayed workspace plot_mode = self.plot_widget.fit_index elif TAB_ORDER[index] in ["Model Fitting"]: plot_mode = self.plot_widget.model_fit_index else: return self.plot_widget.set_plot_view(plot_mode) def handle_transform_performed(self, new_data_workspace_name): self.update_fit_ws_list() self.fitting_tab.fitting_tab_presenter.set_selected_dataset( new_data_workspace_name) def handle_units_changed(self): old_name = self.fitting_tab.fitting_tab_presenter.current_dataset() if old_name == "": return self.update_fit_ws_list() new_name = self.frequency_context.switch_units_in_name(old_name) self.fitting_tab.fitting_tab_presenter.set_selected_dataset(new_name) x_lim = self.frequency_context.range() self.fitting_tab.fitting_tab_presenter.update_start_and_end_x_in_view_and_model( x_lim[0], x_lim[1]) def update_fit_ws_list(self): self.fitting_tab.fitting_tab_presenter.handle_new_data_loaded() self.seq_fitting_tab.seq_fitting_tab_presenter.handle_selected_workspaces_changed( ) def set_tab_warning(self, tab_name: str, message: str): """Sets a warning message as the tooltip of the provided tab.""" self.tabs.set_tab_warning(TAB_ORDER.index(tab_name), message) def setup_disable_notifier(self): self.disable_notifier.add_subscriber( self.home_tab.home_tab_widget.disable_observer) self.disable_notifier.add_subscriber( self.load_widget.load_widget.disable_observer) self.disable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.disable_tab_observer) self.disable_notifier.add_subscriber( self.corrections_tab.corrections_tab_view.disable_tab_observer) self.disable_notifier.add_subscriber( self.fitting_tab.fitting_tab_view.disable_tab_observer) self.disable_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter.disable_tab_observer ) self.disable_notifier.add_subscriber( self.phase_tab.phase_table_presenter.disable_tab_observer) self.disable_notifier.add_subscriber( self.results_tab.results_tab_presenter.disable_tab_observer) self.disable_notifier.add_subscriber(self.transform.disable_observer) def setup_enable_notifier(self): self.enable_notifier.add_subscriber( self.home_tab.home_tab_widget.enable_observer) self.enable_notifier.add_subscriber( self.load_widget.load_widget.enable_observer) self.enable_notifier.add_subscriber( self.corrections_tab.corrections_tab_view.enable_tab_observer) self.enable_notifier.add_subscriber( self.fitting_tab.fitting_tab_view.enable_tab_observer) self.enable_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.phase_tab.phase_table_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.results_tab.results_tab_presenter.enable_tab_observer) self.enable_notifier.add_subscriber(self.transform.enable_observer) self.enable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.enable_tab_observer) def setup_load_observers(self): self.load_widget.load_widget.loadNotifier.add_subscriber( self.home_tab.home_tab_widget.loadObserver) self.load_widget.load_widget.loadNotifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.loadObserver) self.load_widget.load_widget.loadNotifier.add_subscriber( self.corrections_tab.corrections_tab_presenter.load_observer) self.load_widget.load_widget.loadNotifier.add_subscriber( self.phase_tab.phase_table_presenter.run_change_observer) self.load_widget.load_widget.loadNotifier.add_subscriber( self.fitting_tab.fitting_tab_view.disable_tab_observer) self.load_widget.load_widget.loadNotifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter.disable_tab_observer ) def setup_gui_variable_observers(self): self.context.gui_context.gui_variables_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.gui_variables_observer ) for observer in self.plot_widget.rebin_options_set_observers: self.context.gui_context.gui_variables_notifier.add_subscriber( observer) self.grouping_tab_widget.pairing_table_widget.selected_pair_changed_notifier.add_subscriber( self.plot_widget.data_mode.added_group_or_pair_observer) self.grouping_tab_widget.pairing_table_widget.selected_pair_changed_notifier.add_subscriber( self.transform.GroupPairObserver) self.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( self.transform.GroupPairObserver) self.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( self.plot_widget.data_mode.added_group_or_pair_observer) # differences self.grouping_tab_widget.diff_table.add_subscribers([ self.transform.GroupPairObserver, self.plot_widget.data_mode.added_group_or_pair_observer ]) self.fitting_tab.fitting_tab_presenter.fit_function_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. fit_function_updated_observer) self.fitting_tab.fitting_tab_presenter.fit_parameter_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. fit_parameter_updated_observer) self.seq_fitting_tab.seq_fitting_tab_presenter.fit_parameter_changed_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter. fit_parameter_updated_observer) self.seq_fitting_tab.seq_fitting_tab_presenter.sequential_fit_finished_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter. sequential_fit_finished_observer) self.fitting_tab.fitting_tab_presenter.selected_fit_results_changed.add_subscriber( self.plot_widget.fit_mode.plot_selected_fit_observer) self.seq_fitting_tab.seq_fitting_tab_presenter.selected_sequential_fit_notifier.add_subscriber( self.plot_widget.fit_mode.plot_selected_fit_observer) self.phase_tab.phase_table_presenter.selected_phasequad_changed_notifier.add_subscriber( self.plot_widget.data_mode.added_group_or_pair_observer) self.phase_tab.phase_table_presenter.selected_phasequad_changed_notifier.add_subscriber( self.transform.GroupPairObserver) self.phase_tab.phase_table_presenter.selected_phasequad_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. selected_workspaces_observer) def setup_grouping_changed_observers(self): self.grouping_tab_widget.group_tab_presenter.groupingNotifier.add_subscriber( self.home_tab.home_tab_widget.groupingObserver) self.grouping_tab_widget.group_tab_presenter.groupingNotifier.add_subscriber( self.transform.GroupPairObserver) self.grouping_tab_widget.group_tab_presenter.groupingNotifier.add_subscriber( self.phase_tab.phase_table_presenter.group_change_observer) def setup_corrections_changed_observers(self): self.corrections_tab.corrections_tab_presenter.perform_corrections_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.gui_variables_observer ) def setup_instrument_changed_notifier(self): self.context.data_context.instrumentNotifier.add_subscriber( self.home_tab.home_tab_widget.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.load_widget.load_widget.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.corrections_tab.corrections_tab_presenter. instrument_changed_observer) self.context.data_context.instrumentNotifier.add_subscriber( self.transform.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.phase_tab.phase_table_presenter.instrument_changed_observer) self.context.data_context.instrumentNotifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.instrument_changed_observer) for observer in self.plot_widget.clear_plot_observers: self.context.data_context.instrumentNotifier.add_subscriber( observer) def setup_group_calculation_enable_notifier(self): self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) self.corrections_tab.corrections_tab_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) self.fitting_tab.fitting_tab_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) self.phase_tab.phase_table_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) def setup_group_calculation_disabler_notifier(self): self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) self.corrections_tab.corrections_tab_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) self.fitting_tab.fitting_tab_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) self.phase_tab.phase_table_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) def setup_on_load_enabler(self): self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.home_tab.home_tab_widget.enable_observer) self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.enable_observer) self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.transform.enable_observer) def setup_on_load_disabler(self): self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.home_tab.home_tab_widget.disable_observer) self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.disable_observer) self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.transform.disable_observer) def setup_counts_calculation_finished_notifier(self): self.grouping_tab_widget.group_tab_presenter.counts_calculation_finished_notifier.add_subscriber( self.corrections_tab.corrections_tab_presenter. pre_process_and_counts_calculated_observer) def setup_asymmetry_pair_and_diff_calculations_finished_notifier(self): for observer in self.plot_widget.data_changed_observers: self.corrections_tab.corrections_tab_presenter.asymmetry_pair_and_diff_calculations_finished_notifier.\ add_subscriber(observer) self.phase_tab.phase_table_presenter.calculation_finished_notifier.add_subscriber( observer) self.corrections_tab.corrections_tab_presenter.asymmetry_pair_and_diff_calculations_finished_notifier.add_subscriber( self.transform.load_observer) self.corrections_tab.corrections_tab_presenter.asymmetry_pair_and_diff_calculations_finished_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. selected_workspaces_observer) def setup_phase_quad_changed_notifier(self): self.phase_tab.phase_table_presenter.phasequad_calculation_complete_notifier.add_subscriber( self.transform.phase_quad_observer) def setup_phase_table_changed_notifier(self): self.phase_tab.phase_table_presenter.phase_table_calculation_complete_notifier.add_subscriber( self.transform._maxent._presenter.phase_table_observer) self.transform._maxent._presenter.new_phase_table.add_subscriber( self.phase_tab.phase_table_presenter.phase_table_observer) def setup_fitting_notifier(self): """Connect fitting and results tabs to inform of new fits""" self.fitting_context.new_fit_results_notifier.add_subscriber( self.results_tab.results_tab_presenter.new_fit_performed_observer) self.fitting_tab.fitting_tab_presenter.remove_plot_guess_notifier.add_subscriber( self.plot_widget.fit_mode.remove_plot_guess_observer) self.fitting_tab.fitting_tab_presenter.update_plot_guess_notifier.add_subscriber( self.plot_widget.fit_mode.update_plot_guess_observer) def closeEvent(self, event): self.tabs.closeEvent(event) self.context.ads_observer.unsubscribe() self.grouping_tab_widget.group_tab_presenter.closePeriodInfoWidget() super(FrequencyAnalysisGui, self).closeEvent(event)
class MuonAnalysisGui(QtWidgets.QMainWindow): """ The Muon Analysis 2.0 interface. """ @staticmethod def warning_popup(message): message_box.warning(str(message)) def __init__(self, parent=None): super(MuonAnalysisGui, self).__init__(parent) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setFocusPolicy(QtCore.Qt.StrongFocus) self.setObjectName("MuonAnalysis2") self.current_tab = '' try: check_facility() except AttributeError as error: self.warning_popup(error.args[0]) # initialise the data storing classes of the interface self.loaded_data = MuonLoadData() self.data_context = MuonDataContext('Muon Data', self.loaded_data) self.gui_context = MuonGuiContext() self.group_pair_context = MuonGroupPairContext( self.data_context.check_group_contains_valid_detectors) self.phase_context = PhaseTableContext() self.fitting_context = FittingContext() self.context = DataAnalysisContext( muon_data_context=self.data_context, muon_gui_context=self.gui_context, muon_group_context=self.group_pair_context, fitting_context=self.fitting_context, muon_phase_context=self.phase_context) # create the Dockable plot widget self.fitting_tab = FittingTabWidget(self.context, self) self.plot_widget = PlotWidget( self.context, self.fitting_tab.fitting_tab_presenter.get_selected_fit_workspaces, parent=self) self.dockable_plot_widget_window = PlottingDockWidget( parent=self, plotting_widget=self.plot_widget.view) self.dockable_plot_widget_window.setMinimumWidth(575) # Add dock widget to main Muon analysis window self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockable_plot_widget_window) # Need this line to stop the bug where the dock window snaps back to its original size after resizing. # 0 argument is arbitrary and has no effect on fit widget size # This is a qt bug reported at (https://bugreports.qt.io/browse/QTBUG-65592) if QT_VERSION >= LooseVersion("5.6"): self.resizeDocks({self.dockable_plot_widget_window}, {1}, QtCore.Qt.Horizontal) self.disable_notifier = GenericObservable() self.disable_observer = GenericObserver( self.disable_notifier.notify_subscribers) self.enable_notifier = GenericObservable() self.enable_observer = GenericObserver( self.enable_notifier.notify_subscribers) # set up other widgets self.load_widget = LoadWidget(self.loaded_data, self.context, self) self.home_tab = HomeTabWidget(self.context, self) self.grouping_tab_widget = GroupingTabWidget(self.context) self.phase_tab = PhaseTabWidget(self.context, self) self.seq_fitting_tab = SeqFittingTabWidget( self.context, self.fitting_tab.fitting_tab_model, self) self.results_tab = ResultsTabWidget(self.context.fitting_context, self.context, self) self.setup_tabs() self.help_widget = HelpWidget("Muon Analysis 2") central_widget = QtWidgets.QWidget() vertical_layout = QtWidgets.QVBoxLayout() vertical_layout.addWidget(self.load_widget.load_widget_view) vertical_layout.addWidget(self.tabs) vertical_layout.addWidget(self.help_widget.view) central_widget.setLayout(vertical_layout) self.setCentralWidget(central_widget) self.setWindowTitle(self.context.window_title) self.setup_load_observers() self.setup_gui_variable_observers() self.setup_grouping_changed_observers() self.setup_instrument_changed_notifier() self.setup_group_calculation_enable_notifier() self.setup_group_calculation_disabler_notifier() self.setup_on_load_enabler() self.setup_on_load_disabler() self.setup_phase_quad_changed_notifier() self.setup_phase_table_changed_notifier() self.setup_fitting_notifier() self.setup_on_recalulation_finished_notifier() self.context.data_context.message_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.message_observer) self.setup_disable_notifier() self.setup_enable_notifier() def setup_tabs(self): """ Set up the tabbing structure; the tabs work similarly to conventional web browsers. """ self.tabs = DetachableTabWidget(self) self.tabs.addTabWithOrder(self.home_tab.home_tab_view, 'Home') self.tabs.addTabWithOrder(self.grouping_tab_widget.group_tab_view, 'Grouping') self.tabs.addTabWithOrder(self.phase_tab.phase_table_view, 'Phase Table') self.tabs.addTabWithOrder(self.fitting_tab.fitting_tab_view, 'Fitting') self.tabs.addTabWithOrder(self.seq_fitting_tab.seq_fitting_tab_view, 'Sequential Fitting') self.tabs.addTabWithOrder(self.results_tab.results_tab_view, 'Results') self.update_plot_observer = GenericObserver( self.plot_widget.presenter.update_plot) self.tabs.set_slot_for_tab_changed(self.handle_tab_changed) def handle_tab_changed(self): index = self.tabs.currentIndex() if TAB_ORDER[index] in ["Home", "Grouping", "Phase Table"]: # Plot all the selected data plot_mode = PlotMode.Data elif TAB_ORDER[index] in ["Fitting", "Sequential Fitting" ]: # Plot the displayed workspace plot_mode = PlotMode.Fitting else: return self.plot_widget.presenter.handle_plot_mode_changed(plot_mode) def setup_disable_notifier(self): self.disable_notifier.add_subscriber( self.home_tab.home_tab_widget.disable_observer) self.disable_notifier.add_subscriber( self.load_widget.load_widget.disable_observer) self.disable_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.disable_tab_observer) self.disable_notifier.add_subscriber( self.phase_tab.phase_table_presenter.disable_tab_observer) self.disable_notifier.add_subscriber( self.results_tab.results_tab_presenter.disable_tab_observer) self.disable_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter.disable_tab_observer ) self.disable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.disable_tab_observer) def setup_enable_notifier(self): self.enable_notifier.add_subscriber( self.home_tab.home_tab_widget.enable_observer) self.enable_notifier.add_subscriber( self.load_widget.load_widget.enable_observer) self.enable_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.phase_tab.phase_table_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.results_tab.results_tab_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.enable_tab_observer) def setup_load_observers(self): self.load_widget.load_widget.loadNotifier.add_subscriber( self.home_tab.home_tab_widget.loadObserver) self.load_widget.load_widget.loadNotifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.loadObserver) self.load_widget.load_widget.loadNotifier.add_subscriber( self.phase_tab.phase_table_presenter.run_change_observer) def setup_gui_variable_observers(self): self.context.gui_context.gui_variables_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.gui_variables_observer ) self.context.gui_context.gui_variables_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.gui_context_observer) self.context.gui_context.gui_variable_non_calulation_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.gui_context_observer) self.grouping_tab_widget.pairing_table_widget.selected_pair_changed_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.selected_group_pair_observer ) self.grouping_tab_widget.pairing_table_widget.selected_pair_changed_notifier.add_subscriber( self.plot_widget.presenter.added_group_or_pair_observer) self.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.selected_group_pair_observer ) self.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( self.plot_widget.presenter.added_group_or_pair_observer) self.grouping_tab_widget.pairing_table_widget.selected_pair_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. selected_workspaces_observer) self.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. selected_workspaces_observer) self.fitting_tab.fitting_tab_presenter.fit_function_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. fit_function_updated_observer) self.fitting_tab.fitting_tab_presenter.fit_parameter_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. fit_parameter_updated_observer) self.fitting_tab.fitting_tab_presenter.fit_type_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. fit_type_changed_observer) self.fitting_tab.fitting_tab_presenter.selected_single_fit_notifier.add_subscriber( self.plot_widget.presenter.plot_selected_fit_observer) self.seq_fitting_tab.seq_fitting_tab_presenter.selected_sequential_fit_notifier.add_subscriber( self.plot_widget.presenter.plot_selected_fit_observer) def setup_grouping_changed_observers(self): self.grouping_tab_widget.group_tab_presenter.groupingNotifier.add_subscriber( self.home_tab.home_tab_widget.groupingObserver) self.grouping_tab_widget.group_tab_presenter.groupingNotifier.add_subscriber( self.phase_tab.phase_table_presenter.group_change_observer) def setup_instrument_changed_notifier(self): self.context.data_context.instrumentNotifier.add_subscriber( self.home_tab.home_tab_widget.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.load_widget.load_widget.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.phase_tab.phase_table_presenter.instrument_changed_observer) self.context.data_context.instrumentNotifier.add_subscriber( self.plot_widget.presenter.instrument_observer) self.context.data_context.instrumentNotifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.instrument_changed_observer) def setup_group_calculation_enable_notifier(self): self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) self.fitting_tab.fitting_tab_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) self.phase_tab.phase_table_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) def setup_group_calculation_disabler_notifier(self): self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) self.fitting_tab.fitting_tab_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) self.phase_tab.phase_table_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) def setup_on_load_enabler(self): self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.home_tab.home_tab_widget.enable_observer) self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.enable_observer) self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.enable_tab_observer) def setup_on_load_disabler(self): self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.home_tab.home_tab_widget.disable_observer) self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.disable_observer) self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.disable_tab_observer) def setup_on_recalulation_finished_notifier(self): self.grouping_tab_widget.group_tab_presenter.calculation_finished_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.input_workspace_observer) self.grouping_tab_widget.group_tab_presenter.calculation_finished_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. selected_workspaces_observer) self.grouping_tab_widget.group_tab_presenter.calculation_finished_notifier.add_subscriber( self.update_plot_observer) def setup_phase_quad_changed_notifier(self): pass def setup_phase_table_changed_notifier(self): pass def setup_fitting_notifier(self): """Connect fitting and results tabs to inform of new fits""" self.fitting_context.new_fit_results_notifier.add_subscriber( self.results_tab.results_tab_presenter.new_fit_performed_observer) self.fitting_context.plot_guess_notifier.add_subscriber( self.plot_widget.presenter.plot_guess_observer) def closeEvent(self, event): self.removeDockWidget(self.dockable_plot_widget_window) self.tabs.closeEvent(event) self.context.ads_observer.unsubscribe() self.context.ads_observer = None super(MuonAnalysisGui, self).closeEvent(event)
class ElementalAnalysisGui(QtWidgets.QMainWindow): """ The Elemental Analysis 2.0 interface. """ def warning_popup(self, message): message_box.warning(str(message), parent=self) def __init__(self, parent=None): super(ElementalAnalysisGui, self).__init__(parent) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setFocusPolicy(QtCore.Qt.StrongFocus) self.setObjectName("ElementalAnalysis2") # setup error notifier and observer for context and group context self.error_notifier = GenericObservable() self.error_observer = GenericObserverWithArgPassing(self.warning_popup) self.error_notifier.add_subscriber(self.error_observer) self.loaded_data = MuonLoadData() self.data_context = DataContext(self.loaded_data) self.group_context = EAGroupContext( self.data_context.check_group_contains_valid_detectors, self.error_notifier) self.gui_context = MuonGuiContext() self.plot_panes_context = PlotPanesContext() self.context = ElementalAnalysisContext(self.data_context, self.group_context, self.gui_context, self.plot_panes_context, self.error_notifier) self.current_tab = '' self.plot_widget = EAPlotWidget(self.context, parent=self) self.dockable_plot_widget_window = PlottingDockWidget( parent=self, plotting_widget=self.plot_widget.view) self.dockable_plot_widget_window.setMinimumWidth(800) # Add dock widget to main Elemental analysis window self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockable_plot_widget_window) # Need this line to stop the bug where the dock window snaps back to its original size after resizing. # 0 argument is arbitrary and has no effect on fit widget size # This is a qt bug reported at (https://bugreports.qt.io/browse/QTBUG-65592) if QT_VERSION >= LooseVersion("5.6"): self.resizeDocks({self.dockable_plot_widget_window}, {1}, QtCore.Qt.Horizontal) # disable and enable notifiers self.disable_notifier = GenericObservable() self.enable_notifier = GenericObservable() # disable and enable observers self.disable_observer = GenericObserver( self.disable_notifier.notify_subscribers) self.enable_observer = GenericObserver( self.enable_notifier.notify_subscribers) self.setup_dummy() self.setup_tabs() self.help_widget = HelpWidget("Elemental Analysis") central_widget = QtWidgets.QWidget() vertical_layout = QtWidgets.QVBoxLayout() vertical_layout.addWidget(self.load_widget.view) vertical_layout.addWidget(self.tabs) vertical_layout.addWidget(self.help_widget.view) central_widget.setLayout(vertical_layout) self.setCentralWidget(central_widget) self.setWindowTitle(self.context.name) # setup connections between notifiers and observers self.setup_enable_notifier() self.setup_disable_notifier() self.setup_load_observers() self.setup_gui_variable_observers() self.setup_group_calculation_enable_notifier() self.setup_group_calculation_disable_notifier() self.setup_grouping_changed_observers() self.setup_update_view_notifier() self.setMinimumHeight(800) def setup_dummy(self): self.load_widget = LoadWidget(self.loaded_data, self.context, parent=self) self.home_tab = QtWidgets.QLineEdit("home") self.grouping_tab_widget = EAGroupingTabWidget(self.context) self.fitting_tab = QtWidgets.QLineEdit("fitting") self.auto_tab = EAAutoTabWidget(self.context) def setup_tabs(self): """ Set up the tabbing structure; the tabs work similarly to conventional web browsers. """ self.tabs = DetachableTabWidget(self) self.tabs.addTabWithOrder(self.home_tab, 'Home') self.tabs.addTabWithOrder(self.grouping_tab_widget.group_tab_view, 'Grouping') self.tabs.addTabWithOrder(self.auto_tab.auto_tab_view, 'Automatic') self.tabs.addTabWithOrder(self.fitting_tab, 'Fitting') def closeEvent(self, event): self.removeDockWidget(self.dockable_plot_widget_window) self.context.ads_observer.unsubscribe() self.context.ads_observer = None self.tabs.closeEvent(event) super(ElementalAnalysisGui, self).closeEvent(event) def setup_disable_notifier(self): self.disable_notifier.add_subscriber( self.load_widget.load_widget.disable_observer) self.disable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.disable_tab_observer) self.disable_notifier.add_subscriber( self.grouping_tab_widget.grouping_table_view.disable_table_observer ) self.disable_notifier.add_subscriber( self.auto_tab.auto_tab_presenter.disable_tab_observer) def setup_enable_notifier(self): self.enable_notifier.add_subscriber( self.load_widget.load_widget.enable_observer) self.enable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.grouping_tab_widget.grouping_table_view.enable_table_observer) self.enable_notifier.add_subscriber( self.auto_tab.auto_tab_presenter.enable_tab_observer) def setup_load_observers(self): self.load_widget.load_widget.loadNotifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.loadObserver) self.load_widget.load_widget.loadNotifier.add_subscriber( self.auto_tab.auto_tab_presenter.update_view_observer) def setup_gui_variable_observers(self): self.context.gui_context.gui_variables_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.gui_variables_observer ) def setup_grouping_changed_observers(self): self.grouping_tab_widget.grouping_table_widget.data_changed_notifier.add_subscriber( self.auto_tab.auto_tab_presenter.group_change_observer) for observer in self.plot_widget.data_changed_observers: self.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( observer) for observer in self.plot_widget.workspace_deleted_from_ads_observers: self.context.deleted_plots_notifier.add_subscriber(observer) def setup_on_load_enabler(self): self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.enable_observer) def setup_on_load_disabler(self): self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.disable_observer) def setup_group_calculation_enable_notifier(self): self.load_widget.run_widget.enable_notifier.add_subscriber( self.enable_observer) self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) self.context.calculation_finished_notifier.add_subscriber( self.enable_observer) self.auto_tab.auto_tab_presenter.model.calculation_finished_notifier.add_subscriber( self.enable_observer) def setup_group_calculation_disable_notifier(self): self.load_widget.run_widget.disable_notifier.add_subscriber( self.disable_observer) self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) self.context.calculation_started_notifier.add_subscriber( self.disable_observer) self.auto_tab.auto_tab_presenter.model.calculation_started_notifier.add_subscriber( self.disable_observer) def setup_update_view_notifier(self): self.context.update_view_from_model_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter. update_view_from_model_observer) self.context.update_view_from_model_notifier.add_subscriber( self.auto_tab.auto_tab_presenter.update_view_observer) self.context.update_view_from_model_notifier.add_subscriber( self.load_widget.load_widget.update_view_from_model_observer)
class MuonAnalysisGui(QtWidgets.QMainWindow): """ The Muon Analysis 2.0 interface. """ @staticmethod def warning_popup(message): message_box.warning(str(message)) def __init__(self, parent=None, window_flags=None): super(MuonAnalysisGui, self).__init__(parent) if window_flags: self.setWindowFlags(window_flags) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setFocusPolicy(QtCore.Qt.StrongFocus) self.setObjectName("MuonAnalysis2") self.current_tab = '' try: check_facility() except AttributeError as error: self.warning_popup(error.args[0]) # initialise the data storing classes of the interface self.loaded_data = MuonLoadData() self.data_context = MuonDataContext('Muon Data', self.loaded_data) self.gui_context = MuonGuiContext() self.group_pair_context = MuonGroupPairContext( self.data_context.check_group_contains_valid_detectors) self.corrections_context = CorrectionsContext(self.loaded_data) self.phase_context = PhaseTableContext() self.fitting_context = TFAsymmetryFittingContext( allow_double_pulse_fitting=True) self.results_context = ResultsContext() self.model_fitting_context = ModelFittingContext( allow_double_pulse_fitting=False) self.plot_panes_context = PlotPanesContext() self.context = DataAnalysisContext( muon_data_context=self.data_context, muon_gui_context=self.gui_context, muon_group_context=self.group_pair_context, corrections_context=self.corrections_context, fitting_context=self.fitting_context, results_context=self.results_context, model_fitting_context=self.model_fitting_context, muon_phase_context=self.phase_context, plot_panes_context=self.plot_panes_context) # create the Dockable plot widget self.fitting_tab = FittingTabWidget(self.context, self) self.plot_widget = MuonAnalysisPlotWidget(self.context, parent=self) self.dockable_plot_widget_window = PlottingDockWidget( parent=self, plotting_widget=self.plot_widget.view) self.dockable_plot_widget_window.setMinimumWidth(800) # Add dock widget to main Muon analysis window self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockable_plot_widget_window) # Need this line to stop the bug where the dock window snaps back to its original size after resizing. # 0 argument is arbitrary and has no effect on fit widget size # This is a qt bug reported at (https://bugreports.qt.io/browse/QTBUG-65592) if QT_VERSION >= LooseVersion("5.6"): self.resizeDocks({self.dockable_plot_widget_window}, {1}, QtCore.Qt.Horizontal) self.disable_notifier = GenericObservable() self.disable_observer = GenericObserver( self.disable_notifier.notify_subscribers) self.enable_notifier = GenericObservable() self.enable_observer = GenericObserver( self.enable_notifier.notify_subscribers) # set up other widgets self.load_widget = LoadWidget(self.loaded_data, self.context, self) self.home_tab = HomeTabWidget(self.context, self) self.grouping_tab_widget = GroupingTabWidget(self.context, parent) self.corrections_tab = CorrectionsTabWidget(self.context, self) self.phase_tab = PhaseTabWidget(self.context, self) self.seq_fitting_tab = SeqFittingTabWidget( self.context, self.fitting_tab.fitting_tab_model, self) self.results_tab = ResultsTabWidget(self.context.fitting_context, self.context, self) #self.model_fitting_tab = ModelFittingTabWidget(self.context, self) self.setup_tabs() self.help_widget = HelpWidget("Muon Analysis 2") central_widget = QtWidgets.QWidget() vertical_layout = QtWidgets.QVBoxLayout() vertical_layout.addWidget(self.load_widget.load_widget_view) vertical_layout.addWidget(self.tabs) vertical_layout.addWidget(self.help_widget.view) central_widget.setLayout(vertical_layout) self.setCentralWidget(central_widget) self.setWindowTitle(self.context.window_title) self.setup_load_observers() self.setup_gui_variable_observers() self.setup_grouping_changed_observers() self.setup_corrections_changed_observers() self.setup_instrument_changed_notifier() self.setup_group_calculation_enable_notifier() self.setup_group_calculation_disabler_notifier() self.setup_on_load_enabler() self.setup_on_load_disabler() self.setup_phase_quad_changed_notifier() self.setup_phase_table_changed_notifier() self.setup_fitting_notifier() self.setup_counts_calculation_finished_notifier() self.setup_asymmetry_pair_and_diff_calculations_finished_notifier() self.setup_results_notifier() self.context.data_context.message_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.message_observer) self.setup_disable_notifier() self.setup_enable_notifier() def setup_tabs(self): """ Set up the tabbing structure; the tabs work similarly to conventional web browsers. """ self.tabs = DetachableTabWidget(self) self.tabs.addTabWithOrder(self.home_tab.home_tab_view, 'Home') self.tabs.addTabWithOrder(self.grouping_tab_widget.group_tab_view, 'Grouping') self.tabs.addTabWithOrder(self.corrections_tab.corrections_tab_view, "Corrections") self.tabs.addTabWithOrder(self.phase_tab.phase_table_view, 'Phase Table') self.tabs.addTabWithOrder(self.fitting_tab.fitting_tab_view, 'Fitting') self.tabs.addTabWithOrder(self.seq_fitting_tab.seq_fitting_tab_view, 'Sequential Fitting') self.tabs.addTabWithOrder(self.results_tab.results_tab_view, 'Results') #self.tabs.addTabWithOrder(self.model_fitting_tab.model_fitting_tab_view, 'Model Fitting') self.tabs.set_slot_for_tab_changed(self.handle_tab_changed) self.tabs.setElideMode(QtCore.Qt.ElideNone) self.tabs.setUsesScrollButtons(False) def handle_tab_changed(self): index = self.tabs.currentIndex() # the plot mode indicies are from the order the plots are stored if TAB_ORDER[index] in [ "Home", "Grouping", "Corrections", "Phase Table" ]: # Plot all the selected data plot_mode = self.plot_widget.data_index # Plot the displayed workspace elif TAB_ORDER[index] in ["Fitting", "Sequential Fitting"]: plot_mode = self.plot_widget.fit_index #elif TAB_ORDER[index] in ["Model Fitting"]: # plot_mode = self.plot_widget.model_fit_index else: return self.plot_widget.set_plot_view(plot_mode) def set_tab_warning(self, tab_name: str, message: str): """Sets a warning message as the tooltip of the provided tab.""" self.tabs.set_tab_warning(TAB_ORDER.index(tab_name), message) def setup_disable_notifier(self): self.disable_notifier.add_subscriber( self.home_tab.home_tab_widget.disable_observer) self.disable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.disable_tab_observer) self.disable_notifier.add_subscriber( self.corrections_tab.corrections_tab_view.disable_tab_observer) self.disable_notifier.add_subscriber( self.load_widget.load_widget.disable_observer) self.disable_notifier.add_subscriber( self.fitting_tab.fitting_tab_view.disable_tab_observer) #self.disable_notifier.add_subscriber(self.model_fitting_tab.model_fitting_tab_view.disable_tab_observer) self.disable_notifier.add_subscriber( self.phase_tab.phase_table_presenter.disable_tab_observer) self.disable_notifier.add_subscriber( self.results_tab.results_tab_presenter.disable_tab_observer) self.disable_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter.disable_tab_observer ) def setup_enable_notifier(self): self.enable_notifier.add_subscriber( self.home_tab.home_tab_widget.enable_observer) self.enable_notifier.add_subscriber( self.corrections_tab.corrections_tab_view.enable_tab_observer) self.enable_notifier.add_subscriber( self.load_widget.load_widget.enable_observer) self.enable_notifier.add_subscriber( self.fitting_tab.fitting_tab_view.enable_tab_observer) #self.enable_notifier.add_subscriber(self.model_fitting_tab.model_fitting_tab_view.enable_tab_observer) self.enable_notifier.add_subscriber( self.phase_tab.phase_table_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.results_tab.results_tab_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter.enable_tab_observer) self.enable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.enable_tab_observer) def setup_load_observers(self): self.load_widget.load_widget.loadNotifier.add_subscriber( self.home_tab.home_tab_widget.loadObserver) self.load_widget.load_widget.loadNotifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.loadObserver) self.load_widget.load_widget.loadNotifier.add_subscriber( self.corrections_tab.corrections_tab_presenter.load_observer) self.load_widget.load_widget.loadNotifier.add_subscriber( self.phase_tab.phase_table_presenter.run_change_observer) self.load_widget.load_widget.loadNotifier.add_subscriber( self.fitting_tab.fitting_tab_view.disable_tab_observer) self.load_widget.load_widget.loadNotifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter.disable_tab_observer ) #self.load_widget.load_widget.loadNotifier.add_subscriber( # self.plot_widget.raw_mode.new_data_observer) def setup_gui_variable_observers(self): self.context.gui_context.gui_variables_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.gui_variables_observer ) self.context.gui_context.gui_variables_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.gui_context_observer) for observer in self.plot_widget.rebin_options_set_observers: self.context.gui_context.gui_variables_notifier.add_subscriber( observer) self.context.gui_context.gui_variable_non_calulation_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.gui_context_observer) self.grouping_tab_widget.pairing_table_widget.selected_pair_changed_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.selected_group_pair_observer ) self.grouping_tab_widget.pairing_table_widget.selected_pair_changed_notifier.add_subscriber( self.plot_widget.data_mode.added_group_or_pair_observer) self.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.selected_group_pair_observer ) self.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( self.plot_widget.data_mode.added_group_or_pair_observer) self.grouping_tab_widget.pairing_table_widget.selected_pair_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. selected_workspaces_observer) self.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. selected_workspaces_observer) # differences self.grouping_tab_widget.diff_table.add_subscribers([ self.fitting_tab.fitting_tab_presenter. selected_group_pair_observer, self.seq_fitting_tab. seq_fitting_tab_presenter.selected_workspaces_observer, self.plot_widget.data_mode.added_group_or_pair_observer ]) # phase table set up self.phase_tab.phase_table_presenter.selected_phasequad_changed_notifier.add_subscriber( self.plot_widget.data_mode.added_group_or_pair_observer) self.phase_tab.phase_table_presenter.selected_phasequad_changed_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.selected_group_pair_observer ) self.phase_tab.phase_table_presenter.selected_phasequad_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. selected_workspaces_observer) self.fitting_tab.fitting_tab_presenter.fit_function_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. fit_function_updated_observer) self.fitting_tab.fitting_tab_presenter.fit_parameter_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. fit_parameter_updated_observer) self.seq_fitting_tab.seq_fitting_tab_presenter.fit_parameter_changed_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter. fit_parameter_updated_observer) self.seq_fitting_tab.seq_fitting_tab_presenter.sequential_fit_finished_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter. sequential_fit_finished_observer) self.fitting_tab.fitting_tab_presenter.fitting_mode_changed_notifier.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. fit_type_changed_observer) self.fitting_tab.fitting_tab_presenter.simultaneous_fit_by_specifier_changed.add_subscriber( self.seq_fitting_tab.seq_fitting_tab_presenter. selected_workspaces_observer) self.fitting_tab.fitting_tab_presenter.selected_fit_results_changed.add_subscriber( self.plot_widget.fit_mode.plot_selected_fit_observer) self.seq_fitting_tab.seq_fitting_tab_presenter.selected_sequential_fit_notifier.add_subscriber( self.plot_widget.fit_mode.plot_selected_fit_observer) #self.model_fitting_tab.model_fitting_tab_presenter.selected_fit_results_changed.add_subscriber( # self.plot_widget.model_fit_mode.plot_selected_fit_observer) #self.model_fitting_tab.model_fitting_tab_presenter.update_plot_x_range_notifier.add_subscriber( # self.plot_widget.model_fit_mode.update_x_range_observer) #self.model_fitting_tab.model_fitting_tab_presenter.update_override_tick_labels_notifier.add_subscriber( # self.plot_widget.model_fit_mode.update_override_tick_labels_observer) def setup_grouping_changed_observers(self): self.grouping_tab_widget.group_tab_presenter.groupingNotifier.add_subscriber( self.home_tab.home_tab_widget.groupingObserver) self.grouping_tab_widget.group_tab_presenter.groupingNotifier.add_subscriber( self.corrections_tab.corrections_tab_presenter. group_change_observer) self.grouping_tab_widget.group_tab_presenter.groupingNotifier.add_subscriber( self.phase_tab.phase_table_presenter.group_change_observer) def setup_corrections_changed_observers(self): self.corrections_tab.corrections_tab_presenter.perform_corrections_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.gui_variables_observer ) def setup_instrument_changed_notifier(self): self.context.data_context.instrumentNotifier.add_subscriber( self.home_tab.home_tab_widget.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.load_widget.load_widget.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.corrections_tab.corrections_tab_presenter. instrument_changed_observer) self.context.data_context.instrumentNotifier.add_subscriber( self.phase_tab.phase_table_presenter.instrument_changed_observer) self.context.data_context.instrumentNotifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.instrument_changed_observer) for observer in self.plot_widget.clear_plot_observers: self.context.data_context.instrumentNotifier.add_subscriber( observer) def setup_group_calculation_enable_notifier(self): self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) self.corrections_tab.corrections_tab_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) self.fitting_tab.fitting_tab_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) self.phase_tab.phase_table_presenter.enable_editing_notifier.add_subscriber( self.enable_observer) #self.model_fitting_tab.model_fitting_tab_presenter.enable_editing_notifier.add_subscriber( # self.enable_observer) def setup_group_calculation_disabler_notifier(self): self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) self.corrections_tab.corrections_tab_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) self.fitting_tab.fitting_tab_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) self.phase_tab.phase_table_presenter.disable_editing_notifier.add_subscriber( self.disable_observer) #self.model_fitting_tab.model_fitting_tab_presenter.disable_editing_notifier.add_subscriber( # self.disable_observer) def setup_on_load_enabler(self): self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.home_tab.home_tab_widget.enable_observer) self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.enable_observer) self.load_widget.load_widget.load_run_widget.enable_notifier.add_subscriber( self.fitting_tab.fitting_tab_view.enable_tab_observer) def setup_on_load_disabler(self): self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.home_tab.home_tab_widget.disable_observer) self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.disable_observer) self.load_widget.load_widget.load_run_widget.disable_notifier.add_subscriber( self.fitting_tab.fitting_tab_view.disable_tab_observer) def setup_counts_calculation_finished_notifier(self): self.grouping_tab_widget.group_tab_presenter.counts_calculation_finished_notifier.add_subscriber( self.corrections_tab.corrections_tab_presenter. pre_process_and_counts_calculated_observer) def setup_asymmetry_pair_and_diff_calculations_finished_notifier(self): self.corrections_tab.corrections_tab_presenter.asymmetry_pair_and_diff_calculations_finished_notifier.\ add_subscriber(self.fitting_tab.fitting_tab_presenter.input_workspace_observer) self.corrections_tab.corrections_tab_presenter.asymmetry_pair_and_diff_calculations_finished_notifier.\ add_subscriber(self.seq_fitting_tab.seq_fitting_tab_presenter.selected_workspaces_observer) for observer in self.plot_widget.data_changed_observers: self.corrections_tab.corrections_tab_presenter.asymmetry_pair_and_diff_calculations_finished_notifier.\ add_subscriber(observer) self.phase_tab.phase_table_presenter.calculation_finished_notifier.add_subscriber( observer) def setup_phase_quad_changed_notifier(self): pass def setup_phase_table_changed_notifier(self): pass def setup_fitting_notifier(self): """Connect fitting and results tabs to inform of new fits""" self.fitting_context.new_fit_results_notifier.add_subscriber( self.results_tab.results_tab_presenter.new_fit_performed_observer) self.fitting_tab.fitting_tab_presenter.remove_plot_guess_notifier.add_subscriber( self.plot_widget.fit_mode.remove_plot_guess_observer) self.fitting_tab.fitting_tab_presenter.update_plot_guess_notifier.add_subscriber( self.plot_widget.fit_mode.update_plot_guess_observer) #self.model_fitting_tab.model_fitting_tab_presenter.remove_plot_guess_notifier.add_subscriber( # self.plot_widget.model_fit_mode.remove_plot_guess_observer) #self.model_fitting_tab.model_fitting_tab_presenter.update_plot_guess_notifier.add_subscriber( # self.plot_widget.model_fit_mode.update_plot_guess_observer) def setup_results_notifier(self): """Connect results tab to the model fitting tab.""" return #self.results_tab.results_tab_presenter.results_table_created_notifier.add_subscriber( # self.model_fitting_tab.model_fitting_tab_presenter.results_table_created_observer) def closeEvent(self, event): self.removeDockWidget(self.dockable_plot_widget_window) self.tabs.closeEvent(event) self.context.ads_observer.unsubscribe() self.grouping_tab_widget.group_tab_presenter.closePeriodInfoWidget() super(MuonAnalysisGui, self).closeEvent(event)