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

Skip to content

Commit 9b9aaf3

Browse files
committed
updates based on feedback from @QuLogic
1 parent a752b67 commit 9b9aaf3

File tree

3 files changed

+55
-55
lines changed

3 files changed

+55
-55
lines changed

lib/matplotlib/colorizer.py

Lines changed: 32 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ def _set_cmap(self, cmap):
219219
----------
220220
cmap : `.Colormap` or str or None
221221
"""
222-
# bury import to avoid circular imports
223222
in_init = self._cmap is None
224223
cmap_obj = _ensure_cmap(cmap, accept_multivariate=True)
225224
if not in_init and self.norm.n_components != cmap_obj.n_variates:
@@ -258,9 +257,6 @@ def set_clim(self, vmin=None, vmax=None):
258257
vmin, vmax = vmin
259258
except (TypeError, ValueError):
260259
pass
261-
# If the norm's limits are updated self.changed() will be called
262-
# through the callbacks attached to the norm, this causes an inconsistent
263-
# state, to prevent this blocked context manager is used
264260

265261
orig_vmin_vmax = self.norm.vmin, self.norm.vmax
266262

@@ -472,24 +468,24 @@ def _format_cursor_data_override(self, data):
472468
# Note if cm.ScalarMappable is depreciated, this functionality should be
473469
# implemented as format_cursor_data() on ColorizingArtist.
474470
if np.ma.getmask(data) or data is None:
471+
# NOTE: for multivariate data, if *any* of the fields are masked,
472+
# "[]" is returned here
475473
return "[]"
476-
if len(data.dtype.descr) > 1:
477-
# We have multivariate data encoded as a data type with multiple fields
478-
# NOTE: If any of the fields are masked, "[]" would be returned via
479-
# the if statement above.
480-
s_sig_digits_list = []
474+
475+
if isinstance(self.norm, colors.MultiNorm):
476+
norms = self.norm.norms
481477
if isinstance(self.cmap, colors.BivarColormap):
482478
n_s = (self.cmap.N, self.cmap.M)
483-
else:
479+
else: # colors.MultivarColormap
484480
n_s = [part.N for part in self.cmap]
485-
os = [f"{d:-#.{self._sig_digits_from_norm(no, d, n)}g}"
486-
for no, d, n in zip(self.norm.norms, data, n_s)]
487-
return f"[{', '.join(os)}]"
481+
else: # colors.Colormap
482+
norms = [self.norm]
483+
data = [data]
484+
n_s = [self.cmap.N]
488485

489-
# scalar data
490-
n = self.cmap.N
491-
g_sig_digits = self._sig_digits_from_norm(self.norm, data, n)
492-
return f"[{data:-#.{g_sig_digits}g}]"
486+
os = [f"{d:-#.{self._sig_digits_from_norm(no, d, n)}g}"
487+
for no, d, n in zip(norms, data, n_s)]
488+
return f"[{', '.join(os)}]"
493489

494490
@staticmethod
495491
def _sig_digits_from_norm(norm, data, n):
@@ -503,16 +499,13 @@ def _sig_digits_from_norm(norm, data, n):
503499
cur_idx = np.argmin(np.abs(norm.boundaries - data))
504500
neigh_idx = max(0, cur_idx - 1)
505501
# use max diff to prevent delta == 0
506-
delta = np.diff(
507-
norm.boundaries[neigh_idx:cur_idx + 2]
508-
).max()
502+
delta = np.diff(norm.boundaries[neigh_idx:cur_idx + 2]).max()
509503
elif norm.vmin == norm.vmax:
510504
# singular norms, use delta of 10% of only value
511505
delta = np.abs(norm.vmin * .1)
512506
else:
513507
# Midpoints of neighboring color intervals.
514-
neighbors = norm.inverse(
515-
(int(normed * n) + np.array([0, 1])) / n)
508+
neighbors = norm.inverse((int(normed * n) + np.array([0, 1])) / n)
516509
delta = abs(neighbors - data).max()
517510

518511
g_sig_digits = cbook._g_sig_digits(data, delta)
@@ -803,35 +796,28 @@ def _ensure_cmap(cmap, accept_multivariate=False):
803796
- if a string, look it up in three corresponding databases
804797
when not found: raise an error based on the expected shape
805798
- if None, look up the default color map in mpl.colormaps
806-
accept_multivariate : bool, default True
799+
accept_multivariate : bool, default False
807800
- if False, accept only Colormap, string in mpl.colormaps or None
808801
809802
Returns
810803
-------
811804
Colormap
812805
813806
"""
814-
if not accept_multivariate:
815-
if isinstance(cmap, colors.Colormap):
816-
return cmap
817-
cmap_name = cmap if cmap is not None else mpl.rcParams["image.cmap"]
818-
# use check_in_list to ensure type stability of the exception raised by
819-
# the internal usage of this (ValueError vs KeyError)
820-
if cmap_name not in mpl.colormaps:
821-
_api.check_in_list(sorted(mpl.colormaps), cmap=cmap_name)
822-
823-
if isinstance(cmap, (colors.Colormap,
824-
colors.BivarColormap,
825-
colors.MultivarColormap)):
807+
if accept_multivariate:
808+
types = (colors.Colormap, colors.BivarColormap, colors.MultivarColormap)
809+
mappings = (mpl.colormaps, mpl.multivar_colormaps, mpl.bivar_colormaps)
810+
else:
811+
types = (colors.Colormap, )
812+
mappings = (mpl.colormaps, )
813+
814+
if isinstance(cmap, types):
826815
return cmap
827816

