예제 #1
0
 def test_contour_plot_returns_contour(self):
     ax = plt.subplot(111)
     ax.imshow([[1], [1]])
     ax.contour([[1, 1], [1, 1]])
     if LooseVersion("3.5") <= LooseVersion(matplotlib.__version__):
         self.assertEqual(FigureType.Image, figure_type(ax.figure))
     else:
         self.assertEqual(FigureType.Contour, figure_type(ax.figure))
예제 #2
0
    def set_buttons_visibility(self, fig):
        if figure_type(fig) not in [FigureType.Line, FigureType.Errorbar
                                    ] or len(fig.get_axes()) > 1:
            self.set_fit_enabled(False)
            self.set_superplot_enabled(False)

        # if any of the lines are a sample log plot disable fitting
        for ax in fig.get_axes():
            for artist in ax.get_lines():
                try:
                    if ax.get_artists_sample_log_plot_details(
                            artist) is not None:
                        self.set_fit_enabled(False)
                        break
                except Exception:
                    # The artist is not tracked - ignore this one and check the rest
                    continue

        # For plot-to-script button to show, every axis must be a MantidAxes with lines in it
        # Plot-to-script currently doesn't work with waterfall plots so the button is hidden for that plot type.
        if not all((isinstance(ax, MantidAxes) and curve_in_ax(ax)) for ax in fig.get_axes()) or \
                fig.get_axes()[0].is_waterfall():
            self.set_generate_plot_script_enabled(False)

        # reenable script generation for colormaps
        if self.is_colormap(fig):
            self.set_generate_plot_script_enabled(True)

        # Only show options specific to waterfall plots if the axes is a MantidAxes and is a waterfall plot.
        if not isinstance(fig.get_axes()[0],
                          MantidAxes) or not fig.get_axes()[0].is_waterfall():
            self.set_waterfall_options_enabled(False)

        # For contour and wireframe plots, add a toolbar option to change the colour of the lines.
        if figure_type(fig) in [FigureType.Wireframe, FigureType.Contour]:
            self.set_up_color_selector_toolbar_button(fig)

        if figure_type(fig) in [
                FigureType.Surface, FigureType.Wireframe, FigureType.Mesh
        ]:
            self.adjust_for_3d_plots()

        # Determine the toggle state of the grid button. If all subplots have grids, then set it to on.
        is_major_grid_on = False
        for ax in fig.get_axes():
            # Don't look for grids on colour bars.
            if self._is_colorbar(ax):
                continue
            if hasattr(ax, 'grid_on'):
                is_major_grid_on = ax.grid_on()
            else:
                is_major_grid_on = ax.xaxis._major_tick_kw.get(
                    'gridOn', False) and ax.yaxis._major_tick_kw.get(
                        'gridOn', False)
            # If ANY of the axes have no grid, set the button to unchecked.
            if not is_major_grid_on:
                break
        self._actions['toggle_grid'].setChecked(is_major_grid_on)
예제 #3
0
    def _plot_on_here(self, names, ax):
        """
        Assume the list of strings refer to workspace names and they are to be plotted
        on this figure. If the current figure contains an image plot then
        a new image plot will replace the current image. If the current figure
        contains a line plot then the user will be asked what should be plotted and this
        will overplot onto the figure. If the first line of the plot
        :param names: A list of workspace names
        :param ax: The matplotlib axes object to overplot onto
        """
        if len(names) == 0:
            return
        # local import to avoid circular import with FigureManager
        from mantidqt.plotting.functions import pcolormesh, plot_from_names, plot_surface, plot_wireframe, plot_contour

        fig = self._canvas.figure
        fig_type = figure_type(fig, ax)
        if fig_type == FigureType.Image:
            pcolormesh(names, fig=fig)
        elif fig_type == FigureType.Surface:
            plot_surface(names, fig=fig)
        elif fig_type == FigureType.Wireframe:
            plot_wireframe(names, fig=fig)
        elif fig_type == FigureType.Contour:
            plot_contour(names, fig=fig)
        else:
            plot_from_names(names, errors=(fig_type == FigureType.Errorbar),
                            overplot=ax, fig=fig)
