render_labels crashes with cryptic skimage TypeError when label array has float dtype
Description
Labels2DModel.parse accepts float32 arrays without error — this is common output from ML segmentation pipelines. When render_labels is subsequently called on such an element, it crashes deep in _map_color_seg with TypeError: The dtype of an array to be remapped should be integer. from skimage internals. The traceback contains no mention of the element name, the offending dtype, or how to fix the problem.
Environment
spatialdata-plot: 0.3.4.dev (main, 5cfedc7)
spatialdata: 0.5.0
Python: 3.13
Minimal Reproducible Example
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
import spatialdata as sd
from spatialdata.models import Labels2DModel
import spatialdata_plot
# Labels from ML model output — commonly float32
labels = np.zeros((20, 20), dtype=np.float32)
labels[3:8, 3:8] = 1.0
labels[12:17, 12:17] = 2.0
sdata = sd.SpatialData(labels={"lbl": Labels2DModel.parse(labels, dims=["y", "x"])})
fig, ax = plt.subplots()
sdata.pl.render_labels("lbl").pl.show(ax=ax)
Actual Output
TypeError: The dtype of an array to be remapped should be integer.
The full traceback runs through skimage/util/_map_array.py with no spatialdata-plot frame visible. No mention of the element name, its dtype, or what to do about it.
Expected Output
A clear, actionable error at the entry point to _render_labels:
ValueError: Label element 'lbl' has dtype float32. Label arrays must use an integer
dtype (e.g. int32 or uint16). Cast before plotting:
sdata['lbl'] = sdata['lbl'].astype(np.int32)
Fix Sketch
In _render_labels, after the label array is loaded and squeezed, add a dtype guard before any downstream processing:
if np.issubdtype(label.values.dtype, np.floating):
raise ValueError(
f"Label element '{element_name}' has dtype {label.values.dtype}. "
"Label arrays must use an integer dtype (e.g. int32 or uint16). "
"Cast before plotting:\n"
f" import numpy as np\n"
f" sdata['{element_name}'] = sdata['{element_name}'].astype(np.int32)"
)
Alternatively, auto-cast with a UserWarning instead of raising — this trades strictness for convenience when values are small whole-number floats. Raising is the safer default since silent casting may hide upstream pipeline bugs.
Triage tier: Tier 2
render_labelscrashes with cryptic skimageTypeErrorwhen label array has float dtypeDescription
Labels2DModel.parseacceptsfloat32arrays without error — this is common output from ML segmentation pipelines. Whenrender_labelsis subsequently called on such an element, it crashes deep in_map_color_segwithTypeError: The dtype of an array to be remapped should be integer.from skimage internals. The traceback contains no mention of the element name, the offending dtype, or how to fix the problem.Environment
Minimal Reproducible Example
Actual Output
The full traceback runs through
skimage/util/_map_array.pywith no spatialdata-plot frame visible. No mention of the element name, its dtype, or what to do about it.Expected Output
A clear, actionable error at the entry point to
_render_labels:Fix Sketch
In
_render_labels, after the label array is loaded and squeezed, add a dtype guard before any downstream processing:Alternatively, auto-cast with a
UserWarninginstead of raising — this trades strictness for convenience when values are small whole-number floats. Raising is the safer default since silent casting may hide upstream pipeline bugs.Triage tier: Tier 2