diff --git a/scripts/Muon/GUI/Common/fitting_tab_widget/fitting_tab_presenter.py b/scripts/Muon/GUI/Common/fitting_tab_widget/fitting_tab_presenter.py index c7c737a7017cb9d24154a63dffa122989b876b0d..f14dee9123530cc972bb620597842b6f34e0f8b5 100644 --- a/scripts/Muon/GUI/Common/fitting_tab_widget/fitting_tab_presenter.py +++ b/scripts/Muon/GUI/Common/fitting_tab_widget/fitting_tab_presenter.py @@ -78,31 +78,19 @@ class FittingTabPresenter(object): def update_selected_workspace_guess(self): if self.view.fit_type == self.view.simultaneous_fit: - self.update_fit_selector_list() + self.update_fit_specifier_list() if self.manual_selection_made: guess_selection = self.selected_data self.selected_data = guess_selection - elif self.context._frequency_context: - self.update_selected_frequency_workspace_guess() else: - self.update_selected_time_workspace_guess() + self.selected_data = self.get_workspace_selected_list() + + def get_workspace_selected_list(self): + if self.context._frequency_context is not None: + freq = self.context._frequency_context.plot_type + else: + freq = 'None' - def update_selected_frequency_workspace_guess(self): - runs = 'All' - groups_and_pairs = self.context.group_pair_context.selected - if self.view.fit_type == self.view.simultaneous_fit: - if self.view.simultaneous_fit_by == "Run": - runs = self.view.simultaneous_fit_by_specifier - else: - groups_and_pairs = self.view.simultaneous_fit_by_specifier - guess_selection = self.context.get_names_of_workspaces_to_fit( - runs=runs, - group_and_pair=groups_and_pairs, - phasequad=True, - rebin=not self.view.fit_to_raw, freq=self.context._frequency_context.plot_type) - self.selected_data = guess_selection - - def update_selected_time_workspace_guess(self): runs = 'All' groups_and_pairs = self._get_selected_groups_and_pairs() if self.view.fit_type == self.view.simultaneous_fit: @@ -114,13 +102,13 @@ class FittingTabPresenter(object): guess_selection = [] for grppair in groups_and_pairs: guess_selection += self.context.get_names_of_workspaces_to_fit( - runs=runs, - group_and_pair=grppair, - phasequad=False, - rebin=not self.view.fit_to_raw) + runs=runs, + group_and_pair=grppair, + phasequad=False, + rebin=not self.view.fit_to_raw, freq=freq) guess_selection = list(set(self._check_data_exists(guess_selection))) - self.selected_data = guess_selection + return guess_selection def handle_display_workspace_changed(self): current_index = self.view.get_index_for_start_end_times() @@ -149,11 +137,12 @@ class FittingTabPresenter(object): if self.view.fit_type == self.view.simultaneous_fit: self.view.workspace_combo_box_label.setText( 'Display parameters for') - self.view.simul_fit_by_specifier.setVisible(True) - self.update_fit_selector_list() + self.view.simul_fit_by_specifier.setEnabled(True) + self.update_fit_specifier_list() else: + self.update_selected_workspace_guess() self.view.workspace_combo_box_label.setText('Select Workspace') - self.view.simul_fit_by_specifier.setVisible(False) + self.view.simul_fit_by_specifier.setEnabled(False) def handle_plot_guess_changed(self): if self.view.fit_type == self.view.simultaneous_fit: @@ -171,30 +160,31 @@ class FittingTabPresenter(object): self.model.change_plot_guess(self.view.plot_guess, parameters) def fitting_domain_type_changed(self): + # If the fit function has been removed we should remove clear both browsers and the fit information + # and return. + if self._fit_function[0] is None: + self.clear_fit_information() + self.view.function_browser.clear() + self.view.function_browser_multi.clear() + if self.view.fit_type == self.view.simultaneous_fit: - multi_domain_function = self.create_multi_domain_function(self._fit_function) - self._multi_domain_function = multi_domain_function - if multi_domain_function: - self.view.function_browser_multi.blockSignals(True) - self.view.function_browser_multi.setFunction(str(multi_domain_function)) - self.view.function_browser_multi.blockSignals(False) - self._fit_function = [self.view.fit_object] * len(self.selected_data) if self.selected_data else [ - self.view.fit_object] - else: - self._fit_function = [None] * len(self.selected_data) if self.selected_data else [None] self.view.switch_to_simultaneous() - self.clear_fit_information() else: - if self.view.fit_object: - function_list = self.view.function_browser_multi.getGlobalFunction().createEquivalentFunctions() - self._fit_function = function_list - self.view.function_browser.blockSignals(True) - self.view.function_browser.setFunction(str(self._fit_function[0])) - self.view.function_browser.blockSignals(False) - else: - self._fit_function = [None] * len(self.selected_data) if self.selected_data else [None] self.view.switch_to_single() - self.clear_fit_information() + + def sync_single_domain_browser_with_multi_domain_browser(self): + multi_domain_function = self.create_multi_domain_function(self._fit_function) + if multi_domain_function: + self.view.function_browser_multi.blockSignals(True) + self.view.function_browser_multi.setFunction(str(multi_domain_function)) + self.view.function_browser_multi.blockSignals(False) + + def sync_multi_domain_browser_with_single_domain_browser(self): + single_domain_function = self._fit_function[0] + if single_domain_function: + self.view.function_browser.blockSignals(True) + self.view.function_browser.setFunction(str(single_domain_function)) + self.view.function_browser.blockSignals(False) def handle_fit_clicked(self): self.context.fitting_context.number_of_fits = 0 @@ -212,6 +202,7 @@ class FittingTabPresenter(object): self._number_of_fits_cached = 1 simultaneous_fit_parameters = self.get_multi_domain_fit_parameters() global_parameters = self.view.get_global_parameters() + print(simultaneous_fit_parameters) calculation_function = functools.partial( self.model.do_simultaneous_fit, simultaneous_fit_parameters, global_parameters) @@ -347,6 +338,12 @@ class FittingTabPresenter(object): self.view.fit_object) self.model.function_name = self.view.function_name + # resync browsers + if self.view.fit_type == self.view.simultaneous_fit: + self.sync_multi_domain_browser_with_single_domain_browser() + else: + self.sync_single_domain_browser_with_multi_domain_browser() + def handle_tf_asymmetry_mode_changed(self): def calculate_tf_fit_function(original_fit_function): tf_asymmetry_parameters = self.get_parameters_for_tf_function_calculation(original_fit_function) @@ -426,26 +423,27 @@ class FittingTabPresenter(object): def handle_fit_by_changed(self): if self.view.fit_type == self.view.simultaneous_fit: - self.update_fit_selector_list() self.update_selected_workspace_guess() if self.view.simultaneous_fit_by == "Custom": - self.view.simul_fit_by_specifier.setVisible(False) - self.view.select_workspaces_to_fit_button.setVisible(True) + self.view.simul_fit_by_specifier.setEnabled(False) + self.view.select_workspaces_to_fit_button.setEnabled(True) else: - self.view.simul_fit_by_specifier.setVisible(True) - self.view.select_workspaces_to_fit_button.setVisible(False) + self.view.simul_fit_by_specifier.setEnabled(True) + self.view.select_workspaces_to_fit_button.setEnabled(False) else: return def handle_fit_specifier_changed(self): - self.update_selected_workspace_guess() + self.selected_data = self.get_workspace_selected_list() - def update_fit_selector_list(self): + def update_fit_specifier_list(self): if self.view.simultaneous_fit_by == "Run": flattened_run_list = [str(item) for sublist in self.context.data_context.current_runs for item in sublist] simul_choices = flattened_run_list - else: + elif self.view.simultaneous_fit_by == "Group/Pair": simul_choices = self._get_selected_groups_and_pairs() + else: + simul_choices = self.selected_data self.view.setup_fit_by_specifier(simul_choices) diff --git a/scripts/Muon/GUI/Common/fitting_tab_widget/fitting_tab_view.py b/scripts/Muon/GUI/Common/fitting_tab_widget/fitting_tab_view.py index 8558076bb088ebe99e471fbbb5cfdab22ef485fa..458beb77d34fc140fce9b6d5a9567e852a489312 100644 --- a/scripts/Muon/GUI/Common/fitting_tab_widget/fitting_tab_view.py +++ b/scripts/Muon/GUI/Common/fitting_tab_widget/fitting_tab_view.py @@ -38,7 +38,7 @@ class FittingTabView(QtWidgets.QWidget, ui_fitting_tab): self.increment_parameter_display_button.clicked.connect(self.increment_display_combo_box) self.decrement_parameter_display_button.clicked.connect(self.decrement_display_combo_box) - self.select_workspaces_to_fit_button.setVisible(False) + self.select_workspaces_to_fit_button.setEnabled(False) def update_displayed_data_combo_box(self, data_list): self.parameter_display_combo.blockSignals(True) @@ -77,7 +77,7 @@ class FittingTabView(QtWidgets.QWidget, ui_fitting_tab): self.simul_fit_by_combo.addItem("Run") self.simul_fit_by_combo.addItem("Group/Pair") self.simul_fit_by_combo.addItem("Custom") - self.simul_fit_by_specifier.setVisible(False) + self.simul_fit_by_specifier.setEnabled(False) def set_datasets_in_function_browser(self, data_set_name_list): number_of_data_sets = self.function_browser.getNumberOfDatasets() @@ -278,6 +278,7 @@ class FittingTabView(QtWidgets.QWidget, ui_fitting_tab): self.simul_fit_by_specifier.clear() self.simul_fit_by_specifier.addItems(choices) self.simul_fit_by_specifier.blockSignals(False) + self.simul_fit_by_specifier.currentIndexChanged.emit(0) def setup_fit_options_table(self): self.fit_options_table.setRowCount(6) diff --git a/scripts/test/Muon/fitting_tab_widget/fitting_tab_presenter_test.py b/scripts/test/Muon/fitting_tab_widget/fitting_tab_presenter_test.py index e09b830519ab73fb5e5d305fe709e9d37d5bdb64..6a58c69367f193a93ac40b7435ce08db8c6f8307 100644 --- a/scripts/test/Muon/fitting_tab_widget/fitting_tab_presenter_test.py +++ b/scripts/test/Muon/fitting_tab_widget/fitting_tab_presenter_test.py @@ -18,7 +18,7 @@ EXAMPLE_TF_ASYMMETRY_FUNCTION = '(composite=ProductFunction,NumDeriv=false;name= '(name=FlatBackground,A0=1,ties=(A0=1);name=ExpDecayOsc,A=0.2,Lambda=0.2,Frequency=0.1,Phi=0))' \ ';name=ExpDecayMuon,A=0,Lambda=-2.19698,ties=(A=0,Lambda=-2.19698)' -SIMUL_FIT_BY_COMBO_MAP = {"Run": 0, "Group/Pair": 1} +SIMUL_FIT_BY_COMBO_MAP = {"Run": 0, "Group/Pair": 1, "Custom": 2} def retrieve_combobox_info(combo_box): @@ -116,9 +116,11 @@ class FittingTabPresenterTest(unittest.TestCase): def test_fit_clicked_with_simultaneous_selected_and_no_globals(self): self.presenter.model.get_function_name.return_value = 'GausOsc' - self.presenter.selected_data = ['Input Workspace Name_1', 'Input Workspace Name 2'] + self.presenter.get_workspace_selected_list = mock.MagicMock( + return_value=['Input Workspace Name_1', 'Input Workspace Name 2']) self.view.function_browser.setFunction('name=GausOsc,A=0.2,Sigma=0.2,Frequency=0.1,Phi=0') self.view.simul_fit_checkbox.setChecked(True) + print("FIT FUNCTION", self.view.function_browser_multi.getGlobalFunction()) self.presenter.model.do_simultaneous_fit.return_value = (self.view.function_browser_multi.getGlobalFunction(), 'Fit Suceeded', 0.5) @@ -138,8 +140,8 @@ class FittingTabPresenterTest(unittest.TestCase): def test_fit_clicked_with_simultaneous_selected_with_global_parameters(self): self.presenter.model.get_function_name.return_value = 'GausOsc' - - self.presenter.selected_data = ['Input Workspace Name_1', 'Input Workspace Name 2'] + self.presenter.get_workspace_selected_list = mock.MagicMock( + return_value=['Input Workspace Name_1', 'Input Workspace Name 2']) self.view.function_browser.setFunction('name=GausOsc,A=0.2,Sigma=0.2,Frequency=0.1,Phi=0') self.view.simul_fit_checkbox.setChecked(True) self.view.function_browser_multi.setGlobalParameters(['A']) @@ -493,6 +495,9 @@ class FittingTabPresenterTest(unittest.TestCase): self.presenter.selected_data = ['MUSR22725; Group; top; Asymmetry', 'MUSR22725; Group; bottom; Asymmetry', 'MUSR22725; Group; fwd; Asymmetry'] self.view.function_browser.setFunction('name=GausOsc,A=0.2,Sigma=0.2,Frequency=0.1,Phi=0') + self.presenter.get_workspace_selected_list = mock.MagicMock( + return_value=['MUSR22725; Group; top; Asymmetry', 'MUSR22725; Group; bottom; Asymmetry', + 'MUSR22725; Group; fwd; Asymmetry']) self.view.simul_fit_checkbox.setChecked(True) @@ -510,7 +515,7 @@ class FittingTabPresenterTest(unittest.TestCase): self.view.simul_fit_checkbox.setChecked(False) self.assertEqual([str(item) for item in self.presenter._fit_function], [ - 'name=GausOsc,A=0.2,Sigma=0.2,Frequency=0.1,Phi=0'] * 3) + 'name=GausOsc,A=0.2,Sigma=0.2,Frequency=0.1,Phi=0']) def test_undo_fit_button_disabled_until_a_succesful_fit_is_performed(self): self.assertEqual(self.view.undo_fit_button.isEnabled(), False) @@ -570,16 +575,10 @@ class FittingTabPresenterTest(unittest.TestCase): def test_update_selected_ws_guess(self): self.presenter.manual_selection_made = False - self.presenter.update_selected_time_workspace_guess = mock.Mock() - self.presenter.update_selected_workspace_guess() - self.assertEquals(self.presenter.update_selected_time_workspace_guess.call_count, 1) - - def test_update_selected_ws_guess_freq(self): - self.presenter.manual_selection_made = False - self.presenter.context._frequency_context = True - self.presenter.update_selected_frequency_workspace_guess = mock.Mock() + self.presenter.get_workspace_selected_list = mock.Mock() + self.presenter.clear_and_reset_gui_state = mock.Mock() self.presenter.update_selected_workspace_guess() - self.assertEquals(self.presenter.update_selected_frequency_workspace_guess.call_count, 1) + self.assertEquals(self.presenter.get_workspace_selected_list.call_count, 1) def test_update_selected_ws_guess_non(self): self.presenter.manual_selection_made = True @@ -600,14 +599,15 @@ class FittingTabPresenterTest(unittest.TestCase): self.presenter._get_selected_groups_and_pairs = mock.Mock(return_value=["fwd", "bwd"]) self.presenter.clear_and_reset_gui_state = mock.Mock() self.presenter._check_data_exists = mock.Mock(return_value=["test"]) - output = self.presenter.update_selected_time_workspace_guess() + + output = self.presenter.get_workspace_selected_list() self.context.get_names_of_workspaces_to_fit.assert_any_call(runs="All", group_and_pair="bwd", phasequad=False, - rebin=False) + rebin=False, freq='None') self.context.get_names_of_workspaces_to_fit.assert_any_call(runs="All", group_and_pair="fwd", phasequad=False, - rebin=False) + rebin=False, freq='None') self.assertEquals(self.presenter.context.get_names_of_workspaces_to_fit.call_count, 2) - self.assertEquals(self.presenter.selected_data, ["test"]) + self.assertEquals(output, ["test"]) def test_handle_plot_guess_changed_calls_correct_function(self): self.presenter.get_parameters_for_single_fit = mock.Mock(return_value={}) @@ -622,13 +622,13 @@ class FittingTabPresenterTest(unittest.TestCase): self.view.setup_fit_options_table() self.assertEqual(-1, self.view.minimizer_combo.findText('FABADA')) - def test_simul_fit_by_selector_updates_correctly_when_fit_change_to_simultanenous(self): + def test_simul_fit_by_specifier_updates_correctly_when_fit_change_to_simultanenous(self): # test simul fit by Run self.view.simul_fit_by_combo.setCurrentIndex(SIMUL_FIT_BY_COMBO_MAP["Run"]) self.view.simul_fit_checkbox.setChecked(True) - self.assertEqual(str(self.view.simul_fit_by_selector.itemText(0)), str(self.loaded_run)) + self.assertEqual(str(self.view.simul_fit_by_specifier.itemText(0)), str(self.loaded_run)) # simul fit by Group/Pair self.view.simul_fit_by_combo.setCurrentIndex(SIMUL_FIT_BY_COMBO_MAP["Group/Pair"]) @@ -636,18 +636,18 @@ class FittingTabPresenterTest(unittest.TestCase): self.presenter.handle_fit_type_changed() - self.assertEqual(str(self.view.simul_fit_by_selector.itemText(0)), "fwd") - self.assertEqual(str(self.view.simul_fit_by_selector.itemText(1)), "bwd") + self.assertEqual(str(self.view.simul_fit_by_specifier.itemText(0)), "fwd") + self.assertEqual(str(self.view.simul_fit_by_specifier.itemText(1)), "bwd") - def test_simul_fit_by_selector_updates_when_simul_fit_type_changes(self): + def test_simul_fit_by_specifier_updates_when_simul_fit_type_changes(self): self.view.simul_fit_checkbox.setChecked(True) - self.presenter.update_fit_selector_list = mock.MagicMock() + self.presenter.update_fit_specifier_list = mock.MagicMock() self.view.simul_fit_by_combo.setCurrentIndex(SIMUL_FIT_BY_COMBO_MAP["Group/Pair"]) - self.presenter.update_fit_selector_list.assert_called_once() + self.presenter.update_fit_specifier_list.assert_called_once() - def test_simul_fit_by_selector_does_nothing_when_simul_fit_type_changes_but_not_doing_simul_fit(self): + def test_simul_fit_by_specifier_does_nothing_when_simul_fit_type_changes_but_not_doing_simul_fit(self): self.view.simul_fit_checkbox.setChecked(False) self.presenter.update_fit_selector_list = mock.MagicMock() @@ -655,7 +655,7 @@ class FittingTabPresenterTest(unittest.TestCase): self.presenter.update_fit_selector_list.assert_not_called() - def test_simul_fit_by_selector_updates_list_correctly_when_simul_fit_type_changes(self): + def test_simul_fit_by_selector_updates_fit_specifier_correctly_when_simul_fit_type_changes(self): self.view.simul_fit_checkbox.setChecked(True) self.view.simul_fit_by_combo.setCurrentIndex(SIMUL_FIT_BY_COMBO_MAP["Run"]) self.presenter._get_selected_groups_and_pairs = mock.Mock(return_value=["fwd", "bwd"]) @@ -663,8 +663,20 @@ class FittingTabPresenterTest(unittest.TestCase): # now switch to group/pair self.view.simul_fit_by_combo.setCurrentIndex(SIMUL_FIT_BY_COMBO_MAP["Group/Pair"]) - self.assertEqual(str(self.view.simul_fit_by_selector.itemText(0)), "fwd") - self.assertEqual(str(self.view.simul_fit_by_selector.itemText(1)), "bwd") + self.assertEqual(str(self.view.simul_fit_by_specifier.itemText(0)), "fwd") + self.assertEqual(str(self.view.simul_fit_by_specifier.itemText(1)), "bwd") + + def test_simul_fit_by_specifier_correctly_updates_display_combobox(self): + self.view.simul_fit_checkbox.setChecked(True) + self.presenter.get_workspace_selected_list = mock.MagicMock(return_value=['WS1', 'WS2']) + + self.view.simul_fit_by_combo.setCurrentIndex(SIMUL_FIT_BY_COMBO_MAP["Group/Pair"]) + + self.assertEqual(str(self.view.parameter_display_combo.itemText(0)), "WS1") + self.assertEqual(str(self.view.parameter_display_combo.itemText(1)), "WS2") + + def test_simul_fit_by_specifier_corretcly_selects_workspaces_for_fit(self): + pass if __name__ == '__main__':