Skip to content

bounding_box_query(filter_table=True) restores dropped categories but not their colors in uns #1271

Open

Description

@Marius1311

When a query with filter_table=True removes every row of a category, the returned table still lists all original categories, but uns["<column>_colors"] has lost that category's color. Categories and colors are matched by position, so they no longer line up.

import anndata as ad
import geopandas as gpd
import pandas as pd
import shapely
import spatialdata as sd
from spatialdata.models import ShapesModel, TableModel

# three cells of types A, C and B; B lies outside the query box
shapes = gpd.GeoDataFrame(geometry=[shapely.Point(x, 0) for x in (0, 10, 100)], index=["a", "c", "b"]).assign(radius=1.0)
table = ad.AnnData(obs=pd.DataFrame(
    {"region": pd.Categorical(["cells"] * 3), "cell_id": ["a", "c", "b"],
     "cell_type": pd.Categorical(["A", "C", "B"], categories=["A", "B", "C"])}, index=["a", "c", "b"]))
table.uns["cell_type_colors"] = ["red", "green", "blue"]  # A, B, C
sdata = sd.SpatialData(
    shapes={"cells": ShapesModel.parse(shapes)},
    tables={"table": TableModel.parse(table, region="cells", region_key="region", instance_key="cell_id")},
)

crop = sd.bounding_box_query(sdata, axes=("x", "y"), min_coordinate=[-5, -5], max_coordinate=[15, 5],
                             target_coordinate_system="global", filter_table=True)
t = crop["table"]
print(t.obs["cell_type"].cat.categories.tolist(), list(map(str, t.uns["cell_type_colors"])))
['A', 'B', 'C'] ['red', 'blue']

spatialdata-plot then draws C in na_color ("Not enough colors provided for category 'C'"). On a real dataset with nine cell types, the cropped cells came out in other types' colors.

The cause seems to be in the join: table[indices].copy() makes anndata drop the unused category together with its color, and _inplace_fix_subset_categorical_obs then restores the original categories with set_categories but leaves uns as it is. Restoring uns[f"{column}_colors"] from the original table there, when present, would keep them in sync. Workaround: filter_table=False.

spatialdata 0.8.0 (the function is unchanged on main), anndata 0.13.4, pandas 3.0.5, Python 3.12.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions