Exemple #1
0
 def notify_subscribers(self, *args, **kwargs):
     Observable.notify_subscribers(self, *args, **kwargs)
 def notify_subscribers(self, arg=["", "", ""]):
     Observable.notify_subscribers(self, arg)
Exemple #3
0
class PhaseTablePresenter(object):
    def __init__(self, view, context):
        self.view = view
        self.context = context
        self.current_alg = None

        self.group_change_observer = GenericObserver(
            self.update_current_groups_list)
        self.run_change_observer = GenericObserver(
            self.update_current_run_list)
        self.instrument_changed_observer = GenericObserver(
            self.update_current_phase_tables)

        self.phase_table_calculation_complete_notifier = Observable()
        self.phase_quad_calculation_complete_nofifier = Observable()

        self.update_current_phase_tables()

    def update_view_from_model(self):
        for key, item in self.context.phase_context.options_dict.items():
            setattr(self.view, key, item)

    def update_model_from_view(self):
        for key in self.context.phase_context.options_dict:
            self.context.phase_context.options_dict[key] = getattr(
                self.view, key, None)

    def cancel(self):
        if self.current_alg is not None:
            self.current_alg.cancel()

    def handle_calulate_phase_table_clicked(self):
        self.update_model_from_view()

        self.calculation_thread = self.create_calculation_thread()

        self.calculation_thread.threadWrapperSetUp(
            self.handle_phase_table_calculation_started,
            self.handle_calculation_success, self.handle_calculation_error)

        self.calculation_thread.start()

    def create_calculation_thread(self):
        self._calculation_model = ThreadModelWrapper(
            self.calculate_phase_table)
        return thread_model.ThreadModel(self._calculation_model)

    def handle_calculate_phase_quad_button_clicked(self):
        self.update_model_from_view()

        self.phasequad_calculation_thread = self.create_phase_quad_calculation_thread(
        )

        self.phasequad_calculation_thread.threadWrapperSetUp(
            self.handle_calculation_started, self.handle_calculation_success,
            self.handle_calculation_error)

        self.phasequad_calculation_thread.start()

    def create_phase_quad_calculation_thread(self):
        self._phasequad_calculation_model = ThreadModelWrapper(
            self.calculate_phase_quad)
        return thread_model.ThreadModel(self._phasequad_calculation_model)

    def calculate_phase_quad(self):
        parameters = self.get_parameters_for_phase_quad()

        self.current_alg = mantid.AlgorithmManager.create("PhaseQuad")
        phase_quad = run_PhaseQuad(parameters, self.current_alg)
        self.current_alg = None

        self.add_phase_quad_to_ADS(parameters['InputWorkspace'],
                                   parameters['PhaseTable'], phase_quad)

    def get_parameters_for_phase_quad(self):
        parameters = {}
        if self.context.phase_context.options_dict[
                'phase_table_for_phase_quad'] == 'Construct':
            parameters['PhaseTable'] = self.calculate_phase_table()
        else:
            parameters['PhaseTable'] = self.context.phase_context.options_dict[
                'phase_table_for_phase_quad']

        parameters['InputWorkspace'] = self.context.phase_context.options_dict[
            'phase_quad_input_workspace']

        return parameters

    def add_phase_quad_to_ADS(self, input_workspace, input_phase_table,
                              phase_quad):
        run = re.search('[0-9]+', input_workspace).group()
        phasequad_workspace_name = get_phase_quad_workspace_name(
            input_workspace, input_phase_table)
        phase_table_group = get_phase_table_workspace_group_name(
            phasequad_workspace_name, self.context.data_context.instrument)
        directory = get_base_data_directory(self.context,
                                            run) + phase_table_group

        muon_workspace_wrapper = MuonWorkspaceWrapper(
            phase_quad, directory + phasequad_workspace_name)
        muon_workspace_wrapper.show()

        self.context.phase_context.add_phase_quad(muon_workspace_wrapper)
        self.phase_quad_calculation_complete_nofifier.notify_subscribers()

    def handle_calculation_started(self):
        self.view.disable_widget()
        self.view.enable_phasequad_cancel()

    def handle_phase_table_calculation_started(self):
        self.view.disable_widget()
        self.view.enable_cancel()

    def handle_calculation_error(self, error):
        self.view.enable_widget()
        self.view.warning_popup(error)
        self.view.disable_cancel()
        self.current_alg = None

    def handle_calculation_success(self):
        self.phase_table_calculation_complete_notifier.notify_subscribers()
        self.update_current_phase_tables()
        self.view.enable_widget()
        self.view.disable_cancel()
        self.current_alg = None

    def calculate_phase_table(self):
        parameters = self.create_parameters_for_cal_muon_phase_algorithm()

        self.current_alg = mantid.AlgorithmManager.create(
            "CalMuonDetectorPhases")
        detector_table, fitting_information = run_CalMuonDetectorPhases(
            parameters, self.current_alg)
        self.current_alg = None

        self.add_phase_table_to_ADS(parameters['DetectorTable'],
                                    detector_table)
        self.add_fitting_info_to_ADS_if_required(parameters['DetectorTable'],
                                                 fitting_information)

        return parameters['DetectorTable']

    def add_phase_table_to_ADS(self, base_name, detector_table):
        run = re.search('[0-9]+', base_name).group()

        phase_table_group = get_phase_table_workspace_group_name(
            base_name, self.context.data_context.instrument)
        directory = get_base_data_directory(self.context,
                                            run) + phase_table_group
        muon_workspace_wrapper = MuonWorkspaceWrapper(detector_table,
                                                      directory + base_name)
        muon_workspace_wrapper.show()

        self.context.phase_context.add_phase_table(muon_workspace_wrapper)

    def add_fitting_info_to_ADS_if_required(self, base_name,
                                            fitting_information):
        if not self.view.output_fit_information:
            return

        run = re.search('[0-9]+', base_name).group()
        phase_table_group = get_phase_table_workspace_group_name(
            base_name, self.context.data_context.instrument)
        fitting_workspace_name = get_fitting_workspace_name(base_name)
        directory = get_base_data_directory(self.context,
                                            run) + phase_table_group

        muon_workspace_wrapper = MuonWorkspaceWrapper(
            fitting_information, directory + fitting_workspace_name)
        muon_workspace_wrapper.show()

    def create_parameters_for_cal_muon_phase_algorithm(self):
        parameters = {}

        parameters['FirstGoodData'] = self.context.phase_context.options_dict[
            'first_good_time']
        parameters['LastGoodData'] = self.context.phase_context.options_dict[
            'last_good_time']

        parameters['InputWorkspace'] = self.context.phase_context.options_dict[
            'input_workspace']

        forward_group = self.context.phase_context.options_dict[
            'forward_group']
        parameters['ForwardSpectra'] = self.context.group_pair_context[
            forward_group].detectors

        backward_group = self.context.phase_context.options_dict[
            'backward_group']
        parameters['BackwardSpectra'] = self.context.group_pair_context[
            backward_group].detectors

        parameters['DetectorTable'] = parameters['InputWorkspace'].replace(
            '_raw_data', '') + "; PhaseTable"

        parameters['DetectorTable'] = get_phase_table_workspace_name(
            parameters['InputWorkspace'], forward_group, backward_group)

        return parameters

    def update_current_run_list(self):
        self.view.set_input_combo_box(self.context.getGroupedWorkspaceNames())
        self.view.set_group_combo_boxes(
            self.context.group_pair_context.group_names)
        self.update_model_from_view()

    def update_current_groups_list(self):
        self.view.set_group_combo_boxes(
            self.context.group_pair_context.group_names)
        self.update_model_from_view()

    def update_current_phase_tables(self):
        phase_table_list = self.context.phase_context.get_phase_table_list(
            self.context.data_context.instrument)
        phase_table_list.append('Construct')

        self.view.set_phase_table_combo_box(phase_table_list)
