Skip to content

render_labels(fill_alpha=0, outline_alpha=0) silently renders invisible labels instead of erroring #630

@timtreis

Description

@timtreis

render_labels(fill_alpha=0, outline_alpha=0) silently renders invisible labels instead of erroring

Environment: spatialdata-plot 0.3.4.dev (main, commit 5cfedc7), Python 3.13


Problem

The _render_labels dispatch logic contains a branch intended to raise ValueError when both fill_alpha and outline_alpha are zero. That branch is dead code — it is never reached.

The first condition fill_alpha == outline_alpha evaluates to True when both are 0, routing the (0, 0) case into the "fill-only" path before the else is evaluated:

if (fill_alpha > 0.0 and outline_alpha == 0.0) or (
    fill_alpha == outline_alpha  # True when (0.0, 0.0)!
):
    cax = _draw_labels(alpha=fill_alpha)  # called with alpha=0 → invisible
    ...
elif fill_alpha == 0.0 and outline_alpha > 0.0:
    ...
elif fill_alpha > 0.0 and outline_alpha > 0.0:
    ...
else:
    raise ValueError("fill_alpha and outline_alpha cannot both be 0.")  # NEVER REACHED

Result: labels are rendered with alpha=0 (fully transparent, invisible). No error, no warning. The user's fill_alpha=0 and outline_alpha=0 combination is silently accepted and produces an empty plot.


Minimal reproducible example

import matplotlib; matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
import dask; dask.config.set({"dataframe.query-planning": False})
import spatialdata as sd
from spatialdata.models import Labels2DModel
import spatialdata_plot

labels_data = np.zeros((50, 50), dtype=np.int32)
labels_data[5:20, 5:20] = 1
sdata = sd.SpatialData(labels={"lbl": Labels2DModel.parse(labels_data, dims=["y", "x"])})

fig, ax = plt.subplots()
sdata.pl.render_labels("lbl", fill_alpha=0, outline_alpha=0).pl.show(ax=ax)
# No error — labels silently invisible
img = ax.images[0]
print(f"alpha = {img.get_alpha()}")  # 0 — invisible

Expected behaviour

ValueError: Parameters 'fill_alpha' and 'outline_alpha' cannot both be 0.

(This error already exists in the source — it's just in dead code that's never reached.)

Actual behaviour

Labels render with alpha=0 — fully transparent, invisible. The axes appear empty. No error or warning is raised.


Fix sketch

Add an explicit guard before the condition chain at render.py:1749:

if render_params.fill_alpha == 0.0 and render_params.outline_alpha == 0.0:
    raise ValueError(
        "Parameters 'fill_alpha' and 'outline_alpha' cannot both be 0. "
        "Set at least one to a positive value."
    )

This lifts the existing dead-code ValueError to where it can actually be reached. Alternatively, fix the first condition to exclude the (0, 0) case:

if (fill_alpha > 0.0 and outline_alpha == 0.0) or (
    fill_alpha > 0.0 and fill_alpha == outline_alpha
):

Triage tier: Tier 3

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions