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

Skip to content

Commit 9c26a1e

Browse files
committed
Incorporating feedback from @story645
1 parent 09eb12c commit 9c26a1e

7 files changed

Lines changed: 61 additions & 77 deletions

File tree

lib/matplotlib/axes/_axes.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5775,12 +5775,12 @@ def imshow(self, X, cmap=None, norm=None, *, aspect=None,
57755775
colors using normalization and a colormap. See parameters *norm*,
57765776
*cmap*, *vmin*, *vmax*.
57775777
- (K, M, N): multiple images with scalar data. Must be used
5778-
with a multivariate or bivariate colormap. See *cmap*.
5778+
with a multivariate or bivariate colormap that supports K channels.
57795779
- (M, N, 3): an image with RGB values (0-1 float or 0-255 int).
57805780
- (M, N, 4): an image with RGBA values (0-1 float or 0-255 int),
57815781
i.e. including transparency.
57825782
5783-
Here M and N define the rows and columns of the image.
5783+
The dimensions M and N are the number of rows and columns of the image.
57845784
57855785
Out-of-range RGB(A) values are clipped.
57865786
@@ -6268,12 +6268,17 @@ def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None,
62686268
# we need to get the colorizer object to know the number of
62696269
# n_variates that should exist in the array, we therefore get the
62706270
# colorizer here.
6271-
colorizer = mcolorizer.ColorizingArtist._get_colorizer(norm=norm,
6272-
cmap=cmap,
6273-
colorizer=colorizer)
6274-
if colorizer.norm.n_input > 1:
6275-
data = mcolorizer._ensure_multivariate_data(colorizer.norm.n_input, args[0])
6276-
args = (data, *args[1:])
6271+
colorizer_obj = mcolorizer.ColorizingArtist._get_colorizer(norm=norm,
6272+
cmap=cmap,
6273+
colorizer=colorizer)
6274+
if colorizer_obj.norm.n_input > 1:
6275+
# Valid call signatures for pcolor are with args = (C) or args = (X, Y, C)
6276+
# If provided, _pcolorargs will check that X, Y and C have the same shape.
6277+
# Before this check, we need to convert C from shape (K, N, M), where K is
6278+
# the number of variates, to (N, M) with a data type with K fields.
6279+
data = mcolorizer._ensure_multivariate_data(colorizer_obj.norm.n_input,
6280+
args[-1])
6281+
args = (*args[:-1], data)
62776282

62786283
X, Y, C, shading = self._pcolorargs('pcolor', *args, shading=shading,
62796284
kwargs=kwargs)
@@ -6311,7 +6316,7 @@ def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None,
63116316
coords = stack([X, Y], axis=-1)
63126317

63136318
collection = mcoll.PolyQuadMesh(
6314-
coords, array=C, colorizer=colorizer,
6319+
coords, array=C, colorizer=colorizer_obj,
63156320
alpha=alpha, **kwargs)
63166321
collection._scale_norm(norm, vmin, vmax)
63176322

@@ -6546,6 +6551,10 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
65466551
cmap=cmap,
65476552
colorizer=colorizer)
65486553
if colorizer_obj.norm.n_input > 1:
6554+
# Valid call signatures for pcolor are with args = (C) or args = (X, Y, C)
6555+
# If provided, _pcolorargs will check that X, Y and C have the same shape.
6556+
# Before this check, we need to convert C from shape (K, N, M), where K is
6557+
# the number of variates, to (N, M) with a data type with K fields.
65496558
data = mcolorizer._ensure_multivariate_data(colorizer_obj.norm.n_input,
65506559
args[-1])
65516560
args = (*args[:-1], data)

lib/matplotlib/colorizer.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ def _set_cmap(self, cmap):
226226
if self.norm.n_output != cmap_obj.n_variates:
227227
raise ValueError(f"The colormap {cmap} does not support "
228228
f"{self.norm.n_output} variates as required by "
229-
"the norm on this Colorizer.")
229+
f"the {type(self.norm)} on this Colorizer.")
230230
self._cmap = cmap_obj
231231
if not in_init:
232232
self.changed() # Things are not set up properly yet.
@@ -738,13 +738,7 @@ def _ensure_norm(norm, n_variates=1):
738738
if norm is None:
739739
norm = colors.Normalize()
740740
elif isinstance(norm, str):
741-
try:
742-
scale_cls = scale._scale_mapping[norm]
743-
except KeyError:
744-
raise ValueError(
745-
"Invalid norm str name; the following values are "
746-
f"supported: {', '.join(scale._scale_mapping)}"
747-
) from None
741+
scale_cls = scale._get_scale_cls_from_str(norm)
748742
norm = _auto_norm_from_scale(scale_cls)()
749743
return norm
750744
else: # n_variates > 1

