Repository: single-cell-data/TileDB-SOMA (language: python)

Issue:
[r] Use `libtiledbsoma` handles for arrays
Already done for groups

#2406; [[sc-55685]](https://app.shortcut.com/tiledb-inc/story/55685/r-use-libtiledbsoma-for-array-handles).

Steps:

* Status quo is
  * There is a `private$.tiledb_array` with connection to `self$object`
    * This is set on construction/open, and closed on close
  * The `libtiledbsoma` handles are currently ephemeral
    * Every `read` / `write` / `get_metadata` etc which is `libtiledbsoma`-capable currently takes a `uri` and a `ctx` and does open/op/close
* Needing to be done:
  * Remove the last refrences to `private$.tiledb_array` with connection to `self$object`
    * #3129
  * Glitch: while with 3129 we are removing the last references to `self$object` within `R/*.R`, there are hundreds of lines of uses of `$object` within `tests/testthat` -- tracked on #3124
  * Then set a `libtiledbsoma` handle on construction/open, and close it on close
  * Modify all the methods to not take `uri`+`ctx` but rather the open handle

To check:

* Currently the array `set_metadata` does  not error out when the array is opened for read -- this is a bug.
  * This should be auto-fixed by this issue, but, it needs to be tested.


Discussion / hints:
Blocked by #3051 since here
https://github.com/single-cell-data/TileDB-SOMA/blob/1.15.0rc2/apis/r/R/SOMADataFrame.R#L182
the `self$object` is used. Removing that `private$.tiledb_array` / `self$object` from the base class `TileDBArray.R` causes this query-condition logic to return empty results, in a way that makes unit-test cases fail in non-obvious ways.

We need to move the query-condition logic over from TileDB-R before we can continue here.
This is a duplicate of #3061

Fix patch:
diff --git a/apis/r/DESCRIPTION b/apis/r/DESCRIPTION
index e9f63cce8c..ad06b7edd5 100644
--- a/apis/r/DESCRIPTION
+++ b/apis/r/DESCRIPTION
@@ -6,7 +6,7 @@ Description: Interface for working with 'TileDB'-based Stack of Matrices,
     like those commonly used for single cell data analysis. It is documented at
     <https://github.com/single-cell-data>; a formal specification available is at
     <https://github.com/single-cell-data/SOMA/blob/main/abstract_specification.md>.
