|
9 | 9 | import matplotlib.cbook as cbook |
10 | 10 | from matplotlib._cm import * |
11 | 11 |
|
| 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 |
12 | 54 |
|
| 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 |
13 | 60 |
|
14 | 61 | def get_cmap(name=None, lut=None): |
15 | 62 | """ |
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. |
17 | 70 | """ |
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'] |
20 | 73 |
|
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'] |
22 | 85 | return colors.LinearSegmentedColormap(name, datad[name], lut) |
23 | 86 |
|
24 | 87 | class ScalarMappable: |
@@ -116,9 +179,9 @@ def set_cmap(self, cmap): |
116 | 179 | """ |
117 | 180 | set the colormap for luminance data |
118 | 181 |
|
119 | | - ACCEPTS: a colormap |
| 182 | + ACCEPTS: a colormap or registered colormap name |
120 | 183 | """ |
121 | | - if cmap is None: cmap = get_cmap() |
| 184 | + cmap = get_cmap(cmap) |
122 | 185 | self.cmap = cmap |
123 | 186 | self.changed() |
124 | 187 |
|
|
0 commit comments