828817
cmap_name = cmap if cmap is not None else mpl.rcParams["image.cmap"]
829-
if cmap_name in mpl.colormaps:
830-
return mpl.colormaps[cmap_name]
831-
if cmap_name in mpl.multivar_colormaps:
832-
return mpl.multivar_colormaps[cmap_name]
833-
if cmap_name in mpl.bivar_colormaps:
834-
return mpl.bivar_colormaps[cmap_name]
818+
for mapping in mappings:
819+
if cmap_name in mapping:
820+
return mapping[cmap_name]
835821

836822
# this error message is a variant of _api.check_in_list but gives
837823
# additional hints as to how to access multivariate colormaps
@@ -843,13 +829,6 @@ def _ensure_cmap(cmap, accept_multivariate=False):
843829
" `matplotlib.multivar_colormaps()` for"
844830
" bivariate and multivariate colormaps")
845831

846-
if isinstance(cmap, colors.Colormap):
847-
return cmap
848-
cmap_name = cmap if cmap is not None else mpl.rcParams["image.cmap"]
849-
# use check_in_list to ensure type stability of the exception raised by
850-
# the internal usage of this (ValueError vs KeyError)
851-
if cmap_name not in cm.colormaps:
852-
_api.check_in_list(sorted(cm.colormaps), cmap=cmap_name)
853832
return cm.colormaps[cmap_name]
854833

855834

@@ -881,6 +860,11 @@ def _ensure_multivariate_data(data, n_components):
881860
# and already formatted data
882861
return data
883862
elif data.dtype in [np.complex64, np.complex128]:
863+
if n_components != 2:
864+
raise ValueError("Invalid data entry for multivariate data. "
865+
"Complex numbers are incompatible with "
866+
"{n_components} variates.")
867+
884868
# pass complex data
885869
if data.dtype == np.complex128:
886870
dt = np.dtype('float64, float64')

lib/matplotlib/tests/test_colors.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,9 +2098,9 @@ def test_ensure_multivariate_data():
20982098
mcolorizer._ensure_multivariate_data(data, 3)
20992099

21002100
# test input of ints as list of lists
2101-
data = [[0, 0], [1, 1]]
2101+
data = [[0, 0, 0], [1, 1, 1]]
21022102
mdata = mcolorizer._ensure_multivariate_data(data, 2)
2103-
assert mdata.shape == (2,)
2103+
assert mdata.shape == (3,)
21042104
assert mdata.dtype.fields['f0'][0] == np.int64
21052105
assert mdata.dtype.fields['f1'][0] == np.int64
21062106

@@ -2157,9 +2157,11 @@ def test_colorizer_multinorm_implicit():
21572157
[0.99853516, 0.50048437, 0.00244141, 1.]]])
21582158
assert_array_almost_equal(ca.to_rgba(data), res)
21592159

2160-
with pytest.raises(ValueError):
2161-
ca.to_rgba([[0.1, 0.2, 0.3]])
2162-
with pytest.raises(ValueError):
2160+
with pytest.raises(ValueError, match=("This MultiNorm has 2 components, "
2161+
"but got a sequence with 3 elements")):
2162+
ca.to_rgba([0.1, 0.2, 0.3])
2163+
with pytest.raises(ValueError, match=("This MultiNorm has 2 components, "
2164+
"but got a sequence with 1 elements")):
21632165
ca.to_rgba([[0.1]])
21642166

21652167
# test multivariate
@@ -2219,10 +2221,23 @@ def test_colorizer_bivar_cmap():
22192221
# ensure masked value is propagated from input
22202222
a = np.arange(3)
22212223
cartist.set_array((a, np.ma.masked_where(a > 1, a)))
2224+
assert cartist.get_array()['f0'].mask[0] is np.False_
2225+
assert cartist.get_array()['f0'].mask[1] is np.False_
22222226
assert cartist.get_array()['f0'].mask[2] is np.False_
2223-
assert cartist.get_array()['f1'].mask[2] is np.True_
2227+
assert cartist.get_array()['f1'].mask[0] is np.False_
22242228
assert cartist.get_array()['f1'].mask[1] is np.False_
2229+
assert cartist.get_array()['f1'].mask[2] is np.True_
22252230

22262231
# test clearing data
22272232
cartist.set_array(None)
22282233
cartist.get_array() is None
2234+
2235+
2236+
def test_colorizer_multivar_cmap():
2237+
ca = mcolorizer.Colorizer('3VarAddA', [mcolors.Normalize(),
2238+
mcolors.Normalize(),
2239+
'log'])
2240+
cartist = mcolorizer.ColorizingArtist(ca)
2241+
cartist.set_array(np.zeros((3, 5, 5)))
2242+
with pytest.raises(ValueError, match='Complex numbers are incompatible with'):
2243+
cartist.set_array(np.zeros((5, 5), dtype='complex128'))

lib/matplotlib/tests/test_image.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,8 @@ def test_format_cursor_data_multinorm(data, text):
474474
# and use set_array() on the ColorizingArtist rather than the _ImageBase
475475
# but this workaround should be replaced by:
476476
# `ax.imshow(data, cmap=cmap_bivar, vmin=(0,0), vmax=(1,1))`
477-
# once the functionality is available
477+
# once the functionality is available.
478+
# see https://github.com/matplotlib/matplotlib/issues/14168
478479
im = ax.imshow([[0, 1]])
479480
im.colorizer._cmap = cmap_bivar
480481
im.colorizer._norm = colors.MultiNorm([im.norm, im.norm])

0 commit comments

Comments
 (0)