Exemple #4
0
class MuonContext(object):
    def __init__(self,
                 muon_data_context=None,
                 muon_gui_context=None,
                 muon_group_context=None,
                 base_directory='Muon Data',
                 muon_phase_context=None,
                 workspace_suffix=' MA',
                 fitting_context=None):

        self._data_context = muon_data_context
        self._gui_context = muon_gui_context
        self._group_pair_context = muon_group_context
        self._phase_context = muon_phase_context
        self.fitting_context = fitting_context
        self.base_directory = base_directory
        self.workspace_suffix = workspace_suffix
        self.ads_observer = MuonContextADSObserver(
            self.remove_workspace_by_name, self.clear_context)

        self.gui_context.update({
            'DeadTimeSource': 'None',
            'LastGoodDataFromFile': True,
            'selected_group_pair': ''
        })

        self.update_view_from_model_notifier = Observable()

    @property
    def data_context(self):
        return self._data_context

    @property
    def gui_context(self):
        return self._gui_context

    @property
    def group_pair_context(self):
        return self._group_pair_context

    @property
    def phase_context(self):
        return self._phase_context

    def calculate_group(self, group_name, run, rebin=False):
        group_workspace = calculate_group_data(self, group_name, run, rebin)
        group_asymmetry, group_asymmetry_unnormalised = estimate_group_asymmetry_data(
            self, group_name, run, rebin)

        return group_workspace, group_asymmetry, group_asymmetry_unnormalised

    def calculate_pair(self, pair_name, run, rebin=False):
        return calculate_pair_data(self, pair_name, run, rebin)

    def show_all_groups(self):
        self.calculate_all_groups()
        for run in self._data_context.current_runs:
            for group_name in self._group_pair_context.group_names:
                run_as_string = run_list_to_string(run)
                directory = get_base_data_directory(
                    self, run_as_string) + get_group_data_directory(
                        self, run_as_string)

                name = get_group_data_workspace_name(self,
                                                     group_name,
                                                     run_as_string,
                                                     rebin=False)
                asym_name = get_group_asymmetry_name(self,
                                                     group_name,
                                                     run_as_string,
                                                     rebin=False)
                asym_name_unnorm = get_group_asymmetry_unnorm_name(
                    self, group_name, run_as_string, rebin=False)

                self.group_pair_context[group_name].show_raw(
                    run, directory + name, directory + asym_name,
                    asym_name_unnorm)

                if self._do_rebin():
                    name = get_group_data_workspace_name(self,
                                                         group_name,
                                                         run_as_string,
                                                         rebin=True)
                    asym_name = get_group_asymmetry_name(self,
                                                         group_name,
                                                         run_as_string,
                                                         rebin=True)
                    asym_name_unnorm = get_group_asymmetry_unnorm_name(
                        self, group_name, run_as_string, rebin=True)

                    self.group_pair_context[group_name].show_rebin(
                        run, directory + name, directory + asym_name,
                        asym_name_unnorm)

    def show_all_pairs(self):
        self.calculate_all_pairs()
        for run in self._data_context.current_runs:
            for pair_name in self._group_pair_context.pair_names:
                run_as_string = run_list_to_string(run)
                name = get_pair_data_workspace_name(self,
                                                    pair_name,
                                                    run_as_string,
                                                    rebin=False)
                directory = get_base_data_directory(
                    self, run_as_string) + get_pair_data_directory(
                        self, run_as_string)

                self.group_pair_context[pair_name].show_raw(
                    run, directory + name)

                if self._do_rebin():
                    name = get_pair_data_workspace_name(self,
                                                        pair_name,
                                                        run_as_string,
                                                        rebin=True)
                    self.group_pair_context[pair_name].show_rebin(
                        run, directory + name)

    def calculate_all_pairs(self):
        for run in self._data_context.current_runs:
            for pair_name in self._group_pair_context.pair_names:
                pair_asymmetry_workspace = self.calculate_pair(pair_name, run)
                self.group_pair_context[pair_name].update_asymmetry_workspace(
                    pair_asymmetry_workspace, run)

                if self._do_rebin():
                    pair_asymmetry_workspace = self.calculate_pair(pair_name,
                                                                   run,
                                                                   rebin=True)
                    self.group_pair_context[
                        pair_name].update_asymmetry_workspace(
                            pair_asymmetry_workspace, run, rebin=True)

    def calculate_all_groups(self):
        for run in self._data_context.current_runs:
            for group_name in self._group_pair_context.group_names:
                group_workspace, group_asymmetry, group_asymmetry_unormalised = self.calculate_group(
                    group_name, run)
                self.group_pair_context[group_name].update_workspaces(
                    run,
                    group_workspace,
                    group_asymmetry,
                    group_asymmetry_unormalised,
                    rebin=False)

                if self._do_rebin():
                    group_workspace, group_asymmetry, group_asymmetry_unormalised = self.calculate_group(
                        group_name, run, rebin=True)
                    self.group_pair_context[group_name].update_workspaces(
                        run,
                        group_workspace,
                        group_asymmetry,
                        group_asymmetry_unormalised,
                        rebin=True)

    def update_current_data(self):
        # Update the current data; resetting the groups and pairs to their default values
        if len(self.data_context.current_runs) > 0:
            self.data_context.update_current_data()

            if not self.group_pair_context.groups:
                self.group_pair_context.reset_group_and_pairs_to_default(
                    self.data_context.current_workspace,
                    self.data_context.instrument,
                    self.data_context.main_field_direction)
        else:
            self.data_context.clear()

    def show_raw_data(self):
        for run in self.data_context.current_runs:
            run_string = run_list_to_string(run)
            loaded_workspace = self.data_context._loaded_data.get_data(
                run=run, instrument=self.data_context.instrument
            )['workspace']['OutputWorkspace']
            directory = get_base_data_directory(
                self, run_string) + get_raw_data_directory(self, run_string)

            if len(loaded_workspace) > 1:
                # Multi-period data
                for i, single_ws in enumerate(loaded_workspace):
                    name = directory + get_raw_data_workspace_name(
                        self, run_string, period=str(i + 1))
                    single_ws.show(name)
            else:
                # Single period data
                name = directory + get_raw_data_workspace_name(
                    self, run_string)
                loaded_workspace[0].show(name)

    def _do_rebin(self):
        return (self.gui_context['RebinType'] == 'Fixed' and
                'RebinFixed' in self.gui_context and self.gui_context['RebinFixed']) or\
               (self.gui_context['RebinType'] == 'Variable' and
                'RebinVariable' in self.gui_context and self.gui_context['RebinVariable'])

    def get_workspace_names_for_FFT_analysis(self, use_raw=True):
        workspace_options = self.get_names_of_workspaces_to_fit(
            runs='All',
            group_and_pair='All',
            phasequad=True,
            rebin=not use_raw)
        return workspace_options

    def get_detectors_excluded_from_default_grouping_tables(self):
        groups, _, _ = get_default_grouping(
            self.data_context.current_workspace, self.data_context.instrument,
            self.data_context.main_field_direction)
        detectors_in_group = []
        for group in groups:
            detectors_in_group += group.detectors
        detectors_in_group = set(detectors_in_group)

        return [
            det for det in range(1, self.data_context.num_detectors)
            if det not in detectors_in_group
        ]

    # Get the groups/pairs for active WS
    def getGroupedWorkspaceNames(self):
        run_numbers = self.data_context.current_runs
        runs = [
            wsName.get_raw_data_workspace_name(self,
                                               run_list_to_string(run_number),
                                               period=str(period + 1))
            for run_number in run_numbers
            for period in range(self.data_context.num_periods(run_number))
        ]
        return runs

    def first_good_data(self, run):
        if not self.data_context.get_loaded_data_for_run(run):
            return 0.0

        if self.gui_context['FirstGoodDataFromFile']:
            return self.data_context.get_loaded_data_for_run(
                run)["FirstGoodData"]
        else:
            if 'FirstGoodData' in self.gui_context:
                return self.gui_context['FirstGoodData']
            else:
                self.gui_context[
                    'FirstGoodData'] = self.data_context.get_loaded_data_for_run(
                        run)["FirstGoodData"]
                return self.gui_context['FirstGoodData']

    def last_good_data(self, run):
        if not self.data_context.get_loaded_data_for_run(run):
            return 0.0

        if self.gui_context['LastGoodDataFromFile']:
            return round(
                max(
                    self.data_context.get_loaded_data_for_run(run)
                    ["OutputWorkspace"][0].workspace.dataX(0)), 2)
        else:
            if 'LastGoodData' in self.gui_context:
                return self.gui_context['LastGoodData']
            else:
                self.gui_context['LastGoodData'] = round(
                    max(
                        self.data_context.get_loaded_data_for_run(run)
                        ["OutputWorkspace"][0].workspace.dataX(0)), 2)
                return self.gui_context['LastGoodData']

    def dead_time_table(self, run):
        if self.gui_context['DeadTimeSource'] == 'FromADS':
            return self.gui_context['DeadTimeTable']
        elif self.gui_context['DeadTimeSource'] == 'FromFile':
            return self.data_context.get_loaded_data_for_run(
                run)["DataDeadTimeTable"]
        elif self.gui_context['DeadTimeSource'] == 'None':
            return None

    def get_names_of_workspaces_to_fit(self,
                                       runs='',
                                       group_and_pair='',
                                       phasequad=False,
                                       rebin=False):
        if group_and_pair == 'All':
            group = self.group_pair_context.group_names
            pair = self.group_pair_context.pair_names
        else:
            group_pair_list = group_and_pair.replace(' ', '').split(',')
            group = [
                group for group in group_pair_list
                if group in self.group_pair_context.group_names
            ]
            pair = [
                pair for pair in group_pair_list
                if pair in self.group_pair_context.pair_names
            ]

        if runs == 'All':
            run_list = self.data_context.current_runs
        else:
            run_list = [
                run_string_to_list(item)
                for item in runs.replace(' ', '').split(',')
            ]
            flat_list = []
            for sublist in run_list:
                flat_list += [[run] for run in sublist if len(sublist) > 1]
            run_list += flat_list
            run_list = [
                run for run in run_list
                if run in self.data_context.current_runs
            ]

        group_names = self.group_pair_context.get_group_workspace_names(
            run_list, group, rebin)
        pair_names = self.group_pair_context.get_pair_workspace_names(
            run_list, pair, rebin)

        phasequad_names = []
        if phasequad:
            for run in run_list:
                run_string = run_list_to_string(run)
                phasequad_names += self.phase_context.get_phase_quad(
                    self.data_context.instrument, run_string)

        return group_names + pair_names + phasequad_names

    def get_list_of_binned_or_unbinned_workspaces_from_equivalents(
            self, input_list):
        equivalent_list = []

        for item in input_list:
            if 'PhaseQuad' in item:
                equivalent_list.append(item)

            equivalent_group_pair = self.group_pair_context.get_equivalent_group_pair(
                item)
            if equivalent_group_pair:
                equivalent_list.append(equivalent_group_pair)

        return equivalent_list

    def remove_workspace_by_name(self, workspace_name):
        self.data_context.remove_workspace_by_name(workspace_name)
        self.group_pair_context.remove_workspace_by_name(workspace_name)
        self.phase_context.remove_workspace_by_name(workspace_name)
        self.fitting_context.remove_workspace_by_name(workspace_name)
        self.update_view_from_model_notifier.notify_subscribers(workspace_name)

    def clear_context(self):
        self.data_context.clear()
        self.group_pair_context.clear()
        self.phase_context.clear()
        self.fitting_context.clear()
        self.update_view_from_model_notifier.notify_subscribers()
