class LoadPresenterTest(unittest.TestCase): def setUp(self): self._view = mock.create_autospec(LoadView) self._load_model = mock.create_autospec(LoadModel) self._co_model = mock.create_autospec(CoLoadModel) self.presenter = LoadPresenter( self._view, self._load_model, self._co_model) self.view = self.presenter.view def test_equalise_last_loaded_run_empty(self): runs = OrderedDict() self.presenter.co_model.loaded_runs = runs self.presenter.load_model.loaded_runs = runs self.presenter.equalise_last_loaded_run(runs) self.assertEqual(self.presenter._current_run, None) def test_equalise_last_loaded_run_data(self): # need to add each in tern for Python 2 runs = OrderedDict() runs[1]=[] runs[2] =[] runs[5] =[] runs[3]=[] self.presenter.co_model.loaded_runs = runs self.presenter.load_model.loaded_runs = runs self.presenter.equalise_last_loaded_run(runs) self.assertEqual(self.presenter._current_run, '3') def test_update_models(self): self.presenter.load_model = LoadModel() self.presenter.co_model = CoLoadModel() test_value = 10 self.presenter.update_models(test_value) self.assertEqual(self.presenter.load_model.run, test_value) self.assertEqual(self.presenter.co_model.run, test_value) def test_enable_buttons(self): self.presenter.enable_buttons() self.assertEqual(self.view.enable_buttons.call_count, 1) def test_disable_buttons(self): self.presenter.disable_buttons() self.assertEqual(self.view.disable_buttons.call_count, 1) def test_set_coadd_loaded_run(self): self.presenter.equalise_last_loaded_run = mock.Mock() runs = OrderedDict() self.presenter.co_model.loaded_runs = runs self.presenter.load_model.loaded_runs = OrderedDict() self.presenter.set_coadd_loaded_run() self.presenter.equalise_last_loaded_run.assert_called_with(runs.keys()) def test_set_loaded_run(self): self.presenter.equalise_last_loaded_run = mock.Mock() runs = OrderedDict() self.presenter.co_model.loaded_runs = OrderedDict() self.presenter.load_model.loaded_runs = runs self.presenter.set_loaded_run() self.presenter.equalise_last_loaded_run.assert_called_with(runs.keys()) def test_end_load_thread(self): self.presenter.set_loaded_run = mock.Mock() self.presenter.enable_buttons = mock.Mock() self.presenter.load_thread = mock.Mock() self.presenter.load_thread.deleteLater = mock.Mock() self.presenter.end_load_thread() self.assertEqual(self.presenter.set_loaded_run.call_count, 1) self.assertEqual(self.presenter.enable_buttons.call_count, 1) self.assertEqual(self.presenter.load_thread, None) def test_end_co_thread(self): self.presenter.set_coadd_loaded_run = mock.Mock() self.presenter.enable_buttons = mock.Mock() self.presenter.co_thread = mock.Mock() self.presenter.co_thread.deleteLater = mock.Mock() self.presenter.end_co_thread() self.assertEqual(self.presenter.set_coadd_loaded_run.call_count, 1) self.assertEqual(self.presenter.enable_buttons.call_count, 1) self.assertEqual(self.presenter.co_thread, None) def test_last_loaded_run(self): self.presenter._current_run = 5 self.assertEquals(self.presenter.last_loaded_run(), 5)
class ElementalAnalysisGui(QtWidgets.QMainWindow): BLUE = 'C0' ORANGE = 'C1' GREEN = 'C2' def __init__(self, parent=None): super(ElementalAnalysisGui, self).__init__(parent) # set menu self.menu = self.menuBar() self.menu.addAction("File") edit_menu = self.menu.addMenu("Edit") edit_menu.addAction("Change Peak Data file", self.select_data_file) self.menu.addAction("Binning") self.menu.addAction("Normalise") # periodic table stuff self.ptable = PeriodicTablePresenter(PeriodicTableView(), PeriodicTableModel()) self.ptable.register_table_lclicked(self.table_left_clicked) self.ptable.register_table_rclicked(self.table_right_clicked) # load stuff self.load_widget = LoadPresenter(LoadView(), LoadModel(), CoLoadModel()) self.load_widget.on_loading_finished(self.loading_finished) # detectors self.detectors = DetectorsPresenter(DetectorsView()) for detector in self.detectors.detectors: detector.on_checkbox_checked(self.add_plot) detector.on_checkbox_unchecked(self.del_plot) # peaks boxes self.peaks = PeaksPresenter(PeaksView()) self.peaks.major.setChecked(True) self.peaks.major.on_checkbox_checked(self.major_peaks_changed) self.peaks.major.on_checkbox_unchecked(self.major_peaks_changed) self.peaks.minor.on_checkbox_checked(self.minor_peaks_changed) self.peaks.minor.on_checkbox_unchecked(self.minor_peaks_changed) self.peaks.gamma.on_checkbox_checked(self.gammas_changed) self.peaks.gamma.on_checkbox_unchecked(self.gammas_changed) self.peaks.electron.on_checkbox_checked(self.electrons_changed) self.peaks.electron.on_checkbox_unchecked(self.electrons_changed) self.peaks.set_deselect_elements_slot(self.deselect_elements) # Line type boxes self.lines = LineSelectorPresenter(LineSelectorView()) self.lines.total.setChecked(True) self.lines.total.on_checkbox_checked(self.line_total_changed) self.lines.total.on_checkbox_unchecked(self.line_total_changed) self.lines.prompt.on_checkbox_checked(self.line_prompt_changed) self.lines.prompt.on_checkbox_unchecked(self.line_prompt_changed) self.lines.delayed.on_checkbox_checked(self.line_delayed_changed) self.lines.delayed.on_checkbox_unchecked(self.line_delayed_changed) # set up self.widget_list = QtWidgets.QVBoxLayout() self.widget_list.addWidget(self.peaks.view) self.widget_list.addWidget(self.lines.view) self.widget_list.addWidget(self.detectors.view) self.widget_list.addWidget(self.load_widget.view) # plotting self.plot_window = None self.num_colors = len(mpl.rcParams['axes.prop_cycle']) self.used_colors = {} # layout self.box = QtWidgets.QHBoxLayout() self.box.addWidget(self.ptable.view) self.box.addLayout(self.widget_list) self.setCentralWidget(QtWidgets.QWidget(self)) self.centralWidget().setLayout(self.box) self.setWindowTitle("Elemental Analysis") self.element_widgets = {} self.element_lines = {} self.electron_peaks = {} self._generate_element_widgets() def get_color(self, element): """ When requesting the colour for a new element, return the first unused colour of the matplotlib default colour cycle (i.e. mpl.rcParams['axes.prop_cycle']). If all colours are used, return the first among the least used ones. That is if C0-4 are all used twice and C5-9 are used once, C5 will be returned. When requesting the colour for an element that is already plotted return the colour of that element. This prevents the same element from being displayed in different colours in separate plots :param element: Chemical symbol of the element that one wants the colour of :return: Matplotlib colour string: C0, C1, ..., C9 to be used as plt.plot(..., color='C3') """ if element in self.used_colors: return self.used_colors[element] occurrences = [ list(self.used_colors.values()).count('C{}'.format(i)) for i in range(self.num_colors) ] color_index = occurrences.index(min(occurrences)) color = "C{}".format(color_index) self.used_colors[element] = color return color def closeEvent(self, event): if self.plot_window is not None: self.plot_window.closeEvent(event) super(ElementalAnalysisGui, self).closeEvent(event) # general functions def _gen_label(self, name, x_value_in, element=None): if element is None: return # check x value is a float try: x_value = float(x_value_in) except: return if name not in self.element_lines[element]: self.element_lines[element].append(name) # make sure the names are strings and x values are numbers return Label(str(name), x_value, False, offset, True, rotation=-90, protected=True) def _plot_line(self, name, x_value_in, color, element=None): label = self._gen_label(name, x_value_in, element) if self.plot_window is None: return for subplot in self.plotting.get_subplots(): self._plot_line_once(subplot, x_value_in, label, color) def _plot_line_once(self, subplot, x_value, label, color): self.plotting.add_vline_and_annotate(subplot, x_value, label, color) def _rm_line(self, name): if self.plot_window is None: return for subplot in self.plotting.get_subplots(): self.plotting.rm_vline_and_annotate(subplot, name) # setup element pop up def _generate_element_widgets(self): self.element_widgets = {} for element in self.ptable.peak_data: data = self.ptable.element_data(element) widget = PeakSelectorPresenter(PeakSelectorView(data, element)) widget.on_finished(self._update_peak_data) self.element_widgets[element] = widget # interact with periodic table def table_right_clicked(self, item): self.element_widgets[item.symbol].view.show() def table_left_clicked(self, item): if self.ptable.is_selected(item.symbol): self._add_element_lines(item.symbol) else: self._remove_element_lines(item.symbol) def _add_element_lines(self, element, data=None): if data is None: data = self.element_widgets[element].get_checked() if element not in self.element_lines: self.element_lines[element] = [] # Select a different color, if all used then use the first color = self.get_color(element) for name, x_value in data.items(): try: x_value = float(x_value) except ValueError: continue full_name = gen_name(element, name) if full_name not in self.element_lines[element]: self.element_lines[element].append(full_name) self._plot_line(full_name, x_value, color, element) def _remove_element_lines(self, element): if element not in self.element_lines: return names = deepcopy(self.element_lines[element]) for name in names: try: self.element_lines[element].remove(name) self._rm_line(name) if not self.element_lines[element]: del self.element_lines[element] if element in self.used_colors: del self.used_colors[element] except: continue if element in self.element_lines and not self.element_lines[element]: del self.element_lines[element] # loading def load_run(self, detector, run): name = "{}; Detector {}".format(run, detector[-1]) if self.plot_window is None: self.plot_window = MultiPlotWindow(str(run)) self.plotting = self.plot_window.multi_plot self.add_detector_to_plot(detector, name) self.plotting.set_all_values() self.plotting.remove_subplot_connection(self.subplot_removed) self.plotting.remove_line_connection(self.uncheck_on_removed) self.plot_window.show() # untick detectors if plot window is closed self.plot_window.windowClosedSignal.connect(self._unset_detectors) else: self.add_detector_to_plot(detector, name) self.plot_window.show() self.plot_window.raise_() def loading_finished(self): last_run = self.load_widget.last_loaded_run() if last_run is None: return # check all detectors are loaded num_detectors = self.load_widget.get_run_num_loaded_detectors(last_run) for j, detector in enumerate(self.detectors.getNames()): if j < num_detectors: self.detectors.enableDetector(detector) else: # disable checkbox and uncheck box self.detectors.disableDetector(detector) self.detectors.setStateQuietly(detector, False) to_plot = deepcopy( [det.isChecked() for det in self.detectors.detectors]) if self.plot_window is None and any(to_plot) is False: return # generate plots - if new run clear old plot(s) and replace it if self.plot_window is None: for name in self.detectors.getNames(): self.detectors.setStateQuietly(name, False) else: for plot in self.plotting.get_subplots(): self.plotting.remove_subplot(plot) for j in range(len(to_plot)): if to_plot[j]: self.detectors.detectors[j].setChecked(True) # detectors def add_detector_to_plot(self, detector, name): self.plotting.add_subplot(detector) ws = mantid.mtd[name] ws.setYUnit('Counts') # find correct detector number from the workspace group run if self.lines.total.isChecked(): self.plotting.plot(detector, ws.name(), spec_num=spectrum_index["Total"], color=self.BLUE) if self.lines.prompt.isChecked(): self.plotting.plot(detector, ws.name(), spec_num=spectrum_index["Prompt"], color=self.ORANGE) if self.lines.delayed.isChecked(): self.plotting.plot(detector, ws.name(), spec_num=spectrum_index["Delayed"], color=self.GREEN) # add current selection of lines for element in self.ptable.selection: self.add_peak_data(element.symbol, detector) def _unset_detectors(self): self.plot_window.windowClosedSignal.disconnect() self.plot_window = None for name in self.detectors.getNames(): self.detectors.setStateQuietly(name, False) self.uncheck_detectors_if_no_line_plotted() # plotting def add_peak_data(self, element, subplot, data=None): # if already selected add to just new plot if data is None: data = self.element_widgets[element].get_checked() color = self.get_color(element) for name, x_value in data.items(): if isinstance(x_value, float): full_name = gen_name(element, name) label = self._gen_label(full_name, x_value, element) self._plot_line_once(subplot, x_value, label, color) def _update_peak_data(self, element): if self.ptable.is_selected(element): # remove all of the lines for the element self._remove_element_lines(element) # add the ticked lines to the plot self._add_element_lines(element) else: self._remove_element_lines(element) def add_plot(self, checkbox): detector = checkbox.name last_run = self.load_widget.last_loaded_run() # not using load_last_run prevents two calls to last_loaded_run() if last_run is not None: self.load_run(detector, last_run) def del_plot(self, checkbox): if self.load_widget.last_loaded_run() is not None: self.plotting.remove_subplot(checkbox.name) if not self.plotting.get_subplots( ) and self.plot_window is not None: self.plot_window.close() self.plot_window = None def subplot_removed(self, name): # need to change the state without sending signal # as the plot has already been removed self.detectors.setStateQuietly(name, False) if not self.plotting.get_subplots(): self.plot_window.close() self.plot_window = None # sets data file for periodic table def select_data_file(self): old_lines = deepcopy(list(self.element_lines.keys())) filename = QtWidgets.QFileDialog.getOpenFileName() if isinstance(filename, tuple): filename = filename[0] filename = str(filename) if filename: self.ptable.set_peak_datafile(filename) try: self._generate_element_widgets() except ValueError: message_box.warning( 'The file does not contain correctly formatted data, resetting to default data file.' 'See "https://docs.mantidproject.org/nightly/interfaces/' 'Muon%20Elemental%20Analysis.html" for more information.') self.ptable.set_peak_datafile(None) self._generate_element_widgets() for element in old_lines: if element in self.element_widgets.keys(): self.ptable.select_element(element) else: self._remove_element_lines(element) self._update_checked_data() def _update_checked_data(self): self.major_peaks_changed(self.peaks.major) self.minor_peaks_changed(self.peaks.minor) self.gammas_changed(self.peaks.gamma) self.electrons_changed(self.peaks.electron) # general checked data def checked_data(self, element, selection, state): for checkbox in selection: checkbox.setChecked(state) self._update_peak_data(element) def electrons_changed(self, electron_peaks): for element, selector in self.element_widgets.items(): self.checked_data(element, selector.electron_checkboxes, electron_peaks.isChecked()) def gammas_changed(self, gamma_peaks): for element, selector in self.element_widgets.items(): self.checked_data(element, selector.gamma_checkboxes, gamma_peaks.isChecked()) def major_peaks_changed(self, major_peaks): for element, selector in self.element_widgets.items(): self.checked_data(element, selector.primary_checkboxes, major_peaks.isChecked()) def minor_peaks_changed(self, minor_peaks): for element, selector in self.element_widgets.items(): self.checked_data(element, selector.secondary_checkboxes, minor_peaks.isChecked()) def deselect_elements(self): self.peaks.disable_deselect_elements_btn() for element in self.element_widgets.keys(): self.ptable.deselect_element(element) self._remove_element_lines(element) self.peaks.enable_deselect_elements_btn() def add_line_by_type(self, run, _type): # Ensure all detectors are enabled last_run = self.load_widget.last_loaded_run() for i, detector in enumerate(self.detectors.detectors): if i < self.load_widget.get_run_num_loaded_detectors(last_run): if not detector.isEnabled(): detector.setEnabled(True) if self.plot_window is None: return # Plot the correct line type on all open subplots if _type == 'Total': color = self.BLUE elif _type == 'Prompt': color = self.ORANGE else: color = self.GREEN for subplot in self.plotting.get_subplots(): name = '{}; Detector {}'.format(run, subplot[-1]) ws = mantid.mtd[name] self.plotting.plot(subplot, ws.name(), spec_num=spectrum_index[_type], color=color) def remove_line_type(self, run, _type): if self.plot_window is None: self.uncheck_detectors_if_no_line_plotted() return # Remove the correct line type on all open subplots for subplot in self.plotting.get_subplots(): name = '{}; Detector {}'.format(run, subplot[-1]) ws = mantid.mtd[name] self.plotting.remove_line(subplot, ws.name(), spec=spectrum_index[_type]) # If no line type is selected do not allow plotting self.uncheck_detectors_if_no_line_plotted() def uncheck_detectors_if_no_line_plotted(self): last_run = self.load_widget.last_loaded_run() if not any([ self.lines.total.isChecked(), self.lines.prompt.isChecked(), self.lines.delayed.isChecked() ]): for i, detector in enumerate(self.detectors.detectors): if i < self.load_widget.get_run_num_loaded_detectors(last_run): detector.setEnabled(False) # When removing a line with the remove window uncheck the line here def uncheck_on_removed(self, removed_lines): if sum([ 1 if detector.isChecked() else 0 for detector in self.detectors.detectors ]) > 1: return for line in removed_lines: if 'Total' in line: self.lines.total.blockSignals(True) self.lines.total.setChecked(False) self.lines.total.blockSignals(False) if 'Prompt' in line: self.lines.prompt.blockSignals(True) self.lines.prompt.setChecked(False) self.lines.prompt.blockSignals(False) if 'Delayed' in line: self.lines.delayed.blockSignals(True) self.lines.delayed.setChecked(False) self.lines.delayed.blockSignals(False) self.uncheck_detectors_if_no_line_plotted() # Line total def line_total_changed(self, line_total): self.lines.total.setChecked(line_total.isChecked()) if line_total.isChecked(): self.add_line_by_type(self.load_widget.last_loaded_run(), 'Total') else: self.remove_line_type(self.load_widget.last_loaded_run(), 'Total') # Line prompt def line_prompt_changed(self, line_prompt): self.lines.prompt.setChecked(line_prompt.isChecked()) if line_prompt.isChecked(): self.add_line_by_type(self.load_widget.last_loaded_run(), 'Prompt') else: self.remove_line_type(self.load_widget.last_loaded_run(), 'Prompt') # Line delayed def line_delayed_changed(self, line_delayed): self.lines.delayed.setChecked(line_delayed.isChecked()) if line_delayed.isChecked(): self.add_line_by_type(self.load_widget.last_loaded_run(), 'Delayed') else: self.remove_line_type(self.load_widget.last_loaded_run(), 'Delayed')
class ElementalAnalysisGui(QtGui.QMainWindow): def __init__(self, parent=None): super(ElementalAnalysisGui, self).__init__(parent) self.menu = self.menuBar() self.menu.addAction("File") edit_menu = self.menu.addMenu("Edit") edit_menu.addAction("Change Peak Data file", self.select_data_file) self.menu.addAction("Binning") self.menu.addAction("Normalise") self.ptable = PeriodicTablePresenter( PeriodicTableView(), PeriodicTableModel()) self.ptable.register_table_lclicked(self.table_left_clicked) self.ptable.register_table_rclicked(self.table_right_clicked) self.load_widget = LoadPresenter( LoadView(), LoadModel(), CoLoadModel()) self.load_widget.on_loading_finished(self.loading_finished) self.widget_list = QtGui.QVBoxLayout() self.detectors = DetectorsPresenter(DetectorsView()) for detector in self.detectors.detectors: detector.on_checkbox_checked(self.add_plot) detector.on_checkbox_unchecked(self.del_plot) self.peaks = PeaksPresenter(PeaksView()) self.peaks.major.on_checkbox_checked(self.major_peaks_checked) self.peaks.major.on_checkbox_unchecked(self.major_peaks_unchecked) self.peaks.minor.on_checkbox_checked(self.minor_peaks_checked) self.peaks.minor.on_checkbox_unchecked(self.minor_peaks_unchecked) self.peaks.gamma.on_checkbox_checked(self.gammas_checked) self.peaks.gamma.on_checkbox_unchecked(self.gammas_unchecked) self.peaks.electron.on_checkbox_checked(self.electrons_checked) self.peaks.electron.on_checkbox_unchecked(self.electrons_unchecked) self.widget_list.addWidget(self.peaks.view) self.widget_list.addWidget(self.detectors.view) self.widget_list.addWidget(self.load_widget.view) self.plotting = PlotPresenter(PlotView()) self.plotting.view.setMinimumSize(self.plotting.view.sizeHint()) self.plotting.removeSubplotConnection(self.subplotRemoved) self.box = QtGui.QHBoxLayout() self.box.addWidget(self.ptable.view) self.box.addLayout(self.widget_list) self.setCentralWidget(QtGui.QWidget(self)) self.centralWidget().setLayout(self.box) self.setWindowTitle("Elemental Analysis") self.element_widgets = {} self.element_data = {} self.element_lines = {} self.gamma_lines = [] self.gamma_peaks = self.ptable.peak_data["Gammas"] self.electron_peaks = self._get_electron_peaks() self.electron_lines = [] self._generate_element_widgets() self._generate_element_data() self.line_colours = cycle(["r", "g", "b", "c", "m", "y"]) def iterate_over_selectors(self, check_state, primary_checkboxes=True): """ Iterates over element popups. :param check_state: True or False - i.e. check boxes or not :param primary_checkboxes: True if Primary, False if Secondary """ for element, selector in iteritems(self.element_widgets): for checkbox in selector.primary_checkboxes if primary_checkboxes else selector.secondary_checkboxes: checkbox.setChecked(check_state) selector.finish_selection() def major_peaks_checked(self): self.iterate_over_selectors(True, primary_checkboxes=True) def major_peaks_unchecked(self): self.iterate_over_selectors(False, primary_checkboxes=True) self.plotting.update_canvas() def minor_peaks_checked(self): self.iterate_over_selectors(True, primary_checkboxes=False) def minor_peaks_unchecked(self): self.iterate_over_selectors(False, primary_checkboxes=False) self.plotting.update_canvas() def _plot_gammas(self, subplot, colour=None): if colour is None: colour = self.line_colours.next() for element, peaks in iteritems(self.gamma_peaks): for peak_type, peak in iteritems(peaks): if peak is None: continue self.gamma_lines.append( subplot.axvline( peak, 0, 1, color=colour)) self.plotting.update_canvas() def _iterate_over_gamma_selectors(self, check_state): for element, selector in iteritems(self.element_widgets): for checkbox in selector.gamma_checkboxes: checkbox.setChecked(check_state) selector.finish_selection() def gammas_checked(self): self._iterate_over_gamma_selectors(True) def gammas_unchecked(self): self._iterate_over_gamma_selectors(False) for line in self.gamma_lines: line.remove() del line self.gamma_lines = [] self.plotting.update_canvas() def _get_electron_peaks(self): return self.ptable.peak_data["Electrons"].copy() def _plot_electrons(self, subplot, colour=None): if colour is None: colour = self.line_colours.next() for peak, intensity in iteritems(self.electron_peaks): # intensity will be used in the future for labelling lines self.electron_lines.append( subplot.axvline( float(peak), 0, 1, color=colour)) self.plotting.update_canvas() def electrons_checked(self): colour = self.line_colours.next() for subplot_name, subplot in iteritems(self.plotting.get_subplots()): self._plot_electrons(subplot, colour=colour) def electrons_unchecked(self): for line in self.electron_lines: line.remove() del line self.electron_lines = [] self.plotting.update_canvas() def load_run(self, detector, run): name = "{}; Detector {}".format(run, detector[-1]) subplot = self.plotting.add_subplot(detector) subplot.set_title(detector) for plot in mantid.mtd[name]: self.plotting.plot(detector, plot) if self.plotting.view.isHidden(): self.plotting.view.show() if self.peaks.gamma.isChecked(): self._plot_gammas(subplot) if self.peaks.electron.isChecked(): self._plot_electrons(subplot) self.plotting.update_canvas() def load_last_run(self, detector): self.load_run(detector, self.load_widget.last_loaded_run()) def loading_finished(self): last_run = self.load_widget.last_loaded_run() if last_run is None: return self.plotting.view.setWindowTitle(str(last_run)) for plot in self.plotting.get_subplots(): self.plotting.remove_subplot(plot) for detector in self.detectors.detectors: if detector.isChecked(): self.load_run(detector.name, last_run) for item in self.ptable.selection: self._add_element_lines( item.symbol, self.element_data[item.symbol]) def _generate_element_data(self): for element in self.ptable.peak_data: if element in ["Gammas", "Electrons"]: continue try: self.element_data[element] = self.ptable.peak_data[element]["Primary"].copy( ) except KeyError: continue def _add_element_line(self, x_value, element, colour="b"): if x_value is None: return for plot_name in self.plotting.get_subplots(): line = self.plotting.get_subplot( plot_name).axvline(x_value, 0, 1, color=colour) try: self.element_lines[element][x_value].append(line) except KeyError: self.element_lines[element][x_value] = [line] self.plotting.update_canvas() def _add_element_lines(self, element, data): self.element_lines[element] = {} colour = self.line_colours.next() for label, x_value in iteritems(data): # label will be used in the future for labelling lines self._add_element_line(x_value, element, colour=colour) def _remove_element_lines(self, element): for x_value, lines in iteritems(self.element_lines[element]): for line in lines: line.remove() del line self.plotting.update_canvas() self.element_lines[element] = {} def _update_element_lines(self, element, current_dict, new_dict): # can be split up: this section removes lines if len(current_dict) > len(new_dict): # i.e. item removed dict_difference = {k: current_dict[k] for k in set(current_dict) - set(new_dict)} for label, x_value in iteritems(dict_difference): # label will be used in the future for labelling lines for line in self.element_lines[element][x_value]: line.remove() del line self.element_lines[element][x_value] = [] del current_dict[label] self.plotting.update_canvas() # can be split up: this section adds lines elif current_dict != new_dict: # i.e. item added or not closed without changes colour = self.line_colours.next() dict_difference = {k: new_dict[k] for k in set(new_dict) - set(current_dict)} for label, x_value in iteritems(dict_difference): # label will be used in the future for labelling lines self._add_element_line(x_value, element, colour) current_dict.update(dict_difference) def _update_peak_data(self, element, data): if self.ptable.is_selected(element): self._update_element_lines( element, self.element_data[element], data) else: self.element_data[element] = data.copy() def _generate_element_widgets(self): self.element_widgets = {} for element in self.ptable.peak_data: if element in ["Gammas", "Electrons"]: continue data = self.ptable.element_data(element) try: data["Gammas"] = self.ptable.peak_data["Gammas"][element] except KeyError: pass widget = PeakSelectorPresenter(PeakSelectorView(data, element)) widget.on_finished(self._update_peak_data) self.element_widgets[element] = widget def table_left_clicked(self, item): if self.ptable.is_selected(item.symbol): self._add_element_lines( item.symbol, self.element_data[item.symbol]) else: self._remove_element_lines(item.symbol) def table_right_clicked(self, item): self.element_widgets[item.symbol].view.show() def _clear_lines(self, lines): for line in lines: line.remove() del line return [] def _clear_lines_after_data_file_selected(self): for element in self.element_lines.keys(): self._remove_element_lines(element) self.electron_lines = self._clear_lines(self.electron_lines) self.gamma_lines = self._clear_lines(self.gamma_lines) for checkbox in self.peaks.peak_checkboxes: checkbox.setChecked(False) def select_data_file(self): filename = QtGui.QFileDialog.getOpenFileName() if isinstance(filename, tuple): filename = filename[0] filename = str(filename) if filename: self.ptable.set_peak_datafile(filename) self._clear_lines_after_data_file_selected() self._generate_element_widgets() self._generate_element_data() def add_plot(self, checkbox): detector = checkbox.name last_run = self.load_widget.last_loaded_run() # not using load_last_run prevents two calls to last_loaded_run() if last_run is not None: self.load_run(detector, last_run) colour = self.line_colours.next() for element in self.ptable.selection: for label, x_value in iteritems(self.element_data[element.symbol]): # label will be used in the future for labelling lines line = self.plotting.get_subplot(detector).axvline( x_value, 1, 0, color=colour) try: self.element_lines[element.symbol][x_value].append(line) except KeyError: self.element_lines[element.symbol][x_value] = [line] self.plotting.update_canvas() def del_plot(self, checkbox): if self.load_widget.last_loaded_run() is not None: self.plotting.remove_subplot(checkbox.name) if not self.plotting.get_subplots(): self.plotting.view.close() def subplotRemoved(self, name): # need to change the state without sending signal # as the plot has already been removed self.detectors.setStateQuietly(name, False)
class ElementalAnalysisGui(QtWidgets.QMainWindow): def __init__(self, parent=None): super(ElementalAnalysisGui, self).__init__(parent) # set menu self.menu = self.menuBar() self.menu.addAction("File") edit_menu = self.menu.addMenu("Edit") edit_menu.addAction("Change Peak Data file", self.select_data_file) self.menu.addAction("Binning") self.menu.addAction("Normalise") # periodic table stuff self.ptable = PeriodicTablePresenter( PeriodicTableView(), PeriodicTableModel()) self.ptable.register_table_lclicked(self.table_left_clicked) self.ptable.register_table_rclicked(self.table_right_clicked) # load stuff self.load_widget = LoadPresenter( LoadView(), LoadModel(), CoLoadModel()) self.load_widget.on_loading_finished(self.loading_finished) # detectors self.detectors = DetectorsPresenter(DetectorsView()) for detector in self.detectors.detectors: detector.on_checkbox_checked(self.add_plot) detector.on_checkbox_unchecked(self.del_plot) # peaks boxes self.peaks = PeaksPresenter(PeaksView()) self.peaks.major.setChecked(True) self.peaks.major.on_checkbox_checked(self.major_peaks_checked) self.peaks.major.on_checkbox_unchecked(self.major_peaks_unchecked) self.peaks.minor.on_checkbox_checked(self.minor_peaks_checked) self.peaks.minor.on_checkbox_unchecked(self.minor_peaks_unchecked) self.peaks.gamma.on_checkbox_checked(self.gammas_checked) self.peaks.gamma.on_checkbox_unchecked(self.gammas_unchecked) self.peaks.electron.on_checkbox_checked(self.electrons_checked) self.peaks.electron.on_checkbox_unchecked(self.electrons_unchecked) # set up self.widget_list = QtWidgets.QVBoxLayout() self.widget_list.addWidget(self.peaks.view) self.widget_list.addWidget(self.detectors.view) self.widget_list.addWidget(self.load_widget.view) # plotting self.plot_window = None # layout self.box = QtWidgets.QHBoxLayout() self.box.addWidget(self.ptable.view) self.box.addLayout(self.widget_list) self.setCentralWidget(QtWidgets.QWidget(self)) self.centralWidget().setLayout(self.box) self.setWindowTitle("Elemental Analysis") self.element_widgets = {} self.element_lines = {} self.electron_peaks = self._get_electron_peaks() self._generate_element_widgets() def closeEvent(self, event): if self.plot_window is not None: self.plot_window.closeEvent(event) super(ElementalAnalysisGui, self).closeEvent(event) # general functions def _gen_label(self, name, x_value_in, element=None): if element is None: return # check x value is a float x_value = 0.0 try: x_value = float(x_value_in) except: return if name not in self.element_lines[element]: self.element_lines[element].append(name) # make sure the names are strings and x values are numbers return Label(str(name), float(x_value), False, offset, True, rotation=-90, protected=True) def _plot_line(self, name, x_value_in, element=None): label = self._gen_label(name, x_value_in, element) if self.plot_window is None: return for subplot in self.plotting.get_subplots(): self.plotting.add_vline_and_annotate( subplot, float(x_value_in), label) def _plot_line_once(self, subplot, x_value, label): self.plotting.add_vline_and_annotate(subplot, float(x_value), label) def _rm_line(self, name): if self.plot_window is None: return for subplot in self.plotting.get_subplots(): self.plotting.rm_vline_and_annotate(subplot, name) # setup element pop up def _generate_element_widgets(self): self.element_widgets = {} for element in self.ptable.peak_data: if element in ["Gammas", "Electrons"]: continue data = self.ptable.element_data(element) try: data["Gammas"] = self.ptable.peak_data["Gammas"][element] except KeyError: pass widget = PeakSelectorPresenter(PeakSelectorView(data, element)) widget.on_finished(self._update_peak_data) self.element_widgets[element] = widget # interact with periodic table def table_right_clicked(self, item): self.element_widgets[item.symbol].view.show() def table_left_clicked(self, item): if self.ptable.is_selected(item.symbol): self._add_element_lines( item.symbol) else: self._remove_element_lines(item.symbol) def _add_element_lines(self, element, data=None): if data is None: data = self.element_widgets[element].get_checked() if element not in self.element_lines: self.element_lines[element] = [] for name, x_value in iteritems(data): full_name = gen_name(element, name) self._plot_line(full_name, x_value, element) def _remove_element_lines(self, element): if element not in self.element_lines: return names = deepcopy(self.element_lines[element]) for name in names: try: self.element_lines[element].remove(name) self._rm_line(name) except: continue # loading def load_run(self, detector, run): name = "{}; Detector {}".format(run, detector[-1]) if self.plot_window is None: self.plot_window = MultiPlotWindow(str(run)) self.plotting = self.plot_window.multi_plot self.add_detector_to_plot(detector, name) self.plotting.set_all_values() self.plotting.removeSubplotConnection(self.subplotRemoved) self.plot_window.show() # untick detectors if plot window is closed self.plot_window.windowClosedSignal.connect(self._unset_detectors) else: self.add_detector_to_plot(detector, name) self.plot_window.show() self.plot_window.raise_() def loading_finished(self): last_run = self.load_widget.last_loaded_run() if last_run is None: return to_plot = deepcopy([det.isChecked() for det in self.detectors.detectors]) if self.plot_window is None and any(to_plot) is False: return # generate plots - if new run clear old plot(s) and replace it if self.plot_window is None: for name in self.detectors.getNames(): self.detectors.setStateQuietly(name, False) else: for plot in self.plotting.get_subplots(): self.plotting.remove_subplot(plot) for j in range(len(to_plot)): if to_plot[j]: self.detectors.detectors[j].setChecked(True) # detectors def add_detector_to_plot(self, detector, name): self.plotting.add_subplot(detector) for ws in mantid.mtd[name]: self.plotting.plot(detector, ws.getName()) # add current selection of lines for element in self.ptable.selection: self.add_peak_data(element.symbol, detector) def _unset_detectors(self): self.plot_window.windowClosedSignal.disconnect() self.plot_window = None for name in self.detectors.getNames(): self.detectors.setStateQuietly(name, False) # plotting def add_peak_data(self, element, subplot, data=None): # if already selected add to just new plot if data is None: data = self.element_widgets[element].get_checked() for name, x_value in iteritems(data): full_name = gen_name(element, name) label = self._gen_label(full_name, x_value, element) self._plot_line_once(subplot, float(x_value), label) def _update_peak_data(self, element, data=None): if self.ptable.is_selected(element): # remove all of the lines for the element self._remove_element_lines(element) # add the ticked lines to the plot self._add_element_lines(element) else: self._remove_element_lines(element) def add_plot(self, checkbox): detector = checkbox.name last_run = self.load_widget.last_loaded_run() # not using load_last_run prevents two calls to last_loaded_run() if last_run is not None: self.load_run(detector, last_run) if self.peaks.electron.isChecked(): self.add_peak_data("e-", detector, data=self.electron_peaks) def del_plot(self, checkbox): if self.load_widget.last_loaded_run() is not None: self.plotting.remove_subplot(checkbox.name) if not self.plotting.get_subplots() and self.plot_window is not None: self.plot_window.close() self.plot_window = None def subplotRemoved(self, name): # need to change the state without sending signal # as the plot has already been removed self.detectors.setStateQuietly(name, False) if not self.plotting.get_subplots(): self.plot_window.close() self.plot_window = None # sets data file for periodic table def select_data_file(self): filename = QtWidgets.QFileDialog.getOpenFileName() if isinstance(filename, tuple): filename = filename[0] filename = str(filename) if filename: self.ptable.set_peak_datafile(filename) # these are commneted out as they are a bug # see issue 25326 #self._clear_lines_after_data_file_selected() self._generate_element_widgets() #self._generate_element_data() # general checked data def checked_data(self, element, selection, state): for checkbox in selection: checkbox.setChecked(state) self._update_peak_data( element, self.element_widgets[element].get_checked()) # electron Peaks def _get_electron_peaks(self): # make a dict so we can label the peaks electron_dict = {} electron_peaks = self.ptable.peak_data["Electrons"].copy() for peak, intensity in iteritems(electron_peaks): electron_dict[str(peak)] = peak return electron_dict def electrons_checked(self): self._add_element_lines("e-", self.electron_peaks) def electrons_unchecked(self): self._remove_element_lines("e-") # gamma Peaks def gammas_checked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.gamma_checkboxes, True) def gammas_unchecked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.gamma_checkboxes, False) # major peaks def major_peaks_checked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.primary_checkboxes, True) def major_peaks_unchecked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.primary_checkboxes, False) # minor peaks def minor_peaks_checked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.secondary_checkboxes, True) def minor_peaks_unchecked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.secondary_checkboxes, False)
class ElementalAnalysisGui(QtWidgets.QMainWindow): def __init__(self, parent=None): super(ElementalAnalysisGui, self).__init__(parent) # set menu self.menu = self.menuBar() self.menu.addAction("File") edit_menu = self.menu.addMenu("Edit") edit_menu.addAction("Change Peak Data file", self.select_data_file) self.menu.addAction("Binning") self.menu.addAction("Normalise") # periodic table stuff self.ptable = PeriodicTablePresenter(PeriodicTableView(), PeriodicTableModel()) self.ptable.register_table_lclicked(self.table_left_clicked) self.ptable.register_table_rclicked(self.table_right_clicked) # load stuff self.load_widget = LoadPresenter(LoadView(), LoadModel(), CoLoadModel()) self.load_widget.on_loading_finished(self.loading_finished) # detectors self.detectors = DetectorsPresenter(DetectorsView()) for detector in self.detectors.detectors: detector.on_checkbox_checked(self.add_plot) detector.on_checkbox_unchecked(self.del_plot) # peaks boxes self.peaks = PeaksPresenter(PeaksView()) self.peaks.major.setChecked(True) self.peaks.major.on_checkbox_checked(self.major_peaks_checked) self.peaks.major.on_checkbox_unchecked(self.major_peaks_unchecked) self.peaks.minor.on_checkbox_checked(self.minor_peaks_checked) self.peaks.minor.on_checkbox_unchecked(self.minor_peaks_unchecked) self.peaks.gamma.on_checkbox_checked(self.gammas_checked) self.peaks.gamma.on_checkbox_unchecked(self.gammas_unchecked) self.peaks.electron.on_checkbox_checked(self.electrons_checked) self.peaks.electron.on_checkbox_unchecked(self.electrons_unchecked) # set up self.widget_list = QtWidgets.QVBoxLayout() self.widget_list.addWidget(self.peaks.view) self.widget_list.addWidget(self.detectors.view) self.widget_list.addWidget(self.load_widget.view) # plotting self.plot_window = None self.colors = ['b', 'g', 'r', 'y', 'c', 'm', 'b'] self.color_index = 0 # layout self.box = QtWidgets.QHBoxLayout() self.box.addWidget(self.ptable.view) self.box.addLayout(self.widget_list) self.setCentralWidget(QtWidgets.QWidget(self)) self.centralWidget().setLayout(self.box) self.setWindowTitle("Elemental Analysis") self.element_widgets = {} self.element_lines = {} self.electron_peaks = self._get_electron_peaks() self._generate_element_widgets() # Return an unused colour, if all used then start with the first one def get_color(self): color = self.colors[self.color_index] self.color_index = (self.color_index + 1) % len(self.colors) return color def closeEvent(self, event): if self.plot_window is not None: self.plot_window.closeEvent(event) super(ElementalAnalysisGui, self).closeEvent(event) # general functions def _gen_label(self, name, x_value_in, element=None): if element is None: return # check x value is a float x_value = 0.0 try: x_value = float(x_value_in) except: return if name not in self.element_lines[element]: self.element_lines[element].append(name) # make sure the names are strings and x values are numbers return Label(str(name), float(x_value), False, offset, True, rotation=-90, protected=True) def _plot_line(self, name, x_value_in, color, element=None): label = self._gen_label(name, x_value_in, element) if self.plot_window is None: return for subplot in self.plotting.get_subplots(): self._plot_line_once(subplot, float(x_value_in), label, color) def _plot_line_once(self, subplot, x_value, label, color): self.plotting.add_vline_and_annotate(subplot, float(x_value), label, color) def _rm_line(self, name): if self.plot_window is None: return for subplot in self.plotting.get_subplots(): self.plotting.rm_vline_and_annotate(subplot, name) # setup element pop up def _generate_element_widgets(self): self.element_widgets = {} for element in self.ptable.peak_data: if element in ["Gammas", "Electrons"]: continue data = self.ptable.element_data(element) try: data["Gammas"] = self.ptable.peak_data["Gammas"][element] except KeyError: pass widget = PeakSelectorPresenter(PeakSelectorView(data, element)) widget.on_finished(self._update_peak_data) self.element_widgets[element] = widget # interact with periodic table def table_right_clicked(self, item): self.element_widgets[item.symbol].view.show() def table_left_clicked(self, item): if self.ptable.is_selected(item.symbol): self._add_element_lines(item.symbol) else: self._remove_element_lines(item.symbol) def _add_element_lines(self, element, data=None): if data is None: data = self.element_widgets[element].get_checked() if element not in self.element_lines: self.element_lines[element] = [] # Select a different color, if all used then use the first color = self.get_color() for name, x_value in iteritems(data): full_name = gen_name(element, name) self._plot_line(full_name, x_value, color, element) def _remove_element_lines(self, element): if element not in self.element_lines: return names = deepcopy(self.element_lines[element]) for name in names: try: self.element_lines[element].remove(name) self._rm_line(name) except: continue # loading def load_run(self, detector, run): name = "{}; Detector {}".format(run, detector[-1]) if self.plot_window is None: self.plot_window = MultiPlotWindow(str(run)) self.plotting = self.plot_window.multi_plot self.add_detector_to_plot(detector, name) self.plotting.set_all_values() self.plotting.removeSubplotConnection(self.subplotRemoved) self.plot_window.show() # untick detectors if plot window is closed self.plot_window.windowClosedSignal.connect(self._unset_detectors) else: self.add_detector_to_plot(detector, name) self.plot_window.show() self.plot_window.raise_() def loading_finished(self): last_run = self.load_widget.last_loaded_run() if last_run is None: return to_plot = deepcopy( [det.isChecked() for det in self.detectors.detectors]) if self.plot_window is None and any(to_plot) is False: return # generate plots - if new run clear old plot(s) and replace it if self.plot_window is None: for name in self.detectors.getNames(): self.detectors.setStateQuietly(name, False) else: for plot in self.plotting.get_subplots(): self.plotting.remove_subplot(plot) for j in range(len(to_plot)): if to_plot[j]: self.detectors.detectors[j].setChecked(True) # detectors def add_detector_to_plot(self, detector, name): self.plotting.add_subplot(detector) for ws in mantid.mtd[name]: self.plotting.plot(detector, ws.getName()) # add current selection of lines for element in self.ptable.selection: self.add_peak_data(element.symbol, detector) def _unset_detectors(self): self.plot_window.windowClosedSignal.disconnect() self.plot_window = None for name in self.detectors.getNames(): self.detectors.setStateQuietly(name, False) # plotting def add_peak_data(self, element, subplot, data=None): # if already selected add to just new plot if data is None: data = self.element_widgets[element].get_checked() color = self.get_color() for name, x_value in iteritems(data): full_name = gen_name(element, name) label = self._gen_label(full_name, x_value, element) self._plot_line_once(subplot, float(x_value), label, color) def _update_peak_data(self, element, data=None): if self.ptable.is_selected(element): # remove all of the lines for the element self._remove_element_lines(element) # add the ticked lines to the plot self._add_element_lines(element) else: self._remove_element_lines(element) def add_plot(self, checkbox): detector = checkbox.name last_run = self.load_widget.last_loaded_run() # not using load_last_run prevents two calls to last_loaded_run() if last_run is not None: self.load_run(detector, last_run) if self.peaks.electron.isChecked(): self.add_peak_data("e-", detector, data=self.electron_peaks) def del_plot(self, checkbox): if self.load_widget.last_loaded_run() is not None: self.plotting.remove_subplot(checkbox.name) if not self.plotting.get_subplots( ) and self.plot_window is not None: self.plot_window.close() self.plot_window = None def subplotRemoved(self, name): # need to change the state without sending signal # as the plot has already been removed self.detectors.setStateQuietly(name, False) if not self.plotting.get_subplots(): self.plot_window.close() self.plot_window = None # sets data file for periodic table def select_data_file(self): filename = QtWidgets.QFileDialog.getOpenFileName() if isinstance(filename, tuple): filename = filename[0] filename = str(filename) if filename: self.ptable.set_peak_datafile(filename) # these are commneted out as they are a bug # see issue 25326 #self._clear_lines_after_data_file_selected() self._generate_element_widgets() #self._generate_element_data() # general checked data def checked_data(self, element, selection, state): for checkbox in selection: checkbox.setChecked(state) self._update_peak_data(element, self.element_widgets[element].get_checked()) # electron Peaks def _get_electron_peaks(self): # make a dict so we can label the peaks electron_dict = {} electron_peaks = self.ptable.peak_data["Electrons"].copy() for peak, intensity in iteritems(electron_peaks): electron_dict[str(peak)] = peak return electron_dict def electrons_checked(self): self._add_element_lines("e-", self.electron_peaks) def electrons_unchecked(self): self._remove_element_lines("e-") # gamma Peaks def gammas_checked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.gamma_checkboxes, True) def gammas_unchecked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.gamma_checkboxes, False) # major peaks def major_peaks_checked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.primary_checkboxes, True) def major_peaks_unchecked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.primary_checkboxes, False) # minor peaks def minor_peaks_checked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.secondary_checkboxes, True) def minor_peaks_unchecked(self): for element, selector in iteritems(self.element_widgets): self.checked_data(element, selector.secondary_checkboxes, False)
class ElementalAnalysisGui(QtGui.QMainWindow): def __init__(self, parent=None): super(ElementalAnalysisGui, self).__init__(parent) self.menu = self.menuBar() self.menu.addAction("File") edit_menu = self.menu.addMenu("Edit") edit_menu.addAction("Change Peak Data file", self.select_data_file) self.menu.addAction("Binning") self.menu.addAction("Normalise") self.ptable = PeriodicTablePresenter(PeriodicTableView(), PeriodicTableModel()) self.ptable.register_table_lclicked(self.table_left_clicked) self.ptable.register_table_rclicked(self.table_right_clicked) self.load_widget = LoadPresenter(LoadView(), LoadModel(), CoLoadModel()) self.load_widget.on_loading_finished(self.loading_finished) self.widget_list = QtGui.QVBoxLayout() self.detectors = DetectorsPresenter(DetectorsView()) for detector in self.detectors.detectors: detector.on_checkbox_checked(self.add_plot) detector.on_checkbox_unchecked(self.del_plot) self.peaks = PeaksPresenter(PeaksView()) self.peaks.major.on_checkbox_checked(self.major_peaks_checked) self.peaks.major.on_checkbox_unchecked(self.major_peaks_unchecked) self.peaks.minor.on_checkbox_checked(self.minor_peaks_checked) self.peaks.minor.on_checkbox_unchecked(self.minor_peaks_unchecked) self.peaks.gamma.on_checkbox_checked(self.gammas_checked) self.peaks.gamma.on_checkbox_unchecked(self.gammas_unchecked) self.peaks.electron.on_checkbox_checked(self.electrons_checked) self.peaks.electron.on_checkbox_unchecked(self.electrons_unchecked) self.widget_list.addWidget(self.peaks.view) self.widget_list.addWidget(self.detectors.view) self.widget_list.addWidget(self.load_widget.view) self.plotting = PlotPresenter(PlotView()) self.plotting.view.setMinimumSize(self.plotting.view.sizeHint()) self.box = QtGui.QHBoxLayout() self.box.addWidget(self.ptable.view) self.box.addLayout(self.widget_list) self.setCentralWidget(QtGui.QWidget(self)) self.centralWidget().setLayout(self.box) self.setWindowTitle("Elemental Analysis") self.element_widgets = {} self.element_data = {} self.element_lines = {} self.gamma_lines = [] self.gamma_peaks = self.ptable.peak_data["Gammas"] self.electron_peaks = self._get_electron_peaks() self.electron_lines = [] self._generate_element_widgets() self._generate_element_data() self.line_colours = cycle(["r", "g", "b", "c", "m", "y"]) def iterate_over_selectors(self, check_state, primary_checkboxes=True): """ Iterates over element popups. :param check_state: True or False - i.e. check boxes or not :param primary_checkboxes: True if Primary, False if Secondary """ for element, selector in iteritems(self.element_widgets): for checkbox in selector.primary_checkboxes if primary_checkboxes else selector.secondary_checkboxes: checkbox.setChecked(check_state) selector.finish_selection() def major_peaks_checked(self): self.iterate_over_selectors(True, primary_checkboxes=True) def major_peaks_unchecked(self): self.iterate_over_selectors(False, primary_checkboxes=True) self.plotting.update_canvas() def minor_peaks_checked(self): self.iterate_over_selectors(True, primary_checkboxes=False) def minor_peaks_unchecked(self): self.iterate_over_selectors(False, primary_checkboxes=False) self.plotting.update_canvas() def _plot_gammas(self, subplot, colour=None): if colour is None: colour = self.line_colours.next() for element, peaks in iteritems(self.gamma_peaks): for peak_type, peak in iteritems(peaks): if peak is None: continue self.gamma_lines.append( subplot.axvline(peak, 0, 1, color=colour)) self.plotting.update_canvas() def _iterate_over_gamma_selectors(self, check_state): for element, selector in iteritems(self.element_widgets): for checkbox in selector.gamma_checkboxes: checkbox.setChecked(check_state) selector.finish_selection() def gammas_checked(self): self._iterate_over_gamma_selectors(True) def gammas_unchecked(self): self._iterate_over_gamma_selectors(False) for line in self.gamma_lines: line.remove() del line self.gamma_lines = [] self.plotting.update_canvas() def _get_electron_peaks(self): return self.ptable.peak_data["Electrons"].copy() def _plot_electrons(self, subplot, colour=None): if colour is None: colour = self.line_colours.next() for peak, intensity in iteritems(self.electron_peaks): # intensity will be used in the future for labelling lines self.electron_lines.append( subplot.axvline(float(peak), 0, 1, color=colour)) self.plotting.update_canvas() def electrons_checked(self): colour = self.line_colours.next() for subplot_name, subplot in iteritems(self.plotting.get_subplots()): self._plot_electrons(subplot, colour=colour) def electrons_unchecked(self): for line in self.electron_lines: line.remove() del line self.electron_lines = [] self.plotting.update_canvas() def load_run(self, detector, run): name = "{}; Detector {}".format(run, detector[-1]) subplot = self.plotting.add_subplot(detector) subplot.set_title(detector) for plot in mantid.mtd[name]: self.plotting.plot(detector, plot) if self.plotting.view.isHidden(): self.plotting.view.show() if self.peaks.gamma.isChecked(): self._plot_gammas(subplot) if self.peaks.electron.isChecked(): self._plot_electrons(subplot) self.plotting.update_canvas() def load_last_run(self, detector): self.load_run(detector, self.load_widget.last_loaded_run()) def loading_finished(self): last_run = self.load_widget.last_loaded_run() if last_run is None: return self.plotting.view.setWindowTitle(str(last_run)) for plot in self.plotting.get_subplots(): self.plotting.remove_subplot(plot) for detector in self.detectors.detectors: if detector.isChecked(): self.load_run(detector.name, last_run) for item in self.ptable.selection: self._add_element_lines(item.symbol, self.element_data[item.symbol]) def _generate_element_data(self): for element in self.ptable.peak_data: if element in ["Gammas", "Electrons"]: continue try: self.element_data[element] = self.ptable.peak_data[element][ "Primary"].copy() except KeyError: continue def _add_element_line(self, x_value, element, colour="b"): if x_value is None: return for plot_name in self.plotting.get_subplots(): line = self.plotting.get_subplot(plot_name).axvline(x_value, 0, 1, color=colour) try: self.element_lines[element][x_value].append(line) except KeyError: self.element_lines[element][x_value] = [line] self.plotting.update_canvas() def _add_element_lines(self, element, data): self.element_lines[element] = {} colour = self.line_colours.next() for label, x_value in iteritems(data): # label will be used in the future for labelling lines self._add_element_line(x_value, element, colour=colour) def _remove_element_lines(self, element): for x_value, lines in iteritems(self.element_lines[element]): for line in lines: line.remove() del line self.plotting.update_canvas() self.element_lines[element] = {} def _update_element_lines(self, element, current_dict, new_dict): # can be split up: this section removes lines if len(current_dict) > len(new_dict): # i.e. item removed dict_difference = { k: current_dict[k] for k in set(current_dict) - set(new_dict) } for label, x_value in iteritems(dict_difference): # label will be used in the future for labelling lines for line in self.element_lines[element][x_value]: line.remove() del line self.element_lines[element][x_value] = [] del current_dict[label] self.plotting.update_canvas() # can be split up: this section adds lines elif current_dict != new_dict: # i.e. item added or not closed without changes colour = self.line_colours.next() dict_difference = { k: new_dict[k] for k in set(new_dict) - set(current_dict) } for label, x_value in iteritems(dict_difference): # label will be used in the future for labelling lines self._add_element_line(x_value, element, colour) current_dict.update(dict_difference) def _update_peak_data(self, element, data): if self.ptable.is_selected(element): self._update_element_lines(element, self.element_data[element], data) else: self.element_data[element] = data.copy() def _generate_element_widgets(self): self.element_widgets = {} for element in self.ptable.peak_data: if element in ["Gammas", "Electrons"]: continue data = self.ptable.element_data(element) try: data["Gammas"] = self.ptable.peak_data["Gammas"][element] except KeyError: pass widget = PeakSelectorPresenter(PeakSelectorView(data, element)) widget.on_finished(self._update_peak_data) self.element_widgets[element] = widget def table_left_clicked(self, item): if self.ptable.is_selected(item.symbol): self._add_element_lines(item.symbol, self.element_data[item.symbol]) else: self._remove_element_lines(item.symbol) def table_right_clicked(self, item): self.element_widgets[item.symbol].view.show() def _clear_lines(self, lines): for line in lines: line.remove() del line return [] def _clear_lines_after_data_file_selected(self): for element in self.element_lines.keys(): self._remove_element_lines(element) self.electron_lines = self._clear_lines(self.electron_lines) self.gamma_lines = self._clear_lines(self.gamma_lines) for checkbox in self.peaks.peak_checkboxes: checkbox.setChecked(False) def select_data_file(self): filename = str(QtGui.QFileDialog.getOpenFileName()) if filename: self.ptable.set_peak_datafile(filename) self._clear_lines_after_data_file_selected() self._generate_element_widgets() self._generate_element_data() def add_plot(self, checkbox): detector = checkbox.name last_run = self.load_widget.last_loaded_run() # not using load_last_run prevents two calls to last_loaded_run() if last_run is not None: self.load_run(detector, last_run) colour = self.line_colours.next() for element in self.ptable.selection: for label, x_value in iteritems(self.element_data[element.symbol]): # label will be used in the future for labelling lines line = self.plotting.get_subplot(detector).axvline( x_value, 1, 0, color=colour) try: self.element_lines[element.symbol][x_value].append(line) except KeyError: self.element_lines[element.symbol][x_value] = [line] self.plotting.update_canvas() def del_plot(self, checkbox): if self.load_widget.last_loaded_run() is not None: self.plotting.remove_subplot(checkbox.name) if not self.plotting.get_subplots(): self.plotting.view.close()