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)
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 __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)
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]) # 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.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, 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.setup_tabs() 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) 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) 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) 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.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.frequency_index else: return self.plot_widget.set_plot_view(plot_mode) def handle_transform_performed(self, new_data_workspace_name): self.fitting_tab.fitting_tab_presenter.handle_new_data_loaded() self.fitting_tab.fitting_tab_presenter.set_selected_dataset( new_data_workspace_name) 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.plot_widget.raw_mode.new_data_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 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)
def __init__(self, parent=None): super(MuonAnalysisGui, self).__init__(parent) self.setFocusPolicy(QtCore.Qt.StrongFocus) 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 = MuonContext(muon_data_context=self.data_context, muon_gui_context=self.gui_context, muon_group_context=self.group_pair_context, muon_phase_context=self.phase_context, fitting_context=self.fitting_context, workspace_suffix=' MA') # create the dockable widget self.dockable_plot_widget = PlottingWidget(self.context) self.dockable_plot_widget_window = PlottingDockWidget( parent=self, plotting_widget=self.dockable_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) # 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.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.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)
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.setFocusPolicy(QtCore.Qt.StrongFocus) 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 = MuonContext(muon_data_context=self.data_context, muon_gui_context=self.gui_context, muon_group_context=self.group_pair_context, muon_phase_context=self.phase_context, fitting_context=self.fitting_context, workspace_suffix=' MA') # create the dockable widget self.dockable_plot_widget = PlottingWidget(self.context) self.dockable_plot_widget_window = PlottingDockWidget( parent=self, plotting_widget=self.dockable_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) # 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.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.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) 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') 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.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.dockable_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.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.grouping_tab_widget.grouping_table_widget.selected_group_changed_notifier.add_subscriber( self.dockable_plot_widget.presenter.added_group_or_pair_observer) self.context.gui_context.gui_variable_non_calulation_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.gui_context_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) 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.dockable_plot_widget.presenter.instrument_observer) def setup_group_calculation_enable_notifier(self): self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.home_tab.home_tab_widget.enable_observer) self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.load_widget.load_widget.enable_observer) self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.enable_tab_observer) def setup_group_calculation_disabler_notifier(self): self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.home_tab.home_tab_widget.disable_observer) self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.load_widget.load_widget.disable_observer) self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.disable_tab_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.dockable_plot_widget.presenter.input_workspace_observer) self.grouping_tab_widget.group_tab_presenter.calculation_finished_notifier.add_subscriber( self.dockable_plot_widget.presenter.rebin_options_set_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.new_fit_plotting_notifier.add_subscriber( self.dockable_plot_widget.presenter.fit_observer) self.fitting_context.fit_removed_notifier.add_subscriber( self.dockable_plot_widget.presenter.fit_removed_observer) self.fitting_context.plot_guess_notifier.add_subscriber( self.dockable_plot_widget.presenter.plot_guess_observer) def closeEvent(self, event): self.tabs.closeEvent(event) self.dockable_plot_widget_window.widget().close() self.removeDockWidget(self.dockable_plot_widget_window) super(MuonAnalysisGui, self).closeEvent(event) self.context.ads_observer = None
def __init__(self, parent=None): super(FrequencyAnalysisGui, self).__init__(parent) self.setFocusPolicy(QtCore.Qt.StrongFocus) 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('Frequency Domain 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.frequency_context = FrequencyContext() self.context = MuonContext(muon_data_context=self.data_context, muon_gui_context=self.gui_context, muon_group_context=self.group_pair_context, muon_phase_context=self.phase_context, fitting_context=self.fitting_context, workspace_suffix=' FD', frequency_context=self.frequency_context) # create the dockable widget self.plot_widget = PlotWidget(self.context) 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. # 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}, {40}, QtCore.Qt.Horizontal) # construct all the widgets. self.load_widget = LoadWidget(self.loaded_data, self.context, self) self.grouping_tab_widget = GroupingTabWidget(self.context) 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.results_tab = ResultsTabWidget(self.context.fitting_context, self.context, self) self.setup_tabs() 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) 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_recalculation_finished_notifier() self.transform.set_up_calculation_observers( self.fitting_tab.fitting_tab_presenter.enable_tab_observer, self.fitting_tab.fitting_tab_presenter.disable_tab_observer) self.transform.new_data_observer( self.fitting_tab.fitting_tab_presenter.input_workspace_observer) self.transform.new_data_observer( self.plot_widget.presenter.input_workspace_observer) self.context.data_context.message_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.message_observer)
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): super(FrequencyAnalysisGui, self).__init__(parent) self.setFocusPolicy(QtCore.Qt.StrongFocus) 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('Frequency Domain 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.frequency_context = FrequencyContext() self.context = MuonContext(muon_data_context=self.data_context, muon_gui_context=self.gui_context, muon_group_context=self.group_pair_context, muon_phase_context=self.phase_context, fitting_context=self.fitting_context, workspace_suffix=' FD', frequency_context=self.frequency_context) # create the dockable widget self.plot_widget = PlotWidget(self.context) 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. # 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}, {40}, QtCore.Qt.Horizontal) # construct all the widgets. self.load_widget = LoadWidget(self.loaded_data, self.context, self) self.grouping_tab_widget = GroupingTabWidget(self.context) 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.results_tab = ResultsTabWidget(self.context.fitting_context, self.context, self) self.setup_tabs() 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) 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_recalculation_finished_notifier() self.transform.set_up_calculation_observers( self.fitting_tab.fitting_tab_presenter.enable_tab_observer, self.fitting_tab.fitting_tab_presenter.disable_tab_observer) self.transform.new_data_observer( self.fitting_tab.fitting_tab_presenter.input_workspace_observer) self.transform.new_data_observer( self.plot_widget.presenter.input_workspace_observer) self.context.data_context.message_notifier.add_subscriber( self.grouping_tab_widget.group_tab_presenter.message_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.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.results_tab.results_tab_view, 'Results') self.current_tab_observer = GenericObserver( self.update_plot_based_on_current_tab) self.tabs.set_slot_for_tab_changed( self.update_plot_based_on_current_tab) def update_plot_based_on_current_tab(self): index = self.tabs.currentIndex() if TAB_ORDER[index] in [ "Home", "Grouping", "Phase Table", "Transform" ]: # Plot all the selected data self.plot_widget.presenter.handle_data_updated() elif TAB_ORDER[index] == "Fitting": # Plot the displayed workspace self.plot_widget.presenter.handle_plot_selected_fits( self.fitting_tab.fitting_tab_presenter. get_selected_fit_workspaces()) 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.transform.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.plot_widget.presenter.plot_type_changed_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.selected_plot_type_observer) self.fitting_tab.fitting_tab_presenter.selected_single_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.transform.GroupPairObserver) 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.transform.instrumentObserver) self.context.data_context.instrumentNotifier.add_subscriber( self.phase_tab.phase_table_presenter.instrument_changed_observer) def setup_group_calculation_enable_notifier(self): self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.home_tab.home_tab_widget.enable_observer) self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.load_widget.load_widget.enable_observer) self.grouping_tab_widget.group_tab_presenter.enable_editing_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.enable_tab_observer) def setup_group_calculation_disabler_notifier(self): self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.home_tab.home_tab_widget.disable_observer) self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.load_widget.load_widget.disable_observer) self.grouping_tab_widget.group_tab_presenter.disable_editing_notifier.add_subscriber( self.fitting_tab.fitting_tab_presenter.disable_tab_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_on_recalculation_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.current_tab_observer) def setup_phase_quad_changed_notifier(self): self.phase_tab.phase_table_presenter.phase_quad_calculation_complete_nofifier.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) 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.tabs.closeEvent(event) self.context.ads_observer.unsubscribe() self.context.ads_observer = None super(FrequencyAnalysisGui, self).closeEvent(event)