Ejemplo n.º 1
0
class FocusPresenter(object):
    def __init__(self, model, view):
        self.model = model
        self.view = view
        self.worker = None
        self.calibration_observer = CalibrationObserver(self)

        # Observable Setup
        self.focus_run_notifier = GenericObservable()

        # Connect view signals to local methods.
        self.view.set_on_focus_clicked(self.on_focus_clicked)
        self.view.set_enable_controls_connection(
            self.set_focus_controls_enabled)

        # Variables from other GUI tabs.
        self.current_calibration = CalibrationInfo()
        self.instrument = "ENGINX"
        self.rb_num = None

        last_van_path = get_setting(output_settings.INTERFACES_SETTINGS_GROUP,
                                    output_settings.ENGINEERING_PREFIX,
                                    "last_vanadium_run")
        if last_van_path:
            self.view.set_van_file_text_with_search(last_van_path)

    def add_focus_subscriber(self, obs):
        self.focus_run_notifier.add_subscriber(obs)

    def on_focus_clicked(self):
        if not self._validate():
            return
        regions_dict = self.current_calibration.create_focus_roi_dictionary()
        focus_paths = self.view.get_focus_filenames()
        van_path = self.view.get_vanadium_filename()
        if self._number_of_files_warning(focus_paths):
            self.start_focus_worker(focus_paths, van_path,
                                    self.view.get_plot_output(), self.rb_num,
                                    regions_dict)
        van_run = self.view.get_vanadium_run()
        set_setting(output_settings.INTERFACES_SETTINGS_GROUP,
                    output_settings.ENGINEERING_PREFIX, "last_vanadium_run",
                    van_run)

    def start_focus_worker(self, focus_paths: list, van_path: str,
                           plot_output: bool, rb_num: str,
                           regions_dict: dict) -> None:
        """
        Focus data in a separate thread to stop the main GUI from hanging.
        :param focus_paths: List of paths to the files containing the data to focus.
        :param plot_output: True if the output should be plotted.
        :param rb_num: The RB Number from the main window (often an experiment id)
        :param regions_dict: Dictionary containing the regions to focus over, mapping region_name -> grouping_ws_name
        """
        self.worker = AsyncTask(self.model.focus_run,
                                (focus_paths, van_path, plot_output,
                                 self.instrument, rb_num, regions_dict),
                                error_cb=self._on_worker_error,
                                finished_cb=self._on_worker_success)
        self.set_focus_controls_enabled(False)
        self.worker.start()

    def _on_worker_success(self):
        self.emit_enable_button_signal()
        self.focus_run_notifier.notify_subscribers(
            self.model.get_last_focused_files())

    def set_instrument_override(self, instrument):
        instrument = INSTRUMENT_DICT[instrument]
        self.view.set_instrument_override(instrument)
        self.instrument = instrument

    def set_rb_num(self, rb_num):
        self.rb_num = rb_num

    def _validate(self):
        """
        Ensure that the worker is ready to be started.
        :return: True if the worker can be started safely.
        """
        if self.view.is_searching():
            create_error_message(
                self.view, "Mantid is searching for data files. Please wait.")
            return False
        if not self.view.get_focus_valid():
            create_error_message(self.view, "Check run numbers/path is valid.")
            return False
        if not self.view.get_vanadium_valid():
            create_error_message(self.view,
                                 "Check vanadium run number/path is valid.")
            return False
        if not self.current_calibration.is_valid():
            create_error_message(
                self.view,
                "Create or Load a calibration via the Calibration tab before focusing."
            )
            return False
        if self.current_calibration.get_instrument() != self.instrument:
            create_error_message(
                self.view,
                "Please make sure the selected instrument matches instrument for the current calibration.\n"
                "The instrument for the current calibration is: " +
                self.current_calibration.get_instrument())
            return False
        return True

    def _number_of_files_warning(self, paths):
        if len(
                paths
        ) > 10:  # Just a guess on the warning for now. May change in future.
            response = QMessageBox.warning(
                self.view, 'Engineering Diffraction - Warning',
                'You are attempting to focus {} workspaces. This may take some time.\n\n Would you like to continue?'
                .format(len(paths)), QMessageBox.Ok | QMessageBox.Cancel)
            return response == QMessageBox.Ok
        else:
            return True

    def _on_worker_error(self, error_info):
        logger.error(str(error_info))
        self.emit_enable_button_signal()

    def set_focus_controls_enabled(self, enabled):
        self.view.set_focus_button_enabled(enabled)
        self.view.set_plot_output_enabled(enabled)

    def emit_enable_button_signal(self):
        self.view.sig_enable_controls.emit(True)

    def update_calibration(self, calibration):
        """
        Update the current calibration following an call from a CalibrationNotifier
        :param calibration: The new current calibration.
        """
        self.current_calibration = calibration
        region_text = calibration.get_roi_text()
        self.view.set_region_display_text(region_text)
