8000 colormapping sublibrary · matplotlib/matplotlib@e58e5e8 · GitHub
[go: up one dir, main page]

Skip to content

Commit e58e5e8

Browse files
committed
colormapping sublibrary
1 parent b9fb9dd commit e58e5e8

31 files changed

+5002
-4162
lines changed

lib/matplotlib/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1512,5 +1512,6 @@ def inner(ax, *args, data=None, **kwargs):
15121512

15131513
# workaround: we must defer colormaps import to after loading rcParams, because
15141514
# colormap creation depends on rcParams
1515-
from matplotlib.cm import _colormaps as colormaps # noqa: E402
1515+
from matplotlib.colormapping.colormap_registry\
1516+
import _colormaps as colormaps # noqa: E402
15161517
from matplotlib.colors import _color_sequences as color_sequences # noqa: E402

lib/matplotlib/artist.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
import numpy as np
1313

1414
import matplotlib as mpl
15-
from . import _api, cbook, colorizer
16-
from .colors import BoundaryNorm
15+
from . import _api, cbook
16+
from .colormapping.norms import BoundaryNorm
1717
from .path import Path
1818
from .transforms import (BboxBase, Bbox, IdentityTransform, Transform, TransformedBbox,
1919
TransformedPatchPath, TransformedPath)
@@ -1345,13 +1345,14 @@ def format_cursor_data(self, data):
13451345
--------
13461346
get_cursor_data
13471347
"""
1348-
if np.ndim(data) == 0 and (isinstance(self, mpl.cm.ScalarMappable) or
1349-
isinstance(self, colorizer.ColorizingArtist)):
1348+
if np.ndim(data) == 0 and isinstance(self, mpl.cm.ScalarMappable):
13501349
# This block logically belongs to ScalarMappable, but can't be
13511350
# implemented in it because most ScalarMappable subclasses inherit
13521351
# from Artist first and from ScalarMappable second, so
13531352
# Artist.format_cursor_data would always have precedence over
13541353
# ScalarMappable.format_cursor_data.
1354+
1355+
# If ScalarMappable is deprecated, this code block can be removed
13551356
n = self.cmap.N
13561357
if np.ma.getmask(data):
13571358
return "[]"

lib/matplotlib/axes/_axes.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import matplotlib.transforms as mtransforms
3232
import matplotlib.tri as mtri
3333
import matplotlib.units as munits
34+
import matplotlib.colormapping as mcm
3435
from matplotlib import _api, _docstring, _preprocess_data
3536
from matplotlib.axes._base import (
3637
_AxesBase, _TransformedBoundsLocator, _process_plot_format)
@@ -5289,7 +5290,7 @@ def reduce_C_function(C: array) -> float
52895290
_api.warn_external("Only one of 'bins' and 'norm' arguments "
52905291
f"can be supplied, ignoring {bins=}")
52915292
else:
5292-
norm = mcolors.LogNorm(vmin=vmin, vmax=vmax)
5293+
norm = mcm.norms.LogNorm(vmin=vmin, vmax=vmax)
52935294
vmin = vmax = None
52945295
bins = None
52955296

@@ -8355,12 +8356,12 @@ def spy(self, Z, precision=0, marker=None, markersize=None,
83558356
mask = np.abs(Z) > precision
83568357

83578358
if 'cmap' not in kwargs:
8358-
kwargs['cmap'] = mcolors.ListedColormap(['w', 'k'],
8359-
name='binary')
8359+
kwargs['cmap'] = mcm.colormaps.ListedColormap(['w', 'k'],
8360+
name='binary')
83608361
if 'interpolation' in kwargs:
83618362
raise _api.kwarg_error("spy", "interpolation")
83628363
if 'norm' not in kwargs:
8363-
kwargs['norm'] = mcolors.NoNorm()
8364+
kwargs['norm'] = mcm.norms.NoNorm()
83648365
ret = self.imshow(mask, interpolation='nearest',
83658366
aspect=aspect, origin=origin,
83668367
**kwargs)

lib/matplotlib/cm.py

Lines changed: 10 additions & 277 deletions
48DA
Original file line numberDiff line numberDiff line change
@@ -14,232 +14,20 @@
1414
:ref:`colormapnorms` for more details about data normalization.
1515
"""
1616

