Skip to content

Commit e45e946

Browse files
committed
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.
1 parent 838fa1f commit e45e946

File tree

3 files changed

+115
-87
lines changed

3 files changed

+115
-87
lines changed

lib/matplotlib/axes/_base.py

+2
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,8 @@ def add_image(self, image):
17031703
Returns the image.
17041704
"""
17051705
self._set_artist_props(image)
1706+
if not image.get_label():
1707+
image.set_label('_image%d' % len(self.images))
17061708
self.images.append(image)
17071709
image._remove_method = lambda h: self.images.remove(h)
17081710
return image

lib/matplotlib/backends/backend_qt5.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ def _init_toolbar(self):
587587
if figureoptions is not None:
588588
a = self.addAction(self._icon("qt4_editor_options.png"),
589589
'Customize', self.edit_parameters)
590-
a.setToolTip('Edit curves line and axes parameters')
590+
a.setToolTip('Edit axis, curve and image parameters')
591591

592592
self.buttons = {}
593593

lib/matplotlib/backends/qt_editor/figureoptions.py

+112-86
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import matplotlib.backends.qt_editor.formlayout as formlayout
1818
from matplotlib.backends.qt_compat import QtGui
19-
from matplotlib import markers
19+
from matplotlib import cm, markers
2020
from matplotlib.colors import colorConverter, rgb2hex
2121

2222

@@ -43,8 +43,6 @@ def figure_edit(axes, parent=None):
4343
"""Edit matplotlib figure options"""
4444
sep = (None, None) # separator
4545

46-
has_curve = len(axes.get_lines()) > 0
47-
4846
# Get / General
4947
xmin, xmax = map(float, axes.get_xlim())
5048
ymin, ymax = map(float, axes.get_ylim())
@@ -69,79 +67,103 @@ def figure_edit(axes, parent=None):
6967
xunits = axes.xaxis.get_units()
7068
yunits = axes.yaxis.get_units()
7169

72-
if has_curve:
73-
# Get / Curves
74-
linedict = {}
75-
for line in axes.get_lines():
76-
label = line.get_label()
77-
if label == '_nolegend_':
78-
continue
79-
linedict[label] = line
80-
curves = []
81-
82-
def prepare_data(d, init):
83-
"""Prepare entry for FormLayout.
84-
85-
`d` is a mapping of shorthands to style names (a single style may
86-
have multiple shorthands, in particular the shorthands `None`,
87-
`"None"`, `"none"` and `""` are synonyms); `init` is one shorthand
88-
of the initial style.
89-
90-
This function returns an list suitable for initializing a
91-
FormLayout combobox, namely `[initial_name, (shorthand,
92-
style_name), (shorthand, style_name), ...]`.
93-
"""
94-
# Drop duplicate shorthands from dict (by overwriting them during
95-
# the dict comprehension).
96-
name2short = {name: short for short, name in d.items()}
97-
# Convert back to {shorthand: name}.
98-
short2name = {short: name for name, short in name2short.items()}
99-
# Find the kept shorthand for the style specified by init.
100-
canonical_init = name2short[d[init]]
101-
# Sort by representation and prepend the initial value.
102-
return ([canonical_init] +
103-
sorted(short2name.items(),
104-
key=lambda short_and_name: short_and_name[1]))
105-
106-
curvelabels = sorted(linedict.keys())
107-
for label in curvelabels:
108-
line = linedict[label]
109-
color = rgb2hex(colorConverter.to_rgb(line.get_color()))
110-
ec = rgb2hex(colorConverter.to_rgb(line.get_markeredgecolor()))
111-
fc = rgb2hex(colorConverter.to_rgb(line.get_markerfacecolor()))
112-
curvedata = [
113-
('Label', label),
114-
sep,
115-
(None, '<b>Line</b>'),
116-
('Line Style', prepare_data(LINESTYLES, line.get_linestyle())),
117-
('Draw Style', prepare_data(DRAWSTYLES, line.get_drawstyle())),
118-
('Width', line.get_linewidth()),
119-
('Color', color),
120-
sep,
121-
(None, '<b>Marker</b>'),
122-
('Style', prepare_data(MARKERS, line.get_marker())),
123-
('Size', line.get_markersize()),
124-
('Facecolor', fc),
125-
('Edgecolor', ec)]
126-
curves.append([curvedata, label, ""])
127-
128-
# make sure that there is at least one displayed curve
129-
has_curve = bool(curves)
70+
# Get / Curves
71+
linedict = {}
72+
for line in axes.get_lines():
73+
label = line.get_label()
74+
if label == '_nolegend_':
75+
continue
76+
linedict[label] = line
77+
curves = []
78+
79+
def prepare_data(d, init):
80+
"""Prepare entry for FormLayout.
81+
82+
`d` is a mapping of shorthands to style names (a single style may
83+
have multiple shorthands, in particular the shorthands `None`,
84+
`"None"`, `"none"` and `""` are synonyms); `init` is one shorthand
85+
of the initial style.
86+
87+
This function returns an list suitable for initializing a
88+
FormLayout combobox, namely `[initial_name, (shorthand,
89+
style_name), (shorthand, style_name), ...]`.
90+
"""
91+
# Drop duplicate shorthands from dict (by overwriting them during
92+
# the dict comprehension).
93+
name2short = {name: short for short, name in d.items()}
94+
# Convert back to {shorthand: name}.
95+
short2name = {short: name for name, short in name2short.items()}
96+
# Find the kept shorthand for the style specified by init.
97+
canonical_init = name2short[d[init]]
98+
# Sort by representation and prepend the initial value.
99+
return ([canonical_init] +
100+
sorted(short2name.items(),
101+
key=lambda short_and_name: short_and_name[1]))
102+
103+
curvelabels = sorted(linedict.keys())
104+
for label in curvelabels:
105+
line = linedict[label]
106+
color = rgb2hex(colorConverter.to_rgb(line.get_color()))
107+
ec = rgb2hex(colorConverter.to_rgb(line.get_markeredgecolor()))
108+
fc = rgb2hex(colorConverter.to_rgb(line.get_markerfacecolor()))
109+
curvedata = [
110+
('Label', label),
111+
sep,
112+
(None, '<b>Line</b>'),
113+
('Line Style', prepare_data(LINESTYLES, line.get_linestyle())),
114+
('Draw Style', prepare_data(DRAWSTYLES, line.get_drawstyle())),
115+
('Width', line.get_linewidth()),
116+
('Color', color),
117+
sep,
118+
(None, '<b>Marker</b>'),
119+
('Style', prepare_data(MARKERS, line.get_marker())),
120+
('Size', line.get_markersize()),
121+
('Facecolor', fc),
122+
('Edgecolor', ec)]
123+
curves.append([curvedata, label, ""])
124+
# Is there a curve displayed?
125+
has_curve = bool(curves)
126+
127+
# Get / Images
128+
imagedict = {}
129+
for image in axes.get_images():
130+
label = image.get_label()
131+
if label == '_nolegend_':
132+
continue
133+
imagedict[label] = image
134+
imagelabels = sorted(imagedict)
135+
images = []
136+
cmaps = [(cmap, name) for name, cmap in sorted(cm.cmap_d.items())]
137+
for label in imagelabels:
138+
image = imagedict[label]
139+
cmap = image.get_cmap()
140+
if cmap not in cm.cmap_d:
141+
cmaps = [(cmap, cmap.name)] + cmaps
142+
imagedata = [
143+
('Label', label),
144+
('Colormap', [cmap.name] + cmaps)
145+
]
146+
images.append([imagedata, label, ""])
147+
# Is there an image displayed?
148+
has_image = bool(images)
130149

131150
datalist = [(general, "Axes", "")]
132-
if has_curve:
151+
if curves:
133152
datalist.append((curves, "Curves", ""))
153+
if images:
154+
datalist.append((images, "Images", ""))
134155

135156
def apply_callback(data):
136157
"""This function will be called to apply changes"""
137-
if has_curve:
138-
general, curves = data
139-
else:
140-
general, = data
158+
general = data.pop(0)
159+
curves = data.pop(0) if has_curve else []
160+
images = data.pop(0) if has_image else []
161+
if data:
162+
raise ValueError("Unexpected field")
141163

142164
# Set / General
143-
title, xmin, xmax, xlabel, xscale, ymin, ymax, ylabel, yscale, \
144-
generate_legend = general
165+
(title, xmin, xmax, xlabel, xscale, ymin, ymax, ylabel, yscale,
166+
generate_legend) = general
145167
axes.set_xscale(xscale)
146168
axes.set_yscale(yscale)
147169
axes.set_title(title)
@@ -158,26 +180,30 @@ def apply_callback(data):
158180
axes.xaxis._update_axisinfo()
159181
axes.yaxis._update_axisinfo()
160182

161-
if has_curve:
162-
# Set / Curves
163-
for index, curve in enumerate(curves):
164-
line = linedict[curvelabels[index]]
165-
label, linestyle, drawstyle, linewidth, color, \
166-
marker, markersize, markerfacecolor, markeredgecolor \
167-
= curve
168-
line.set_label(label)
169-
line.set_linestyle(linestyle)
170-
line.set_drawstyle(drawstyle)
171-
line.set_linewidth(linewidth)
172-
line.set_color(color)
173-
if marker is not 'none':
174-
line.set_marker(marker)
175-
line.set_markersize(markersize)
176-
line.set_markerfacecolor(markerfacecolor)
177-
line.set_markeredgecolor(markeredgecolor)
183+
# Set / Curves
184+
for index, curve in enumerate(curves):
185+
line = linedict[curvelabels[index]]
186+
(label, linestyle, drawstyle, linewidth, color, marker, markersize,
187+
markerfacecolor, markeredgecolor) = curve
188+
line.set_label(label)
189+
line.set_linestyle(linestyle)
190+
line.set_drawstyle(drawstyle)
191+
line.set_linewidth(linewidth)
192+
line.set_color(color)
193+
if marker is not 'none':
194+
line.set_marker(marker)
195+
line.set_markersize(markersize)
196+
line.set_markerfacecolor(markerfacecolor)
197+
line.set_markeredgecolor(markeredgecolor)
198+
199+
# Set / Images
200+
for index, image_settings in enumerate(images):
201+
image = imagedict[imagelabels[index]]
202+
label, cmap = image_settings
203+
image.set_label(label)
204+
image.set_cmap(cm.get_cmap(cmap))
178205

179206
# re-generate legend, if checkbox is checked
180-
181207
if generate_legend:
182208
draggable = None
183209
ncol = None

0 commit comments

Comments
 (0)