Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 75ede62

Browse files
committed
User-generated colormaps are handled more easily.
svn path=/trunk/matplotlib/; revision=7309
1 parent 075e336 commit 75ede62

File tree

6 files changed

+138
-14
lines changed

6 files changed

+138
-14
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
2009-07-30 Add set_cmap and register_cmap, and improve get_cmap,
2+
to provide convenient handling of user-generated
3+
colormaps. - EF
4+
15
2009-07-28 Quiver speed improved, thanks to tip by Ray Speth. -EF
26

37
2009-07-27 Simplify argument handling code for plot method. -EF

doc/api/api_changes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ list may help describe what changes may be necessary in your code.
2121
Changes beyond 0.98.x
2222
=====================
2323

24+
* User-generated colormaps can now be added to the set recognized
25+
by :func:`matplotlib.cm.get_cmap`. Colormaps can be made the
26+
default and applied to the current image using
27+
:func:`matplotlib.pyplot.set_cmap`.
28+
2429
* changed use_mrecords default to False in mlab.csv2rec since this is
2530
partially broken
2631

examples/pylab_examples/custom_cmap.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,24 @@
103103
(1.0, 0.0, 0.0))
104104
}
105105

106+
# Now we will use this example to illustrate 3 ways of
107+
# handling custom colormaps.
108+
# First, the most direct and explicit:
106109

107110
blue_red1 = LinearSegmentedColormap('BlueRed1', cdict1)
111+
112+
# Second, create the map explicitly and register it.
113+
# Like the first method, this method works with any kind
114+
# of Colormap, not just
115+
# a LinearSegmentedColormap:
116+
108117
blue_red2 = LinearSegmentedColormap('BlueRed2', cdict2)
109-
blue_red3 = LinearSegmentedColormap('BlueRed3', cdict3)
118+
plt.register_cmap(cmap=blue_red2)
119+
120+
# Third, for LinearSegmentedColormap only,
121+
# leave everything to register_cmap:
122+
123+
plt.register_cmap(name='BlueRed3', data=cdict3) # optional lut kwarg
110124

111125
x = np.arange(0, np.pi, 0.1)
112126
y = np.arange(0, 2*np.pi, 0.1)
@@ -121,13 +135,33 @@
121135
plt.colorbar()
122136

123137
plt.subplot(1,3,2)
124-
plt.imshow(Z, interpolation='nearest', cmap=blue_red2)
138+
cmap = plt.get_cmap('BlueRed2')
139+
plt.imshow(Z, interpolation='nearest', cmap=cmap)
125140
plt.colorbar()
126141

142+
# Now we will set the third cmap as the default. One would
143+
# not normally do this in the middle of a script like this;
144+
# it is done here just to illustrate the method.
145+
146+
plt.rcParams['image.cmap'] = 'BlueRed3'
147+
148+
# Also see below for an alternative, particularly for
149+
# interactive use.
150+
127151
plt.subplot(1,3,3)
128-
plt.imshow(Z, interpolation='nearest', cmap=blue_red3)
152+
plt.imshow(Z, interpolation='nearest')
129153
plt.colorbar()
130154

155+
# Or as yet another variation, we could replace the rcParams
156+
# specification *before* the imshow with the following *after*
157+
# imshow:
158+
#
159+
# plt.set_cmap('BlueRed3')
160+
#
161+
# This sets the new default *and* sets the colormap of the last
162+
# image-like item plotted via pyplot, if any.
163+
164+
131165
plt.suptitle('Custom Blue-Red colormaps')
132166

133167
plt.show()

lib/matplotlib/cm.py

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,79 @@
99
import matplotlib.cbook as cbook
1010
from matplotlib._cm import *
1111

12+
# Dictionary for user-registered colormaps:
13+
cmap_d = dict()
14+
15+
# Using this second dictionary allows us to handle any
16+
# Colormap instance; the built-in datad is only for
17+
# LinearSegmentedColormaps. The advantage of keeping
18+
# datad is that it delays the generation of the Colormap
19+
# instance until it is actually needed. Generating the
20+
# instance is fast enough, and typically done few enough
21+
# times, that there is no need to cache the result.
22+
23+
def register_cmap(name=None, cmap=None, data=None, lut=None):
24+
"""
25+
Add a colormap to the set recognized by :func:`get_cmap`.
26+
27+
It can be used in two ways::
28+
29+
register_cmap(name='swirly', cmap=swirly_cmap)
30+
31+
register_cmap(name='choppy', data=choppydata, lut=128)
32+
33+
In the first case, *cmap* must be a :class:`colors.Colormap`
34+
instance. The *name* is optional; if absent, the name will
35+
be the :attr:`name` attribute of the *cmap*.
36+
37+
In the second case, the three arguments are passed to
38+
the :class:`colors.LinearSegmentedColormap` initializer,
39+
and the resulting colormap is registered.
40+
41+
"""
42+
if name is None:
43+
try:
44+
name = cmap.name
45+
except AttributeError:
46+
raise ValueError("Arguments must include a name or a Colormap")
47+
48+
if not cbook.is_string_like(name):
49+
raise ValueError("Colormap name must be a string")
50+
51+
if isinstance(cmap, colors.Colormap):
52+
cmap_d[name] = cmap
53+
return
1254

