diff --git a/docs/changelog.md b/docs/changelog.md index 89658c92a..6bbecc425 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -13,4 +13,5 @@ For developers, please consult the [contributing guide](https://github.com/scver ### Fixed +- `relabel_sequential()` now works for unsigned integer arrays (e.g. `uint8`/`uint16`/`uint32` labels); with NumPy 2 it raised an `OverflowError`. - Querying a `SpatialData` object with multiple (batched) bounding boxes now raises an explicit `NotImplementedError` instead of failing with an opaque `AssertionError`. Batched queries are supported when querying a `SpatialElement` directly, but not when querying a `SpatialData` object, since that would require returning one `SpatialData` object per bounding box. diff --git a/src/spatialdata/_core/operations/map.py b/src/spatialdata/_core/operations/map.py index b0738dbff..03ef29a94 100644 --- a/src/spatialdata/_core/operations/map.py +++ b/src/spatialdata/_core/operations/map.py @@ -252,7 +252,9 @@ def relabel_sequential(arr: da.Array) -> da.Array: max_label = unique_labels[-1] - new_labeling = da.full(max_label + 1, -1, dtype=arr.dtype) + # The fill value is never read (every label in `arr` is overwritten below). Use 0 rather than -1, since -1 can't + # be cast to unsigned dtypes. + new_labeling = da.zeros(max_label + 1, dtype=arr.dtype) # Note that both sides are ordered as da.unique returns an ordered array. new_labeling[unique_labels] = da.arange(len(unique_labels), dtype=arr.dtype) diff --git a/tests/core/operations/test_map.py b/tests/core/operations/test_map.py index cde00fd31..5967f15ad 100644 --- a/tests/core/operations/test_map.py +++ b/tests/core/operations/test_map.py @@ -368,6 +368,14 @@ def _is_sequential(arr): assert np.array_equal(relabel_sequential(arr).compute(), np.array([3, 1, 2])) +@pytest.mark.parametrize("dtype", [np.uint8, np.uint16, np.uint32, np.uint64, np.int8, np.int32, np.int64]) +def test_relabel_sequential_dtypes(dtype): + arr = da.from_array(np.array([[0, 5, 9], [9, 5, 0]], dtype=dtype), chunks=(2, 3)) + relabeled = relabel_sequential(arr) + assert relabeled.dtype == dtype + assert np.array_equal(relabeled.compute(), np.array([[0, 1, 2], [2, 1, 0]], dtype=dtype)) + + def test_relabel_sequential_fails(sdata_blobs): with pytest.raises( ValueError, match=re.escape(f"Sequential relabeling is only supported for arrays of type {np.integer}.")