Skip to content

Backport qt editor improvements #6717

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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.
  • Loading branch information
anntzer committed Jul 10, 2016
commit 240d24b15e29e1ec4f9689e51725fb01d4ba124d
2 changes: 2 additions & 0 deletions lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,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)
self.stale = True
Expand Down
198 changes: 112 additions & 86 deletions lib/matplotlib/backends/qt_editor/figureoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand All @@ -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 = axes.get_xlim()
ymin, ymax = axes.get_ylim()
Expand All @@ -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, '<b>Line</b>'),
('Line Style', prepare_data(LINESTYLES, line.get_linestyle())),
('Draw Style', prepare_data(DRAWSTYLES, line.get_drawstyle())),
('Width', line.get_linewidth()),
('Color', color),
sep,
(None, '<b>Marker</b>'),
('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, '<b>Line</b>'),
('Line Style', prepare_data(LINESTYLES, line.get_linestyle())),
('Draw Style', prepare_data(DRAWSTYLES, line.get_drawstyle())),
('Width', line.get_linewidth()),
('Color', color),
sep,
(None, '<b>Marker</b>'),
('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

if axes.get_xscale() != xscale:
axes.set_xscale(xscale)
Expand All @@ -162,26 +184,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 = 1
Expand Down