55+
# For the remainder, let exceptions propagate.
56+
if lut is None:
57+
lut = mpl.rcParams['image.lut']
58+
cmap = colors.LinearSegmentedColormap(name, data, lut)
59+
cmap_d[name] = cmap
1360

1461
def get_cmap(name=None, lut=None):
1562
"""
16-
Get a colormap instance, defaulting to rc values if *name* is None
63+
Get a colormap instance, defaulting to rc values if *name* is None.
64+
65+
Colormaps added with :func:`register_cmap` take precedence over
66+
builtin colormaps.
67+
68+
If *name* is a :class:`colors.Colormap` instance, it will be
69+
returned.
1770
"""
18-
if name is None: name = mpl.rcParams['image.cmap']
19-
if lut is None: lut = mpl.rcParams['image.lut']
71+
if name is None:
72+
name = mpl.rcParams['image.cmap']
2073

21-
assert(name in datad.keys())
74+
if isinstance(name, colors.Colormap):
75+
return name
76+
77+
if name in cmap_d:
78+
return cmap_d[name]
79+
80+
if name not in datad:
81+
raise ValueError("%s is not a known colormap name" % name)
82+
83+
if lut is None:
84+
lut = mpl.rcParams['image.lut']
2285
return colors.LinearSegmentedColormap(name, datad[name], lut)
2386

2487
class ScalarMappable:
@@ -116,9 +179,9 @@ def set_cmap(self, cmap):
116179
"""
117180
set the colormap for luminance data
118181
119-
ACCEPTS: a colormap
182+
ACCEPTS: a colormap or registered colormap name
120183
"""
121-
if cmap is None: cmap = get_cmap()
184+
cmap = get_cmap(cmap)
122185
self.cmap = cmap
123186
self.changed()
124187

lib/matplotlib/image.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ def set_norm(self, norm):
512512
def set_cmap(self, cmap):
513513
if self._A is not None:
514514
raise RuntimeError('Cannot change colors after loading data')
515-
cm.ScalarMappable.set_cmap(self, norm)
515+
cm.ScalarMappable.set_cmap(self, cmap)
516516

517517
class PcolorImage(martist.Artist, cm.ScalarMappable):
518518
'''

lib/matplotlib/pyplot.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from matplotlib.scale import get_scale_docs, get_scale_names
1818

1919
from matplotlib import cm
20-
from matplotlib.cm import get_cmap
20+
from matplotlib.cm import get_cmap, register_cmap
2121

2222
import numpy as np
2323

@@ -1396,6 +1396,24 @@ def clim(vmin=None, vmax=None):
13961396
im.set_clim(vmin, vmax)
13971397
draw_if_interactive()
13981398

1399+
def set_cmap(cmap):
1400+
'''
1401+
set the default colormap to *cmap* and apply to current image if any.
1402+
See help(colormaps) for more information.
1403+
1404+
*cmap* must be a :class:`colors.Colormap` instance, or
1405+
the name of a registered colormap.
1406+
1407+
See :func:`register_cmap` and :func:`get_cmap`.
1408+
'''
1409+
cmap = cm.get_cmap(cmap)
1410+
1411+
rc('image', cmap=cmap.name)
1412+
im = gci()
1413+
1414+
if im is not None:
1415+
im.set_cmap(cmap)
1416+
draw_if_interactive()
13991417

14001418

14011419
def imread(*args, **kwargs):
@@ -6327,12 +6345,12 @@ def legend(*args, **kwargs):
63276345
*bbox_to_anchor* keyword argument. bbox_to_anchor can be an instance
63286346
of BboxBase(or its derivatives) or a tuple of 2 or 4 floats.
63296347
For example, ::
6330-
6348+
63316349
loc = 'upper right', bbox_to_anchor = (0.5, 0.5)
63326350
63336351
will place the legend so that the upper right corner of the legend at
63346352
the center of the axes.
6335-
6353+
63366354
The legend location can be specified in other coordinate, by using the
63376355
*bbox_transform* keyword.
63386356
@@ -6365,7 +6383,7 @@ def legend(*args, **kwargs):
63656383
63666384
*fancybox*: [ None | False | True ]
63676385
if True, draw a frame with a round fancybox. If None, use rc
6368-
6386+
63696387
*shadow*: [ None | False | True ]
63706388
If *True*, draw a shadow behind legend. If *None*, use rc settings.
63716389

0 commit comments

Comments
 (0)