Exemple #5
0
 def notify_subscribers(self, arg=["", "", ""]):
     Observable.notify_subscribers(self, arg)
Exemple #6
0
class FittingContext(object):
    """Context specific to fitting.

    It holds details are any fits performed including:
       - input workspaces
       - parameters
       - function names
    """
    def __init__(self, fit_list=None):
        self.fit_list = fit_list if fit_list is not None else []
        # Register callbacks with this object to observe when new fits
        # are added
        self.new_fit_notifier = Observable()
        self._number_of_fits = 0
        self._number_of_fits_cache = 0

    def __len__(self):
        """
        :return: The number of fits in the list
        """
        return len(self.fit_list)

    def add_fit_from_values(self,
                            parameter_workspace,
                            fit_function_name,
                            input_workspace,
                            output_workspace_names,
                            global_parameters=None):
        """
        Add a new fit information object based on the raw values.
        See FitInformation constructor for details are arguments.
        """
        self.add_fit(
            FitInformation(parameter_workspace, fit_function_name,
                           input_workspace, output_workspace_names,
                           global_parameters))

    def add_fit(self, fit):
        """
        Add a new fit to the context. Subscribers are notified of the update.
        :param fit: A new FitInformation object
        """
        if fit in self.fit_list:
            self.fit_list.pop(self.fit_list.index(fit))
        self.fit_list.append(fit)
        self._number_of_fits += 1
        self.new_fit_notifier.notify_subscribers()

    def fit_function_names(self):
        """
        :return: a list of unique function names used in the fit
        """
        return list(set([fit.fit_function_name for fit in self.fit_list]))

    def find_output_workspaces_for_input_workspace_name(
            self, input_workspace_name):
        """
        Find the fits in the list whose input workspace matches
        :param input_workspace_name: The name of the input_workspace
        :return: A list of matching fits
        """
        workspace_list = []
        for fit in self.fit_list:
            for index, workspace in enumerate(fit.input_workspaces):
                if workspace == input_workspace_name:
                    workspace_list.append(fit.output_workspace_names[index])

        return workspace_list

    def remove_workspace_by_name(self, workspace_name):
        list_of_fits_to_remove = []
        for fit in self.fit_list:
            if workspace_name in fit.output_workspace_names or workspace_name == fit.parameter_workspace_name:
                self._number_of_fits_cache = 0
                list_of_fits_to_remove.append(fit)

        for fit in list_of_fits_to_remove:
            index = self.fit_list.index(fit)
            if index >= len(self.fit_list) - self._number_of_fits:
                self._number_of_fits -= 1
            self.fit_list.remove(fit)

    def log_names(self, filter_fn=None):
        """
        The names of the logs on the workspaces associated with all of the workspaces.

        :filter_fn: An optional unary function to filter the names out. For more information see
        FitInformation.log_names
        :return: A list of names of logs
        """
        return [
            name for fit in self.fit_list for name in fit.log_names(filter_fn)
        ]

    def clear(self):
        self.fit_list = []

    def remove_latest_fit(self, number_of_fits_to_remove):
        self.fit_list = self.fit_list[:-number_of_fits_to_remove]
        self._number_of_fits = self._number_of_fits_cache
        self.new_fit_notifier.notify_subscribers()

    @property
    def number_of_fits(self):
        return self._number_of_fits

    @number_of_fits.setter
    def number_of_fits(self, value):
        self._number_of_fits_cache = self._number_of_fits
        self._number_of_fits = value
 def notify_subscribers(self, arg=None):
     Observable.notify_subscribers(self, arg)