Ejemplo n.º 2
0
class FocusPresenter(object):
    def __init__(self, model, view):
        self.model = model
        self.view = view
        self.worker = None
        self.calibration_observer = self.CalibrationObserver(self)

        # Connect view signals to local methods.
        self.view.set_on_focus_clicked(self.on_focus_clicked)
        self.view.set_enable_controls_connection(self.set_focus_controls_enabled)
        self.view.set_on_check_cropping_state_changed(self.show_cropping)

        # Variables from other GUI tabs.
        self.current_calibration = CalibrationInfo()
        self.instrument = "ENGINX"
        self.rb_num = None

        # Cropping Options
        self.cropping_widget = CroppingWidget(self.view, view=self.view.get_cropping_widget())
        self.show_cropping(False)

    def on_focus_clicked(self):
        if not self._validate():
            return
        banks, spectrum_numbers = self._get_banks()
        focus_paths = self.view.get_focus_filenames()
        if self._number_of_files_warning(focus_paths):
            self.start_focus_worker(focus_paths, banks, self.view.get_plot_output(), self.rb_num, spectrum_numbers)

    def start_focus_worker(self, focus_paths, banks, plot_output, rb_num, spectrum_numbers=None):
        """
        Focus data in a separate thread to stop the main GUI from hanging.
        :param focus_paths: List of paths to the files containing the data to focus.
        :param banks: A list of banks that are to be focused.
        :param plot_output: True if the output should be plotted.
        :param rb_num: The RB Number from the main window (often an experiment id)
        :param spectrum_numbers: Optional parameter to crop to a specific list of spectrum numbers.
        """
        self.worker = AsyncTask(self.model.focus_run,
                                (focus_paths, banks, plot_output, self.instrument, rb_num, spectrum_numbers),
                                error_cb=self._on_worker_error,
                                finished_cb=self.emit_enable_button_signal)
        self.set_focus_controls_enabled(False)
        self.worker.start()

    def set_instrument_override(self, instrument):
        instrument = INSTRUMENT_DICT[instrument]
        self.view.set_instrument_override(instrument)
        self.instrument = instrument

    def set_rb_num(self, rb_num):
        self.rb_num = rb_num

    def _validate(self):
        """
        Ensure that the worker is ready to be started.
        :return: True if the worker can be started safely.
        """
        if self.view.is_searching():
            create_error_message(self.view, "Mantid is searching for data files. Please wait.")
            return False
        if not self.view.get_focus_valid():
            create_error_message(self.view, "Check run numbers/path is valid.")
            return False
        if not check_workspaces_exist() or not self.current_calibration.is_valid():
            create_error_message(
                self.view, "Create or Load a calibration via the Calibration tab before focusing.")
            return False
        if self.current_calibration.get_instrument() != self.instrument:
            create_error_message(
                self.view,
                "Please make sure the selected instrument matches instrument for the current calibration.\n"
                "The instrument for the current calibration is: " + self.current_calibration.get_instrument())
            return False
        if self.view.get_crop_checked() and not self.cropping_widget.is_valid():
            create_error_message(self.view, "Check cropping values are valid.")
            return False
        return True

    def _number_of_files_warning(self, paths):
        if len(paths) > 10:  # Just a guess on the warning for now. May change in future.
            response = QMessageBox.warning(
                self.view, 'Engineering Diffraction - Warning',
                'You are attempting to focus {} workspaces. This may take some time.\n\n Would you like to continue?'
                .format(len(paths)), QMessageBox.Ok | QMessageBox.Cancel)
            return response == QMessageBox.Ok
        else:
            return True

    def _on_worker_error(self, _):
        self.emit_enable_button_signal()

    def set_focus_controls_enabled(self, enabled):
        self.view.set_focus_button_enabled(enabled)
        self.view.set_plot_output_enabled(enabled)

    def _get_banks(self):
        if self.view.get_crop_checked():
            if self.cropping_widget.is_custom():
                return None, self.cropping_widget.get_custom_spectra()
            else:
                return [self.cropping_widget.get_bank()], None
        else:
            return ["1", "2"], None

    def emit_enable_button_signal(self):
        self.view.sig_enable_controls.emit(True)

    def update_calibration(self, calibration):
        """
        Update the current calibration following an call from a CalibrationNotifier
        :param calibration: The new current calibration.
        """
        self.current_calibration = calibration

    def show_cropping(self, visible):
        self.view.set_cropping_widget_visibility(visible)

    # -----------------------
    # Observers / Observables
    # -----------------------
    class CalibrationObserver(Observer):
        def __init__(self, outer):
            Observer.__init__(self)
            self.outer = outer

        def update(self, observable, calibration):
            self.outer.update_calibration(calibration)