예제 #4
0
    def set_up_color_selector_toolbar_button(self, fig):
        # check if the action is already in the toolbar
        if self._actions.get('line_colour'):
            return

        a = self.addAction(get_icon('mdi.palette'), "Line Colour", lambda: None)
        self._actions['line_colour'] = a

        if figure_type(fig) == FigureType.Wireframe:
            a.setToolTip("Set the colour of the wireframe.")
        else:
            a.setToolTip("Set the colour of the contour lines.")

        line_collection = next(col for col in fig.get_axes()[0].collections if isinstance(col, LineCollection))
        initial_colour = convert_color_to_hex(line_collection.get_color()[0])

        colour_dialog = QtWidgets.QColorDialog(QtGui.QColor(initial_colour))
        colour_dialog.setOption(QtWidgets.QColorDialog.NoButtons)
        colour_dialog.setOption(QtWidgets.QColorDialog.DontUseNativeDialog)
        colour_dialog.currentColorChanged.connect(self.change_line_collection_colour)

        button = [child for child in self.children() if isinstance(child, QtWidgets.QToolButton)][-1]

        menu = QtWidgets.QMenu("Menu", parent=button)
        colour_selector_action = QtWidgets.QWidgetAction(menu)
        colour_selector_action.setDefaultWidget(colour_dialog)
        menu.addAction(colour_selector_action)

        button.setMenu(menu)
        button.setPopupMode(QtWidgets.QToolButton.InstantPopup)
예제 #5
0
    def __init__(self, canvas, axes, axis_id):
        """

        :param canvas: A reference to the target canvas
        :param axes: The axes object holding the properties to be edited
        :param axis_id: A string ID for the axis
        """
        super(AxisEditor, self).__init__('axiseditor.ui', canvas)
        # suppress errors
        self.ui.errors.hide()
        # Ensure that only floats can be entered
        self.ui.editor_min.setValidator(QDoubleValidator())
        self.ui.editor_max.setValidator(QDoubleValidator())
        if figure_type(canvas.figure) == FigureType.Image:
            self.ui.logBox.hide()
            self.ui.gridBox.hide()

        self.axes = axes
        self.axis_id = axis_id
        self.lim_setter = getattr(axes, 'set_{}lim'.format(axis_id))
        self.scale_setter = getattr(axes, 'set_{}scale'.format(axis_id))
        self.linthresholdkw = 'linthres' + axis_id
        # Grid has no direct accessor from the axes
        axis = axes.xaxis if axis_id == 'x' else axes.yaxis

        memento = AxisEditorModel()
        self._memento = memento
        memento.min, memento.max = getattr(axes, 'get_{}lim'.format(axis_id))()
        memento.log = getattr(axes,
                              'get_{}scale'.format(axis_id))() != 'linear'
        memento.grid = axis.majorTicks[0].gridOn

        self._fill(memento)
예제 #6
0
    def __init__(self, canvas, axes, axis_id):
        """

        :param canvas: A reference to the target canvas
        :param axes: The axes object holding the properties to be edited
        :param axis_id: A string ID for the axis
        """
        super(AxisEditor, self).__init__('axiseditor.ui', canvas)
        # suppress errors
        self.ui.errors.hide()
        # Ensure that only floats can be entered
        self.ui.editor_min.setValidator(QDoubleValidator())
        self.ui.editor_max.setValidator(QDoubleValidator())
        if figure_type(
                canvas.figure) in [FigureType.Surface, FigureType.Wireframe]:
            self.ui.logBox.hide()
            self.ui.gridBox.hide()
        self.ui.editor_format.addItem('Decimal Format')
        self.ui.editor_format.addItem('Scientific Format')
        self.axes = axes
        self.axis_id = axis_id
        self.lim_getter = getattr(axes, 'get_{}lim'.format(axis_id))

        if isinstance(axes, Axes3D):
            self.lim_setter = getattr(axes, 'set_{}lim3d'.format(axis_id))
        else:
            self.lim_setter = getattr(axes, 'set_{}lim'.format(axis_id))

        self.scale_setter = getattr(axes, 'set_{}scale'.format(axis_id))
        self.nonposkw = 'nonpos' + axis_id
        # Grid has no direct accessor from the axes
        self.axis = axes.xaxis if axis_id == 'x' else axes.yaxis
