Skip to content

render_images and render_labels give cryptic internal errors for 3D (z-stack) data #608

@timtreis

Description

@timtreis

render_images and render_labels give cryptic internal errors for 3D (z-stack) data instead of a clear unsupported message

Description

3D z-stack data (Image3DModel, Labels3DModel) is standard in confocal and lightsheet microscopy workflows. render_images and render_labels accept 3D elements without any validation and proceed until crashing with opaque errors from matplotlib and numpy internals. No part of the error message mentions "3D", "z-stack", the unsupported dimensionality, or any workaround. GitHub issue #386 confirms this is a known gap.

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 Image3DModel
import spatialdata_plot

img3d = np.random.rand(2, 5, 20, 20).astype(np.float32)  # (c, z, y, x)
image3d = Image3DModel.parse(img3d, dims=["c", "z", "y", "x"], c_coords=["DAPI", "GFP"])
sdata = sd.SpatialData(images={"img3d": image3d})

fig, ax = plt.subplots()
sdata.pl.render_images("img3d").pl.show(ax=ax)
# TypeError: Invalid shape (5, 20, 3, 4) for image data

Actual Output

render_images with a 3D image:

TypeError: Invalid shape (5, 20, 3, 4) for image data

render_labels with 3D labels:

ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 3...

Both errors originate in matplotlib or numpy internals. No spatialdata-plot frame is visible; no mention of the unsupported dimensionality.

Expected Output

ValueError: render_images does not support 3D images. Element 'img3d' has a 'z'
dimension with 5 slices. Select a 2D slice before plotting:

    sdata['img3d'].isel(z=0)          # select first z-slice
    sd.bounding_box_query(sdata, ...)  # or use a bounding box query

Fix Sketch

Add an early dimensionality guard at the top of _render_images and _render_labels:

# In _render_images:
if "z" in element.dims:
    raise ValueError(
        f"render_images does not support 3D images. Element '{element_name}' "
        f"has a 'z' dimension with {element.sizes['z']} slices. "
        "Select a 2D slice before plotting:\n"
        f"    sdata['{element_name}'].isel(z=0)\n"
        "or use sd.bounding_box_query() to extract a 2D region."
    )

# In _render_labels (analogous):
if "z" in element.dims:
    raise ValueError(
        f"render_labels does not support 3D labels. Element '{element_name}' "
        f"has a 'z' dimension with {element.sizes['z']} slices. "
        "Select a 2D slice before plotting:\n"
        f"    sdata['{element_name}'].isel(z=0)"
    )

Related


Triage tier: Tier 2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions