You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
render_shapes(method="datashader") fails with KeyError: 'global' when the element has no "global" coordinate system #782
render_shapes(..., method="datashader") raises KeyError: 'global' when the shapes element has no "global" coordinate system. This breaks the Visium HD example notebooks (technology_visium_hd, technology_visium_hd_mouse_4.0.1): data from spatialdata-io has no global CS, and datashader is used either explicitly or automatically (more than 10k shapes).
MRE (PEP 723, run with uv run mre.py)
# /// script# requires-python = ">=3.12"# dependencies = [# "spatialdata @ git+https://github.com/scverse/spatialdata.git@main",# "spatialdata-plot @ git+https://github.com/scverse/spatialdata-plot.git@main",# ]# ///importmatplotlibmatplotlib.use("Agg")
importspatialdataassdimportspatialdata_plot# noqa: F401fromspatialdata.transformationsimportget_transformation, set_transformationsdata=sd.datasets.cells()
# Move every element from "global" to a custom CS, as spatialdata-io does for Visium HD.cs="my_sample"for_, name, elementinsdata.gen_spatial_elements():
set_transformation(element, {cs: get_transformation(element, "global")}, set_all=True)
assert"global"notinsdata.coordinate_systemssdata.pl.render_shapes("cell_boundaries", method="matplotlib").pl.show(coordinate_systems=cs) # OKsdata.pl.render_shapes("cell_boundaries", method="datashader").pl.show(coordinate_systems=cs) # KeyError: 'global'
(spatialdata is installed from main because datasets.cells() is not in a release yet.)
Traceback (abridged)
File .../spatialdata_plot/pl/render.py, in _render_shapes
plot_width, plot_height, x_ext, y_ext, factor = _get_extent_and_range_for_datashader_canvas(
transformed_element, "global", fig_params
)
File .../spatialdata_plot/pl/_datashader.py, in _get_extent_and_range_for_datashader_canvas
extent = _fast_extent(spatial_element, coordinate_system)
File .../spatialdata_plot/pl/utils.py, in _fast_extent
return _element_extent_fast(element, coordinate_system) or get_extent(element, coordinate_system=coordinate_system)
File .../spatialdata_plot/pl/utils.py, in _element_extent_fast
matrix = transformations[coordinate_system].to_affine_matrix(("x", "y"), ("x", "y"))
KeyError: 'global'
Root cause
In the datashader branch of _render_shapes, the already-transformed geometry is wrapped with ShapesModel.parse(gpd.GeoDataFrame(data=shapes.drop("geometry", axis=1), ...)), and the canvas extent is then computed in a hardcoded "global" CS. Because shapes.drop(...) keeps .attrs, the new element inherits the original transformations (here only my_sample) and never gets a "global" entry, so the lookup in _element_extent_fast fails.
The lookup came in with #703 (fast axis-aligned extent), so that's the likely regression point; not confirmed by bisecting.
Possible fix
The geometry is already in the target CS, so pass transformations={"global": Identity()} to that ShapesModel.parse call (or clear attrs before parsing). A regression test rendering shapes with datashader in a non-global CS would cover this.
Activity
fix(datashader): render_shapes in a non-global coordinate system (#782)…