Since #1131, filtering a table that annotates multiple regions reorders its obs rows by region instead of preserving the original order. This shifts table rows relative to element geometries and broke an ordering assertion in a spatialdata-plot test.
Cause:_filter_table_by_elements was changed from a boolean mask (order-preserving) to join_spatialelement_table(how="left"), which does obs.groupby(region) and thus regroups the rows.
MRE
importnumpyasnpimportpandasaspdfromanndataimportAnnDatafromgeopandasimportGeoDataFramefromshapely.geometryimportPointimportspatialdataassdfromspatialdata.modelsimportShapesModel, TableModeldefcircles(n):
gdf=GeoDataFrame({"geometry": [Point(i, i) foriinrange(n)], "radius": [1.0] *n})
returnShapesModel.parse(gdf)
# table annotates two regions, obs rows INTERLEAVED: a,b,a,b,a,bobs=pd.DataFrame(
{
"region": pd.Categorical(["a", "b", "a", "b", "a", "b"]),
"instance_id": [0, 0, 1, 1, 2, 2],
"label": ["a0", "b0", "a1", "b1", "a2", "b2"],
}
)
table=TableModel.parse(
AnnData(X=np.zeros((6, 1)), obs=obs, var=pd.DataFrame(index=["g0"])),
region=["a", "b"],
region_key="region",
instance_key="instance_id",
)
sdata=sd.SpatialData(shapes={"a": circles(3), "b": circles(3)}, tables={"table": table})
before=list(sdata["table"].obs["label"])
after=list(sdata.filter_by_coordinate_system("global")["table"].obs["label"])
assertafter==before, f"obs reordered {before} -> {after}"Result
┌─────────┬───────────────────────────────────────┐
│ version │ obs after filter_by_coordinate_system │
├─────────┼───────────────────────────────────────┤
│ 0.7.2 │ a0, b0, a1, b1, a2, b2 (preserved) ✅ │
├─────────┼───────────────────────────────────────┤
│ 0.8 │ a0, a1, a2, b0, b1, b2 (regrouped) ❌ │
└─────────┴───────────────────────────────────────┘
Since #1131, filtering a table that annotates multiple regions reorders its
obsrows by region instead of preserving the original order. This shifts table rows relative to element geometries and broke an ordering assertion in aspatialdata-plottest.Cause:
_filter_table_by_elementswas changed from a boolean mask (order-preserving) tojoin_spatialelement_table(how="left"), which doesobs.groupby(region)and thus regroups the rows.MRE
Result