Skip to content

Commit 69560ef

Browse files
authored
Fix render_images(norm=LogNorm()) crash on zero/non-positive data (#672)
1 parent 96582ac commit 69560ef

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

src/spatialdata_plot/pl/basic.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from geopandas import GeoDataFrame
2121
from matplotlib.axes import Axes
2222
from matplotlib.backend_bases import RendererBase
23-
from matplotlib.colors import Colormap, Normalize
23+
from matplotlib.colors import Colormap, LogNorm, Normalize
2424
from matplotlib.figure import Figure
2525
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
2626
from spatialdata import get_extent
@@ -1299,6 +1299,18 @@ def _draw_colorbar(
12991299
base_offsets_axes: dict[str, float],
13001300
trackers_axes: dict[str, float],
13011301
) -> None:
1302+
norm = spec.mappable.norm
1303+
if isinstance(norm, LogNorm):
1304+
vmin, vmax = norm.vmin, norm.vmax
1305+
if vmin is None or vmax is None or vmin <= 0 or vmin >= vmax:
1306+
warnings.warn(
1307+
"Data contains zeros or non-positive values; colorbar suppressed for `LogNorm`. "
1308+
"Pass `colorbar=False` to silence this warning, or clip the data to positive values.",
1309+
UserWarning,
1310+
stacklevel=2,
1311+
)
1312+
return
1313+
13021314
base_layout = {
13031315
"location": CBAR_DEFAULT_LOCATION,
13041316
"fraction": CBAR_DEFAULT_FRACTION,

tests/pl/test_render_images.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import numpy as np
55
import pytest
66
import scanpy as sc
7-
from matplotlib.colors import Normalize
7+
from matplotlib.colors import LogNorm, Normalize
88
from spatial_image import to_spatial_image
99
from spatialdata import SpatialData
1010
from spatialdata.models import Image2DModel
@@ -682,3 +682,16 @@ def test_channels_as_legend_coexists_with_other_elements(self, sdata_blobs: Spat
682682
assert "0" in labels
683683
assert "1" in labels
684684
plt.close("all")
685+
686+
687+
def test_lognorm_with_zeros_suppresses_colorbar_with_warning():
688+
# regression test for #604: LogNorm + non-positive data must not raise an opaque
689+
# matplotlib ValueError; instead suppress the colorbar with an actionable UserWarning.
690+
img = np.zeros((1, 5, 5), dtype=np.float32)
691+
sdata = SpatialData(images={"img": Image2DModel.parse(img, c_coords=["DAPI"])})
692+
fig, ax = plt.subplots()
693+
try:
694+
with pytest.warns(UserWarning, match="LogNorm"):
695+
sdata.pl.render_images("img", norm=LogNorm()).pl.show(ax=ax)
696+
finally:
697+
plt.close(fig)

0 commit comments

Comments
 (0)