diff --git a/apis/python/examples/soco-batch-query.py b/apis/python/examples/soco-batch-query.py index 41cd1da926..bb11387641 100755 --- a/apis/python/examples/soco-batch-query.py +++ b/apis/python/examples/soco-batch-query.py @@ -33,7 +33,7 @@ for i, ctot_id in enumerate(ctot_ids): soma_slices = soco.query( obs_attrs=["cell_type_ontology_term_id"], - obs_query_string=f'cell_type_ontology_term_id == "{ctot_id}"', + obs_query_string=f"cell_type_ontology_term_id == {ctot_id!r}", ) if soma_slices == []: continue diff --git a/apis/python/examples/uniformizer.py b/apis/python/examples/uniformizer.py index 666d12362f..a173a8f948 100755 --- a/apis/python/examples/uniformizer.py +++ b/apis/python/examples/uniformizer.py @@ -67,7 +67,7 @@ def main() -> int: return uniformizer.add_soma(args.dataset_id, args.soma) else: raise Exception( - f'Internal coding error: handler for "{args.func_name}" not found.' + f"Internal coding error: handler for {args.func_name!r} not found." ) diff --git a/apis/python/src/tiledbsoma/annotation_dataframe.py b/apis/python/src/tiledbsoma/annotation_dataframe.py index b528dc5a1c..c16d5a3388 100644 --- a/apis/python/src/tiledbsoma/annotation_dataframe.py +++ b/apis/python/src/tiledbsoma/annotation_dataframe.py @@ -94,7 +94,7 @@ def __repr__(self) -> str: """ Default display of soma.obs and soma.var. """ - return ", ".join(f"'{key}'" for key in self.keys()) + return ", ".join(f"{key!r}" for key in self.keys()) # ---------------------------------------------------------------- def __len__(self) -> int: diff --git a/apis/python/src/tiledbsoma/annotation_matrix_group.py b/apis/python/src/tiledbsoma/annotation_matrix_group.py index 4256f59caa..8df3455aad 100644 --- a/apis/python/src/tiledbsoma/annotation_matrix_group.py +++ b/apis/python/src/tiledbsoma/annotation_matrix_group.py @@ -47,7 +47,7 @@ def __repr__(self) -> str: """ Default display of soma.obsm and soma.varm. """ - return ", ".join(f"'{key}'" for key in self.keys()) + return ", ".join(f"{key!r}" for key in self.keys()) # ---------------------------------------------------------------- def __iter__(self) -> Iterator[AnnotationMatrix]: @@ -68,7 +68,7 @@ def __getattr__(self, name: str) -> Optional[AnnotationMatrix]: with self._open() as G: if name not in G: raise AttributeError( - f"'{self.__class__.__name__}' object has no attribute '{name}'" + f"{self.__class__.__name__!r} object has no attribute {name!r}" ) return self[name] diff --git a/apis/python/src/tiledbsoma/annotation_pairwise_matrix_group.py b/apis/python/src/tiledbsoma/annotation_pairwise_matrix_group.py index 9910fd9922..f7326d014d 100644 --- a/apis/python/src/tiledbsoma/annotation_pairwise_matrix_group.py +++ b/apis/python/src/tiledbsoma/annotation_pairwise_matrix_group.py @@ -57,7 +57,7 @@ def __repr__(self) -> str: """ Default display of soma.obsp and soma.varp. """ - return ", ".join(f"'{key}'" for key in self.keys()) + return ", ".join(f"{key!r}" for key in self.keys()) # ---------------------------------------------------------------- def __getattr__(self, name: str) -> Optional[AssayMatrix]: @@ -68,7 +68,7 @@ def __getattr__(self, name: str) -> Optional[AssayMatrix]: with self._open() as G: if name not in G: raise AttributeError( - f"'{self.__class__.__name__}' object has no attribute '{name}'" + f"{self.__class__.__name__!r} object has no attribute {name!r}" ) return self[name] diff --git a/apis/python/src/tiledbsoma/assay_matrix_group.py b/apis/python/src/tiledbsoma/assay_matrix_group.py index 72127fb489..ab9302a077 100644 --- a/apis/python/src/tiledbsoma/assay_matrix_group.py +++ b/apis/python/src/tiledbsoma/assay_matrix_group.py @@ -54,7 +54,7 @@ def __repr__(self) -> str: """ Default display of soma.X. """ - return ", ".join(f"'{key}'" for key in self.keys()) + return ", ".join(f"{key!r}" for key in self.keys()) # ---------------------------------------------------------------- def __getattr__(self, name: str) -> Optional[AssayMatrix]: @@ -65,7 +65,7 @@ def __getattr__(self, name: str) -> Optional[AssayMatrix]: with self._open() as G: if name not in G: raise AttributeError( - f"'{self.__class__.__name__}' object has no attribute '{name}'" + f"{self.__class__.__name__!r} object has no attribute {name!r}" ) return self[name] diff --git a/apis/python/src/tiledbsoma/util_tiledb.py b/apis/python/src/tiledbsoma/util_tiledb.py index 4d4fd8d453..e07829ee7d 100644 --- a/apis/python/src/tiledbsoma/util_tiledb.py +++ b/apis/python/src/tiledbsoma/util_tiledb.py @@ -89,7 +89,7 @@ def show_tiledb_group_array_schemas(uri: str, ctx: Optional[tiledb.Ctx] = None) # ---------------------------------------------------------------- def list_fragments(array_uri: str) -> None: - print(f"Listing fragments for array: '{array_uri}'") + print(f"Listing fragments for array: {array_uri!r}") vfs = tiledb.VFS() fragments = [] diff --git a/apis/r/DESCRIPTION b/apis/r/DESCRIPTION index ed4e801718..eb9895ed25 100644 --- a/apis/r/DESCRIPTION +++ b/apis/r/DESCRIPTION @@ -7,7 +7,7 @@ Description: Interface for working with 'TileDB'-based Stack of Matrices, from and export to in-memory formats used by popular toolchains like 'Seurat', 'Bioconductor', and even 'AnnData' using the companion Python package. -Version: 0.1.22.9000 +Version: 0.1.22.9001 Authors@R: c( person(given = "Aaron", family = "Wolen", diff --git a/apis/r/NEWS.md b/apis/r/NEWS.md index 97402a706f..90eb1073d1 100644 --- a/apis/r/NEWS.md +++ b/apis/r/NEWS.md @@ -2,7 +2,8 @@ ## Features -* New function `dataset_seurat_pbmc3k()` to download the pbmc3k dataset from 10X and import as a `Seurat` object without requiring any extra dependencies. +- The `SOMACollection`'s `to_seurat()` method gains a `somas` argument that makes it possible to select a subset of `SOMA`s and `X` layers to be retrieved (#571). +- New function `dataset_seurat_pbmc3k()` to download the pbmc3k dataset from 10X and import as a `Seurat` object without requiring any extra dependencies. # tiledbsoma 0.1.19 @@ -14,7 +15,7 @@ ## Features -- The `AnnotationMatrix`'s `to_matrix()` method now supports batched reads via the `batch_mode` argument. This functionality can also be leveraged from `SOMA`'s `get_seurat_dimreductions_list()` and `get_seurat_dimreduction()` methods. +- The `AnnotationMatrix`'s `to_matrix()` method now supports batched reads via the `batch_mode` argument. This functionality can also be leveraged from `SOMA`'s `get_seurat_dimreductions_list()` and `get_seurat_dimreduction()` methods (#548). ## Changes @@ -22,7 +23,7 @@ ## Fixes -- Don't use default assay name when recreating a `Seurat` object (thanks @dan11mcguire) +- Don't use default assay name when recreating a `Seurat` object (thanks @dan11mcguire). # tiledbsoma 0.1.12 diff --git a/apis/r/R/SOMACollection.R b/apis/r/R/SOMACollection.R index 021e3ad57d..c6ba54d8b0 100644 --- a/apis/r/R/SOMACollection.R +++ b/apis/r/R/SOMACollection.R @@ -199,14 +199,48 @@ SOMACollection <- R6::R6Class( #' @description Convert to a [SeuratObject::Seurat] object. #' @param project [`SeuratObject::Project`] name for the `Seurat` object #' @param batch_mode logical, if `TRUE`, batch query mode is enabled for - #' retrieving `X`, `obsm`/`varm`, and `obsp`/`varp` layers. See + #' retrieving `X` layers. See #' [`AssayMatrix$to_dataframe()`][`AssayMatrix`] for more information. - to_seurat = function(project = "SeuratProject", batch_mode = FALSE) { - stopifnot(is_scalar_character(project)) + #' @param somas character vector, names of `SOMA`s to include as + #' [`SeuratObject::Assay`]s in the `Seurat` object. If `NULL`, all `SOMA`s + #' are included. Can also be a named list of character vectors, where each + #' element corresponds to a `SOMA` name and the value is a character vector + #' of `X` layers from that `SOMA` to include as assays (e.g., `list("RNA" = + #' c("counts", "logcounts"))`). + to_seurat = function( + project = "SeuratProject", + somas = NULL, + batch_mode = FALSE + ) { + stopifnot( + is_scalar_character(project), + "'somas' must be a character vector or named list" + = is.null(somas) || is.character(somas) || is.list(somas) + ) + + # default list containing all somas and all layers + soma_list <- sapply( + names(self$somas), + FUN = function(x) c("counts", "data", "scale.data"), + simplify = FALSE + ) + + if (is.character(somas)) { + stopifnot(assert_subset(somas, names(soma_list))) + soma_list <- soma_list[somas] + } else if (is.list(somas)) { + stopifnot(assert_subset(names(somas), names(soma_list))) + soma_list <- somas + } - assays <- lapply( - X = self$somas, - FUN = function(x) x$to_seurat_assay(batch_mode = batch_mode) + assays <- mapply( + FUN = function(soma, layers, batch_mode) { + soma$to_seurat_assay(layers = layers, batch_mode = batch_mode) + }, + soma = self$somas[names(soma_list)], + layers = soma_list, + MoreArgs = list(batch_mode = batch_mode), + SIMPLIFY = FALSE ) nassays <- length(assays) @@ -243,8 +277,9 @@ SOMACollection <- R6::R6Class( # Retrieve list of all techniques used in any soma's obsm/varm # dimensionality reduction arrays. The association between assay and # dimreduction is maintained by the DimReduc's `assay.used` slot. - dimreductions <- lapply(self$somas, - function(x) x$get_seurat_dimreductions_list(batch_mode) + dimreductions <- lapply( + self$somas, + function(x) x$get_seurat_dimreductions_list() ) object@reductions <- Reduce(base::c, dimreductions) diff --git a/apis/r/R/utils.R b/apis/r/R/utils.R index 982442ba4a..5cc9ae60d0 100644 --- a/apis/r/R/utils.R +++ b/apis/r/R/utils.R @@ -105,7 +105,8 @@ file_path <- function(..., fsep = .Platform$file.sep) { file.path(..., fsep = fsep) } -#' Assert all values of `x` are a subset of `y`. @param x,y vectors of values +#' Assert all values of `x` are a subset of `y`. +#' @param x,y vectors of values #' @param type A character vector of length 1 used in the error message #' @return `TRUE` if all values of `x` are present in `y`, otherwise an #' informative error is thrown with the missing values. diff --git a/apis/r/man/SOMACollection.Rd b/apis/r/man/SOMACollection.Rd index 68472c0db8..f7aeeaa8e9 100644 --- a/apis/r/man/SOMACollection.Rd +++ b/apis/r/man/SOMACollection.Rd @@ -175,7 +175,11 @@ dimensionality reduction method (e.g., \code{"pca"}). \subsection{Method \code{to_seurat()}}{ Convert to a \link[SeuratObject:Seurat-class]{SeuratObject::Seurat} object. \subsection{Usage}{ -\if{html}{\out{