-Version: 1.15.99.5
+Version: 1.15.99.6
 Authors@R: c(
     person(given = "Aaron", family = "Wolen",
            role = c("cre", "aut"), email = "aaron@tiledb.com",
diff --git a/apis/r/NEWS.md b/apis/r/NEWS.md
index 665e4fe24a..30f558be41 100644
--- a/apis/r/NEWS.md
+++ b/apis/r/NEWS.md
@@ -12,6 +12,7 @@
 * Add new Arrow-to-R type mapper
 * Add transitional/non-exported `parse_query_condition_new` [#3162](https://github.com/single-cell-data/TileDB-SOMA/pull/3162)
 * Apply new `parse_query_condition` [#3174](https://github.com/single-cell-data/TileDB-SOMA/pull/3174)
+* Apply new `non_empty_domain` [#3176](https://github.com/single-cell-data/TileDB-SOMA/pull/3176)
 
 # tiledbsoma 1.14.1
 
diff --git a/apis/r/R/QueryCondition.R b/apis/r/R/QueryCondition.R
index bbd006f4c1..982e090410 100644
--- a/apis/r/R/QueryCondition.R
+++ b/apis/r/R/QueryCondition.R
@@ -263,7 +263,6 @@ setClass(
 #' @param somactx (optional) A TileDB Ctx object; if not supplied the default
 #' context object is retrieved
 #' @return A 'tiledbsoma_query_condition' object
-#' @export
 tiledbsoma_empty_query_condition <- function(somactx) {
     stopifnot("The argument must be a somactx object" = is(somactx, "externalptr"))
     ptr <- libtiledbsoma_empty_query_condition(somactx)
diff --git a/apis/r/R/RcppExports.R b/apis/r/R/RcppExports.R
index e62722e056..7f73472cf0 100644
--- a/apis/r/R/RcppExports.R
+++ b/apis/r/R/RcppExports.R
@@ -198,8 +198,8 @@ maxshape <- function(uri, ctxxp) {
     .Call(`_tiledbsoma_maxshape`, uri, ctxxp)
 }
 
-non_empty_domain_new <- function(uri, ctxxp) {
-    .Call(`_tiledbsoma_non_empty_domain_new`, uri, ctxxp)
+non_empty_domain <- function(uri, ctxxp) {
+    .Call(`_tiledbsoma_non_empty_domain`, uri, ctxxp)
 }
 
 domain <- function(uri, ctxxp) {
diff --git a/apis/r/R/SOMADenseNDArray.R b/apis/r/R/SOMADenseNDArray.R
index 15bd47063e..faf0ef101d 100644
--- a/apis/r/R/SOMADenseNDArray.R
+++ b/apis/r/R/SOMADenseNDArray.R
@@ -46,7 +46,7 @@ SOMADenseNDArray <- R6::R6Class(
 
       if (is.null(coords)) {
         # These are 0-up: add 1 for R use
-        ned <- self$non_empty_domain()
+        ned <- self$non_empty_domain(max_only=TRUE)
         coords <- lapply(X=as.integer(ned), FUN=function(x){0:x})
       }
       coords <- private$.convert_coords(coords)
@@ -87,7 +87,7 @@ SOMADenseNDArray <- R6::R6Class(
                 "Array must contain column 'soma_data'" = all.equal("soma_data", attrnames))
 
       if (is.null(coords)) {
-        ned <- self$non_empty_domain()
+        ned <- self$non_empty_domain(max_only=TRUE)
         # These are 0-up: add 1 for R use
         nrow <- as.numeric(ned[[1]]) + 1
         ncol <- as.numeric(ned[[2]]) + 1
diff --git a/apis/r/R/SOMAExperimentAxisQuery.R b/apis/r/R/SOMAExperimentAxisQuery.R
index d97fa88c3e..2d0ae47586 100644
--- a/apis/r/R/SOMAExperimentAxisQuery.R
+++ b/apis/r/R/SOMAExperimentAxisQuery.R
@@ -420,7 +420,7 @@ SOMAExperimentAxisQuery <- R6::R6Class(
         for (i in seq_along(ldims)) {
           ldim <- ldims[i]
           if (is.null(coords[[ldim]])) {
-            coords[[ldim]] <- seq_len(as.numeric(layer$non_empty_domain()[i] + 1L))
+            coords[[ldim]] <- seq_len(as.numeric(layer$non_empty_domain(index1=TRUE, max_only=TRUE)[i]))
           }
         }
         mat <- matrix(
diff --git a/apis/r/R/TileDBArray.R b/apis/r/R/TileDBArray.R
index 54ece1450d..7235474d3b 100644
--- a/apis/r/R/TileDBArray.R
+++ b/apis/r/R/TileDBArray.R
@@ -217,48 +217,28 @@ TileDBArray <- R6::R6Class(
       return(utilized)
     },
 
-    #' @description Retrieve the non-empty domain for each dimension. This
-    #' method calls [`tiledb::tiledb_array_get_non_empty_domain_from_name`] for
-    #' each dimension in the array.
-    #' @param index1 Return the non-empty domain with 1-based indices.
-    #' @return A vector of [`bit64::integer64`]s with one entry for
-    #' each dimension.
-    non_empty_domain = function(index1 = FALSE) {
-      dims <- self$dimnames()
-      ned <- bit64::integer64(length = length(dims))
-      ## added during C++-ification as self$object could close
-      if (isFALSE(tiledb::tiledb_array_is_open(self$object))) {
-          arrhandle <- tiledb::tiledb_array_open(self$object, type = "READ")
-      } else {
-          arrhandle <- self$object
-      }
-      for (i in seq_along(along.with = ned)) {
-        dom <- max(tiledb::tiledb_array_get_non_empty_domain_from_name(
-          arrhandle, # instead of:  self$object,
-          name = dims[i]
-        ))
-        if (isTRUE(x = index1)) {
-          dom <- dom + 1L
-        }
-        ned[i] <- dom
-      }
-      return(ned)
-    },
-
     #' @description Returns a named list of minimum/maximum pairs, one per index
     #' column, which are the smallest and largest values written on that
     #' index column.
-    #'
-    #' As tracked on https://github.com/single-cell-data/TileDB-SOMA/issues/2407
-    #' this will replace the existing `non_empty_domain` method.
-    #'
+    #' @param index1 Return the non-empty domain with 1-based indices.
+    #' @param max_only Return only the max value per dimension, and return
+    #' this as a vector. Names are dropped.
     #' (lifecycle: maturing)
-    #' @return Named list of minimum/maximum values.
-    non_empty_domain_new = function() {
-      as.list(
+    #' @return Named list of minimum/maximum values, or integer vector
+    #' of maximum values.
+    non_empty_domain = function(index1 = FALSE, max_only = FALSE) {
+      retval <- as.list(
         arrow::as_record_batch(
           arrow::as_arrow_table(
-            non_empty_domain_new(self$uri, private$.soma_context))))
+            non_empty_domain(self$uri, private$.soma_context))))
+      if (index1) {
+        retval <- lapply(retval, function(c) {c+1})
+      }
+      if (max_only) {
+        # No vapply options since SOMADataFrame can have varying types.
+        retval <- unname(unlist(lapply(retval, function(e) {e[[2]]})))
+      }
+      return(retval)
     },
 
     #' @description Retrieve number of dimensions (lifecycle: maturing)
diff --git a/apis/r/R/utils.R b/apis/r/R/utils.R
index 61bfa2fca7..a43799ccdc 100644
--- a/apis/r/R/utils.R
+++ b/apis/r/R/utils.R
@@ -19,7 +19,6 @@ vapply_int <- function(X, FUN, ..., USE.NAMES = TRUE) {
   vapply(X, FUN, FUN.VALUE = integer(1L), ..., USE.NAMES = USE.NAMES)
 }
 
-# rename(iris, c(petal_length = "Petal.Length", species = "Species", hi = "YO"))
 rename <- function(x, names) {
   stopifnot(
     "'x' must be named" = is_named(x),
diff --git a/apis/r/man/SOMAArrayBase.Rd b/apis/r/man/SOMAArrayBase.Rd
index 61885f1c9d..246111ddac 100644
--- a/apis/r/man/SOMAArrayBase.Rd
+++ b/apis/r/man/SOMAArrayBase.Rd
@@ -44,7 +44,6 @@ experimental)
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="maxshape"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-maxshape'><code>tiledbsoma::TileDBArray$maxshape()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="ndim"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-ndim'><code>tiledbsoma::TileDBArray$ndim()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain'><code>tiledbsoma::TileDBArray$non_empty_domain()</code></a></span></li>
-<li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain_new"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain_new'><code>tiledbsoma::TileDBArray$non_empty_domain_new()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="open"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-open'><code>tiledbsoma::TileDBArray$open()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="print"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-print'><code>tiledbsoma::TileDBArray$print()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="schema"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-schema'><code>tiledbsoma::TileDBArray$schema()</code></a></span></li>
diff --git a/apis/r/man/SOMADataFrame.Rd b/apis/r/man/SOMADataFrame.Rd
index 13cfb96d6b..a4ffade826 100644
--- a/apis/r/man/SOMADataFrame.Rd
+++ b/apis/r/man/SOMADataFrame.Rd
@@ -47,7 +47,6 @@ row and is intended to act as a join key for other objects, such as
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="index_column_names"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-index_column_names'><code>tiledbsoma::TileDBArray$index_column_names()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="ndim"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-ndim'><code>tiledbsoma::TileDBArray$ndim()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain'><code>tiledbsoma::TileDBArray$non_empty_domain()</code></a></span></li>
-<li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain_new"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain_new'><code>tiledbsoma::TileDBArray$non_empty_domain_new()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="open"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-open'><code>tiledbsoma::TileDBArray$open()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="print"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-print'><code>tiledbsoma::TileDBArray$print()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="schema"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-schema'><code>tiledbsoma::TileDBArray$schema()</code></a></span></li>
diff --git a/apis/r/man/SOMADenseNDArray.Rd b/apis/r/man/SOMADenseNDArray.Rd
index b57740ed72..f508dffafd 100644
--- a/apis/r/man/SOMADenseNDArray.Rd
+++ b/apis/r/man/SOMADenseNDArray.Rd
@@ -56,7 +56,6 @@ The \code{write} method is currently limited to writing from 2-d matrices.
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="maxshape"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-maxshape'><code>tiledbsoma::TileDBArray$maxshape()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="ndim"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-ndim'><code>tiledbsoma::TileDBArray$ndim()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain'><code>tiledbsoma::TileDBArray$non_empty_domain()</code></a></span></li>
-<li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain_new"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain_new'><code>tiledbsoma::TileDBArray$non_empty_domain_new()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="open"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-open'><code>tiledbsoma::TileDBArray$open()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="print"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-print'><code>tiledbsoma::TileDBArray$print()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="schema"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-schema'><code>tiledbsoma::TileDBArray$schema()</code></a></span></li>
diff --git a/apis/r/man/SOMANDArrayBase.Rd b/apis/r/man/SOMANDArrayBase.Rd
index 31e85127c2..514cd0e48d 100644
--- a/apis/r/man/SOMANDArrayBase.Rd
+++ b/apis/r/man/SOMANDArrayBase.Rd
@@ -40,7 +40,6 @@ Adds NDArray-specific functionality to the \code{\link{SOMAArrayBase}} class.
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="maxshape"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-maxshape'><code>tiledbsoma::TileDBArray$maxshape()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="ndim"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-ndim'><code>tiledbsoma::TileDBArray$ndim()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain'><code>tiledbsoma::TileDBArray$non_empty_domain()</code></a></span></li>
-<li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain_new"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain_new'><code>tiledbsoma::TileDBArray$non_empty_domain_new()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="open"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-open'><code>tiledbsoma::TileDBArray$open()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="print"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-print'><code>tiledbsoma::TileDBArray$print()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="schema"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-schema'><code>tiledbsoma::TileDBArray$schema()</code></a></span></li>
diff --git a/apis/r/man/SOMASparseNDArray.Rd b/apis/r/man/SOMASparseNDArray.Rd
index bd9a0f810b..b69003a99c 100644
--- a/apis/r/man/SOMASparseNDArray.Rd
+++ b/apis/r/man/SOMASparseNDArray.Rd
@@ -56,7 +56,6 @@ the object are overwritten and new index values are added. (lifecycle: maturing)
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="maxshape"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-maxshape'><code>tiledbsoma::TileDBArray$maxshape()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="ndim"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-ndim'><code>tiledbsoma::TileDBArray$ndim()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain'><code>tiledbsoma::TileDBArray$non_empty_domain()</code></a></span></li>
-<li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="non_empty_domain_new"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-non_empty_domain_new'><code>tiledbsoma::TileDBArray$non_empty_domain_new()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="open"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-open'><code>tiledbsoma::TileDBArray$open()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="print"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-print'><code>tiledbsoma::TileDBArray$print()</code></a></span></li>
 <li><span class="pkg-link" data-pkg="tiledbsoma" data-topic="TileDBArray" data-id="schema"><a href='../../tiledbsoma/html/TileDBArray.html#method-TileDBArray-schema'><code>tiledbsoma::TileDBArray$schema()</code></a></span></li>
diff --git a/apis/r/man/TileDBArray.Rd b/apis/r/man/TileDBArray.Rd
index 9ef26bdcc7..c15ca72c53 100644
--- a/apis/r/man/TileDBArray.Rd
+++ b/apis/r/man/TileDBArray.Rd
@@ -35,7 +35,6 @@ Base class for representing an individual TileDB array.
 \item \href{#method-TileDBArray-maxshape}{\code{TileDBArray$maxshape()}}
 \item \href{#method-TileDBArray-used_shape}{\code{TileDBArray$used_shape()}}
 \item \href{#method-TileDBArray-non_empty_domain}{\code{TileDBArray$non_empty_domain()}}
-\item \href{#method-TileDBArray-non_empty_domain_new}{\code{TileDBArray$non_empty_domain_new()}}
 \item \href{#method-TileDBArray-ndim}{\code{TileDBArray$ndim()}}
 \item \href{#method-TileDBArray-attributes}{\code{TileDBArray$attributes()}}
 \item \href{#method-TileDBArray-dimnames}{\code{TileDBArray$dimnames()}}
@@ -262,43 +261,27 @@ If \code{simplify = TRUE}, returns a vector of only the upper bounds.
 \if{html}{\out{<a id="method-TileDBArray-non_empty_domain"></a>}}
 \if{latex}{\out{\hypertarget{method-TileDBArray-non_empty_domain}{}}}
 \subsection{Method \code{non_empty_domain()}}{
-Retrieve the non-empty domain for each dimension. This
-method calls \code{\link[tiledb:tiledb_array_get_non_empty_domain_from_name]{tiledb::tiledb_array_get_non_empty_domain_from_name}} for
-each dimension in the array.
+Returns a named list of minimum/maximum pairs, one per index
+column, which are the smallest and largest values written on that
+index column.
 \subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{TileDBArray$non_empty_domain(index1 = FALSE)}\if{html}{\out{</div>}}
+\if{html}{\out{<div class="r">}}\preformatted{TileDBArray$non_empty_domain(index1 = FALSE, max_only = FALSE)}\if{html}{\out{</div>}}
 }
 
 \subsection{Arguments}{
 \if{html}{\out{<div class="arguments">}}
 \describe{
 \item{\code{index1}}{Return the non-empty domain with 1-based indices.}
+
+\item{\code{max_only}}{Return only the max value per dimension, and return
+this as a vector. Names are dropped.
+(lifecycle: maturing)}
 }
 \if{html}{\out{</div>}}
 }
 \subsection{Returns}{
-A vector of \code{\link[bit64:bit64-package]{bit64::integer64}}s with one entry for
-each dimension.
-}
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-TileDBArray-non_empty_domain_new"></a>}}
-\if{latex}{\out{\hypertarget{method-TileDBArray-non_empty_domain_new}{}}}
-\subsection{Method \code{non_empty_domain_new()}}{
-Returns a named list of minimum/maximum pairs, one per index
-column, which are the smallest and largest values written on that
-index column.
-
-As tracked on https://github.com/single-cell-data/TileDB-SOMA/issues/2407
-this will replace the existing \code{non_empty_domain} method.
-
-(lifecycle: maturing)
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{TileDBArray$non_empty_domain_new()}\if{html}{\out{</div>}}
-}
-
-\subsection{Returns}{
-Named list of minimum/maximum values.
+Named list of minimum/maximum values, or integer vector
+of maximum values.
 }
 }
 \if{html}{\out{<hr>}}
diff --git a/apis/r/src/RcppExports.cpp b/apis/r/src/RcppExports.cpp
index 0b68b3942e..772071e714 100644
--- a/apis/r/src/RcppExports.cpp
+++ b/apis/r/src/RcppExports.cpp
@@ -432,15 +432,15 @@ BEGIN_RCPP
     return rcpp_result_gen;
 END_RCPP
 }
-// non_empty_domain_new
-SEXP non_empty_domain_new(const std::string& uri, Rcpp::XPtr<somactx_wrap_t> ctxxp);
-RcppExport SEXP _tiledbsoma_non_empty_domain_new(SEXP uriSEXP, SEXP ctxxpSEXP) {
+// non_empty_domain
+SEXP non_empty_domain(const std::string& uri, Rcpp::XPtr<somactx_wrap_t> ctxxp);
+RcppExport SEXP _tiledbsoma_non_empty_domain(SEXP uriSEXP, SEXP ctxxpSEXP) {
 BEGIN_RCPP
     Rcpp::RObject rcpp_result_gen;
     Rcpp::RNGScope rcpp_rngScope_gen;
     Rcpp::traits::input_parameter< const std::string& >::type uri(uriSEXP);
     Rcpp::traits::input_parameter< Rcpp::XPtr<somactx_wrap_t> >::type ctxxp(ctxxpSEXP);
-    rcpp_result_gen = Rcpp::wrap(non_empty_domain_new(uri, ctxxp));
+    rcpp_result_gen = Rcpp::wrap(non_empty_domain(uri, ctxxp));
     return rcpp_result_gen;
 END_RCPP
 }
@@ -806,7 +806,7 @@ static const R_CallMethodDef CallEntries[] = {
     {"_tiledbsoma_check_arrow_array_tag", (DL_FUNC) &_tiledbsoma_check_arrow_array_tag, 1},
     {"_tiledbsoma_shape", (DL_FUNC) &_tiledbsoma_shape, 2},
     {"_tiledbsoma_maxshape", (DL_FUNC) &_tiledbsoma_maxshape, 2},
-    {"_tiledbsoma_non_empty_domain_new", (DL_FUNC) &_tiledbsoma_non_empty_domain_new, 2},
+    {"_tiledbsoma_non_empty_domain", (DL_FUNC) &_tiledbsoma_non_empty_domain, 2},
     {"_tiledbsoma_domain", (DL_FUNC) &_tiledbsoma_domain, 2},
     {"_tiledbsoma_maxdomain", (DL_FUNC) &_tiledbsoma_maxdomain, 2},
     {"_tiledbsoma_maybe_soma_joinid_shape", (DL_FUNC) &_tiledbsoma_maybe_soma_joinid_shape, 2},
diff --git a/apis/r/src/rinterface.cpp b/apis/r/src/rinterface.cpp
index a6a3c02b0d..0d4f3271d2 100644
--- a/apis/r/src/rinterface.cpp
+++ b/apis/r/src/rinterface.cpp
@@ -279,7 +279,7 @@ Rcpp::NumericVector maxshape(
 }
 
 // [[Rcpp::export]]
-SEXP non_empty_domain_new(
+SEXP non_empty_domain(
     const std::string& uri, Rcpp::XPtr<somactx_wrap_t> ctxxp) {
     auto sdf = tdbs::SOMADataFrame::open(uri, OpenMode::read, ctxxp->ctxptr);
     tdbs::ArrowTable arrow_table = sdf->get_non_empty_domain();


Test patch:
diff --git a/apis/r/tests/testthat/test-SOMASparseNDArray.R b/apis/r/tests/testthat/test-SOMASparseNDArray.R
index 9777bcaefd..b6c5d7b896 100644
--- a/apis/r/tests/testthat/test-SOMASparseNDArray.R
+++ b/apis/r/tests/testthat/test-SOMASparseNDArray.R
@@ -696,11 +696,11 @@ test_that("SOMASparseNDArray bounding box implicitly-stored values", {
   ranges <- bit64::integer64(2L)
   for (i in seq_along(ranges)) {
     s <- c('i', 'j')[i]
-    ranges[i] <- bit64::as.integer64(max(range(slot(mat, s))))
+    ranges[i] <- max(range(slot(mat, s)))
   }
-  expect_equal(ndarray$non_empty_domain(), ranges)
+  expect_equal(bit64::as.integer64(ndarray$non_empty_domain(max_only=TRUE)), ranges)
   expect_true(all(
-    ndarray$non_empty_domain() < suppressWarnings(
+    ndarray$non_empty_domain(max_only=TRUE) < suppressWarnings(
       ndarray$used_shape(simplify = TRUE),
       classes = "deprecatedWarning"
     )
diff --git a/apis/r/tests/testthat/test-shape.R b/apis/r/tests/testthat/test-shape.R
index 21be77e62c..ae627532cc 100644
--- a/apis/r/tests/testthat/test-shape.R
+++ b/apis/r/tests/testthat/test-shape.R
@@ -406,8 +406,9 @@ test_that("SOMASparseNDArray shape", {
     ndarray$close()
 
     ndarray <- SOMASparseNDArrayOpen(uri)
-    ned <- ndarray$non_empty_domain()
-    expect_equal(ned, c(2,4))
+    ned <- ndarray$non_empty_domain(max_only=TRUE)
+    #expect_equal(ned, c(2,4))
+    expect_equal(as.integer(ned), as.integer(c(2,4)))
 
     # Test reads out of bounds
     coords <- list(bit64::as.integer64(c(1,2)), bit64::as.integer64(c(3,4)))
@@ -495,7 +496,7 @@ test_that("SOMADenseNDArray shape", {
     ndarray$close()
 
     ndarray <- SOMADenseNDArrayOpen(uri)
-    ned <- ndarray$non_empty_domain()
+    ned <- ndarray$non_empty_domain(max_only=TRUE)
     expect_equal(ned, c(99, 199))
 
     # Test reads out of bounds