scverse / scverse/spatialdata-plot

No support for .obsm keys as color source in render functions

Abierto
#632 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

enhancement priority: medium utils :wrench:
Lenguaje dominante
Python
Estrellas
86
Forks
21
Merge medio
14 h 50 min
PR fusionados (30 d)
3

Descripción

No support for .obsm keys as color source in render functions

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


Problem

render_shapes, render_labels, and render_points resolve color= from table.obs columns and table.var_names (gene expression), but they do not check table.obsm. Any per-cell metric stored in .obsm — spatial QC scores, embedding coordinates, tiling statistics, cell neighborhood features — cannot be used for coloring.

Users must work around this by manually copying the .obsm column into .obs, which pollutes the AnnData object and requires extra bookkeeping.

This is tracked in GitHub issue #587.


Minimal reproducible example

import matplotlib; matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np, pandas as pd, geopandas as gpd, anndata as ad
import dask; dask.config.set({"dataframe.query-planning": False})
from shapely.geometry import box
import spatialdata as sd
from spatialdata.models import ShapesModel, TableModel
import spatialdata_plot

shapes = ShapesModel.parse(gpd.GeoDataFrame(
    {"geometry": [box(i, 0, i+1, 1) for i in range(3)], "radius": [0.5]*3},
    geometry="geometry"
))
obs = pd.DataFrame({
    "region": pd.Categorical(["s"]*3),
    "instance_id": [0, 1, 2],
})
adata = ad.AnnData(X=np.zeros((3, 1)), obs=obs)
# Per-cell QC metrics stored in obsm — cannot currently use for coloring
adata.obsm["spatial_qc"] = pd.DataFrame(
    {"n_counts": [100.0, 250.0, 50.0], "density": [0.8, 0.6, 0.9]},
    index=adata.obs_names
)
table = TableModel.parse(adata, region="s", region_key="region", instance_key="instance_id")
sdata = sd.SpatialData(shapes={"s": shapes}, tables={"t": table})

fig, ax = plt.subplots()
# Desired: sdata.pl.render_shapes("s", color="spatial_qc:n_counts").pl.show(ax=ax)
# Actual workaround needed:
adata.obs["n_counts"] = adata.obsm["spatial_qc"]["n_counts"].values
sdata.pl.render_shapes("s", color="n_counts").pl.show(ax=ax)

Expected behaviour

A syntax like color="spatial_qc:n_counts" (or equivalent) that lets users specify an obsm key and column directly, without manually copying into obs.

Actual behaviour

KeyError: "Unable to locate color key 'spatial_qc:n_counts' for element 's'."

.obsm is never checked in _validate_col_for_column_table (utils.py:2838–2872).


Feature request

Extend the color key resolution in _validate_col_for_column_table (and/or _locate_value) to support .obsm DataFrames. Possible syntaxes:

  • color="obsm_key:column" — explicit separator
  • color="column" with fallback to obsm keys when obs lookup fails
  • A dedicated obsm_key= parameter

This would unlock a common workflow where spatial QC, embeddings, or multi-modal per-cell metrics are stored in .obsm and need to be visualized spatially.


Triage tier: Tier 3

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Empieza en utils.py alrededor de _validate_col_for_column_table (líneas 2838–2872) e inspecciona _locate_value, así como las rutas de resolución de color de render_shapes, render_labels y render_points. Usa el ejemplo mínimo para verificar que se puede seleccionar un valor de un DataFrame de .obsm sin copiarlo en obs, y añade o actualiza la cobertura para la sintaxis de clave elegida y los colores resultantes.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
python
Área
data-visualization
Tipo de issue
Nueva funcionalidad
Dificultad
3/5
Tiempo estimado
1-2 días
Estado de actividad
Tranquilo
Claridad
Bastante claro
Aptitud para principiantes
68/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.