17-
from collections.abc import Mapping
1817

1918
import numpy as np
20-
2119
import matplotlib as mpl
22-
from matplotlib import _api, colors, cbook, colorizer
23-
from matplotlib._cm import datad
24-
from matplotlib._cm_listed import cmaps as cmaps_listed
25-
26-
27-
_LUTSIZE = mpl.rcParams['image.lut']
28-
29-
30-
def _gen_cmap_registry():
31-
"""
32-
Generate a dict mapping standard colormap names to standard colormaps, as
33-
well as the reversed colormaps.
34-
"""
35-
cmap_d = {**cmaps_listed}
36-
for name, spec in datad.items():
37-
cmap_d[name] = ( # Precache the cmaps at a fixed lutsize..
38- F987
colors.LinearSegmentedColormap(name, spec, _LUTSIZE)
39-
if 'red' in spec else
40-
colors.ListedColormap(spec['listed'], name)
41-
if 'listed' in spec else
42-
colors.LinearSegmentedColormap.from_list(name, spec, _LUTSIZE))
43-
44-
# Register colormap aliases for gray and grey.
45-
aliases = {
46-
# alias -> original name
47-
'grey': 'gray',
48-
'gist_grey': 'gist_gray',
49-
'gist_yerg': 'gist_yarg',
50-
'Grays': 'Greys',
51-
}
52-
for alias, original_name in aliases.items():
53-
cmap = cmap_d[original_name].copy()
54-
cmap.name = alias
55-
cmap_d[alias] = cmap
56-
57-
# Generate reversed cmaps.
58-
for cmap in list(cmap_d.values()):
59-
rmap = cmap.reversed()
60-
cmap_d[rmap.name] = rmap
61-
return cmap_d
62-
63-
64-
class ColormapRegistry(Mapping):
65-
r"""
66-
Container for colormaps that are known to Matplotlib by name.
67-
68-
The universal registry instance is `matplotlib.colormaps`. There should be
69-
no need for users to instantiate `.ColormapRegistry` themselves.
70-
71-
Read access uses a dict-like interface mapping names to `.Colormap`\s::
72-
73-
import matplotlib as mpl
74< 1241 /code>-
cmap = mpl.colormaps['viridis']
75-
76-
Returned `.Colormap`\s are copies, so that their modification does not
77-
change the global definition of the colormap.
78-
79-
Additional colormaps can be added via `.ColormapRegistry.register`::
80-
81-
mpl.colormaps.register(my_colormap)
82-
83-
To get a list of all registered colormaps, you can do::
84-
85-
from matplotlib import colormaps
86-
list(colormaps)
87-
"""
88-
def __init__(self, cmaps):
89-
self._cmaps = cmaps
90-
self._builtin_cmaps = tuple(cmaps)
91-
92-
def __getitem__(self, item):
93-
try:
94-
return self._cmaps[item].copy()
95-
except KeyError:
96-
raise KeyError(f"{item!r} is not a known colormap name") from None
97-
98-
def __iter__(self):
99-
return iter(self._cmaps)
100-
101-
def __len__(self):
102-
return len(self._cmaps)
103-
104-
def __str__(self):
105-
return ('ColormapRegistry; available colormaps:\n' +
106-
', '.join(f"'{name}'" for name in self))
107-
108-
def __call__(self):
109-
"""
110-
Return a list of the registered colormap names.
111-
112-
This exists only for backward-compatibility in `.pyplot` which had a
113-
``plt.colormaps()`` method. The recommended way to get this list is
114-
now ``list(colormaps)``.
115-
"""
116-
return list(self)
117-
118-
def register(self, cmap, *, name=None, force=False):
119-
"""
120-
Register a new colormap.
121-
122-
The colormap name can then be used as a string argument to any ``cmap``
123-
parameter in Matplotlib. It is also available in ``pyplot.get_cmap``.
124-
125-
The colormap registry stores a copy of the given colormap, so that
126-
future changes to the original colormap instance do not affect the
127-
registered colormap. Think of this as the registry taking a snapshot
128-
of the colormap at registration.
129-
130-
Parameters
131-
----------
132-
cmap : matplotlib.colors.Colormap
133-
The colormap to register.
134-
135-
name : str, optional
136-
The name for the colormap. If not given, ``cmap.name`` is used.
137-
138-
force : bool, default: False
139-
If False, a ValueError is raised if trying to overwrite an already
140-
registered name. True supports overwriting registered colormaps
141-
other than the builtin colormaps.
142-
"""
143-
_api.check_isinstance(colors.Colormap, cmap=cmap)
144-
145-
name = name or cmap.name
146-
if name in self:
147-
if not force:
148-
# don't allow registering an already existing cmap
149-
# unless explicitly asked to
150-
raise ValueError(
151-
f'A colormap named "{name}" is already registered.')
152-
elif name in self._builtin_cmaps:
153-
# We don't allow overriding a builtin.
154-
raise ValueError("Re-registering the builtin cmap "
155-
f"{name!r} is not allowed.")
156-
157-
# Warn that we are updating an already existing colormap
158-
_api.warn_external(f"Overwriting the cmap {name!r} "
159-
"that was already in the registry.")
160-
161-
self._cmaps[name] = cmap.copy()
162-
# Someone may set the extremes of a builtin colormap and want to register it
163-
# with a different name for future lookups. The object would still have the
164-
# builtin name, so we should update it to the registered name
165-
if self._cmaps[name].name != name:
166-
self._cmaps[name].name = name
167-
168-
def unregister(self, name):
169-
"""
170-
Remove a colormap from the registry.
171-
172-
You cannot remove built-in colormaps.
173-
174-
If the named colormap is not registered, returns with no error, raises
175-
if you try to de-register a default colormap.
176-
177-
.. warning::
178-
179-
Colormap names are currently a shared namespace that may be used
180-
by multiple packages. Use `unregister` only if you know you
181-
have registered that name before. In particular, do not
182-
unregister just in case to clean the name before registering a
183-
new colormap.
184-
185-
Parameters
186-
----------
187-
name : str
188-
The name of the colormap to be removed.
189-
190-
Raises
191-
------
192-
ValueError
193-
If you try to remove a default built-in colormap.
194-
"""
195-
if name in self._builtin_cmaps:
196-
raise ValueError(f"cannot unregister {name!r} which is a builtin "
197-
"colormap.")
198-
self._cmaps.pop(name, None)
199-
200-
def get_cmap(self, cmap):
201-
"""
202-
Return a color map specified through *cmap*.
203-
204-
Parameters
205-
----------
206-
cmap : str or `~matplotlib.colors.Colormap` or None
207-
208-
- if a `.Colormap`, return it
209-
- if a string, look it up in ``mpl.colormaps``
210-
- if None, return the Colormap defined in :rc:`image.cmap`
211-
212-
Returns
213-
-------
214-
Colormap
215-
"""
216-
# get the default color map
217-
if cmap is None:
218-
return self[mpl.rcParams["image.cmap"]]
219-
220-
# if the user passed in a Colormap, simply return it
221-
if isinstance(cmap, colors.Colormap):
222-
return cmap
223-
if isinstance(cmap, str):
224-
_api.check_in_list(sorted(_colormaps), cmap=cmap)
225-
# otherwise, it must be a string so look it up
226-
return self[cmap]
227-
raise TypeError(
228-
'get_cmap expects None or an instance of a str or Colormap . ' +
229-
f'you passed {cmap!r} of type {type(cmap)}'
230-
)
231-
232-
233-
# public access to the colormaps should be via `matplotlib.colormaps`. For now,
234-
# we still create the registry here, but that should stay an implementation
235-
# detail.
236-
_colormaps = ColormapRegistry(_gen_cmap_registry())
237-
globals().update(_colormaps)
238-
20+
from matplotlib import _api, cbook
21+
from .colormapping import colorizer
22+
from .colormapping.colormap_registry import _colormaps
23+
### compatibility between old colors.py and new colormapping submodule
24+
from .colormapping.colorizer import _ensure_cmap # noqa: F401
23925

