From 5162b216e65fb5d9db4bccb2711b07eb21a9187a Mon Sep 17 00:00:00 2001 From: mkeller <7525285+keller-mark@users.noreply.github.com> Date: Thu, 27 Jan 2022 12:24:08 -0500 Subject: [PATCH 1/5] Giotto object from nanostring website --- R/data_to_zarr.R | 22 ++++-- R/wrappers_giotto.R | 18 +++-- vignettes/giotto.Rmd | 1 + vignettes/giotto_nanostring.Rmd | 116 ++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 vignettes/giotto_nanostring.Rmd diff --git a/R/data_to_zarr.R b/R/data_to_zarr.R index ba90988..99f8878 100644 --- a/R/data_to_zarr.R +++ b/R/data_to_zarr.R @@ -220,7 +220,7 @@ spe_to_ome_zarr <- function(spe_obj, sample_id, image_id, out_path) { #' obj <- get_giotto_obj() #' giotto_to_anndata_zarr(obj, "data/giotto.zarr") #' @importFrom methods slot -giotto_to_anndata_zarr <- function(giotto_obj, out_path, X_slot = "raw_exprs") { +giotto_to_anndata_zarr <- function(giotto_obj, out_path, X_slot) { # Use basilisk proc <- basilisk::basiliskStart(py_env) @@ -229,6 +229,7 @@ giotto_to_anndata_zarr <- function(giotto_obj, out_path, X_slot = "raw_exprs") { success <- basilisk::basiliskRun(proc, function(giotto_obj, out_path, X_slot) { anndata <- reticulate::import("anndata") zarr <- reticulate::import("zarr") + np <- reticulate::import("numpy", convert=FALSE) # Reference: https://github.com/theislab/zellkonverter/blob/master/R/SCE2AnnData.R#L237 make_numpy_friendly <- function(x, transpose = TRUE) { @@ -236,15 +237,25 @@ giotto_to_anndata_zarr <- function(giotto_obj, out_path, X_slot = "raw_exprs") { x <- Matrix::t(x) } if (DelayedArray::is_sparse(x)) { - methods::as(x, "dgCMatrix") + x <- methods::as(x, "dgCMatrix") } else { - as.matrix(x) + x <- as.matrix(x) } + + y <- np$array(x) + y <- y$astype(" 0) { - # TODO make_numpy_friendly is outside scope obsm <- lapply(obsm, make_numpy_friendly) adata$obsm <- obsm } diff --git a/R/wrappers_giotto.R b/R/wrappers_giotto.R index 09b6344..ed01a8e 100644 --- a/R/wrappers_giotto.R +++ b/R/wrappers_giotto.R @@ -19,6 +19,9 @@ GiottoWrapper <- R6::R6Class("GiottoWrapper", #' @field obj The object to wrap. #' @keywords internal obj = NULL, + #' @field expr_matrix The key for the expression matrix. + #' @keywords internal + expr_matrix = NULL, #' @field cell_embeddings The keys in the Seurat object's reductions/cell.embeddings #' to use for creating dimensionality reduction mappings. #' @keywords internal @@ -64,9 +67,10 @@ GiottoWrapper <- R6::R6Class("GiottoWrapper", #' and keys for annotation scores. #' @param ... Parameters inherited from `AbstractWrapper`. #' @return A new `GiottoWrapper` object. - initialize = function(obj, cell_embeddings = NA, cell_embedding_names = NA, cell_embedding_dims = NA, cell_set_metas = NA, cell_set_meta_names = NA, cell_set_meta_scores = NA, ...) { + initialize = function(obj, expr_matrix = NA, cell_embeddings = NA, cell_embedding_names = NA, cell_embedding_dims = NA, cell_set_metas = NA, cell_set_meta_names = NA, cell_set_meta_scores = NA, ...) { super$initialize(...) self$obj <- obj + self$expr_matrix <- expr_matrix self$cell_embeddings <- cell_embeddings self$cell_embedding_names <- cell_embedding_names self$cell_embedding_dims <- cell_embedding_dims @@ -88,8 +92,12 @@ GiottoWrapper <- R6::R6Class("GiottoWrapper", warning("Object is not of type giotto.") success <- FALSE } + if(!is_na(self$expr_matrix) && self$expr_matrix %in% slotNames(self$obj)) { + warning("Specified expr_matrix not present in Giotto object slot names.") + success <- FALSE + } if(!is_na(self$cell_embeddings) && !all(self$cell_embeddings %in% names(self$obj@dimension_reduction$cells))) { - warning("Specified cell_embeddings not all present in Giotto object dimension_reduction") + warning("Specified cell_embeddings not all present in Giotto object dimension_reduction.") success <- FALSE } if(!is_na(self$cell_set_metas) && !all(self$cell_set_metas %in% colnames(self$obj@cell_metadata))) { @@ -128,7 +136,7 @@ GiottoWrapper <- R6::R6Class("GiottoWrapper", zarr_filepath <- self$get_zarr_path(dataset_uid, obj_i) if(!file.exists(zarr_filepath) || !self$use_cache) { - giotto_to_anndata_zarr(self$obj, out_path = zarr_filepath) + giotto_to_anndata_zarr(self$obj, out_path = zarr_filepath, X_slot = self$expr_matrix) } # Get the file definition creator functions. @@ -139,7 +147,9 @@ GiottoWrapper <- R6::R6Class("GiottoWrapper", # Append the new file definition creators functions to the main list. self$file_def_creators <- append(self$file_def_creators, cells_file_creator) self$file_def_creators <- append(self$file_def_creators, cell_sets_file_creator) - self$file_def_creators <- append(self$file_def_creators, expression_matrix_file_creator) + if(!is_na(self$expr_matrix)) { + self$file_def_creators <- append(self$file_def_creators, expression_matrix_file_creator) + } # Create a web server route object for the directory of JSON files. self$routes <- append(self$routes, self$get_out_dir_route(dataset_uid, obj_i)) diff --git a/vignettes/giotto.Rmd b/vignettes/giotto.Rmd index be60e8b..3113b8f 100644 --- a/vignettes/giotto.Rmd +++ b/vignettes/giotto.Rmd @@ -125,6 +125,7 @@ library(vitessceR) w <- GiottoWrapper$new( SS_seqfish, + expr_matrix = "raw_exprs", cell_set_metas = c("cell_types"), cell_set_meta_names = c("Cell Types"), cell_embeddings = c("pca", "tsne"), diff --git a/vignettes/giotto_nanostring.Rmd b/vignettes/giotto_nanostring.Rmd new file mode 100644 index 0000000..1d86468 --- /dev/null +++ b/vignettes/giotto_nanostring.Rmd @@ -0,0 +1,116 @@ +--- +title: "Usage with Giotto" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Usage with Giotto} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +The following is a full example of usage of the widget with a [Giotto](https://github.com/RubD/Giotto) object. + +First, install the R dependencies: + +```r +install.packages("devtools") +devtools::install_github("RubD/Giotto") +``` + +Download and un-tar the giotto object: https://nanostring-public-share.s3.us-west-2.amazonaws.com/SMI-Compressed/All+SMI+Giotto+object.tar.gz + + +Load the giotto object: + +```r +rdata_path <- file.path("data", "giotto", "SMI_Giotto_Object.RData") +load(rdata_path) + +gem@cell_metadata <- gem@cell_metadata$rna +gem@spatial_locs <- gem@spatial_locs$raw +gem@raw_exprs <- NULL +gem@norm_expr <- NULL +gem@norm_scaled_expr <- NULL +gem@custom_expr <- NULL +gem@gene_metadata <- NULL +gem@gene_ID <- NULL +``` + +Filter to select only the data from the "Lung13" tissue sample: + +```r +cell_metadata <- gem@cell_metadata +cell_ids <- cell_metadata[cell_metadata$tissue %in% c("Lung13")]$cell_ID +gem <- Giotto::subsetGiotto(gem, cell_ids = cell_ids) + +for(dr in names(gem@dimension_reduction$cells)) { + old_coord <- gem@dimension_reduction$cells[[dr]][[dr]]$coordinates + new_coord <- old_coord[rownames(old_coord) %in% cell_ids,] + gem@dimension_reduction$cells[[dr]][[dr]]$coordinates <- new_coord +} +``` + +Rescale the coordinates to help with saving as a NumPy array: + +```r +# Rescale spatial coordinates +spatial_locs <- gem@spatial_locs +spatial_locs$sdimx <- spatial_locs$sdimx*10000 +spatial_locs$sdimy <- spatial_locs$sdimy*10000 +gem@spatial_locs <- spatial_locs + +# Rescale dimensionality reduction coordinates +for(dr in names(gem@dimension_reduction$cells)) { + old_coord_2d <- gem@dimension_reduction$cells[[dr]][[dr]]$coordinates[, c(1, 2)] + old_coord_2d[, 1] <- old_coord_2d[, 1] - min(old_coord_2d[, 1]) + old_coord_2d[, 1] <- (old_coord_2d[, 1] / max(old_coord_2d[, 1])) * 10000 + old_coord_2d[, 2] <- old_coord_2d[, 2] - min(old_coord_2d[, 2]) + old_coord_2d[, 2] <- (old_coord_2d[, 2] / max(old_coord_2d[, 2])) * 10000 + + new_coord_2d <- old_coord_2d + gem@dimension_reduction$cells[[dr]][[dr]]$coordinates[, c(1, 2)] <- new_coord_2d +} +``` + +Set up the Vitessce widget: + +```r +library(vitessceR) + +w <- GiottoWrapper$new( + gem, + cell_set_metas = c("patient", "tissue", "cell_type", "niche"), + cell_set_meta_names = c("Patient", "Tissue", "Cell Type", "Niche"), + cell_embeddings = c("pca", "umapnew", "um.n200"), + cell_embedding_names = c("PCA", "Expression profile UMAP", "Neighborhood UMAP"), + out_dir = file.path("data", "giotto_nanostring") +) + +vc <- VitessceConfig$new("My config") +dataset <- vc$add_dataset("My dataset")$add_object(w) +spatial <- vc$add_view(dataset, Component$SPATIAL) +scatterplot_expr <- vc$add_view(dataset, Component$SCATTERPLOT, mapping = "Expression profile UMAP") +scatterplot_nbrh <- vc$add_view(dataset, Component$SCATTERPLOT, mapping = "Neighborhood UMAP") +cell_sets <- vc$add_view(dataset, Component$CELL_SETS) +status <- vc$add_view(dataset, Component$STATUS) +desc <- vc$add_view(dataset, Component$DESCRIPTION) +desc <- desc$set_props(description = "Visualization of a Giotto object.") + +vc$layout( + hconcat( + vconcat( + spatial, + scatterplot_expr + ), + vconcat( + hconcat(cell_sets, vconcat(desc, status)), + scatterplot_nbrh + ) + ) +) + +# Render the Vitessce widget +vc$widget(theme = "light") +``` + + + From ef43ddfd033691a2297ff34a1f8f8b108093565f Mon Sep 17 00:00:00 2001 From: mkeller <7525285+keller-mark@users.noreply.github.com> Date: Thu, 27 Jan 2022 12:26:22 -0500 Subject: [PATCH 2/5] Update example --- vignettes/giotto_nanostring.Rmd | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vignettes/giotto_nanostring.Rmd b/vignettes/giotto_nanostring.Rmd index 1d86468..e77f335 100644 --- a/vignettes/giotto_nanostring.Rmd +++ b/vignettes/giotto_nanostring.Rmd @@ -7,7 +7,7 @@ vignette: > %\VignetteEncoding{UTF-8} --- -The following is a full example of usage of the widget with a [Giotto](https://github.com/RubD/Giotto) object. +The following is an example of usage of the widget with a [Giotto](https://github.com/RubD/Giotto) object from [NanoString](https://www.nanostring.com/products/cosmx-spatial-molecular-imager/ffpe-dataset/). First, install the R dependencies: @@ -16,15 +16,16 @@ install.packages("devtools") devtools::install_github("RubD/Giotto") ``` -Download and un-tar the giotto object: https://nanostring-public-share.s3.us-west-2.amazonaws.com/SMI-Compressed/All+SMI+Giotto+object.tar.gz +Download and un-tar the Giotto object: https://nanostring-public-share.s3.us-west-2.amazonaws.com/SMI-Compressed/All+SMI+Giotto+object.tar.gz -Load the giotto object: +Load the Giotto object in R: ```r rdata_path <- file.path("data", "giotto", "SMI_Giotto_Object.RData") load(rdata_path) +# Clean up gem@cell_metadata <- gem@cell_metadata$rna gem@spatial_locs <- gem@spatial_locs$raw gem@raw_exprs <- NULL From 0522686668ef94cb0bef8ce7866616e24f01cd9e Mon Sep 17 00:00:00 2001 From: mkeller <7525285+keller-mark@users.noreply.github.com> Date: Thu, 27 Jan 2022 12:45:46 -0500 Subject: [PATCH 3/5] Giotto example updates --- R/data_to_zarr.R | 13 +++++++------ R/wrappers_giotto.R | 2 +- pkgdown/_pkgdown.yml | 2 ++ vignettes/{giotto.Rmd => giotto_basic.Rmd} | 20 ++++++++++++++++++-- vignettes/giotto_nanostring.Rmd | 4 ++-- 5 files changed, 30 insertions(+), 11 deletions(-) rename vignettes/{giotto.Rmd => giotto_basic.Rmd} (85%) diff --git a/R/data_to_zarr.R b/R/data_to_zarr.R index 99f8878..38a0029 100644 --- a/R/data_to_zarr.R +++ b/R/data_to_zarr.R @@ -232,7 +232,7 @@ giotto_to_anndata_zarr <- function(giotto_obj, out_path, X_slot) { np <- reticulate::import("numpy", convert=FALSE) # Reference: https://github.com/theislab/zellkonverter/blob/master/R/SCE2AnnData.R#L237 - make_numpy_friendly <- function(x, transpose = TRUE) { + make_numpy_friendly <- function(x, transpose = TRUE, as_type = NA) { if (transpose) { x <- Matrix::t(x) } @@ -241,11 +241,12 @@ giotto_to_anndata_zarr <- function(giotto_obj, out_path, X_slot) { } else { x <- as.matrix(x) } + if(!is.na(as_type)) { + x <- np$array(x) + x <- x$astype(as_type) + } - y <- np$array(x) - y <- y$astype(" 0) { - obsm <- lapply(obsm, make_numpy_friendly) + obsm <- lapply(obsm, make_numpy_friendly, as_type = " - %\VignetteIndexEntry{Usage with Giotto} + %\VignetteIndexEntry{Usage with Giotto: Basic Example} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -118,6 +118,22 @@ SS_seqfish <- runPCA(gobject = SS_seqfish, genes_to_use = featgenes, scale_unit SS_seqfish <- runtSNE(SS_seqfish, dimensions_to_use = 1:15) ``` +Rescale the coordinates to help with saving as a NumPy array: + +```r +# Rescale dimensionality reduction coordinates +for(dr in names(SS_seqfish@dimension_reduction$cells)) { + old_coord_2d <- SS_seqfish@dimension_reduction$cells[[dr]][[dr]]$coordinates[, c(1, 2)] + old_coord_2d[, 1] <- old_coord_2d[, 1] - min(old_coord_2d[, 1]) + old_coord_2d[, 1] <- (old_coord_2d[, 1] / max(old_coord_2d[, 1])) * 10000 + old_coord_2d[, 2] <- old_coord_2d[, 2] - min(old_coord_2d[, 2]) + old_coord_2d[, 2] <- (old_coord_2d[, 2] / max(old_coord_2d[, 2])) * 10000 + + new_coord_2d <- old_coord_2d + SS_seqfish@dimension_reduction$cells[[dr]][[dr]]$coordinates[, c(1, 2)] <- new_coord_2d +} +``` + Set up the Vitessce widget: ```r diff --git a/vignettes/giotto_nanostring.Rmd b/vignettes/giotto_nanostring.Rmd index e77f335..08e3bbe 100644 --- a/vignettes/giotto_nanostring.Rmd +++ b/vignettes/giotto_nanostring.Rmd @@ -1,8 +1,8 @@ --- -title: "Usage with Giotto" +title: "Usage with Giotto: NanoString dataset" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Usage with Giotto} + %\VignetteIndexEntry{Usage with Giotto: NanoString dataset} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- From 60e639f02b4ca2bb3c922b1f885aa4de335a6fff Mon Sep 17 00:00:00 2001 From: mkeller <7525285+keller-mark@users.noreply.github.com> Date: Thu, 27 Jan 2022 13:03:31 -0500 Subject: [PATCH 4/5] Docs --- R/wrappers_giotto.R | 13 +++++++------ man/GiottoWrapper.Rd | 17 +++++++++++------ man/giotto_to_anndata_zarr.Rd | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/R/wrappers_giotto.R b/R/wrappers_giotto.R index 4c09f6f..c2de703 100644 --- a/R/wrappers_giotto.R +++ b/R/wrappers_giotto.R @@ -22,7 +22,7 @@ GiottoWrapper <- R6::R6Class("GiottoWrapper", #' @field expr_matrix The key for the expression matrix. #' @keywords internal expr_matrix = NULL, - #' @field cell_embeddings The keys in the Seurat object's reductions/cell.embeddings + #' @field cell_embeddings The keys in the Giotto object's reductions/cell.embeddings #' to use for creating dimensionality reduction mappings. #' @keywords internal cell_embeddings = NULL, @@ -34,15 +34,15 @@ GiottoWrapper <- R6::R6Class("GiottoWrapper", #' to use for creating dimensionality reduction mappings. #' @keywords internal cell_embedding_dims = NULL, - #' @field cell_set_metas The keys in the Seurat object's meta.data + #' @field cell_set_metas The keys in the Giotto object's cell_metadata #' to use for creating cell sets. #' @keywords internal cell_set_metas = NULL, - #' @field cell_set_meta_names The keys in the Seurat object's meta.data + #' @field cell_set_meta_names The keys in the Giotto object's cell_metadata #' to use for cell set names mapped to new names. #' @keywords internal cell_set_meta_names = NULL, - #' @field cell_set_meta_scores The keys in the Seurat object's meta.data + #' @field cell_set_meta_scores The keys in the Giotto object's cell_metadata #' to use for cell set names mapped to keys for scores. #' @keywords internal cell_set_meta_scores = NULL, @@ -50,9 +50,10 @@ GiottoWrapper <- R6::R6Class("GiottoWrapper", #' @keywords internal zarr_folder = NULL, #' @description - #' Create a wrapper around a Seurat object. + #' Create a wrapper around a Giotto object. #' @param obj The object to wrap. - #' @param cell_embeddings The keys in the Seurat object's reductions/cell.embeddings + #' @param expr_matrix The name of the slot in the Giotto object. + #' @param cell_embeddings The keys in the Giotto object's reductions/cell.embeddings #' to use for creating dimensionality reduction plots. #' @param cell_embedding_names Names #' to use for creating dimensionality reduction plots. diff --git a/man/GiottoWrapper.Rd b/man/GiottoWrapper.Rd index 60dbc45..495cb9c 100644 --- a/man/GiottoWrapper.Rd +++ b/man/GiottoWrapper.Rd @@ -27,7 +27,9 @@ w <- GiottoWrapper$new( \describe{ \item{\code{obj}}{The object to wrap.} -\item{\code{cell_embeddings}}{The keys in the Seurat object's reductions/cell.embeddings +\item{\code{expr_matrix}}{The key for the expression matrix.} + +\item{\code{cell_embeddings}}{The keys in the Giotto object's reductions/cell.embeddings to use for creating dimensionality reduction mappings.} \item{\code{cell_embedding_names}}{Names @@ -36,13 +38,13 @@ to use for creating dimensionality reduction mappings.} \item{\code{cell_embedding_dims}}{The dimension indices to use for creating dimensionality reduction mappings.} -\item{\code{cell_set_metas}}{The keys in the Seurat object's meta.data +\item{\code{cell_set_metas}}{The keys in the Giotto object's cell_metadata to use for creating cell sets.} -\item{\code{cell_set_meta_names}}{The keys in the Seurat object's meta.data +\item{\code{cell_set_meta_names}}{The keys in the Giotto object's cell_metadata to use for cell set names mapped to new names.} -\item{\code{cell_set_meta_scores}}{The keys in the Seurat object's meta.data +\item{\code{cell_set_meta_scores}}{The keys in the Giotto object's cell_metadata to use for cell set names mapped to keys for scores.} \item{\code{zarr_folder}}{The name for the folder at the root of the zarr store.} @@ -80,10 +82,11 @@ to use for cell set names mapped to keys for scores.} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-new}{}}} \subsection{Method \code{new()}}{ -Create a wrapper around a Seurat object. +Create a wrapper around a Giotto object. \subsection{Usage}{ \if{html}{\out{
}}\preformatted{GiottoWrapper$new( obj, + expr_matrix = NA, cell_embeddings = NA, cell_embedding_names = NA, cell_embedding_dims = NA, @@ -99,7 +102,9 @@ Create a wrapper around a Seurat object. \describe{ \item{\code{obj}}{The object to wrap.} -\item{\code{cell_embeddings}}{The keys in the Seurat object's reductions/cell.embeddings +\item{\code{expr_matrix}}{The name of the slot in the Giotto object.} + +\item{\code{cell_embeddings}}{The keys in the Giotto object's reductions/cell.embeddings to use for creating dimensionality reduction plots.} \item{\code{cell_embedding_names}}{Names diff --git a/man/giotto_to_anndata_zarr.Rd b/man/giotto_to_anndata_zarr.Rd index 50eea05..802ab4f 100644 --- a/man/giotto_to_anndata_zarr.Rd +++ b/man/giotto_to_anndata_zarr.Rd @@ -4,7 +4,7 @@ \alias{giotto_to_anndata_zarr} \title{Save a Giotto object to an AnnData-Zarr store} \usage{ -giotto_to_anndata_zarr(giotto_obj, out_path, X_slot = "raw_exprs") +giotto_to_anndata_zarr(giotto_obj, out_path, X_slot) } \arguments{ \item{giotto_obj}{The object to save.} From c5700ec72bb284d6b2edf4c9bd38b783228c14ee Mon Sep 17 00:00:00 2001 From: mkeller <7525285+keller-mark@users.noreply.github.com> Date: Thu, 27 Jan 2022 14:17:31 -0500 Subject: [PATCH 5/5] Docs --- R/data_to_zarr.R | 2 +- README.md | 1 + man/giotto_to_anndata_zarr.Rd | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/R/data_to_zarr.R b/R/data_to_zarr.R index 38a0029..a126304 100644 --- a/R/data_to_zarr.R +++ b/R/data_to_zarr.R @@ -218,7 +218,7 @@ spe_to_ome_zarr <- function(spe_obj, sample_id, image_id, out_path) { #' @export #' @examples #' obj <- get_giotto_obj() -#' giotto_to_anndata_zarr(obj, "data/giotto.zarr") +#' giotto_to_anndata_zarr(obj, "data/giotto.zarr", "raw_exprs") #' @importFrom methods slot giotto_to_anndata_zarr <- function(giotto_obj, out_path, X_slot) { diff --git a/README.md b/README.md index 3c3ccc4..16ebbce 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ devtools::load_all() ```r devtools::check() devtools::test() +devtools::run_examples() ``` ## Documentation diff --git a/man/giotto_to_anndata_zarr.Rd b/man/giotto_to_anndata_zarr.Rd index 802ab4f..4401520 100644 --- a/man/giotto_to_anndata_zarr.Rd +++ b/man/giotto_to_anndata_zarr.Rd @@ -21,6 +21,6 @@ Save a Giotto object to an AnnData-Zarr store } \examples{ obj <- get_giotto_obj() -giotto_to_anndata_zarr(obj, "data/giotto.zarr") +giotto_to_anndata_zarr(obj, "data/giotto.zarr", "raw_exprs") } \keyword{internal}