class PhaseTablePresenter(object):
    def __init__(self, view, context):
        self.view = view
        self.context = context
        self.current_alg = None

        self.group_change_observer = GenericObserver(self.update_current_groups_list)
        self.run_change_observer = GenericObserver(self.update_current_run_list)
        self.instrument_changed_observer = GenericObserver(self.update_current_phase_tables)

        self.phase_table_calculation_complete_notifier = Observable()
        self.phase_quad_calculation_complete_nofifier = Observable()

        self.update_current_phase_tables()

    def update_view_from_model(self):
        for key, item in self.context.phase_context.options_dict.items():
            setattr(self.view, key, item)

    def update_model_from_view(self):
        for key in self.context.phase_context.options_dict:
            self.context.phase_context.options_dict[key] = getattr(self.view, key, None)

    def cancel(self):
        if self.current_alg is not None:
            self.current_alg.cancel()

    def handle_calulate_phase_table_clicked(self):
        self.update_model_from_view()

        self.calculation_thread = self.create_calculation_thread()

        self.calculation_thread.threadWrapperSetUp(self.handle_phase_table_calculation_started,
                                                   self.handle_calculation_success,
                                                   self.handle_calculation_error)

        self.calculation_thread.start()

    def create_calculation_thread(self):
        self._calculation_model = ThreadModelWrapper(self.calculate_phase_table)
        return thread_model.ThreadModel(self._calculation_model)

    def handle_calculate_phase_quad_button_clicked(self):
        self.update_model_from_view()

        self.phasequad_calculation_thread = self.create_phase_quad_calculation_thread()

        self.phasequad_calculation_thread.threadWrapperSetUp(self.handle_calculation_started,
                                                             self.handle_calculation_success,
                                                             self.handle_calculation_error)

        self.phasequad_calculation_thread.start()

    def create_phase_quad_calculation_thread(self):
        self._phasequad_calculation_model = ThreadModelWrapper(self.calculate_phase_quad)
        return thread_model.ThreadModel(self._phasequad_calculation_model)

    def calculate_phase_quad(self):
        parameters = self.get_parameters_for_phase_quad()

        self.current_alg = mantid.AlgorithmManager.create("PhaseQuad")
        phase_quad = run_PhaseQuad(parameters, self.current_alg)
        self.current_alg = None

        self.add_phase_quad_to_ADS(parameters['InputWorkspace'], parameters['PhaseTable'], phase_quad)

    def get_parameters_for_phase_quad(self):
        parameters = {}
        if self.context.phase_context.options_dict['phase_table_for_phase_quad'] == 'Construct':
            parameters['PhaseTable'] = self.calculate_phase_table()
        else:
            parameters['PhaseTable'] = self.context.phase_context.options_dict['phase_table_for_phase_quad']

        parameters['InputWorkspace'] = self.context.phase_context.options_dict['phase_quad_input_workspace']

        return parameters

    def add_phase_quad_to_ADS(self, input_workspace, input_phase_table, phase_quad):
        run = re.search('[0-9]+', input_workspace).group()
        phasequad_workspace_name = get_phase_quad_workspace_name(input_workspace, input_phase_table)
        phase_table_group = get_phase_table_workspace_group_name(phasequad_workspace_name,
                                                                 self.context.data_context.instrument)
        directory = get_base_data_directory(self.context, run) + phase_table_group

        muon_workspace_wrapper = MuonWorkspaceWrapper(phase_quad, directory + phasequad_workspace_name)
        muon_workspace_wrapper.show()

        self.context.phase_context.add_phase_quad(muon_workspace_wrapper)
        self.phase_quad_calculation_complete_nofifier.notify_subscribers()

    def handle_calculation_started(self):
        self.view.disable_widget()
        self.view.enable_phasequad_cancel()

    def handle_phase_table_calculation_started(self):
        self.view.disable_widget()
        self.view.enable_cancel()

    def handle_calculation_error(self, error):
        self.view.enable_widget()
        self.view.warning_popup(error)
        self.view.disable_cancel()
        self.current_alg = None

    def handle_calculation_success(self):
        self.phase_table_calculation_complete_notifier.notify_subscribers()
        self.update_current_phase_tables()
        self.view.enable_widget()
        self.view.disable_cancel()
        self.current_alg = None

    def calculate_phase_table(self):
        parameters = self.create_parameters_for_cal_muon_phase_algorithm()

        self.current_alg = mantid.AlgorithmManager.create("CalMuonDetectorPhases")
        detector_table, fitting_information = run_CalMuonDetectorPhases(parameters, self.current_alg)
        self.current_alg = None

        self.add_phase_table_to_ADS(parameters['DetectorTable'], detector_table)
        self.add_fitting_info_to_ADS_if_required(parameters['DetectorTable'], fitting_information)

        return parameters['DetectorTable']

    def add_phase_table_to_ADS(self, base_name, detector_table):
        run = re.search('[0-9]+', base_name).group()

        phase_table_group = get_phase_table_workspace_group_name(base_name,
                                                                 self.context.data_context.instrument)
        directory = get_base_data_directory(self.context, run) + phase_table_group
        muon_workspace_wrapper = MuonWorkspaceWrapper(detector_table, directory + base_name)
        muon_workspace_wrapper.show()

        self.context.phase_context.add_phase_table(muon_workspace_wrapper)

    def add_fitting_info_to_ADS_if_required(self, base_name, fitting_information):
        if not self.view.output_fit_information:
            return

        run = re.search('[0-9]+', base_name).group()
        phase_table_group = get_phase_table_workspace_group_name(base_name,
                                                                 self.context.data_context.instrument)
        fitting_workspace_name = get_fitting_workspace_name(base_name)
        directory = get_base_data_directory(self.context, run) + phase_table_group

        muon_workspace_wrapper = MuonWorkspaceWrapper(fitting_information, directory + fitting_workspace_name)
        muon_workspace_wrapper.show()

    def create_parameters_for_cal_muon_phase_algorithm(self):
        parameters = {}

        parameters['FirstGoodData'] = self.context.phase_context.options_dict['first_good_time']
        parameters['LastGoodData'] = self.context.phase_context.options_dict['last_good_time']

        parameters['InputWorkspace'] = self.context.phase_context.options_dict['input_workspace']

        forward_group = self.context.phase_context.options_dict['forward_group']
        parameters['ForwardSpectra'] = self.context.group_pair_context[forward_group].detectors

        backward_group = self.context.phase_context.options_dict['backward_group']
        parameters['BackwardSpectra'] = self.context.group_pair_context[backward_group].detectors

        parameters['DetectorTable'] = parameters['InputWorkspace'].replace('_raw_data', '') + "; PhaseTable"

        parameters['DetectorTable'] = get_phase_table_workspace_name(parameters['InputWorkspace'], forward_group,
                                                                     backward_group)

        return parameters

    def update_current_run_list(self):
        self.view.set_input_combo_box(self.context.getGroupedWorkspaceNames())
        self.view.set_group_combo_boxes(self.context.group_pair_context.group_names)
        self.update_model_from_view()

    def update_current_groups_list(self):
        self.view.set_group_combo_boxes(self.context.group_pair_context.group_names)
        self.update_model_from_view()

    def update_current_phase_tables(self):
        phase_table_list = self.context.phase_context.get_phase_table_list(self.context.data_context.instrument)
        phase_table_list.append('Construct')

        self.view.set_phase_table_combo_box(phase_table_list)
 def notify_subscribers(self, *args, **kwargs):
     Observable.notify_subscribers(self, *args)
 def notify_subscribers(self, arg=None):
     Observable.notify_subscribers(self, arg)