예제 #7
0
    def __init__(self, canvas, axes, axis_id):
        """

        :param canvas: A reference to the target canvas
        :param axes: The axes object holding the properties to be edited
        :param axis_id: A string ID for the axis
        """
        super(AxisEditor, self).__init__('axiseditor.ui', canvas)
        # suppress errors
        self.ui.errors.hide()
        # Ensure that only floats can be entered
        self.ui.editor_min.setValidator(QDoubleValidator())
        self.ui.editor_max.setValidator(QDoubleValidator())
        if figure_type(canvas.figure) in [
                FigureType.Surface, FigureType.Wireframe, FigureType.Mesh
        ]:
            self.ui.logBox.hide()
            self.ui.gridBox.hide()
        self.ui.editor_format.addItem(DECIMAL_FORMAT)
        self.ui.editor_format.addItem(SCIENTIFIC_FORMAT)
        self.axes = axes
        self.axis_id = axis_id
        self.lim_getter = getattr(axes, 'get_{}lim'.format(axis_id))

        if isinstance(axes, Axes3D):
            self.lim_setter = getattr(axes, 'set_{}lim3d'.format(axis_id))
        else:
            self.lim_setter = getattr(axes, 'set_{}lim'.format(axis_id))

        self.scale_setter = getattr(axes, 'set_{}scale'.format(axis_id))
        self.nonposkw = 'nonpos' + axis_id
        # Store the axis for attributes that can't be directly accessed
        # from axes object (e.g. grid and tick parameters).
        self.axis = getattr(axes, '{}axis'.format(axis_id))
예제 #8
0
    def __init__(self, canvas, axes, axis_id):
        """

        :param canvas: A reference to the target canvas
        :param axes: The axes object holding the properties to be edited
        :param axis_id: A string ID for the axis
        """
        super(AxisEditor, self).__init__('axiseditor.ui', canvas)
        # suppress errors
        self.ui.errors.hide()
        # Ensure that only floats can be entered
        self.ui.editor_min.setValidator(QDoubleValidator())
        self.ui.editor_max.setValidator(QDoubleValidator())
        if figure_type(canvas.figure) == FigureType.Image:
            self.ui.logBox.hide()
            self.ui.gridBox.hide()

        self.axes = axes
        self.axis_id = axis_id
        self.lim_setter = getattr(axes, 'set_{}lim'.format(axis_id))
        self.scale_setter = getattr(axes, 'set_{}scale'.format(axis_id))
        self.linthresholdkw = 'linthres' + axis_id
        # Grid has no direct accessor from the axes
        axis = axes.xaxis if axis_id == 'x' else axes.yaxis

        memento = AxisEditorModel()
        self._momento = memento
        memento.min, memento.max = getattr(axes, 'get_{}lim'.format(axis_id))()
        memento.log = getattr(axes, 'get_{}scale'.format(axis_id))() != 'linear'
        memento.grid = axis.majorTicks[0].gridOn

        self._fill(memento)
예제 #9
0
    def show(self):
        self.window.show()
        self.window.activateWindow()
        self.window.raise_()
        if self.window.windowState() & Qt.WindowMinimized:
            # windowState() stores a combination of window state enums
            # and multiple window states can be valid. On Windows
            # a window can be both minimized and maximized at the
            # same time, so we make a check here. For more info see:
            # http://doc.qt.io/qt-5/qt.html#WindowState-enum
            if self.window.windowState() & Qt.WindowMaximized:
                self.window.setWindowState(Qt.WindowMaximized)
            else:
                self.window.setWindowState(Qt.WindowNoState)

        # Hack to ensure the canvas is up to date
        self.canvas.draw_idle()
        if figure_type(self.canvas.figure) not in [FigureType.Line, FigureType.Errorbar] \
                or self.toolbar is not None and len(self.canvas.figure.get_axes()) > 1:
            self._set_fit_enabled(False)

        # For plot-to-script button to show, we must have a MantidAxes with lines in it
        # Plot-to-script currently doesn't work with waterfall plots so the button is hidden for that plot type.
        if not any((isinstance(ax, MantidAxes) and curve_in_ax(ax))
                   for ax in self.canvas.figure.get_axes()
                   ) or self.canvas.figure.get_axes()[0].is_waterfall():
            self.toolbar.set_generate_plot_script_enabled(False)

        # Only show options specific to waterfall plots if the axes is a MantidAxes and is a waterfall plot.
        if not isinstance(self.canvas.figure.get_axes()[0],
                          MantidAxes) or not self.canvas.figure.get_axes(
                          )[0].is_waterfall():
            self.toolbar.set_waterfall_options_enabled(False)
예제 #10
0
    def _toggle_normalization(self, selected_ax):
        if figure_type(self.canvas.figure) == FigureType.Image and len(self.canvas.figure.get_axes()) > 1:
            axes = datafunctions.get_axes_from_figure(self.canvas.figure)
        else:
            axes = [selected_ax]

        for ax in axes:
            waterfall = isinstance(ax, MantidAxes) and ax.is_waterfall()
            if waterfall:
                x, y = ax.waterfall_x_offset, ax.waterfall_y_offset
                has_fill = ax.waterfall_has_fill()

                if has_fill:
                    line_colour_fill = datafunctions.waterfall_fill_is_line_colour(ax)
                    if line_colour_fill:
                        fill_colour = None
                    else:
                        fill_colour = datafunctions.get_waterfall_fills(ax)[0].get_facecolor()

                ax.update_waterfall(0, 0)

            # The colorbar can get screwed up with ragged workspaces and log scales as they go
            # through the normalisation toggle.
            # Set it to Linear and change it back after if necessary, since there's no reason
            # to duplicate the handling.
            colorbar_log = False
            if ax.images:
                colorbar_log = isinstance(ax.images[-1].norm, LogNorm)
                if colorbar_log:
                    self._change_colorbar_axes(Normalize)

            self._change_plot_normalization(ax)

            if ax.lines:  # Relim causes issues with colour plots, which have no lines.
                ax.relim()
                ax.autoscale()

            if ax.images:  # Colour bar limits are wrong if workspace is ragged. Set them manually.
                colorbar_min = np.nanmin(ax.images[-1].get_array())
                colorbar_max = np.nanmax(ax.images[-1].get_array())
                for image in ax.images:
                    image.set_clim(colorbar_min, colorbar_max)

                    # Update the colorbar label
                    cb = image.colorbar
                    if cb:
                        datafunctions.add_colorbar_label(cb, ax.get_figure().axes)
                if colorbar_log:  # If it had a log scaled colorbar before, put it back.
                    self._change_colorbar_axes(LogNorm)

                axesfunctions.update_colorplot_datalimits(ax, ax.images)

            datafunctions.set_initial_dimensions(ax)
            if waterfall:
                ax.update_waterfall(x, y)

                if has_fill:
                    ax.set_waterfall_fill(True, fill_colour)

        self.canvas.draw()
예제 #11
0
    def _show_context_menu(self, event):
        """Display a relevant context menu on the canvas
        :param event: The MouseEvent that generated this call
        """
        if not event.inaxes:
            # the current context menus are ony relevant for axes
            return

        fig_type = figure_type(self.canvas.figure)
        if fig_type == FigureType.Empty:
            # Fitting or changing scale types does not make sense in this case
            return

        menu = QMenu()

        if fig_type == FigureType.Image or fig_type == FigureType.Contour:
            if isinstance(event.inaxes, MantidAxes):
                self._add_axes_scale_menu(menu, event.inaxes)
                self._add_normalization_option_menu(menu, event.inaxes)
                self._add_colorbar_axes_scale_menu(menu, event.inaxes)
        elif fig_type == FigureType.Surface:
            self._add_colorbar_axes_scale_menu(menu, event.inaxes)
        elif fig_type != FigureType.Wireframe:
            if self.fit_browser.tool is not None:
                self.fit_browser.add_to_menu(menu)
                menu.addSeparator()
            self._add_axes_scale_menu(menu, event.inaxes)
            if isinstance(event.inaxes, MantidAxes):
                self._add_normalization_option_menu(menu, event.inaxes)
            self.add_error_bars_menu(menu, event.inaxes)
            self._add_marker_option_menu(menu, event)
            self._add_plot_type_option_menu(menu, event.inaxes)

        menu.exec_(QCursor.pos())
예제 #12
0
    def _toggle_normalization(self, ax):
        waterfall = isinstance(ax, MantidAxes) and ax.is_waterfall()
        if waterfall:
            x, y = ax.waterfall_x_offset, ax.waterfall_y_offset
            has_fill = ax.waterfall_has_fill()

            if has_fill:
                line_colour_fill = datafunctions.waterfall_fill_is_line_colour(ax)
                if line_colour_fill:
                    fill_colour = None
                else:
                    fill_colour = datafunctions.get_waterfall_fills(ax)[0].get_facecolor()

            ax.update_waterfall(0, 0)

        is_normalized = self._is_normalized(ax)
        for arg_set in ax.creation_args:
            if arg_set['workspaces'] in ax.tracked_workspaces:
                workspace = ads.retrieve(arg_set['workspaces'])
                arg_set['distribution'] = is_normalized
                arg_set_copy = copy(arg_set)
                [
                    arg_set_copy.pop(key)
                    for key in ['function', 'workspaces', 'autoscale_on_update', 'norm']
                    if key in arg_set_copy.keys()
                ]
                if 'specNum' not in arg_set:
                    if 'wkspIndex' in arg_set:
                        arg_set['specNum'] = workspace.getSpectrum(
                            arg_set.pop('wkspIndex')).getSpectrumNo()
                    else:
                        raise RuntimeError("No spectrum number associated with plot of "
                                           "workspace '{}'".format(workspace.name()))
                # 2D plots have no spec number so remove it
                if figure_type(self.canvas.figure) == FigureType.Image:
                    arg_set_copy.pop('specNum')
                for ws_artist in ax.tracked_workspaces[workspace.name()]:
                    if ws_artist.spec_num == arg_set.get('specNum'):
                        ws_artist.is_normalized = not is_normalized
                        ws_artist.replace_data(workspace, arg_set_copy)
        if ax.lines:  # Relim causes issues with colour plots, which have no lines.
            ax.relim()

        if ax.images:  # Colour bar limits are wrong if workspace is ragged. Set them manually.
            colorbar_min = np.nanmin(ax.images[-1].get_array())
            colorbar_max = np.nanmax(ax.images[-1].get_array())
            for image in ax.images:
                image.set_clim(colorbar_min, colorbar_max)

        ax.autoscale()

        datafunctions.set_initial_dimensions(ax)
        if waterfall:
            ax.update_waterfall(x, y)

            if has_fill:
                ax.set_waterfall_fill(True, fill_colour)

        self.canvas.draw()
예제 #13
0
 def is_colormap(self, fig):
     """Identify as a single colour map if it has a axes, one with the plot and the other the colorbar"""
     if figure_type(fig) in [FigureType.Image] and len(fig.get_axes()) == 2:
         if len(fig.get_axes()[0].get_images()) == 1 and len(fig.get_axes()[1].get_images()) == 0 \
                 and self._is_colorbar(fig.get_axes()[1]):
             return True
     else:
         return False
예제 #14
0
파일: toolbar.py 프로젝트: ethoeng/mantid
    def set_buttons_visiblity(self, fig):
        if figure_type(fig) not in [FigureType.Line, FigureType.Errorbar
                                    ] or len(fig.get_axes()) > 1:
            self.set_fit_enabled(False)

        # if any of the lines are a sample log plot disable fitting
        for ax in fig.get_axes():
            for artist in ax.get_lines():
                try:
                    if ax.get_artists_sample_log_plot_details(
                            artist) is not None:
                        self.set_fit_enabled(False)
                        break
                except Exception:
                    # The artist is not tracked - ignore this one and check the rest
                    continue

        # For plot-to-script button to show, every axis must be a MantidAxes with lines in it
        # Plot-to-script currently doesn't work with waterfall plots so the button is hidden for that plot type.
        if not all((isinstance(ax, MantidAxes) and curve_in_ax(ax)) for ax in fig.get_axes()) or \
                fig.get_axes()[0].is_waterfall():
            self.set_generate_plot_script_enabled(False)

        # reenable script generation for colormaps
        if self.is_colormap(fig):
            self.set_generate_plot_script_enabled(True)

        # Only show options specific to waterfall plots if the axes is a MantidAxes and is a waterfall plot.
        if not isinstance(fig.get_axes()[0],
                          MantidAxes) or not fig.get_axes()[0].is_waterfall():
            self.set_waterfall_options_enabled(False)

        # For contour and wireframe plots, add a toolbar option to change the colour of the lines.
        if figure_type(fig) in [FigureType.Wireframe, FigureType.Contour]:
            self.set_up_color_selector_toolbar_button(fig)

        if figure_type(fig) in [FigureType.Surface, FigureType.Wireframe]:
            self.adjust_for_3d_plots()
예제 #15
0
    def _change_plot_normalization(self, ax):
        is_normalized = self._is_normalized(ax)
        for arg_set in ax.creation_args:
            if arg_set['function'] == 'contour':
                continue

            if arg_set['workspaces'] in ax.tracked_workspaces:
                workspace = ads.retrieve(arg_set['workspaces'])
                arg_set['distribution'] = is_normalized
                arg_set_copy = copy(arg_set)
                [
                    arg_set_copy.pop(key) for key in
                    ['function', 'workspaces', 'autoscale_on_update', 'norm']
                    if key in arg_set_copy.keys()
                ]
                if 'specNum' not in arg_set:
                    if 'wkspIndex' in arg_set:
                        arg_set['specNum'] = workspace.getSpectrum(
                            arg_set.pop('wkspIndex')).getSpectrumNo()
                    else:
                        raise RuntimeError(
                            "No spectrum number associated with plot of "
                            "workspace '{}'".format(workspace.name()))
                # 2D plots have no spec number so remove it
                if figure_type(self.canvas.figure) in [
                        FigureType.Image, FigureType.Contour
                ]:
                    arg_set_copy.pop('specNum')
                for ws_artist in ax.tracked_workspaces[workspace.name()]:
                    if ws_artist.spec_num == arg_set_copy.get('specNum'):
                        ws_artist.is_normalized = not is_normalized

                        # This check is to prevent the contour lines being re-plotted using the colorfill plot args.
                        if isinstance(ws_artist._artists[0], QuadContourSet):
                            contour_line_colour = ws_artist._artists[
                                0].collections[0].get_color()

                            ws_artist.replace_data(workspace, None)

                            # Re-apply the contour line colour
                            for col in ws_artist._artists[0].collections:
                                col.set_color(contour_line_colour)
                        else:
                            ws_artist.replace_data(workspace, arg_set_copy)
예제 #16
0
def can_overplot():
    """
    Checks if overplotting on the current figure can proceed
    with the given options

    :return: A 2-tuple of boolean indicating compatability and
    a string containing an error message if the current figure is not
    compatible.
    """
    compatible = False
    msg = "Unable to overplot on currently active plot type.\n" \
          "Please select another plot."
    fig = current_figure_or_none()
    if fig is not None:
        figtype = figure_type(fig)
        if figtype is FigureType.Line or figtype is FigureType.Errorbar:
            compatible, msg = True, None

    return compatible, msg
예제 #17
0
    def show(self):  # noqa
        self.window.show()
        self.window.activateWindow()
        self.window.raise_()
        if self.window.windowState() & Qt.WindowMinimized:
            # windowState() stores a combination of window state enums
            # and multiple window states can be valid. On Windows
            # a window can be both minimized and maximized at the
            # same time, so we make a check here. For more info see:
            # http://doc.qt.io/qt-5/qt.html#WindowState-enum
            if self.window.windowState() & Qt.WindowMaximized:
                self.window.setWindowState(Qt.WindowMaximized)
            else:
                self.window.setWindowState(Qt.WindowNoState)

        # Hack to ensure the canvas is up to date
        self.canvas.draw_idle()
        if figure_type(self.canvas.figure) not in [FigureType.Line, FigureType.Errorbar]:
            self._set_fit_enabled(False)
예제 #18
0
def can_overplot():
    """
    Checks if overplotting on the current figure can proceed
    with the given options

    :return: A 2-tuple of boolean indicating compatability and
    a string containing an error message if the current figure is not
    compatible.
    """
    compatible = False
    fig = current_figure_or_none()
    if fig is not None:
        figtype = figure_type(fig)
        if figtype in [
                FigureType.Line, FigureType.Errorbar, FigureType.Waterfall
        ]:
            compatible = True

    return compatible
예제 #19
0
def can_overplot():
    """
    Checks if overplotting on the current figure can proceed
    with the given options

    :return: A 2-tuple of boolean indicating compatability and
    a string containing an error message if the current figure is not
    compatible.
    """
    compatible = False
    msg = "Unable to overplot on currently active plot type.\n" \
          "Please select another plot."
    fig = current_figure_or_none()
    if fig is not None:
        figtype = figure_type(fig)
        if figtype is FigureType.Line or figtype is FigureType.Errorbar:
            compatible, msg = True, None

    return compatible, msg
예제 #20
0
    def show(self):  # noqa
        self.window.show()
        self.window.activateWindow()
        self.window.raise_()
        if self.window.windowState() & Qt.WindowMinimized:
            # windowState() stores a combination of window state enums
            # and multiple window states can be valid. On Windows
            # a window can be both minimized and maximized at the
            # same time, so we make a check here. For more info see:
            # http://doc.qt.io/qt-5/qt.html#WindowState-enum
            if self.window.windowState() & Qt.WindowMaximized:
                self.window.setWindowState(Qt.WindowMaximized)
            else:
                self.window.setWindowState(Qt.WindowNoState)

        # Hack to ensure the canvas is up to date
        self.canvas.draw_idle()
        if figure_type(self.canvas.figure) != FigureType.Line:
            self._set_fit_enabled(False)
예제 #21
0
    def _toggle_normalization(self, ax):
        waterfall = isinstance(ax, MantidAxes) and ax.is_waterfall()
        if waterfall:
            x, y = ax.waterfall_x_offset, ax.waterfall_y_offset
            ax.update_waterfall(0, 0)

        is_normalized = self._is_normalized(ax)
        for arg_set in ax.creation_args:
            if arg_set['workspaces'] in ax.tracked_workspaces:
                workspace = ads.retrieve(arg_set['workspaces'])
                arg_set['distribution'] = is_normalized
                arg_set_copy = copy(arg_set)
                [
                    arg_set_copy.pop(key) for key in
                    ['function', 'workspaces', 'autoscale_on_update', 'norm']
                    if key in arg_set_copy.keys()
                ]
                if 'specNum' not in arg_set:
                    if 'wkspIndex' in arg_set:
                        arg_set['specNum'] = workspace.getSpectrum(
                            arg_set.pop('wkspIndex')).getSpectrumNo()
                    else:
                        raise RuntimeError(
                            "No spectrum number associated with plot of "
                            "workspace '{}'".format(workspace.name()))
                # 2D plots have no spec number so remove it
                if figure_type(self.canvas.figure) == FigureType.Image:
                    arg_set_copy.pop('specNum')
                for ws_artist in ax.tracked_workspaces[workspace.name()]:
                    if ws_artist.spec_num == arg_set.get('specNum'):
                        ws_artist.is_normalized = not is_normalized
                        ws_artist.replace_data(workspace, arg_set_copy)
        if ax.lines:  # Relim causes issues with colour plots, which have no lines.
            ax.relim()

        ax.autoscale()

        if waterfall:
            datafunctions.set_initial_dimensions(ax)
            ax.update_waterfall(x, y)

        self.canvas.draw()
예제 #22
0
    def _show_context_menu(self, event):
        """Display a relevant context menu on the canvas
        :param event: The MouseEvent that generated this call
        """
        if not event.inaxes:
            # the current context menus are ony relevant for axes
            return

        fig_type = figure_type(self.canvas.figure)
        if fig_type == FigureType.Empty or fig_type == FigureType.Image:
            # Fitting or changing scale types does not make sense in
            # these cases
            return

        menu = QMenu()
        if self.fit_browser.tool is not None:
            self.fit_browser.add_to_menu(menu)
            menu.addSeparator()
        self._add_axes_scale_menu(menu)
        menu.exec_(QCursor.pos())
예제 #23
0
    def _plot_on_here(self, names):
        """
        Assume the list of strings refer to workspace names and they are to be plotted
        on this figure. If the current figure contains an image plot then
        a new image plot will replace the current image. If the current figure
        contains a line plot then the user will be asked what should be plotted and this
        will overplot onto the figure. If the first line of the plot
        :param names: A list of workspace names
        """
        if len(names) == 0:
            return
        # local import to avoid circular import with FigureManager
        from mantidqt.plotting.functions import pcolormesh_from_names, plot_from_names

        fig = self._canvas.figure
        fig_type = figure_type(fig)
        if fig_type == FigureType.Image:
            pcolormesh_from_names(names, fig=fig)
        else:
            plot_from_names(names, errors=(fig_type == FigureType.Errorbar),
                            overplot=True, fig=fig)
예제 #24
0
    def _show_markers_menu(self, markers, event):
        """
        This is opened when right-clicking on top of a marker.
        The menu will have an entry for each marker near the cursor at the time of clicking.
        The menu will allow deletion and single marker editing
        :param markers: list of markers close to the cursor at the time of clicking
        :param event: The MouseEvent that generated this call
        """
        if not event.inaxes:
            return

        QApplication.restoreOverrideCursor()
        fig_type = figure_type(self.canvas.figure)
        if fig_type == FigureType.Empty or fig_type == FigureType.Image:
            return

        menu = QMenu()

        for marker in markers:
            self._single_marker_menu(menu, marker)

        menu.exec_(QCursor.pos())
예제 #25
0
    def _show_context_menu(self, event):
        """Display a relevant context menu on the canvas
        :param event: The MouseEvent that generated this call
        """
        if not event.inaxes:
            # the current context menus are ony relevant for axes
            return

        fig_type = figure_type(self.canvas.figure)
        if fig_type == FigureType.Empty:
            # Fitting or changing scale types does not make sense in this case
            return

        menu = QMenu()

        if fig_type == FigureType.Image:
            if isinstance(event.inaxes, MantidAxes):
                self._add_axes_scale_menu(menu, event.inaxes)
                self._add_normalization_option_menu(menu, event.inaxes)
                self._add_colorbar_axes_scale_menu(menu, event.inaxes)
        else:
            if self.fit_browser.tool is not None:
                self.fit_browser.add_to_menu(menu)
                menu.addSeparator()
            self._add_axes_scale_menu(menu, event.inaxes)
            if isinstance(event.inaxes, MantidAxes):
                self._add_normalization_option_menu(menu, event.inaxes)
            self.add_error_bars_menu(menu, event.inaxes)
            self._add_marker_option_menu(menu, event)

        # Able to change the plot type to waterfall if there is only one axes, it is a MantidAxes, and there is more
        # than one line on the axes.
        if len(event.inaxes.get_figure().get_axes()) == 1 and isinstance(event.inaxes, MantidAxes)\
                and len(event.inaxes.get_lines()) > 1:
            self._add_plot_type_option_menu(menu, event.inaxes)

        menu.exec_(QCursor.pos())
