diff --git a/scripts/Muon/GUI/Common/home_instrument_widget/__init__.py b/scripts/Muon/GUI/Common/home_instrument_widget/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/scripts/Muon/GUI/Common/home_instrument_widget/home_instrument_widget_model.py b/scripts/Muon/GUI/Common/home_instrument_widget/home_instrument_widget_model.py new file mode 100644 index 0000000000000000000000000000000000000000..f865d122f2d7a170fc9ce269fe236ab524d90da2 --- /dev/null +++ b/scripts/Muon/GUI/Common/home_instrument_widget/home_instrument_widget_model.py @@ -0,0 +1,108 @@ +from __future__ import (absolute_import, division, print_function) + +from Muon.GUI.Common.muon_context import MuonContext +from mantid.api import ITableWorkspace, WorkspaceGroup +from mantid import api + + +class InstrumentWidgetModel(object): + """ + The model holds the muon context and interacts with it, only able to modify the pre-processing parts of each + run. + + The model should not take care of processing data, it should only interact with and modify the muon context data + so that when processing is done from elsewhere the parameters of the pre-processing are up-to-date with the + GUI. + """ + + def __init__(self, muon_data=MuonContext()): + self._data = muon_data + + def clear_data(self): + """When e.g. instrument changed""" + self._data.clear() + + def get_file_time_zero(self): + return self._data.loaded_data["TimeZero"] + + def get_user_time_zero(self): + if "UserTimeZero" in self._data.loaded_data.keys(): + time_zero = self._data.loaded_data["UserTimeZero"] + else: + # default to loaded value, keep a record of the data vaue + self._data.loaded_data["DataTimeZero"] = self._data.loaded_data["TimeZero"] + time_zero = self._data.loaded_data["TimeZero"] + return time_zero + + def get_file_first_good_data(self): + return self._data.loaded_data["FirstGoodData"] + + def get_user_first_good_data(self): + if "UserFirstGoodData" in self._data.loaded_data.keys(): + first_good_data = self._data.loaded_data["UserFirstGoodData"] + else: + # Default to loaded value + self._data.loaded_data["FirstGoodData"] = self._data.loaded_data["FirstGoodData"] + first_good_data = self._data.loaded_data["FirstGoodData"] + return first_good_data + + def set_user_time_zero(self, time_zero): + self._data.loaded_data["UserTimeZero"] = time_zero + + def set_user_first_good_data(self, first_good_data): + self._data.loaded_data["UserFirstGoodData"] = first_good_data + + def get_dead_time_table_from_data(self): + if self._data.is_multi_period(): + return self._data.loaded_data["DataDeadTimeTable"][0] + else: + return self._data.loaded_data["DataDeadTimeTable"] + + def get_dead_time_table(self): + return self._data.dead_time_table + + def add_fixed_binning(self, fixed_bin_size): + self._data.loaded_data["Rebin"] = str(fixed_bin_size) + + def add_variable_binning(self, rebin_params): + self._data.loaded_data["Rebin"] = str(rebin_params) + + # ------------------------------------------------------------------------------------------------------------------ + # Dead Time + # ------------------------------------------------------------------------------------------------------------------ + + def load_dead_time(self): + # TODO : Create this function + pass + + def check_dead_time_file_selection(self, selection): + try: + table = api.AnalysisDataServiceImpl.Instance().retrieve(str(selection)) + except Exception: + raise ValueError("Workspace " + str(selection) + " does not exist") + assert isinstance(table, ITableWorkspace) + # are column names correct? + col = table.getColumnNames() + if len(col) != 2: + raise ValueError("Expected 2 columns, found ", str(max(0, len(col)))) + if col[0] != "spectrum" or col[1] != "dead-time": + raise ValueError("Columns have incorrect names") + rows = table.rowCount() + if rows != self._data.loaded_workspace.getNumberHistograms(): + raise ValueError("Number of histograms do not match number of rows in dead time table") + return True + + def set_dead_time_to_none(self): + self._data.loaded_data["DeadTimeTable"] = None + + def set_dead_time_from_data(self): + data_dead_time = self._data.loaded_data["DataDeadTimeTable"] + if isinstance(data_dead_time, WorkspaceGroup): + self._data.loaded_data["DeadTimeTable"] = data_dead_time[0] + else: + self._data.loaded_data["DeadTimeTable"] = data_dead_time + + def set_user_dead_time_from_ADS(self, name): + dtc = api.AnalysisDataServiceImpl.Instance().retrieve(str(name)) + self._data.loaded_data["UserDeadTimeTable"] = dtc + self._data.loaded_data["DeadTimeTable"] = dtc diff --git a/scripts/Muon/GUI/Common/home_instrument_widget/home_instrument_widget_presenter.py b/scripts/Muon/GUI/Common/home_instrument_widget/home_instrument_widget_presenter.py new file mode 100644 index 0000000000000000000000000000000000000000..4a7f474dae271ca66e42e1f8d272ca89bb9b3460 --- /dev/null +++ b/scripts/Muon/GUI/Common/home_instrument_widget/home_instrument_widget_presenter.py @@ -0,0 +1,203 @@ +# Mantid Repository : https://github.com/mantidproject/mantid +# +# Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, +# NScD Oak Ridge National Laboratory, European Spallation Source +# & Institut Laue - Langevin +# SPDX - License - Identifier: GPL - 3.0 + +from __future__ import (absolute_import, division, print_function) + +from Muon.GUI.Common.home_tab.home_tab_presenter import HomeTabSubWidget +import Muon.GUI.Common.load_utils as load_utils +from Muon.GUI.Common.muon_file_utils import filter_for_extensions +from Muon.GUI.Common.observer_pattern import Observable + + +class InstrumentWidgetPresenter(HomeTabSubWidget): + + @staticmethod + def dead_time_from_data_text(dead_times): + mean = sum(dead_times) / len(dead_times) + label = "From {0:.3f} to {1:.3f} (ave. {2:.3f})".format(min(dead_times), max(dead_times), mean) + return label + + def __init__(self, view, model): + self._view = view + self._model = model + + self._view.on_time_zero_checkState_changed(self.handle_loaded_time_zero_checkState_change) + self._view.on_time_zero_changed(self.handle_user_changes_time_zero) + + self._view.on_first_good_data_checkState_changed(self.handle_loaded_first_good_data_checkState_change) + self._view.on_first_good_data_changed(self.handle_user_changes_first_good_data) + + self._view.on_fixed_rebin_edit_changed(self.handle_fixed_rebin_changed) + self._view.on_variable_rebin_edit_changed(self.handle_variable_rebin_changed) + + self._view.on_dead_time_from_data_selected(self.handle_user_selects_dead_time_from_data) + self._view.on_dead_time_unselected(self.handle_dead_time_unselected) + self._view.on_dead_time_browse_clicked(self.handle_dead_time_browse_clicked) + self._view.on_dead_time_from_file_selected(self.handle_dead_time_from_file_selected) + self._view.on_dead_time_file_option_changed(self.handle_dead_time_from_file_changed) + + self._view.on_instrument_changed(self.handle_instrument_changed) + + # notifier for instrument changes + self.instrumentNotifier = InstrumentWidgetPresenter.InstrumentNotifier(self) + + def show(self): + self._view.show() + + def update_view_from_model(self): + self.handle_loaded_first_good_data_checkState_change() + self.handle_loaded_time_zero_checkState_change() + self._view.set_instrument(self._model._data.instrument) + + def clear_view(self): + self._view.set_time_zero(0.0) + self._view.set_first_good_data(0.0) + self._view.set_combo_boxes_to_default() + self._view.set_checkboxes_to_defualt() + + # ------------------------------------------------------------------------------------------------------------------ + # Time Zero + # ------------------------------------------------------------------------------------------------------------------ + + def handle_user_changes_time_zero(self): + time_zero = self._view.get_time_zero() + self._model.set_user_time_zero(time_zero) + + def handle_loaded_time_zero_checkState_change(self): + if self._view.time_zero_state(): + time_zero = self._model.get_file_time_zero() + self._view.set_time_zero(time_zero) + else: + time_zero = self._model.get_user_time_zero() + self._view.set_time_zero(time_zero) + + # ------------------------------------------------------------------------------------------------------------------ + # First Good Data + # ------------------------------------------------------------------------------------------------------------------ + + def handle_user_changes_first_good_data(self): + first_good_data = self._view.get_first_good_data() + self._model.set_user_first_good_data(first_good_data) + + def handle_loaded_first_good_data_checkState_change(self): + if self._view.first_good_data_state(): + first_good_data = self._model.get_file_first_good_data() + self._view.set_first_good_data(first_good_data) + else: + first_good_data = self._model.get_user_first_good_data() + self._view.set_first_good_data(first_good_data) + + # ------------------------------------------------------------------------------------------------------------------ + # Rebin + # ------------------------------------------------------------------------------------------------------------------ + + def handle_fixed_rebin_changed(self): + fixed_bin_size = float(self._view.get_fixed_bin_text()) + self._model.add_fixed_binning(fixed_bin_size) + + def handle_variable_rebin_changed(self): + variable_bin_size = float(self._view.get_fixed_bin_text()) + self._model.add_variable_binning(variable_bin_size) + + # ------------------------------------------------------------------------------------------------------------------ + # Instrument + # ------------------------------------------------------------------------------------------------------------------ + + def handle_instrument_changed(self): + """User changes the selected instrument.""" + instrument = self._view.get_instrument() + current_instrument = self._view.cached_instrument + if instrument != self._model._data.instrument: + # prompt user to continue or not + user_response = self._view.instrument_changed_warning() + if user_response == 1: + # User selects "Ok" + self._model.clear_data() + self.clear_view() + self._view.set_instrument(instrument, block=True) + self.instrumentNotifier.notify_subscribers(instrument) + else: + # User selects "Cancel", reset the instrument selector + self._view.set_instrument(current_instrument, block=True) + + # ------------------------------------------------------------------------------------------------------------------ + # Dead Time + # ------------------------------------------------------------------------------------------------------------------ + + def handle_dead_time_browse_clicked(self): + """User selects the option to Browse for a nexus file to load dead times from.""" + filename = self._view.show_file_browser_and_return_selection( + filter_for_extensions(['nxs']), [''], multiple_files=False)[0] + name = load_utils.load_dead_time_from_filename(filename) + if name == "": + self._view.warning_popup("File does not appear to contain dead time data.") + return + + # switch the view to the "from table workspace" option + self._view.set_dead_time_selection(2) + is_set = self._view.set_dead_time_file_selection_text(name) + if not is_set: + self._view.warning_popup("Dead time table cannot be loaded") + + def handle_user_selects_dead_time_from_data(self): + """User chooses to load dead time from the currently loaded workspace.""" + dtc = self._model.get_dead_time_table_from_data() + if dtc is not None: + self._model.set_dead_time_from_data() + dead_times = dtc.toDict()['dead-time'] + dead_time_text = self.dead_time_from_data_text(dead_times) + self._view.set_dead_time_label(dead_time_text) + else: + self._view.set_dead_time_label("No loaded dead time") + + def set_dead_time_text_to_default(self): + """by default the dead time text should onl contain 0.0.""" + dead_time_text = self.dead_time_from_data_text([0.0]) + self._view.set_dead_time_label(dead_time_text) + + def handle_dead_time_from_file_selected(self): + """User has selected the dead time "from Table Workspace" option.""" + table_names = load_utils.get_table_workspace_names_from_ADS() + self._view.populate_dead_time_combo(table_names) + self.set_dead_time_text_to_default() + + def handle_dead_time_unselected(self): + """User has set dead time combo to 'None'.""" + self.set_dead_time_text_to_default() + self._model.set_dead_time_to_none() + + def handle_dead_time_from_file_changed(self): + """The user changes the selected Table Workspace to use as dead time.""" + selection = self._view.get_dead_time_file_selection() + if selection == "None" or selection == "": + self.handle_dead_time_unselected() + return + try: + self._model.check_dead_time_file_selection(selection) + self._model.set_user_dead_time_from_ADS(selection) + dead_times = self._model.get_dead_time_table().toDict()['dead-time'] + dead_time_text = self.dead_time_from_data_text(dead_times) + self._view.set_dead_time_label(dead_time_text) + except ValueError as error: + self._handle_selected_table_is_invalid() + self._view.warning_popup(error.args[0]) + + def _handle_selected_table_is_invalid(self): + self._model.set_dead_time_to_none() + self._view.set_dead_time_file_selection(0) + self.set_dead_time_text_to_default() + + # ------------------------------------------------------------------------------------------------------------------ + # Observer / Observable + # ------------------------------------------------------------------------------------------------------------------ + + class InstrumentNotifier(Observable): + def __init__(self, outer): + Observable.__init__(self) + self.outer = outer # handle to containing class + + def notify_subscribers(self, *args, **kwargs): + Observable.notify_subscribers(self, *args) diff --git a/scripts/Muon/GUI/Common/home_instrument_widget/home_instrument_widget_view.py b/scripts/Muon/GUI/Common/home_instrument_widget/home_instrument_widget_view.py new file mode 100644 index 0000000000000000000000000000000000000000..190a9442fafa98157a8897e12253f5953c008bf2 --- /dev/null +++ b/scripts/Muon/GUI/Common/home_instrument_widget/home_instrument_widget_view.py @@ -0,0 +1,569 @@ +# Mantid Repository : https://github.com/mantidproject/mantid +# +# Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, +# NScD Oak Ridge National Laboratory, European Spallation Source +# & Institut Laue - Langevin +# SPDX - License - Identifier: GPL - 3.0 + +# -*- coding: utf8 -*- +from __future__ import (absolute_import, division, print_function) + +from PyQt4 import QtGui, QtCore +from PyQt4.QtCore import pyqtSignal as Signal + +from Muon.GUI.Common.muon_file_utils import allowed_instruments +from Muon.GUI.Common.run_string_utils import valid_float_regex +from Muon.GUI.Common.message_box import warning + + +class InstrumentWidgetView(QtGui.QWidget): + dataChanged = Signal() + + def __init__(self, parent=None): + super(InstrumentWidgetView, self).__init__(parent) + + self.layout = QtGui.QGridLayout(self) + + self._button_height = 40 + self._cached_instrument = ["None", "None"] + + self.setup_interface() + self.apply_to_all_hidden(True) + self.dead_time_file_loader_hidden(True) + self.dead_time_other_file_hidden(True) + + self.deadtime_selector.currentIndexChanged.connect(self.on_dead_time_combo_changed) + self.rebin_selector.currentIndexChanged.connect(self.on_rebin_combo_changed) + self.timezero_checkbox.stateChanged.connect(self.on_time_zero_checkbox_state_change) + self.firstgooddata_checkbox.stateChanged.connect(self.on_first_good_data_checkbox_state_change) + + self._on_dead_time_from_data_selected = None + self._on_dead_time_from_other_file_selected = lambda: 0 + + self.firstgooddata_checkbox.setChecked(1) + self.timezero_checkbox.setChecked(1) + self.time_zero_edit_enabled(True) + self.first_good_data_edit_enabled(True) + + self._on_time_zero_changed = lambda: 0 + self._on_first_good_data_changed = lambda: 0 + self._on_dead_time_from_file_selected = lambda: 0 + self._on_dead_time_file_option_selected = lambda: 0 + self._on_dead_time_unselected = lambda: 0 + + self.timezero_edit.editingFinished.connect( + lambda: self._on_time_zero_changed() if not self.is_time_zero_checked() else None) + self.firstgooddata_edit.editingFinished.connect( + lambda: self._on_first_good_data_changed() if not self.is_first_good_data_checked() else None) + self.deadtime_file_selector.currentIndexChanged.connect(self.on_dead_time_file_combo_changed) + + def apply_to_all_hidden(self, hidden=True): + if hidden: + self.apply_all_label.hide() + self.apply_all_checkbox.hide() + if not hidden: + self.apply_all_label.setVisible(True) + self.apply_all_checkbox.setVisible(True) + + def setup_filter_row(self): + self.apply_all_label = QtGui.QLabel(self) + self.apply_all_label.setObjectName("applyAllLabel") + self.apply_all_label.setText("Apply to all loaded data ") + + self.apply_all_checkbox = QtGui.QCheckBox(self) + + self.horizontal_layout_6 = QtGui.QHBoxLayout() + self.horizontal_layout_6.setObjectName("horizontalLayout6") + self.horizontal_layout_6.addWidget(self.apply_all_label) + self.horizontal_layout_6.addWidget(self.apply_all_checkbox) + + def setup_interface(self): + self.setObjectName("InstrumentWidget") + + self.setup_instrument_row() + self.setup_time_zero_row() + self.setup_first_good_data_row() + self.setup_dead_time_row() + self.setup_rebin_row() + self.setup_filter_row() + + self.group = QtGui.QGroupBox("Run Pre-processing Parameters") + self.group.setFlat(False) + self.setStyleSheet("QGroupBox {border: 1px solid grey;border-radius: 10px;margin-top: 1ex; margin-right: 0ex}" + "QGroupBox:title {" + 'subcontrol-origin: margin;' + "padding: 0 3px;" + 'subcontrol-position: top center;' + 'padding-top: -10px;' + 'padding-bottom: 0px;' + "padding-right: 10px;" + ' color: grey; }') + + self.group.setLayout(self.layout) + + self.group2 = QtGui.QGroupBox("Rebin") + self.group2.setFlat(False) + self.vertical_layout2 = QtGui.QVBoxLayout() + self.vertical_layout2.addItem(self.horizontal_layout_5) + self.group2.setLayout(self.horizontal_layout_5) + + self.widget_layout = QtGui.QVBoxLayout(self) + self.widget_layout.addWidget(self.group) + self.widget_layout.addWidget(self.group2) + self.setLayout(self.widget_layout) + + def show_file_browser_and_return_selection(self, file_filter, search_directories, multiple_files=False): + default_directory = search_directories[0] + if multiple_files: + chosen_files = QtGui.QFileDialog.getOpenFileNames(self, "Select files", default_directory, + file_filter) + return [str(chosen_file) for chosen_file in chosen_files] + else: + chosen_file = QtGui.QFileDialog.getOpenFileName(self, "Select file", default_directory, + file_filter) + return [str(chosen_file)] + + def set_combo_boxes_to_default(self): + self.rebin_selector.setCurrentIndex(0) + self.rebin_fixed_hidden(True) + self.rebin_variable_hidden(True) + self.deadtime_selector.setCurrentIndex(0) + self.dead_time_data_info_hidden(True) + self.dead_time_file_loader_hidden(True) + + def set_checkboxes_to_defualt(self): + self.timezero_checkbox.setChecked(1) + self.firstgooddata_checkbox.setChecked(1) + + def warning_popup(self, message): + warning(message, parent=self) + + # ------------------------------------------------------------------------------------------------------------------ + # Instrument selection + # ------------------------------------------------------------------------------------------------------------------ + + def _fixed_aspect_ratio_size_policy(self, widget): + size_policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + size_policy.setHorizontalStretch(0) + size_policy.setVerticalStretch(0) + size_policy.setHeightForWidth(widget.sizePolicy().hasHeightForWidth()) + return size_policy + + def setup_instrument_row(self): + self.instrument_selector = QtGui.QComboBox(self) + self.instrument_selector.setSizePolicy(self._fixed_aspect_ratio_size_policy(self.instrument_selector)) + self.instrument_selector.setObjectName("instrumentSelector") + self.instrument_selector.addItems(["None"] + allowed_instruments) + + self.instrument_label = QtGui.QLabel(self) + self.instrument_label.setObjectName("instrumentLabel") + self.instrument_label.setText("Instrument : ") + + self.horizontal_layout = QtGui.QHBoxLayout() + self.horizontal_layout.setObjectName("horizontalLayout") + self.horizontal_layout.addWidget(self.instrument_label) + self.horizontal_layout.addWidget(self.instrument_selector) + self.horizontal_layout.addStretch(0) + + self.layout.addWidget(self.instrument_label, 0, 0) + self.layout.addWidget(self.instrument_selector, 0, 1) + + def get_instrument(self): + return self.instrument_selector.currentText() + + def set_instrument(self, instrument, block=False): + index = self.instrument_selector.findText(instrument) + if index != -1: + self.instrument_selector.blockSignals(block) + self.instrument_selector.setCurrentIndex(index) + self.instrument_selector.blockSignals(False) + + def on_instrument_changed(self, slot): + self.instrument_selector.currentIndexChanged.connect(slot) + self.instrument_selector.currentIndexChanged.connect(self.cache_instrument) + + def cache_instrument(self): + self._cached_instrument.pop(0) + self._cached_instrument.append(str(self.instrument_selector.currentText())) + + @property + def cached_instrument(self): + return self._cached_instrument[-1] + + def instrument_changed_warning(self): + msg = QtGui.QMessageBox(self) + msg.setIcon(QtGui.QMessageBox.Warning) + msg.setText("Changing instrument will reset the interface, continue?") + msg.setWindowTitle("Changing Instrument") + msg.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) + retval = msg.exec_() + if retval == 1024: + # The "OK" code + return 1 + else: + return 0 + + # ------------------------------------------------------------------------------------------------------------------ + # Time zero + # ------------------------------------------------------------------------------------------------------------------ + + def setup_time_zero_row(self): + self.timezero_label = QtGui.QLabel(self) + self.timezero_label.setObjectName("timeZeroLabel") + self.timezero_label.setText("Time Zero : ") + + self.timezero_edit = QtGui.QLineEdit(self) + timezero_validator = QtGui.QRegExpValidator(QtCore.QRegExp(valid_float_regex), self.timezero_edit) + self.timezero_edit.setValidator(timezero_validator) + self.timezero_edit.setObjectName("timeZeroEdit") + self.timezero_edit.setText("") + + self.timezero_unit_label = QtGui.QLabel(self) + self.timezero_unit_label.setObjectName("timeZeroUnitLabel") + self.timezero_unit_label.setText(u" µs (From data file ") + + self.timezero_checkbox = QtGui.QCheckBox(self) + self.timezero_checkbox.setObjectName("timeZeroCheckbox") + self.timezero_checkbox.setChecked(True) + + self.timezero_label_2 = QtGui.QLabel(self) + self.timezero_label_2.setObjectName("timeZeroLabel") + self.timezero_label_2.setText(" )") + + self.horizontal_layout_2 = QtGui.QHBoxLayout() + self.horizontal_layout_2.setObjectName("horizontalLayout2") + self.horizontal_layout_2.addSpacing(10) + self.horizontal_layout_2.addWidget(self.timezero_unit_label) + self.horizontal_layout_2.addWidget(self.timezero_checkbox) + self.horizontal_layout_2.addWidget(self.timezero_label_2) + self.horizontal_layout_2.addStretch(0) + + self.layout.addWidget(self.timezero_label, 1, 0) + self.layout.addWidget(self.timezero_edit, 1, 1) + self.layout.addItem(self.horizontal_layout_2, 1, 2) + + def set_time_zero(self, time_zero): + self.timezero_edit.setText("{0:.3f}".format(round(float(time_zero), 3))) + + def get_time_zero(self): + return float(self.timezero_edit.text()) + + def time_zero_edit_enabled(self, enabled): + self.timezero_edit.setEnabled(not enabled) + + def is_time_zero_checked(self): + return self.timezero_checkbox.checkState() + + def on_time_zero_changed(self, slot): + self._on_time_zero_changed = slot + + def on_time_zero_checkState_changed(self, slot): + self.timezero_checkbox.stateChanged.connect(slot) + + def time_zero_state(self): + return self.timezero_checkbox.checkState() + + def on_time_zero_checkbox_state_change(self): + self.time_zero_edit_enabled(self.timezero_checkbox.checkState()) + + # ------------------------------------------------------------------------------------------------------------------ + # First good data + # ------------------------------------------------------------------------------------------------------------------ + + def setup_first_good_data_row(self): + + self.firstgooddata_label = QtGui.QLabel(self) + self.firstgooddata_label.setObjectName("firstgooddataLabel") + self.firstgooddata_label.setText("First Good Data : ") + + self.firstgooddata_edit = QtGui.QLineEdit(self) + firstgooddata_validator = QtGui.QRegExpValidator(QtCore.QRegExp(valid_float_regex), self.timezero_edit) + self.timezero_edit.setValidator(firstgooddata_validator) + self.firstgooddata_edit.setObjectName("firstgooddataEdit") + self.firstgooddata_edit.setText("") + + self.firstgooddata_unit_label = QtGui.QLabel(self) + self.firstgooddata_unit_label.setObjectName("firstgooddataUnitLabel") + self.firstgooddata_unit_label.setText(u" U+03BCs (From data file ") + + self.firstgooddata_checkbox = QtGui.QCheckBox(self) + self.firstgooddata_checkbox.setObjectName("firstgooddataCheckbox") + self.firstgooddata_checkbox.setChecked(True) + + self.firstgooddata_label_2 = QtGui.QLabel(self) + self.firstgooddata_label_2.setObjectName("timeZeroLabel") + self.firstgooddata_label_2.setText(" )") + + self.horizontal_layout_3 = QtGui.QHBoxLayout() + self.horizontal_layout_3.setObjectName("horizontalLayout3") + self.horizontal_layout_3.addSpacing(10) + self.horizontal_layout_3.addWidget(self.firstgooddata_unit_label) + self.horizontal_layout_3.addWidget(self.firstgooddata_checkbox) + self.horizontal_layout_3.addWidget(self.firstgooddata_label_2) + self.horizontal_layout_3.addStretch(0) + + self.layout.addWidget(self.firstgooddata_label, 2, 0) + self.layout.addWidget(self.firstgooddata_edit, 2, 1) + self.layout.addItem(self.horizontal_layout_3, 2, 2) + + def on_first_good_data_changed(self, slot): + self._on_first_good_data_changed = slot + + def set_first_good_data(self, first_good_data): + self.firstgooddata_edit.setText("{0:.3f}".format(round(float(first_good_data), 3))) + + def on_first_good_data_checkState_changed(self, slot): + self.firstgooddata_checkbox.stateChanged.connect(slot) + + def first_good_data_state(self): + return self.firstgooddata_checkbox.checkState() + + def is_first_good_data_checked(self): + return self.firstgooddata_checkbox.checkState() + + def on_first_good_data_checkbox_state_change(self): + self.first_good_data_edit_enabled(self.firstgooddata_checkbox.checkState()) + + def first_good_data_edit_enabled(self, disabled): + self.firstgooddata_edit.setEnabled(not disabled) + + def get_first_good_data(self): + return float(self.firstgooddata_edit.text()) + + # ------------------------------------------------------------------------------------------------------------------ + # Dead time correction + # ------------------------------------------------------------------------------------------------------------------ + + def setup_dead_time_row(self): + self.deadtime_label = QtGui.QLabel(self) + self.deadtime_label.setObjectName("deadTimeLabel") + self.deadtime_label.setText("Dead Time : ") + + self.deadtime_selector = QtGui.QComboBox(self) + self.deadtime_selector.setObjectName("deadTimeSelector") + self.deadtime_selector.addItems(["None", "From data file", "From table workspace", "From other file"]) + + self.deadtime_label_2 = QtGui.QLabel(self) + self.deadtime_label_2.setObjectName("deadTimeFileLabel") + self.deadtime_label_2.setText("Dead Time Workspace : ") + + self.deadtime_label_3 = QtGui.QLabel(self) + self.deadtime_label_3.setObjectName("deadTimeInfoLabel") + self.deadtime_label_3.setText("") + + self.deadtime_file_selector = QtGui.QComboBox(self) + self.deadtime_file_selector.setObjectName("deadTimeCombo") + self.deadtime_file_selector.addItem("None") + self.deadtime_file_selector.setToolTip("Select a table which is loaded into the ADS.") + + self.deadtime_browse_button = QtGui.QPushButton(self) + self.deadtime_browse_button.setObjectName("deadTimeBrowseButton") + self.deadtime_browse_button.setText("Browse") + self.deadtime_browse_button.setToolTip("Browse for a .nxs file to load dead times from. If valid, the " + "dead times will be saved as a table, and automatically selected " + "as the dead time for the current data.") + + self.horizontal_layout_4 = QtGui.QHBoxLayout() + self.horizontal_layout_4.setObjectName("horizontalLayout3") + self.horizontal_layout_4.addSpacing(10) + self.horizontal_layout_4.addWidget(self.deadtime_label_3) + + self.dead_time_file_layout = QtGui.QHBoxLayout() + self.dead_time_file_layout.addWidget(self.deadtime_browse_button) + self.dead_time_file_layout.addStretch(0) + + self.dead_time_other_file_label = QtGui.QLabel(self) + self.dead_time_other_file_label.setText("From other file : ") + + self.layout.addWidget(self.deadtime_label, 3, 0) + self.layout.addWidget(self.deadtime_selector, 3, 1) + self.layout.addItem(self.horizontal_layout_4, 3, 2) + self.layout.addWidget(self.deadtime_label_2, 4, 0) + self.layout.addWidget(self.deadtime_file_selector, 4, 1) + self.layout.addWidget(self.dead_time_other_file_label, 5, 0) + self.layout.addWidget(self.deadtime_browse_button, 5, 1) + + def on_dead_time_file_option_changed(self, slot): + self._on_dead_time_file_option_selected = slot + + def on_dead_time_from_data_selected(self, slot): + self._on_dead_time_from_data_selected = slot + + def on_dead_time_unselected(self, slot): + self._on_dead_time_unselected = slot + + def on_dead_time_browse_clicked(self, slot): + self.deadtime_browse_button.clicked.connect(slot) + + def on_dead_time_from_file_selected(self, slot): + self._on_dead_time_from_file_selected = slot + + def populate_dead_time_combo(self, names): + self.deadtime_file_selector.clear() + self.deadtime_file_selector.addItem("None") + for name in names: + self.deadtime_file_selector.addItem(name) + + def get_dead_time_file_selection(self): + return self.deadtime_file_selector.currentText() + + def set_dead_time_file_selection_text(self, text): + index = self.deadtime_file_selector.findText(text) + if index >= 0: + self.deadtime_file_selector.setCurrentIndex(index) + return True + return False + + def set_dead_time_file_selection(self, index): + self.deadtime_file_selector.setCurrentIndex(index) + + def set_dead_time_selection(self, index): + self.deadtime_selector.setCurrentIndex(index) + + def dead_time_file_loader_hidden(self, hidden=True): + if hidden: + self.deadtime_file_selector.hide() + + self.deadtime_label_2.hide() + self.dead_time_data_info_hidden(hidden) + if not hidden: + self.deadtime_file_selector.setVisible(True) + self.deadtime_label_2.setVisible(True) + self.dead_time_data_info_hidden(hidden) + + def dead_time_other_file_hidden(self, hidden): + if hidden: + self.dead_time_other_file_label.hide() + self.deadtime_browse_button.hide() + + if not hidden: + self.deadtime_browse_button.setVisible(True) + self.dead_time_other_file_label.setVisible(True) + + def dead_time_data_info_hidden(self, hidden=True): + if hidden: + self.deadtime_label_3.hide() + if not hidden: + self.deadtime_label_3.setVisible(True) + + def set_dead_time_label(self, text): + self.deadtime_label_3.setText(text) + + def on_dead_time_combo_changed(self, index): + if index == 0: + self._on_dead_time_unselected() + self.dead_time_file_loader_hidden(True) + self.dead_time_data_info_hidden(True) + self.dead_time_other_file_hidden(True) + if index == 1: + self._on_dead_time_from_data_selected() + self.dead_time_file_loader_hidden(True) + self.dead_time_data_info_hidden(False) + self.dead_time_other_file_hidden(True) + if index == 2: + self._on_dead_time_from_file_selected() + self.dead_time_file_loader_hidden(False) + self.dead_time_data_info_hidden(False) + self.dead_time_other_file_hidden(True) + if index == 3: + self._on_dead_time_from_other_file_selected() + self.dead_time_file_loader_hidden(True) + self.dead_time_data_info_hidden(True) + self.dead_time_other_file_hidden(False) + + def on_dead_time_from_other_file_selected(self, slot): + self._on_dead_time_from_other_file_selected = slot + + def on_dead_time_file_combo_changed(self, index): + self._on_dead_time_file_option_selected() + + # ------------------------------------------------------------------------------------------------------------------ + # Rebin row + # ------------------------------------------------------------------------------------------------------------------ + + def setup_rebin_row(self): + self.rebin_label = QtGui.QLabel(self) + self.rebin_label.setObjectName("rebinLabel") + self.rebin_label.setText("Rebin : ") + + self.rebin_selector = QtGui.QComboBox(self) + self.rebin_selector.setObjectName("rebinSelector") + self.rebin_selector.addItems(["None", "Fixed", "Variable"]) + + self.rebin_steps_label = QtGui.QLabel(self) + self.rebin_steps_label.setText("Steps : ") + + self.rebin_steps_edit = QtGui.QLineEdit(self) + + self.rebin_variable_label = QtGui.QLabel(self) + self.rebin_variable_label.setText("Bin Boundaries : ") + self.rebin_variable_edit = QtGui.QLineEdit(self) + + self.rebin_help_button = QtGui.QPushButton(self) + size_policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + size_policy.setHorizontalStretch(0) + size_policy.setVerticalStretch(0) + size_policy.setHeightForWidth(self.rebin_help_button.sizePolicy().hasHeightForWidth()) + self.rebin_help_button.setSizePolicy(size_policy) + self.rebin_help_button.setMinimumSize(QtCore.QSize(40, 40)) + self.rebin_help_button.setMaximumSize(QtCore.QSize(40, 40)) + self.rebin_help_button.setObjectName("rebinHelpButton") + self.rebin_help_button.setText("?") + + self.horizontal_layout_5 = QtGui.QHBoxLayout() + self.horizontal_layout_5.setObjectName("horizontalLayout3") + self.horizontal_layout_5.addSpacing(10) + + self.horizontal_layout_5.addWidget(self.rebin_label) + self.horizontal_layout_5.addWidget(self.rebin_selector) + + self.horizontal_layout_5.addWidget(self.rebin_steps_label) + self.horizontal_layout_5.addWidget(self.rebin_steps_edit) + self.horizontal_layout_5.addWidget(self.rebin_variable_label) + self.horizontal_layout_5.addWidget(self.rebin_variable_edit) + self.horizontal_layout_5.addStretch(0) + self.horizontal_layout_5.addSpacing(10) + self.horizontal_layout_5.addWidget(self.rebin_help_button) + + self.rebin_steps_label.hide() + self.rebin_steps_edit.hide() + self.rebin_variable_label.hide() + self.rebin_variable_edit.hide() + + def rebin_fixed_hidden(self, hidden=True): + if hidden: + self.rebin_steps_label.hide() + self.rebin_steps_edit.hide() + if not hidden: + self.rebin_steps_label.setVisible(True) + self.rebin_steps_edit.setVisible(True) + + def rebin_variable_hidden(self, hidden=True): + if hidden: + self.rebin_variable_label.hide() + self.rebin_variable_edit.hide() + if not hidden: + self.rebin_variable_label.setVisible(True) + self.rebin_variable_edit.setVisible(True) + + def on_rebin_combo_changed(self, index): + if index == 0: + self.rebin_fixed_hidden(True) + self.rebin_variable_hidden(True) + if index == 1: + self.rebin_fixed_hidden(False) + self.rebin_variable_hidden(True) + if index == 2: + self.rebin_fixed_hidden(True) + self.rebin_variable_hidden(False) + + def on_fixed_rebin_edit_changed(self, slot): + self.rebin_steps_edit.editingFinished.connect(slot) + + def on_variable_rebin_edit_changed(self, slot): + self.rebin_variable_edit.editingFinished.connect(slot) + + def get_fixed_bin_text(self): + return self.rebin_steps_edit.text() + + def get_variable_bin_text(self): + return self.rebin_variable_edit.text()