Source code for schrodinger.ui.qt.figureoptions
# -*- coding: utf-8 -*-
#
# Copyright © 2009 Pierre Raybaut
# Licensed under the terms of the MIT License
# see the mpl licenses directory for a copy of the license
"""Module that provides a GUI-based editor for matplotlib's figure options"""
import os.path as osp
import matplotlib.backends.qt_editor.formlayout as formlayout
from matplotlib import markers
from matplotlib.backends.qt_compat import QtGui
[docs]def get_icon(name):
    import matplotlib
    basedir = osp.join(matplotlib.rcParams['datapath'], 'images')
    return QtGui.QIcon(osp.join(basedir, name))
LINESTYLES = {
    '-': 'Solid',
    '--': 'Dashed',
    '-.': 'DashDot',
    ':': 'Dotted',
    'steps': 'Steps',
    'none': 'None',
}
MARKERS = markers.MarkerStyle.markers
COLORS = {
    'b': '#0000ff',
    'g': '#00ff00',
    'r': '#ff0000',
    'c': '#ff00ff',
    'm': '#ff00ff',
    'y': '#ffff00',
    'k': '#000000',
    'w': '#ffffff'
}
def _get_scale_options(default, allow_log, allow_linear):
    scale_options = [default]
    if allow_linear:
        scale_options.append('linear')
    if allow_log:
        scale_options.append('log')
    return scale_options
[docs]def figure_edit(axes, parent=None, allow_log=True, allow_linear=True):
    """Edit matplotlib figure options"""
    sep = (None, None)  # separator
    has_curve = len(axes.get_lines()) > 0
    xscale_options = _get_scale_options(axes.get_xscale(), allow_log,
                                        allow_linear)
    yscale_options = _get_scale_options(axes.get_yscale(), allow_log,
                                        allow_linear)
    # Get / General
    xmin, xmax = axes.get_xlim()
    ymin, ymax = axes.get_ylim()
    general = [('Title', axes.get_title()), sep, (None, "<b>X-Axis</b>"),
               ('Min', xmin), ('Max', xmax), ('Label', axes.get_xlabel()),
               ('Scale', xscale_options), sep, (None, "<b>Y-Axis</b>"),
               ('Min', ymin), ('Max', ymax), ('Label', axes.get_ylabel()),
               ('Scale', yscale_options)]
    if has_curve:
        # Get / Curves
        linedict = {}
        for line in axes.get_lines():
            label = line.get_label()
            if label == '_nolegend_':
                continue
            linedict[label] = line
        curves = []
        linestyles = list(LINESTYLES.items())
        markers = list(MARKERS.items())
        curvelabels = sorted(list(linedict))
        for label in curvelabels:
            line = linedict[label]
            curvedata = [
                ('Label', label),
                sep,
                (None, '<b>Line</b>'),
                ('Style', [line.get_linestyle()] + linestyles),
                ('Width', line.get_linewidth()),
                ('Color', col2hex(line.get_color())),
                sep,
                (None, '<b>Marker</b>'),
                ('Style', [line.get_marker()] + markers),
                ('Size', line.get_markersize()),
                ('Facecolor', col2hex(line.get_markerfacecolor())),
                ('Edgecolor', col2hex(line.get_markeredgecolor())),
            ]
            curves.append([curvedata, label, ""])
    datalist = [(general, "Axes", "")]
    if has_curve:
        datalist.append((curves, "Curves", ""))
    def apply_callback(data):
        """This function will be called to apply changes"""
        if has_curve:
            general, curves = data
        else:
            general, = data
        # Set / General
        title, xmin, xmax, xlabel, xscale, ymin, ymax, ylabel, yscale = general
        if axes.get_xscale() != xscale:
            axes.set_xscale(xscale)
        if axes.get_yscale() != yscale:
            axes.set_yscale(yscale)
        axes.set_title(title)
        axes.set_xlim(xmin, xmax)
        axes.set_xlabel(xlabel)
        axes.set_ylim(ymin, ymax)
        axes.set_ylabel(ylabel)
        if has_curve:
            # Set / Curves
            for index, curve in enumerate(curves):
                line = linedict[curvelabels[index]]
                label, linestyle, linewidth, color, \
                    marker, markersize, markerfacecolor, markeredgecolor = curve
                line.set_label(label)
                line.set_linestyle(linestyle)
                line.set_linewidth(linewidth)
                line.set_color(color)
                if marker != 'none':
                    line.set_marker(marker)
                    line.set_markersize(markersize)
                    line.set_markerfacecolor(markerfacecolor)
                    line.set_markeredgecolor(markeredgecolor)
            # Recalculate the color and style of legend artists - note, this
            # does not work for multiple legends on the same figure.  But it's
            # an improvement over the current situation of not working for any
            # legends.
            figure = axes.get_figure()
            all_axes = figure.get_axes()
            for legend in figure.legends:
                # Need to gather all the legend items from all the subplots
                all_handles = []
                all_labels = []
                for one_axes in all_axes:
                    handles, labels = one_axes.get_legend_handles_labels()
                    all_handles.extend(handles)
                    all_labels.extend(labels)
                # Location and title are altered by the _init_legend_box
                # function, so preserve the current values
                loc = legend._loc
                title = legend.get_title().get_text()
                if title == 'None':
                    title = None
                # This function recalculates colors and styles
                legend._init_legend_box(all_handles, all_labels)
                legend._loc = loc
                legend.set_title(title)
            # Redraw
        figure = axes.get_figure()
        figure.canvas.draw()
    data = formlayout.fedit(datalist,
                            title="Figure options",
                            parent=parent,
                            icon=get_icon('qt4_editor_options.svg'),
                            apply=apply_callback)
    if data is not None:
        apply_callback(data)