예제 #26
0
    def show(self):
        self.window.show()
        self.window.activateWindow()
        self.window.raise_()
        if self.window.windowState() & Qt.WindowMinimized:
            # windowState() stores a combination of window state enums
            # and multiple window states can be valid. On Windows
            # a window can be both minimized and maximized at the
            # same time, so we make a check here. For more info see:
            # http://doc.qt.io/qt-5/qt.html#WindowState-enum
            if self.window.windowState() & Qt.WindowMaximized:
                self.window.setWindowState(Qt.WindowMaximized)
            else:
                self.window.setWindowState(Qt.WindowNoState)

        # Hack to ensure the canvas is up to date
        self.canvas.draw_idle()
        if figure_type(self.canvas.figure) not in [FigureType.Line, FigureType.Errorbar]:
            self._set_fit_enabled(False)

        # For plot-to-script button to show, we must have a MantidAxes with lines in it
        if not any((isinstance(ax, MantidAxes) and curve_in_ax(ax))
                   for ax in self.canvas.figure.get_axes()):
            self._set_generate_plot_script_enabled(False)
예제 #27
0
 def test_error_plot_returns_error(self):
     ax = plt.subplot(111)
     ax.errorbar([1], [1], yerr=[0.01])
     self.assertEqual(FigureType.Errorbar, figure_type(ax.figure))
예제 #28
0
 def test_line_plot_returns_line(self):
     ax = plt.subplot(111)
     ax.plot([1])
     self.assertEqual(FigureType.Line, figure_type(ax.figure))
예제 #29
0
 def test_subplot_with_multiple_plots_returns_other(self):
     ax = plt.subplot(221)
     self.assertEqual(FigureType.Other, figure_type(ax.figure))
예제 #30
0
 def test_figure_type_empty_figure_returns_empty(self):
     self.assertEqual(FigureType.Empty, figure_type(plt.figure()))
예제 #31
0
 def test_figure_type_empty_figure_returns_empty(self):
     self.assertEqual(FigureType.Empty, figure_type(plt.figure()))
예제 #32
0
 def test_subplot_with_multiple_plots_returns_other(self):
     ax = plt.subplot(221)
     self.assertEqual(FigureType.Other, figure_type(ax.figure))
예제 #33
0
 def test_mesh_plot_returns_mesh(self):
     a = np.array([[[1, 1, 1], [2, 2, 2], [3, 3, 3]]])
     mesh_polygon = Poly3DCollection(a)
     fig, ax = plt.subplots(subplot_kw={'projection': 'mantid3d'})
     ax.add_collection3d(mesh_polygon)
     self.assertEqual(FigureType.Mesh, figure_type(ax.figure))
예제 #34
0
 def test_error_plot_returns_error(self):
     ax = plt.subplot(111)
     ax.errorbar([1], [1], yerr=[0.01])
     self.assertEqual(FigureType.Errorbar, figure_type(ax.figure))
예제 #35
0
 def test_image_plot_returns_image(self):
     ax = plt.subplot(111)
     ax.imshow([[1], [1]])
     self.assertEqual(FigureType.Image, figure_type(ax.figure))
예제 #36
0
 def test_wireframe_plot_returns_wireframe(self):
     a = np.array([[1]])
     ax = plt.subplot(111, projection='3d')
     ax.plot_wireframe(a, a, a)
     self.assertEqual(FigureType.Wireframe, figure_type(ax.figure))
예제 #37
0
 def test_image_plot_returns_image(self):
     ax = plt.subplot(111)
     ax.imshow([[1], [1]])
     self.assertEqual(FigureType.Image, figure_type(ax.figure))
예제 #38
0
 def show_help_page_for_figure(cls, figure):
     fig_type = figure_type(figure)
     doc_url = HELP_PAGES[fig_type]
     InterfaceManager().showHelpPage(doc_url)
예제 #39
0
 def test_line_plot_returns_line(self):
     ax = plt.subplot(111)
     ax.plot([1])
     self.assertEqual(FigureType.Line, figure_type(ax.figure))