diff --git a/src/spatialdata/_core/_utils.py b/src/spatialdata/_core/_utils.py index a55815655..9dfd613b3 100644 --- a/src/spatialdata/_core/_utils.py +++ b/src/spatialdata/_core/_utils.py @@ -158,9 +158,9 @@ def get_unique_name(name: str, attr: str, is_dataframe_column: bool = False) -> # Handle other attributes for attr in ("obsm", "obsp", "varm", "varp", "uns", "layers"): d = getattr(sanitized, attr) - new_keys = {old: get_unique_name(old, attr) for old in d} - # Create new dictionary with sanitized keys - new_dict = {new_keys[old]: value for old, value in d.items()} + # None is a valid key in layers (anndata >= 0.13: represents X); skip sanitizing it + new_keys = {old: get_unique_name(old, attr) for old in d if old is not None} + new_dict = {(new_keys[old] if old is not None else old): value for old, value in d.items()} setattr(sanitized, attr, new_dict) return None if inplace else sanitized diff --git a/tests/utils/test_sanitize.py b/tests/utils/test_sanitize.py index 6b2fd3150..dac069430 100644 --- a/tests/utils/test_sanitize.py +++ b/tests/utils/test_sanitize.py @@ -164,6 +164,22 @@ def test_sanitize_table_uns_and_layers(): assert list(sanitized.layers.keys()) == ["bad_layer"] +def test_sanitize_table_layers_preserves_x(): + # anndata >= 0.13 stores X as layers[None]; sanitize_table must not corrupt it + X = np.array([[0, 1], [1, 0]]) + ad = AnnData(X=X, obs=pd.DataFrame({"x": [1, 2]}, index=["0", "1"]), var=pd.DataFrame(index=["v1", "v2"])) + ad.layers["bad#layer"] = np.array([[1, 0], [0, 1]]) + none_in_layers_before = None in ad.layers + sanitized = sanitize_table(ad, inplace=False) + assert sanitized.X is not None + np.testing.assert_array_equal(sanitized.X, X) + string_keys = [k for k in sanitized.layers if k is not None] + assert string_keys == ["bad_layer"] + # If anndata stores X as layers[None], the None key must survive sanitization + if none_in_layers_before: + assert None in sanitized.layers + + def test_sanitize_table_empty_returns_empty(): ad = AnnData() sanitized = sanitize_table(ad, inplace=False)