`render_shapes` with datashader fails with `KeyError: 'global'` on non-"global" coordinate systems with geopandas 1.2
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 72/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- python
- Área
- data-visualization
Línea de trabajo
Empieza en spatialdata_plot/pl/render.py, en la rama de datashader de _render_shapes, donde se construye transformed_element con ShapesModel.parse. Ejecuta el reproductor de 12 000 shapes del issue en un sistema de coordenadas no global, con geopandas 1.2.0 y 1.1.4. Está terminado cuando renderiza con ambas versiones, se eliminan los atributos transform copiados y se establece explícitamente la transformación de identidad "global".
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
With geopandas 1.2.0, render_shapes() fails with KeyError: 'global' when the element has more than 10,000 shapes (so the datashader method is used) and the element is not in the "global" coordinate system.
The same code works with geopandas 1.1.4.
Minimal example
import geopandas as gpd
import matplotlib.pyplot as plt
import numpy as np
import shapely
import spatialdata as sd
import spatialdata_plot # noqa: F401
from spatialdata.models import ShapesModel
from spatialdata.transformations import Identity
# More than 10,000 shapes so that render_shapes picks the datashader method
rng = np.random.default_rng(0)
xy = rng.uniform(0, 1000, size=(12_000, 2))
shapes = gpd.GeoDataFrame(geometry=[shapely.box(x, y, x + 2, y + 2) for x, y in xy])
# The element is only in a coordinate system that is not "global"
sdata = sd.SpatialData(
shapes={"squares": ShapesModel.parse(shapes, transformations={"sample": Identity()})}
)
fig, ax = plt.subplots()
sdata.pl.render_shapes("squares").pl.show(ax=ax, coordinate_systems="sample")
With geopandas==1.2.0:
File ".../spatialdata_plot/pl/render.py", line 910, 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", line 830, in _get_extent_and_range_for_datashader_canvas
extent = _fast_extent(spatial_element, coordinate_system)
File ".../spatialdata_plot/pl/utils.py", line 1678, in _fast_extent
return _element_extent_fast(element, coordinate_system) or get_extent(element, coordinate_system=coordinate_system)
File ".../spatialdata_plot/pl/utils.py", line 1585, in _element_extent_fast
matrix = transformations[coordinate_system].to_affine_matrix(("x", "y"), ("x", "y"))
KeyError: 'global'
With geopandas<1.2 (1.1.4) the plot renders correctly.
With method="matplotlib" it also renders correctly.
Cause
In the datashader path of _render_shapes, the geometry is transformed into the target coordinate system and a new element is made:
transformed_element = ShapesModel.parse(
gpd.GeoDataFrame(
data=shapes.drop("geometry", axis=1),
geometry=transformed_geometry,
)
)
The extent is then computed in a hard-coded "global" coordinate system.
This relies on ShapesModel.parse adding the default {"global": Identity()} transformation.
shapes.drop(...) keeps DataFrame.attrs, which hold the original transform.
geopandas 1.1.4 dropped these attrs in the GeoDataFrame constructor, but geopandas 1.2.0 keeps them:
import geopandas as gpd, shapely
g = gpd.GeoDataFrame({"a": [1]}, geometry=[shapely.Point(0, 0)])
g.attrs["transform"] = {"sample": 1}
print(gpd.GeoDataFrame(data=g.drop("geometry", axis=1), geometry=g["geometry"]).attrs)
# geopandas 1.1.4: {}
# geopandas 1.2.0: {'transform': {'sample': 1}}
So with geopandas 1.2.0 ShapesModel.parse keeps the original transformations (here only "sample"), no "global" transformation is added, and the lookup fails.
Possible fix
The geometry is already in the target coordinate system, so the copied transform attrs can be removed before parsing.
Just passing transformations={"global": Identity()} to ShapesModel.parse is not sufficient. With geopandas 1.2.0 it raises ValueError: Transformations are both specified for the element and also passed as an argument to the parser.
This change makes the example above work with both geopandas 1.1.4 and 1.2.0:
- transformed_element = ShapesModel.parse(
- gpd.GeoDataFrame(
- data=shapes.drop("geometry", axis=1),
- geometry=transformed_geometry,
- )
- )
+ transformed_gdf = gpd.GeoDataFrame(
+ data=shapes.drop("geometry", axis=1),
+ geometry=transformed_geometry,
+ )
+ # geometry is already in the target coordinate system; drop any transform
+ # carried over in attrs (geopandas >= 1.2 propagates DataFrame.attrs)
+ transformed_gdf.attrs.pop("transform", None)
+ transformed_element = ShapesModel.parse(transformed_gdf, transformations={"global": Identity()})
Versions
spatialdata-plot 0.4.2
geopandas 1.2.0
spatialdata 0.8.0
pandas 3.0.6
shapely 2.2.0
datashader 0.19.1
numpy 2.5.3
Python 3.13.5
OS macOS-26.7.1-arm64
- Lenguaje dominante
- Python
- Estrellas
- 86
- Forks
- 22
- Merge medio
- 4 d 5 h
- PR fusionados (30 d)
- 5
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de scverse/spatialdata-plot
-
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
scverse/spatialdata-plot#747 ·
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 45/100
scverse/spatialdata-plot#677 ·
-
enhancement priority: medium utils :wrench:
Dificultad 3/5 1-2 días Aptitud para principiantes 68/100
scverse/spatialdata-plot#632 ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
scverse/spatialdata-plot#534 · 1 comentario ·
-
Enable auto-completionAbierto
Dificultad 4/5 3-5 días Aptitud para principiantes 30/100
scverse/spatialdata-plot#476 ·
Todos los issues de scverse/spatialdata-plot
Issues similares
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 88/100
gradio-app/gradio#13964 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 93/100
BSData/horus-heresy-3rd-edition#3232 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
jbacalso24/mimry#123 ·
Los mantenedores suelen responder en 1 día
-
p:3-mid pydanty:bug pydanty:is-working
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
pydantic/pydantic-ai#10153 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
good first issue priority: medium size: S testing
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
cubrid-lab/cubrid-cookbook-python#316 ·
Los mantenedores suelen responder en 1 día