From e45e9460e998bb1f718953bf006c12d86ddf1059 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 12 Nov 2015 01:24:12 -0800 Subject: [PATCH] Set image cmap from figure options. This patch allows the user to interactively set an image's colormap from the axes and lines (and now images) parameters editor (in the Qt backend). Colormaps are listed from those registered with matplotlib.cm. Colorbars seem to be handled properly. --- lib/matplotlib/axes/_base.py | 2 + lib/matplotlib/backends/backend_qt5.py | 2 +- .../backends/qt_editor/figureoptions.py | 198 ++++++++++-------- 3 files changed, 115 insertions(+), 87 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index fa0a42f17c99..dec202cdef9e 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1703,6 +1703,8 @@ def add_image(self, image): Returns the image. """ self._set_artist_props(image) + if not image.get_label(): + image.set_label('_image%d' % len(self.images)) self.images.append(image) image._remove_method = lambda h: self.images.remove(h) return image diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index cea7b5d7b21c..fc24fe186f1d 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -587,7 +587,7 @@ def _init_toolbar(self): if figureoptions is not None: a = self.addAction(self._icon("qt4_editor_options.png"), 'Customize', self.edit_parameters) - a.setToolTip('Edit curves line and axes parameters') + a.setToolTip('Edit axis, curve and image parameters') self.buttons = {} diff --git a/lib/matplotlib/backends/qt_editor/figureoptions.py b/lib/matplotlib/backends/qt_editor/figureoptions.py index f2fc9e115efc..566c06d8bfb5 100644 --- a/lib/matplotlib/backends/qt_editor/figureoptions.py +++ b/lib/matplotlib/backends/qt_editor/figureoptions.py @@ -16,7 +16,7 @@ import matplotlib.backends.qt_editor.formlayout as formlayout from matplotlib.backends.qt_compat import QtGui -from matplotlib import markers +from matplotlib import cm, markers from matplotlib.colors import colorConverter, rgb2hex @@ -43,8 +43,6 @@ def figure_edit(axes, parent=None): """Edit matplotlib figure options""" sep = (None, None) # separator - has_curve = len(axes.get_lines()) > 0 - # Get / General xmin, xmax = map(float, axes.get_xlim()) ymin, ymax = map(float, axes.get_ylim()) @@ -69,79 +67,103 @@ def figure_edit(axes, parent=None): xunits = axes.xaxis.get_units() yunits = axes.yaxis.get_units() - if has_curve: - # Get / Curves - linedict = {} - for line in axes.get_lines(): - label = line.get_label() - if label == '_nolegend_': - continue - linedict[label] = line - curves = [] - - def prepare_data(d, init): - """Prepare entry for FormLayout. - - `d` is a mapping of shorthands to style names (a single style may - have multiple shorthands, in particular the shorthands `None`, - `"None"`, `"none"` and `""` are synonyms); `init` is one shorthand - of the initial style. - - This function returns an list suitable for initializing a - FormLayout combobox, namely `[initial_name, (shorthand, - style_name), (shorthand, style_name), ...]`. - """ - # Drop duplicate shorthands from dict (by overwriting them during - # the dict comprehension). - name2short = {name: short for short, name in d.items()} - # Convert back to {shorthand: name}. - short2name = {short: name for name, short in name2short.items()} - # Find the kept shorthand for the style specified by init. - canonical_init = name2short[d[init]] - # Sort by representation and prepend the initial value. - return ([canonical_init] + - sorted(short2name.items(), - key=lambda short_and_name: short_and_name[1])) - - curvelabels = sorted(linedict.keys()) - for label in curvelabels: - line = linedict[label] - color = rgb2hex(colorConverter.to_rgb(line.get_color())) - ec = rgb2hex(colorConverter.to_rgb(line.get_markeredgecolor())) - fc = rgb2hex(colorConverter.to_rgb(line.get_markerfacecolor())) - curvedata = [ - ('Label', label), - sep, - (None, 'Line'), - ('Line Style', prepare_data(LINESTYLES, line.get_linestyle())), - ('Draw Style', prepare_data(DRAWSTYLES, line.get_drawstyle())), - ('Width', line.get_linewidth()), - ('Color', color), - sep, - (None, 'Marker'), - ('Style', prepare_data(MARKERS, line.get_marker())), - ('Size', line.get_markersize()), - ('Facecolor', fc), - ('Edgecolor', ec)] - curves.append([curvedata, label, ""]) - - # make sure that there is at least one displayed curve - has_curve = bool(curves) + # Get / Curves + linedict = {} + for line in axes.get_lines(): + label = line.get_label() + if label == '_nolegend_': + continue + linedict[label] = line + curves = [] + + def prepare_data(d, init): + """Prepare entry for FormLayout. + + `d` is a mapping of shorthands to style names (a single style may + have multiple shorthands, in particular the shorthands `None`, + `"None"`, `"none"` and `""` are synonyms); `init` is one shorthand + of the initial style. + + This function returns an list suitable for initializing a + FormLayout combobox, namely `[initial_name, (shorthand, + style_name), (shorthand, style_name), ...]`. + """ + # Drop duplicate shorthands from dict (by overwriting them during + # the dict comprehension). + name2short = {name: short for short, name in d.items()} + # Convert back to {shorthand: name}. + short2name = {short: name for name, short in name2short.items()} + # Find the kept shorthand for the style specified by init. + canonical_init = name2short[d[init]] + # Sort by representation and prepend the initial value. + return ([canonical_init] + + sorted(short2name.items(), + key=lambda short_and_name: short_and_name[1])) + + curvelabels = sorted(linedict.keys()) + for label in curvelabels: + line = linedict[label] + color = rgb2hex(colorConverter.to_rgb(line.get_color())) + ec = rgb2hex(colorConverter.to_rgb(line.get_markeredgecolor())) + fc = rgb2hex(colorConverter.to_rgb(line.get_markerfacecolor())) + curvedata = [ + ('Label', label), + sep, + (None, 'Line'), + ('Line Style', prepare_data(LINESTYLES, line.get_linestyle())), + ('Draw Style', prepare_data(DRAWSTYLES, line.get_drawstyle())), + ('Width', line.get_linewidth()), + ('Color', color), + sep, + (None, 'Marker'), + ('Style', prepare_data(MARKERS, line.get_marker())), + ('Size', line.get_markersize()), + ('Facecolor', fc), + ('Edgecolor', ec)] + curves.append([curvedata, label, ""]) + # Is there a curve displayed? + has_curve = bool(curves) + + # Get / Images + imagedict = {} + for image in axes.get_images(): + label = image.get_label() + if label == '_nolegend_': + continue + imagedict[label] = image + imagelabels = sorted(imagedict) + images = [] + cmaps = [(cmap, name) for name, cmap in sorted(cm.cmap_d.items())] + for label in imagelabels: + image = imagedict[label] + cmap = image.get_cmap() + if cmap not in cm.cmap_d: + cmaps = [(cmap, cmap.name)] + cmaps + imagedata = [ + ('Label', label), + ('Colormap', [cmap.name] + cmaps) + ] + images.append([imagedata, label, ""]) + # Is there an image displayed? + has_image = bool(images) datalist = [(general, "Axes", "")] - if has_curve: + if curves: datalist.append((curves, "Curves", "")) + if images: + datalist.append((images, "Images", "")) def apply_callback(data): """This function will be called to apply changes""" - if has_curve: - general, curves = data - else: - general, = data + general = data.pop(0) + curves = data.pop(0) if has_curve else [] + images = data.pop(0) if has_image else [] + if data: + raise ValueError("Unexpected field") # Set / General - title, xmin, xmax, xlabel, xscale, ymin, ymax, ylabel, yscale, \ - generate_legend = general + (title, xmin, xmax, xlabel, xscale, ymin, ymax, ylabel, yscale, + generate_legend) = general axes.set_xscale(xscale) axes.set_yscale(yscale) axes.set_title(title) @@ -158,26 +180,30 @@ def apply_callback(data): axes.xaxis._update_axisinfo() axes.yaxis._update_axisinfo() - if has_curve: - # Set / Curves - for index, curve in enumerate(curves): - line = linedict[curvelabels[index]] - label, linestyle, drawstyle, linewidth, color, \ - marker, markersize, markerfacecolor, markeredgecolor \ - = curve - line.set_label(label) - line.set_linestyle(linestyle) - line.set_drawstyle(drawstyle) - line.set_linewidth(linewidth) - line.set_color(color) - if marker is not 'none': - line.set_marker(marker) - line.set_markersize(markersize) - line.set_markerfacecolor(markerfacecolor) - line.set_markeredgecolor(markeredgecolor) + # Set / Curves + for index, curve in enumerate(curves): + line = linedict[curvelabels[index]] + (label, linestyle, drawstyle, linewidth, color, marker, markersize, + markerfacecolor, markeredgecolor) = curve + line.set_label(label) + line.set_linestyle(linestyle) + line.set_drawstyle(drawstyle) + line.set_linewidth(linewidth) + line.set_color(color) + if marker is not 'none': + line.set_marker(marker) + line.set_markersize(markersize) + line.set_markerfacecolor(markerfacecolor) + line.set_markeredgecolor(markeredgecolor) + + # Set / Images + for index, image_settings in enumerate(images): + image = imagedict[imagelabels[index]] + label, cmap = image_settings + image.set_label(label) + image.set_cmap(cm.get_cmap(cmap)) # re-generate legend, if checkbox is checked - if generate_legend: draggable = None ncol = None