24026
# This is an exact copy of pyplot.get_cmap(). It was removed in 3.9, but apparently
24127
# caused more user trouble than expected. Re-added for 3.9.1 and extended the
24228
# deprecation period for two additional minor releases.
29+
30+
24331
@_api.deprecated(
24432
'3.7',
24533
removal='3.11',
@@ -266,7 +54,7 @@ def get_cmap(name=None, lut=None):
26654
"""
26755
if name is None:
26856
name = mpl.rcParams['image.cmap']
269-
if isinstance(name, colors.Colormap):
57+
if isinstance(name, mpl.colormapping.colormaps.Colormap):
27058
return name
27159
_api.check_in_list(sorted(_colormaps), name=name)
27260
if lut is None:
@@ -348,60 +136,5 @@ def changed(self):
348136
self.stale = True
349137

350138

351-
# The docstrings here must be generic enough to apply to all relevant methods.
352-
mpl._docstring.interpd.update(
353-
cmap_doc="""\
354-
cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap`
355-
The Colormap instance or registered colormap name used to map scalar data
356-
to colors.""",
357-
norm_doc="""\
358-
norm : str or `~matplotlib.colors.Normalize`, optional
359-
The normalization method used to scale scalar data to the [0, 1] range
360-
before mapping to colors using *cmap*. By default, a linear scaling is
361-
used, mapping the lowest value to 0 and the highest to 1.
362-
363-
If given, this can be one of the following:
364-
365-
- An instance of `.Normalize` or one of its subclasses
366-
(see :ref:`colormapnorms`).
367-
- A scale name, i.e. one of "linear", "log", "symlog", "logit", etc. For a
368-
list of available scales, call `matplotlib.scale.get_scale_names()`.
369-
In that case, a suitable `.Normalize` subclass is dynamically generated
370-
and instantiated.""",
371-
vmin_vmax_doc="""\
372-
vmin, vmax : float, optional
373-
When using scalar data and no explicit *norm*, *vmin* and *vmax* define
374-
the data range that the colormap covers. By default, the colormap covers
375-
the complete value range of the supplied data. It is an error to use
376-
*vmin*/*vmax* when a *norm* instance is given (but using a `str` *norm*
377-
name together with *vmin*/*vmax* is acceptable).""",
378-
)
379-
380-
381-
def _ensure_cmap(cmap):
382-
"""
383-
Ensure that we have a `.Colormap` object.
384-
385-
For internal use to preserve type stability of errors.
386-
387-
Parameters
388-
----------
389-
cmap : None, str, Colormap
390-
391-
- if a `Colormap`, return it
392-
- if a string, look it up in mpl.colormaps
393-
- if None, look up the default color map in mpl.colormaps
394-
395-
Returns
396-
-------
397-
Colormap
398-
399-
"""
400-
if isinstance(cmap, colors.Colormap):
401-
return cmap
402-
cmap_name = cmap if cmap is not None else mpl.rcParams["image.cmap"]
403-
# use check_in_list to ensure type stability of the exception raised by
404-
# the internal usage of this (ValueError vs KeyError)
405-
if cmap_name not in _colormaps:
406-
_api.check_in_list(sorted(_colormaps), cmap=cmap_name)
407-
return mpl.colormaps[cmap_name]
139+
# backward compatibility
140+
globals().update(_colormaps)

lib/matplotlib/collections.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
import numpy as np
1818

1919
import matplotlib as mpl
20-
from . import (_api, _path, artist, cbook, colorizer as mcolorizer, colors as mcolors,
21-
_docstring, hatch as mhatch, lines as mlines, path as mpath, transforms)
20+
from . import (_api, _path, artist, cbook, colors as mcolors, _docstring,
21+
hatch as mhatch, lines as mlines, path as mpath, transforms)
22+
from .colormapping import colorizer as mcolorizer
2223
from ._enums import JoinStyle, CapStyle
2324

2425

0 commit comments

Comments
 (0)
0