lib/matplotlib/colors.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3260,13 +3260,7 @@ def __init__(self, norms, vmin=None, vmax=None, clip=False):
32603260
if n is None:
32613261
norms[i] = Normalize()
32623262
elif isinstance(n, str):
3263-
try:
3264-
scale_cls = scale._scale_mapping[n]
3265-
except KeyError:
3266-
raise ValueError(
3267-
"Invalid norm str name; the following values are "
3268-
f"supported: {', '.join(scale._scale_mapping)}"
3269-
) from None
3263+
scale_cls = scale._get_scale_cls_from_str(n)
32703264
norms[i] = mpl.colorizer._auto_norm_from_scale(scale_cls)()
32713265

32723266
# Convert the list of norms to a tuple to make it immutable.
@@ -3377,9 +3371,8 @@ def __call__(self, value, clip=None):
33773371
"""
33783372
if clip is None:
33793373
clip = self.clip
3380-
else:
3381-
if not np.iterable(clip):
3382-
clip = [clip]*self.n_input
3374+
elif not np.iterable(clip):
3375+
clip = [clip]*self.n_input
33833376

33843377
value = self._iterable_variates_in_data(value, self.n_input)
33853378
result = [n(v, clip=c) for n, v, c in zip(self.norms, value, clip)]

lib/matplotlib/scale.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,35 @@ def get_scale_names():
715715
return sorted(_scale_mapping)
716716

717717

718+
def _get_scale_cls_from_str(scale_as_str):
719+
"""
720+
Returns the scale class from a string.
721+
722+
Used in the creation of norms from a string to ensure a reasonable error
723+
in the case where an invalid string is used. This cannot use
724+
`_api.check_getitem()`, because the norm keyword accepts arguments
725+
other than strings.
726+
727+
Parameters
728+
----------
729+
scale_as_str : string
730+
A string corresponding to a scale
731+
732+
Returns
733+
-------
734+
A subclass of ScaleBase.
735+
736+
"""
737+
try:
738+
scale_cls = _scale_mapping[scale_as_str]
739+
except KeyError:
740+
raise ValueError(
741+
"Invalid norm str name; the following values are "
742+
f"supported: {', '.join(_scale_mapping)}"
743+
) from None
744+
return scale_cls
745+
746+
718747
def scale_factory(scale, axis, **kwargs):
719748
"""
720749
Return a scale class by name.
535 Bytes
Loading
483 Bytes
Loading

lib/matplotlib/tests/test_multivariate_axes.py

Lines changed: 9 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from matplotlib.testing.decorators import (image_comparison,
55
remove_ticks_and_titles)
66
import matplotlib.colors as mcolors
7+
from matplotlib import cbook
78
import matplotlib as mpl
89
import pytest
910
import re
@@ -14,7 +15,7 @@ def test_bivariate_visualizations():
1415
x_0 = np.arange(25, dtype='float32').reshape(5, 5) % 5
1516
x_1 = np.arange(25, dtype='float32').reshape(5, 5).T % 5
1617

17-
fig, axes = plt.subplots(1, 6, figsize=(10, 2))
18+
fig, axes = plt.subplots(1, 7, figsize=(12, 2))
1819

1920
axes[0].imshow((x_0, x_1), cmap='BiPeak', interpolation='nearest')
2021
axes[1].matshow((x_0, x_1), cmap='BiPeak')
@@ -24,7 +25,8 @@ def test_bivariate_visualizations():
2425
x = np.arange(5)
2526
y = np.arange(5)
2627
X, Y = np.meshgrid(x, y)
27-
axes[4].pcolormesh(X, Y, (x_0, x_1), cmap='BiPeak')
28+
axes[4].pcolor(X, Y, (x_0, x_1), cmap='BiPeak')
29+
axes[5].pcolormesh(X, Y, (x_0, x_1), cmap='BiPeak')
2830

2931
patches = [
3032
mpl.patches.Wedge((.3, .7), .1, 0, 360), # Full circle
@@ -36,7 +38,7 @@ def test_bivariate_visualizations():
3638
colors_1 = np.arange(len(patches)) % 2
3739
p = mpl.collections.PatchCollection(patches, cmap='BiPeak', alpha=0.5)
3840
p.set_array((colors_0, colors_1))
39-
axes[5].add_collection(p)
41+
axes[6].add_collection(p)
4042

4143
remove_ticks_and_titles(fig)
4244

@@ -47,7 +49,7 @@ def test_multivariate_visualizations():
4749
x_1 = np.arange(25, dtype='float32').reshape(5, 5).T % 5
4850
x_2 = np.arange(25, dtype='float32').reshape(5, 5) % 6
4951

50-
fig, axes = plt.subplots(1, 6, figsize=(10, 2))
52+
fig, axes = plt.subplots(1, 7, figsize=(12, 2))
5153

5254
axes[0].imshow((x_0, x_1, x_2), cmap='3VarAddA', interpolation='nearest')
5355
axes[1].matshow((x_0, x_1, x_2), cmap='3VarAddA')
@@ -57,7 +59,8 @@ def test_multivariate_visualizations():
5759
x = np.arange(5)
5860
y = np.arange(5)
5961
X, Y = np.meshgrid(x, y)
60-
axes[4].pcolormesh(X, Y, (x_0, x_1, x_2), cmap='3VarAddA')
62+
axes[4].pcolor(X, Y, (x_0, x_1, x_2), cmap='3VarAddA')
63+
axes[5].pcolormesh(X, Y, (x_0, x_1, x_2), cmap='3VarAddA')
6164

6265
patches = [
6366
mpl.patches.Wedge((.3, .7), .1, 0, 360), # Full circle
@@ -70,7 +73,7 @@ def test_multivariate_visualizations():
7073
colors_2 = np.arange(len(patches)) % 3
7174
p = mpl.collections.PatchCollection(patches, cmap='3VarAddA', alpha=0.5)
7275
p.set_array((colors_0, colors_1, colors_2))
73-
axes[5].add_collection(p)
76+
axes[6].add_collection(p)
7477

7578
remove_ticks_and_titles(fig)
7679

@@ -625,52 +628,8 @@ def test_cmap_error():
625628
)):
626629
mpl.collections.PatchCollection([], cmap='not_a_cmap')
627630

628-
if 0:
629-
def test_artist_format_cursor_data_multivar():
630-
631-
X = np.zeros((3, 3))
632-
X[0, 0] = 0.9
633-
X[0, 1] = 0.99
634-
X[0, 2] = 0.999
635-
X[1, 0] = -1
636-
X[1, 1] = 0
637-
X[1, 2] = 1
638-
X[2, 0] = 0.09
639-
X[2, 1] = 0.009
640-
X[2, 2] = 0.0009
641-
642-
labels_list = [
643-
"[0.9, 0.0]",
644-
"[1., 0.0]",
645-
"[1., 0.0]",
646-
"[-1.0, 0.0]",
647-
"[0.0, 0.0]",
648-
"[1.0, 0.0]",
649-
"[0.09, 0.0]",
650-
"[0.009, 0.0]",
651-
"[0.0009, 0.0]",
652-
]
653-
654-
pos = [[0, 0], [1, 0], [2, 0],
655-
[0, 1], [1, 1], [2, 1],
656-
[0, 2], [1, 2], [2, 2]]
657-
658-
from matplotlib.backend_bases import MouseEvent
659-
660-
for cmap in ['BiOrangeBlue', '2VarAddA']:
661-
fig, ax = plt.subplots()
662-
norm = mpl.colors.BoundaryNorm(np.linspace(-1, 1, 20), 256)
663-
data = (X, np.zeros(X.shape))
664-
im = ax.imshow(data, cmap=cmap, norm=(norm, None))
665-
666-
for v, text in zip(pos, labels_list):
667-
xdisp, ydisp = ax.transData.transform(v)
668-
event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
669-
assert im.format_cursor_data(im.get_cursor_data(event)) == text
670-
671631

672632
def test_multivariate_safe_masked_invalid():
673-
from matplotlib import cbook
674633
dt = np.dtype('float32, float32').newbyteorder('>')
675634
x = np.zeros(2, dtype=dt)
676635
x['f0'][0] = np.nan

0 commit comments

Comments
 (0)