From 2f9c096be18c4e56c726dbf13953a71087270f65 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Wed, 16 Oct 2024 16:23:58 +0000 Subject: [PATCH] [python] Support for current domain on dense arrays --- apis/python/src/tiledbsoma/_dense_nd_array.py | 52 +++++++++++++++---- apis/python/src/tiledbsoma/_tdb_handles.py | 14 ++--- apis/python/tests/test_shape.py | 12 +++-- libtiledbsoma/test/unit_soma_dense_ndarray.cc | 3 -- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/apis/python/src/tiledbsoma/_dense_nd_array.py b/apis/python/src/tiledbsoma/_dense_nd_array.py index ba646efa0f..38f6de741d 100644 --- a/apis/python/src/tiledbsoma/_dense_nd_array.py +++ b/apis/python/src/tiledbsoma/_dense_nd_array.py @@ -20,6 +20,7 @@ from ._arrow_types import pyarrow_to_carrow_type from ._common_nd_array import NDArray from ._exception import SOMAError, map_exception_for_create +from ._flags import NEW_SHAPE_FEATURE_FLAG_ENABLED from ._tdb_handles import DenseNDArrayWrapper from ._types import OpenTimestamp, Slice from ._util import dense_indices_to_shape @@ -103,15 +104,43 @@ def create( for dim_idx, dim_shape in enumerate(shape): dim_name = f"soma_dim_{dim_idx}" pa_field = pa.field(dim_name, pa.int64()) - dim_capacity, dim_extent = cls._dim_capacity_and_extent( - dim_name, - dim_shape, - TileDBCreateOptions.from_platform_config(platform_config), - ) - index_column_schema.append(pa_field) - # TODO: support current domain for dense arrays once we have core support. - # https://github.com/single-cell-data/TileDB-SOMA/issues/2955 + + if NEW_SHAPE_FEATURE_FLAG_ENABLED and clib.embedded_version_triple() >= ( + 2, + 27, + 0, + ): + dim_capacity, dim_extent = cls._dim_capacity_and_extent( + dim_name, + # The user specifies current domain -- this is the max domain + # which is taken from the max ranges for the dim datatype. + # We pass None here to detect those. + None, + TileDBCreateOptions.from_platform_config(platform_config), + ) + + if dim_shape == 0: + raise ValueError("DenseNDArray shape slots must be at least 1") + if dim_shape is None: + dim_shape = dim_capacity + + index_column_data[pa_field.name] = [ + 0, + dim_capacity - 1, + dim_extent, + 0, + dim_shape - 1, + ] + + else: + dim_capacity, dim_extent = cls._dim_capacity_and_extent( + dim_name, + dim_shape, + TileDBCreateOptions.from_platform_config(platform_config), + ) + index_column_data[pa_field.name] = [0, dim_capacity - 1, dim_extent] + index_column_schema.append(pa_field) index_column_info = pa.RecordBatch.from_pydict( index_column_data, schema=pa.schema(index_column_schema) @@ -309,9 +338,10 @@ def resize(self, newshape: Sequence[Union[int, None]]) -> None: """Supported for ``SparseNDArray``; scheduled for implementation for ``DenseNDArray`` in TileDB-SOMA 1.15 """ - # TODO: support current domain for dense arrays once we have core support. - # https://github.com/single-cell-data/TileDB-SOMA/issues/2955 - raise NotImplementedError() + if clib.embedded_version_triple() >= (2, 27, 0): + self._handle.resize(newshape) + else: + raise NotImplementedError() @classmethod def _dim_capacity_and_extent( diff --git a/apis/python/src/tiledbsoma/_tdb_handles.py b/apis/python/src/tiledbsoma/_tdb_handles.py index 0c43c67631..209406c0b1 100644 --- a/apis/python/src/tiledbsoma/_tdb_handles.py +++ b/apis/python/src/tiledbsoma/_tdb_handles.py @@ -619,9 +619,10 @@ def resize(self, newshape: Sequence[Union[int, None]]) -> None: """Supported for ``SparseNDArray``; scheduled for implementation for ``DenseNDArray`` in TileDB-SOMA 1.15 """ - # TODO: support current domain for dense arrays once we have core support. - # https://github.com/single-cell-data/TileDB-SOMA/issues/2955 - raise NotImplementedError() + if clib.embedded_version_triple() >= (2, 27, 0): + self._handle.resize(newshape) + else: + raise NotImplementedError() def tiledbsoma_can_resize( self, newshape: Sequence[Union[int, None]] @@ -629,9 +630,10 @@ def tiledbsoma_can_resize( """Supported for ``SparseNDArray``; scheduled for implementation for ``DenseNDArray`` in TileDB-SOMA 1.15. """ - # TODO: support current domain for dense arrays once we have core support. - # https://github.com/single-cell-data/TileDB-SOMA/issues/2955 - raise NotImplementedError() + if clib.embedded_version_triple() >= (2, 27, 0): + return cast(StatusAndReason, self._handle.tiledbsoma_can_resize(newshape)) + else: + raise NotImplementedError() class SparseNDArrayWrapper(SOMAArrayWrapper[clib.SOMASparseNDArray]): diff --git a/apis/python/tests/test_shape.py b/apis/python/tests/test_shape.py index fd3272a74a..136f4a6a73 100644 --- a/apis/python/tests/test_shape.py +++ b/apis/python/tests/test_shape.py @@ -198,8 +198,6 @@ def test_sparse_nd_array_basics( (ok, msg) = snda.resize(new_shape, check_only=True) -## Pending 2.27 timeframe for dense support for current domain, including resize -## https://github.com/single-cell-data/TileDB-SOMA/issues/2955 def test_dense_nd_array_basics(tmp_path): uri = tmp_path.as_posix() shape = (100, 200) @@ -212,12 +210,18 @@ def test_dense_nd_array_basics(tmp_path): assert dnda.non_empty_domain() == ((0, 0), (0, 0)) with tiledbsoma.DenseNDArray.open(uri, "w") as dnda: - with pytest.raises(NotImplementedError): + if tiledbsoma.pytiledbsoma.embedded_version_triple() >= (2, 27, 0): dnda.resize((300, 400)) + else: + with pytest.raises(NotImplementedError): + dnda.resize((300, 400)) with tiledbsoma.DenseNDArray.open(uri) as dnda: assert dnda.non_empty_domain() == ((0, 0), (0, 0)) - assert dnda.shape == (100, 200) + if tiledbsoma.pytiledbsoma.embedded_version_triple() >= (2, 27, 0): + assert dnda.shape == (300, 400) + else: + assert dnda.shape == (100, 200) @pytest.mark.parametrize( diff --git a/libtiledbsoma/test/unit_soma_dense_ndarray.cc b/libtiledbsoma/test/unit_soma_dense_ndarray.cc index 69b4747290..8f9ba01b78 100644 --- a/libtiledbsoma/test/unit_soma_dense_ndarray.cc +++ b/libtiledbsoma/test/unit_soma_dense_ndarray.cc @@ -185,9 +185,6 @@ TEST_CASE("SOMADenseNDArray: platform_config", "[SOMADenseNDArray]") { auto index_columns = helper::create_column_index_info(dim_infos); if (use_current_domain) { - // Setting a current domain on a TileDB dense array is not (yet) - // supported - // https://github.com/single-cell-data/TileDB-SOMA/issues/2955 if (helper::have_dense_current_domain_support()) { SOMADenseNDArray::create( uri,