Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions ultraplot/axes/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -7700,11 +7700,18 @@ def spy(self, z, **kwargs):
"""
kw = kwargs.copy()
kw.update(_pop_props(kw, "line")) # takes valid Line2D properties
default_cmap = pcolors.DiscreteColormap(["w", "k"], "_no_name")
center_levels = kw.pop("center_levels", None)
kw = self._parse_cmap(
z, center_levels=center_levels, default_cmap=default_cmap, **kw
)
# NOTE: Matplotlib's spy draws an image when no marker is given, and a
# Line2D of markers otherwise. Only the image understands a colormap, so
# parsing one for the marker path would hand 'cmap' to a Line2D.
markers = kw.get("marker", None) is not None or kw.get("markersize") is not None
if not markers:
default_cmap = pcolors.DiscreteColormap(["w", "k"], "_no_name")
center_levels = kw.pop("center_levels", None)
kw = self._parse_cmap(
z, center_levels=center_levels, default_cmap=default_cmap, **kw
)
else:
kw.pop("center_levels", None)
guide_kw = _pop_params(kw, self._update_guide)
m = self._call_native("spy", z, **kw)
self._update_guide(m, queue_colorbar=False, **guide_kw)
Expand Down
32 changes: 32 additions & 0 deletions ultraplot/tests/test_2dplots.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,38 @@ def test_tripcolor_warns_when_z_and_facecolors_given():
)


def test_spy_marker_path_takes_no_colormap():
"""
Marker-style spy must not be handed a colormap.

Matplotlib's spy draws an image when no marker is given and a Line2D of
markers otherwise; only the image understands `cmap`, so parsing one for
the marker path raised `Line2D.set() got an unexpected keyword argument`.
"""
from matplotlib.image import AxesImage
from matplotlib.lines import Line2D

matrix = np.random.default_rng(51423).random((12, 12)) > 0.8
_, axs = uplt.subplots(ncols=4)
assert isinstance(axs[0].spy(matrix), AxesImage)
assert isinstance(axs[1].spy(matrix, markersize=2), Line2D)
assert isinstance(axs[2].spy(matrix, marker="s"), Line2D)
assert isinstance(axs[3].spy(matrix, color="denim", markersize=3), Line2D)


def test_spy_image_path_still_takes_a_colormap():
"""
The image path keeps its colormap handling, including the discrete default.
"""
from matplotlib.image import AxesImage

matrix = np.random.default_rng(51423).random((12, 12)) > 0.8
_, ax = uplt.subplots()
image = ax.spy(matrix, cmap="Greys")
assert isinstance(image, AxesImage)
assert "greys" in image.get_cmap().name.lower()


def test_tricontour_explicit_colors_match_levels():
"""
Explicit triangular contour colors should map one-to-one with levels.
Expand Down