From 9138988261272492daa86de5071e1896e92f8f85 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:08:00 -0500 Subject: [PATCH 01/16] change scrublet seed setting --- R/python_scrublet.R | 11 +++++------ inst/python/python_scrublet.py | 5 +++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/R/python_scrublet.R b/R/python_scrublet.R index 0f422ceae..2740134f0 100644 --- a/R/python_scrublet.R +++ b/R/python_scrublet.R @@ -73,11 +73,9 @@ doScrubletDetect <- function( # set seed if (!is.null(seed)) { - seed_number <- as.numeric(seed) - reticulate::py_set_seed( - seed = seed_number, - disable_hash_randomization = TRUE - ) + seed_number <- as.integer(seed) + } else { + seed_number <- random_seed() } # Set feat_type and spat_unit @@ -116,7 +114,8 @@ doScrubletDetect <- function( min_counts = min_counts, min_cells = min_cells, min_gene_variability_pctl = min_gene_variability_pctl, - n_prin_comps = n_prin_comps + n_prin_comps = n_prin_comps, + seed_number = seed_number ) scrublet_out <- data.table::data.table( diff --git a/inst/python/python_scrublet.py b/inst/python/python_scrublet.py index 4b856b53d..faedcc0e5 100644 --- a/inst/python/python_scrublet.py +++ b/inst/python/python_scrublet.py @@ -1,13 +1,14 @@ import scrublet as scr -def python_scrublet(counts_matrix, expected_doublet_rate, min_counts, min_cells, min_gene_variability_pctl, n_prin_comps): +def python_scrublet(counts_matrix, expected_doublet_rate, min_counts, min_cells, min_gene_variability_pctl, n_prin_comps, seed_number=1234): min_counts = int(min_counts) min_cells = int(min_cells) min_gene_variability_pctl = int(min_gene_variability_pctl) n_prin_comps = int(n_prin_comps) + random_state = int(seed_number) - scrub = scr.Scrublet(counts_matrix=counts_matrix, expected_doublet_rate=expected_doublet_rate) + scrub = scr.Scrublet(counts_matrix=counts_matrix, expected_doublet_rate=expected_doublet_rate, random_state=random_state) doublet_scores, predicted_doublets = scrub.scrub_doublets(min_counts=min_counts,min_cells=min_cells, min_gene_variability_pctl=min_gene_variability_pctl, n_prin_comps=n_prin_comps) return_list = [] From e3464a280e056d51007595cc8664599f826498ad Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:48:33 -0500 Subject: [PATCH 02/16] allow access to transcript datatable --- R/convenience_xenium.R | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 9dc52cfc9..506410479 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -238,6 +238,7 @@ setMethod( dropcols = c(), qv_threshold = obj@qv, cores = determine_cores(), + output = c("giottoPoints", "data.table"), verbose = NULL) { .xenium_transcript( path = path, @@ -247,6 +248,7 @@ setMethod( dropcols = dropcols, qv_threshold = qv_threshold, cores = cores, + output = output, verbose = verbose ) } @@ -690,6 +692,7 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { dropcols = c(), qv_threshold = 20, cores = determine_cores(), + output = c("giottoPoints", "data.table"), verbose = NULL) { if (missing(path)) { stop(wrap_txt( @@ -704,6 +707,8 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { vmsg(.v = verbose, .is_debug = TRUE, "[TX_READ] FMT =", e) vmsg(.v = verbose, .is_debug = TRUE, path) + output <- match.arg(output, choices = c("giottoPoints", "data.table")) + # read in as data.table a <- list( path = path, @@ -726,6 +731,8 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { y <- NULL # NSE var if (flip_vertical) tx[, y := -y] + if (output == "data.table") return(tx) + # create gpoints gpointslist <- createGiottoPoints( x = tx, @@ -734,7 +741,8 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { verbose = FALSE ) - if (inherits(gpointslist, "list")) { + # enforce list + if (!inherits(gpointslist, "list")) { gpointslist <- list(gpointslist) } From ebff4234adc3116d928a6c5a0ba41fc6072d1710 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:11:05 -0500 Subject: [PATCH 03/16] refactor: var explained New internals - .varexp() - variance explained per PC - .cumvar() - cumulative variance per PC --- R/dimension_reduction.R | 55 +++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/R/dimension_reduction.R b/R/dimension_reduction.R index 8bd3bccaa..3b26e77b1 100644 --- a/R/dimension_reduction.R +++ b/R/dimension_reduction.R @@ -1928,24 +1928,9 @@ jackstrawPlot <- function( } n <- ncol(dat) m <- nrow(dat) - ndf <- min(m, n - 1, ncp) # this is a limitation of svd singular values - sum_of_squared_singular_vals <- sum(dat^2) - - # pick SVD fun based on whether partial or full is appropriate - # These biocsingular functions should not scale or center - svd_fun <- if (ndf >= 0.5 * m || ndf >= 100) { - BiocSingular::runExactSVD - } else { - BiocSingular::runIrlbaSVD - } # partial SVDs - - .calc_svd_var_explained <- function(x, k) { - res <- svd_fun(x, k = k) - singular_val_square <- res$d[1:k]^2 - return(singular_val_square / sum_of_squared_singular_vals) - } - - dstat <- .calc_svd_var_explained(dat, k = ndf) + ndf <- min(m, n - 1, ncp) # this is also calculated in .varexp + + dstat <- .varexp(dat, k = ncp) cum_var_explained <- cumsum(dstat) # randomize and compare @@ -1961,7 +1946,7 @@ jackstrawPlot <- function( for (i in seq_len(iter)) { pb() dat0 <- t(apply(dat, 1, sample)) - dstat0[i, ] <- .calc_svd_var_explained(dat0, k = ndf) + dstat0[i, ] <- .varexp(dat0, k = ncp) } }) @@ -1977,7 +1962,39 @@ jackstrawPlot <- function( return(list(r = r, p = p, cum_var_explained = cum_var_explained)) } +# calculate SVD variance explained, with support for partial SVDs +.varexp <- function(dat, k = 20) { + if (missing(dat)) { + stop("`dat` is required!") + } + n <- ncol(dat) + m <- nrow(dat) + ndf <- min(m, n - 1, k) # this is a limitation of svd singular values + sum_of_squared_singular_vals <- sum(dat^2) + + # pick SVD fun based on whether partial or full is appropriate + # These biocsingular functions should not scale or center + svd_fun <- if (ndf >= 0.5 * m || ndf >= 100) { + BiocSingular::runExactSVD + } else { + BiocSingular::runIrlbaSVD + } # partial SVDs + + res <- svd_fun(dat, k) + singular_val_square <- res$d[1:k]^2 + perc <- singular_val_square / sum_of_squared_singular_vals + return(perc) +} +# cumulative variance explained +.cumvar <- function(dat, k = 20, last = TRUE) { + a <- get_args_list(keep = c("dat", "k")) + res <- cumsum(do.call(.varexp, a)) + if (last) { + res <- tail(res, 1L) + } + return(res) +} #' @title signPCA From 4d29198a554ef6d802fbb408d96d5918e66a09f1 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:10:40 -0500 Subject: [PATCH 04/16] enh: labelTransfer with integration --- R/clustering.R | 178 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 163 insertions(+), 15 deletions(-) diff --git a/R/clustering.R b/R/clustering.R index 7cc71d97c..c7d41257c 100644 --- a/R/clustering.R +++ b/R/clustering.R @@ -3309,12 +3309,18 @@ getDendrogramSplits <- function( #' one of the sets to the other based on KNN similarity voting in that space. #' @param x target object #' @param y source object +#' @param spat_unit spatial unit. A character vector of 2 can also be passed +#' for x (1) and y (2). Setting defaults with `activeSpatUnit()` may be easier +#' @param feat_type feature type. A character vector of 2 can also be passed +#' for x (1) and y (2). Setting defaults with `activeFeatType()` may be easier #' @param source_cell_ids cell/spatial IDs with the source labels to transfer #' @param target_cell_ids cell/spatial IDs to transfer the labels to. #' IDs from `source_cell_ids` are always included as well. #' @param labels metadata column in source with labels to transfer #' @param k number of k-neighbors to train a KNN classifier #' @param name metadata column in target to apply the full set of labels to +#' @param integration_method character. Integration method to use when +#' transferring labels. Options are "none" (default) and "harmony". #' @param prob output knn probabilities together with label predictions #' @param reduction reduction on cells or features (default = "cells") #' @param reduction_method shared reduction method (default = "pca" space) @@ -3364,45 +3370,187 @@ setGeneric( function(x, y, ...) standardGeneric("labelTransfer") ) + +.lab_trnsfr_harmony <- function(x, y, + expression_values = "raw", + dimensions_to_use = 1:10, + spat_unit = NULL, + feat_type = NULL, + filter_params = list( + expression_threshold = 1, + feat_det_in_min_cells = 1, + min_det_feats_per_cell = 10 + ), + normalize_params = list(), + use_hvf = TRUE, + pca_params = list(), + integration_params = list(), + ... # passes to labelTransfer +) { + # NSE vars + cell_ID <- transfer <- transfer_prob <- NULL + + # match features + ufids <- intersect(featIDs(x), featIDs(y)) + if (length(ufids) == 0L) { + stop("labelTransfer harmony: No common features between `x` and `y`", + call. = FALSE) + } + + # get needed subobjects + xdata <- x[[ + c("expression", "spatial_locs"), + expression_values, + spat_unit = spat_unit[[1]], + feat_type = feat_type[[1]], + ]] + ydata <- y[[ + c("expression", "spatial_locs"), + expression_values, + spat_unit = spat_unit[[2]], + feat_type = feat_type[[2]], + ]] + ymeta <- y[[ + "cell_metadata", + spat_unit = spat_unit[[2]], + feat_type = feat_type[[2]] + ]] + + # harmonize nesting + objName(xdata) <- rep("join", length(xdata)) + objName(ydata) <- rep("join", length(ydata)) + ydata <- c(ydata, ymeta) + spatUnit(xdata) <- rep("join", length(xdata)) + featType(xdata) <- rep("join", length(xdata)) + spatUnit(ydata) <- rep("join", length(ydata)) + featType(ydata) <- rep("join", length(ydata)) + + # generate temp objects + xj <- setGiotto(giotto(initialize = FALSE), xdata, verbose = FALSE) + yj <- setGiotto(giotto(initialize = FALSE), ydata, verbose = FALSE) + + # join on intersected feats + j <- joinGiottoObjects( + list(xj[ufids], yj[ufids]), + gobject_names = c("x", "y") + ) + + # process + j <- do.call( + normalizeGiotto, args = c(list(gobject = j), normalize_params) + ) + if (use_hvf) { + j <- calculateHVF(j) + pca_params$feats_to_use = pca_params$feats_to_use %null% "hvf" + } else { + pca_params$feats_to_use = NULL + } + j <- do.call(runPCA, args = c(list(gobject = j), pca_params)) + + # TODO determine dims to use via cumvar >= 30% + + # harmony + integration_params$name <- "harmony" + integration_params$vars_use = "list_ID" + integration_params$dim_reduction_name = "pca" + integration_params$dimensions_to_use = dimensions_to_use + + j <- do.call(runGiottoHarmony, c(list(gobject = j), integration_params)) + + transfer_args <- list( + x = j, + source_cell_ids = spatIDs(j, subset = list_ID == "y"), + name = "transfer", + dimensions_to_use = dimensions_to_use, + reduction = "cells", + reduction_method = "harmony", + reduction_name = "harmony", + ... + ) + j <- do.call(labelTransfer, transfer_args) + + res <- pDataDT(j) + res <- res[list_ID == "x"] + res[, cell_ID := gsub("^x-", "", cell_ID)] + res <- res[, .(cell_ID, transfer, transfer_prob)] + + x <- addCellMetadata(x, + new_metadata = res, + by_column = TRUE, + column_cell_ID = "cell_ID" + ) + return(x) +} + + + #' @rdname labelTransfer #' @export setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function( x, y, - spat_unit = NULL, - feat_type = NULL, labels, k = 10, name = paste0("trnsfr_", labels), + integration_method = c("none", "harmony"), prob = TRUE, reduction = "cells", reduction_method = "pca", reduction_name = "pca", dimensions_to_use = 1:10, + spat_unit = NULL, + feat_type = NULL, return_gobject = TRUE, ...) { - # NSE vars - temp_name <- cell_ID <- temp_name_prob <- NULL package_check(pkg_name = "FNN", repository = "CRAN") - spat_unit <- set_default_spat_unit(x, spat_unit = spat_unit) - feat_type <- set_default_feat_type(x, - spat_unit = spat_unit, feat_type = feat_type + + integration_method <- match.arg(integration_method, choices = c( + "none", "harmony" + )) + + if (!labels %in% colnames(pDataDT(y))) { + stop("`labels` not found in cell metadata of `y`", call. = FALSE) + } + + # norm su and ft lengths + if (length(spat_unit) == 1L) { + spat_unit <- rep(spat_unit, 2L) + } + if (length(feat_type) == 1L) { + feat_type <- rep(feat_type, 2L) + } + + if (integration_method == "harmony") { + a <- get_args_list(...) + return(.lab_transfr_harmony(...)) + } + + # NSE vars + temp_name <- cell_ID <- temp_name_prob <- NULL + + su1 <- set_default_spat_unit(x, spat_unit = spat_unit[[1]]) + su2 <- set_default_spat_unit(y, spat_unit = spat_unit[[2]]) + ft1 <- set_default_feat_type( + x, spat_unit = su1, feat_type = feat_type[[1]] + ) + ft2 <- set_default_feat_type( + y, spat_unit = su2, feat_type = feat_type[[2]] ) # get data cx_src <- getCellMetadata(y, - spat_unit = spat_unit, - feat_type = feat_type, + spat_unit = su2, + feat_type = ft2, output = "data.table" ) cx_tgt <- getCellMetadata(x, - spat_unit = spat_unit, - feat_type = feat_type, + spat_unit = su1, + feat_type = ft1, output = "data.table" ) dim_coord <- getDimReduction(x, - spat_unit = spat_unit, - feat_type = feat_type, + spat_unit = su1, + feat_type = ft1, reduction = reduction, reduction_method = reduction_method, name = reduction_name, @@ -3479,8 +3627,8 @@ setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function( if (return_gobject) { x <- addCellMetadata(x, - spat_unit = spat_unit, - feat_type = feat_type, + spat_unit = su1, + feat_type = ft1, new_metadata = cx_tgt, by_column = TRUE, column_cell_ID = "cell_ID" From 5035de8452047f45a119e09c20711f73258c8c0d Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:11:37 -0500 Subject: [PATCH 05/16] chore: docs --- man/labelTransfer.Rd | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/man/labelTransfer.Rd b/man/labelTransfer.Rd index dbf876a0b..e1d13ce8b 100644 --- a/man/labelTransfer.Rd +++ b/man/labelTransfer.Rd @@ -10,16 +10,17 @@ voting} \S4method{labelTransfer}{giotto,giotto}( x, y, - spat_unit = NULL, - feat_type = NULL, labels, k = 10, name = paste0("trnsfr_", labels), + integration_method = c("none", "harmony"), prob = TRUE, reduction = "cells", reduction_method = "pca", reduction_name = "pca", dimensions_to_use = 1:10, + spat_unit = NULL, + feat_type = NULL, return_gobject = TRUE, ... ) @@ -53,6 +54,9 @@ voting} \item{name}{metadata column in target to apply the full set of labels to} +\item{integration_method}{character. Integration method to use when +transferring labels. Options are "none" (default) and "harmony".} + \item{prob}{output knn probabilities together with label predictions} \item{reduction}{reduction on cells or features (default = "cells")} @@ -64,6 +68,12 @@ voting} \item{dimensions_to_use}{dimensions to use in shared reduction space (default = 1:10)} +\item{spat_unit}{spatial unit. A character vector of 2 can also be passed +for x (1) and y (2). Setting defaults with \code{activeSpatUnit()} may be easier} + +\item{feat_type}{feature type. A character vector of 2 can also be passed +for x (1) and y (2). Setting defaults with \code{activeFeatType()} may be easier} + \item{...}{ Arguments passed on to \code{\link[FNN:knn]{FNN::knn}} \describe{ From be6ad66cd1e804704dd49b9f2868a4e45b18345f Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Sun, 24 Nov 2024 21:22:41 -0500 Subject: [PATCH 06/16] chore: fix typo --- R/clustering.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/clustering.R b/R/clustering.R index c7d41257c..1b78563ec 100644 --- a/R/clustering.R +++ b/R/clustering.R @@ -3371,7 +3371,7 @@ setGeneric( ) -.lab_trnsfr_harmony <- function(x, y, +.lab_transfer_harmony <- function(x, y, expression_values = "raw", dimensions_to_use = 1:10, spat_unit = NULL, @@ -3522,7 +3522,7 @@ setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function( if (integration_method == "harmony") { a <- get_args_list(...) - return(.lab_transfr_harmony(...)) + return(.lab_transfer_harmony(...)) } # NSE vars From 4b22026801e35c92606fe66e41ecea226497e849 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Sun, 24 Nov 2024 22:20:59 -0500 Subject: [PATCH 07/16] fix param passing --- R/clustering.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/clustering.R b/R/clustering.R index 1b78563ec..9222374db 100644 --- a/R/clustering.R +++ b/R/clustering.R @@ -3522,7 +3522,7 @@ setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function( if (integration_method == "harmony") { a <- get_args_list(...) - return(.lab_transfer_harmony(...)) + return(do.call(.lab_transfer_harmony, a)) } # NSE vars From bfc8d26e4dcb3b9c2132a6e199f46172400ddf5d Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Tue, 26 Nov 2024 09:24:19 -0500 Subject: [PATCH 08/16] Update clustering.R --- R/clustering.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/clustering.R b/R/clustering.R index 9222374db..0bcdf57d1 100644 --- a/R/clustering.R +++ b/R/clustering.R @@ -3399,13 +3399,13 @@ setGeneric( # get needed subobjects xdata <- x[[ - c("expression", "spatial_locs"), + c("expression"), expression_values, spat_unit = spat_unit[[1]], feat_type = feat_type[[1]], ]] ydata <- y[[ - c("expression", "spatial_locs"), + c("expression"), expression_values, spat_unit = spat_unit[[2]], feat_type = feat_type[[2]], From 74826a7628e4b5c0ae96e2f7179d611640c36ed5 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:17:19 -0500 Subject: [PATCH 09/16] fix: prevent drop during matrix indexing --- R/spatial_enrichment.R | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/R/spatial_enrichment.R b/R/spatial_enrichment.R index 8864acc02..ec2852a73 100644 --- a/R/spatial_enrichment.R +++ b/R/spatial_enrichment.R @@ -2279,7 +2279,7 @@ enrich_deconvolution <- function( ct_exp, cutoff) { ##### generate enrich 0/1 matrix based on expression matrix - ct_exp <- ct_exp[rowSums(ct_exp) > 0, ] + ct_exp <- ct_exp[rowSums(ct_exp) > 0, , drop = FALSE] enrich_matrix <- matrix(0, nrow = dim(ct_exp)[1], ncol = dim(ct_exp)[2]) rowmax_col <- Rfast::rowMaxs(ct_exp) for (i in seq_along(rowmax_col)) { @@ -2321,9 +2321,9 @@ enrich_deconvolution <- function( ct_gene <- c(ct_gene, sig_gene_j) } uniq_ct_gene <- intersect(rownames(expr), unique(ct_gene)) - select_sig_exp <- ct_exp[uniq_ct_gene, ct] + select_sig_exp <- ct_exp[uniq_ct_gene, ct, drop = FALSE] cluster_i_cell <- which(cluster_info == cluster_sort[i]) - cluster_cell_exp <- expr[uniq_ct_gene, cluster_i_cell] + cluster_cell_exp <- expr[uniq_ct_gene, cluster_i_cell, drop = FALSE] cluster_i_dwls <- optimize_deconvolute_dwls( cluster_cell_exp, select_sig_exp @@ -2383,9 +2383,9 @@ spot_deconvolution <- function( ct_gene <- c(ct_gene, sig_gene_j) } uniq_ct_gene <- intersect(rownames(expr), unique(ct_gene)) - select_sig_exp <- ct_exp[uniq_ct_gene, ct_i] + select_sig_exp <- ct_exp[uniq_ct_gene, ct_i, drop = FALSE] cluster_i_cell <- which(cluster_info == cluster_sort[i]) - cluster_cell_exp <- expr[uniq_ct_gene, cluster_i_cell] + cluster_cell_exp <- expr[uniq_ct_gene, cluster_i_cell, drop = FALSE] ###### calculate ###### overlap signature with spatial genes all_exp <- Matrix::rowMeans(cluster_cell_exp) From 11d2880dc424b31c9dd34ecb023c5de4e243b9ba Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Sun, 8 Dec 2024 03:46:28 -0500 Subject: [PATCH 10/16] enh: labelTransfer() harmony integration --- DESCRIPTION | 2 +- R/clustering.R | 120 +++++++++++++++++++++++++++++++++++++------------ R/normalize.R | 6 ++- 3 files changed, 96 insertions(+), 32 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index fccb7569a..5d2293a15 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -28,7 +28,7 @@ RoxygenNote: 7.3.2 Depends: R (>= 4.4.1), methods, - GiottoClass (>= 0.4.1) + GiottoClass (>= 0.4.5) Imports: BiocParallel, BiocSingular, diff --git a/R/clustering.R b/R/clustering.R index 0bcdf57d1..687069816 100644 --- a/R/clustering.R +++ b/R/clustering.R @@ -3385,27 +3385,35 @@ setGeneric( use_hvf = TRUE, pca_params = list(), integration_params = list(), + verbose = NULL, ... # passes to labelTransfer ) { # NSE vars cell_ID <- transfer <- transfer_prob <- NULL + # turn off lower level updates + options("giotto.update_param" = FALSE) + on.exit({ + options("giotto.update_param" = TRUE) + }, add = TRUE) + + vmsg(.v = verbose, "1. Creating temporary joined object...") # match features ufids <- intersect(featIDs(x), featIDs(y)) if (length(ufids) == 0L) { stop("labelTransfer harmony: No common features between `x` and `y`", call. = FALSE) } - + # get needed subobjects xdata <- x[[ - c("expression"), + "expression", expression_values, spat_unit = spat_unit[[1]], feat_type = feat_type[[1]], ]] ydata <- y[[ - c("expression"), + "expression", expression_values, spat_unit = spat_unit[[2]], feat_type = feat_type[[2]], @@ -3417,34 +3425,72 @@ setGeneric( ]] # harmonize nesting - objName(xdata) <- rep("join", length(xdata)) - objName(ydata) <- rep("join", length(ydata)) + objName(xdata) <- rep("raw", length(xdata)) + objName(ydata) <- rep("raw", length(ydata)) ydata <- c(ydata, ymeta) - spatUnit(xdata) <- rep("join", length(xdata)) - featType(xdata) <- rep("join", length(xdata)) - spatUnit(ydata) <- rep("join", length(ydata)) - featType(ydata) <- rep("join", length(ydata)) + spatUnit(xdata) <- rep("cell", length(xdata)) + featType(xdata) <- rep("rna", length(xdata)) + spatUnit(ydata) <- rep("cell", length(ydata)) + featType(ydata) <- rep("rna", length(ydata)) - # generate temp objects - xj <- setGiotto(giotto(initialize = FALSE), xdata, verbose = FALSE) - yj <- setGiotto(giotto(initialize = FALSE), ydata, verbose = FALSE) + dummy_sl_x <- data.table::data.table( + cell_ID = colnames(xdata[[1]][]), + sdimx = 0, sdimy = 0 + ) |> + createSpatLocsObj( + name = "raw", spat_unit = "cell", verbose = FALSE + ) + dummy_sl_y <- data.table::data.table( + cell_ID = colnames(ydata[[1]][]), + sdimx = 0, sdimy = 0 + ) |> + createSpatLocsObj( + name = "raw", spat_unit = "cell", verbose = FALSE + ) + dummy_instrs <- instructions(x) + + xdata <- c(xdata, dummy_sl_x) + ydata <- c(ydata, dummy_sl_y) + # generate temp objects + xj <- setGiotto(giotto(instructions = dummy_instrs, initialize = FALSE), + xdata, verbose = FALSE) + yj <- setGiotto(giotto(instructions = dummy_instrs, initialize = FALSE), + ydata, verbose = FALSE) + # join on intersected feats j <- joinGiottoObjects( list(xj[ufids], yj[ufids]), gobject_names = c("x", "y") ) + # cleanup + rm(y, xj, yj, xdata, ydata, ymeta, dummy_sl_x, dummy_sl_y, dummy_instrs) + + vmsg(.v = verbose, "2. Performing simple filter...") + j <- filterGiotto(j, + expression_threshold = 1, + min_det_feats_per_cell = 1, + feat_det_in_min_cells = 1, + verbose = FALSE + ) + + vmsg(.v = verbose, "3. Running normalize...") + normalize_params$verbose <- FALSE # process - j <- do.call( - normalizeGiotto, args = c(list(gobject = j), normalize_params) + j <- do.call(normalizeGiotto, + args = c(list(gobject = j), normalize_params) ) + if (use_hvf) { + vmsg(.v = verbose, "-- Calculating HVF...") j <- calculateHVF(j) pca_params$feats_to_use = pca_params$feats_to_use %null% "hvf" } else { - pca_params$feats_to_use = NULL + pca_params <- c(pca_params, list(feats_to_use = NULL)) } + + vmsg(.v = verbose, "4. Running PCA...") j <- do.call(runPCA, args = c(list(gobject = j), pca_params)) # TODO determine dims to use via cumvar >= 30% @@ -3455,25 +3501,29 @@ setGeneric( integration_params$dim_reduction_name = "pca" integration_params$dimensions_to_use = dimensions_to_use - j <- do.call(runGiottoHarmony, c(list(gobject = j), integration_params)) - - transfer_args <- list( - x = j, - source_cell_ids = spatIDs(j, subset = list_ID == "y"), - name = "transfer", - dimensions_to_use = dimensions_to_use, - reduction = "cells", - reduction_method = "harmony", - reduction_name = "harmony", - ... + vmsg(.v = verbose, "5. Generating shared Harmony embedding space...") + j <- do.call(runGiottoHarmony, + c(list(gobject = j), integration_params) ) + + # transfer + transfer_args <- list(...) + transfer_args$x <- j + transfer_args$source_cell_ids <- spatIDs(j, subset = list_ID == "y") + transfer_args$dimensions_to_use = dimensions_to_use + transfer_args$reduction = "cells" + transfer_args$reduction_method = "harmony" + transfer_args$reduction_name = "harmony" + + vmsg(.v = verbose, "6. Performing label transfer...") j <- do.call(labelTransfer, transfer_args) res <- pDataDT(j) res <- res[list_ID == "x"] res[, cell_ID := gsub("^x-", "", cell_ID)] - res <- res[, .(cell_ID, transfer, transfer_prob)] - + tname <- transfer_args$name + res <- res[, .SD, .SDcols = c("cell_ID", tname, paste0(tname, "_prob"))] + x <- addCellMetadata(x, new_metadata = res, by_column = TRUE, @@ -3483,6 +3533,7 @@ setGeneric( } +# ** giotto, giotto #### #' @rdname labelTransfer #' @export @@ -3522,7 +3573,15 @@ setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function( if (integration_method == "harmony") { a <- get_args_list(...) - return(do.call(.lab_transfer_harmony, a)) + a$integration_method <- NULL + # this function needs error handling or it locks the console + res <- tryCatch({ + do.call(.lab_transfer_harmony, a) + }, error = function(e) { + stop(wrap_txtf("labelTransfer: harmony:\n%s", e$message), + call. = FALSE) + }) + return(res) } # NSE vars @@ -3639,6 +3698,9 @@ setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function( } }) + +# ** giotto, missing #### + #' @rdname labelTransfer #' @export setMethod("labelTransfer", signature(x = "giotto", y = "missing"), function( diff --git a/R/normalize.R b/R/normalize.R index 510788d8f..47ca2eca5 100644 --- a/R/normalize.R +++ b/R/normalize.R @@ -425,8 +425,10 @@ normalizeGiotto <- function(gobject, ) ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### - gobject <- setGiotto(gobject, norm_expr, initialize = FALSE) - gobject <- setGiotto(gobject, norm_scaled_expr, initialize = FALSE) + gobject <- setGiotto( + gobject, norm_expr, verbose = verbose, initialize = FALSE) + gobject <- setGiotto( + gobject, norm_scaled_expr, verbose = verbose, initialize = FALSE) ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## 6. return Giotto object From 771acc2b0b5f5154de9213dcf711eba9a068fb66 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Dec 2024 01:47:31 -0500 Subject: [PATCH 11/16] enh: labelTransfer() harmony integration - docs - add cell_id subsets - plotting of labels in joined umap --- DESCRIPTION | 2 +- R/clustering.R | 129 ++++++++++++++++++++++++++++++++++++++----- man/labelTransfer.Rd | 39 ++++++++++++- 3 files changed, 153 insertions(+), 17 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5d2293a15..9596ed514 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -37,7 +37,7 @@ Imports: dbscan (>= 1.1-3), ggraph, ggplot2 (>= 3.1.1), - GiottoUtils (>= 0.2.0), + GiottoUtils (>= 0.2.2), GiottoVisuals (>= 0.2.6), igraph (>= 1.2.4.1), Matrix (>= 1.6-2), diff --git a/R/clustering.R b/R/clustering.R index 687069816..1a4c8cf60 100644 --- a/R/clustering.R +++ b/R/clustering.R @@ -3320,15 +3320,20 @@ getDendrogramSplits <- function( #' @param k number of k-neighbors to train a KNN classifier #' @param name metadata column in target to apply the full set of labels to #' @param integration_method character. Integration method to use when -#' transferring labels. Options are "none" (default) and "harmony". +#' transferring labels. Options are "none" (default) and "harmony". See section +#' below for more info and params. #' @param prob output knn probabilities together with label predictions #' @param reduction reduction on cells or features (default = "cells") #' @param reduction_method shared reduction method (default = "pca" space) #' @param reduction_name name of shared reduction space (default name = "pca") #' @param dimensions_to_use dimensions to use in shared reduction space #' (default = 1:10) -#' @returns object `x` with new transferred labels added to metadata #' @inheritDotParams FNN::knn -train -test -cl -k -prob +#' @returns object `x` with new transferred labels added to metadata. If +#' running on `x` and `y` objects, `integration_method = "harmony"`, +#' `plot_join_labels = TRUE`, and `return_plot = TRUE` is set, output will +#' be instead a named list of `gobject` (updated `x`), and `label_source_plot` +#' and `label_target_plot` `ggplot2` objects #' @details #' This function trains a KNN classifier with [FNN::knn()]. #' The training data is from object `y` or `source_cell_ids` subset in `x` and @@ -3348,6 +3353,34 @@ getDendrogramSplits <- function( #' used to transfer labels from one set of annotated data to another dataset #' based on expression similarity after joining and integrating. #' +#' # integration_method +#' When running `labelTranfer()` on two `giotto` objects, an integration +#' pipeline can also be run to align the two datasets together before the +#' transfer. `integration_method = "harmony"` will make a temporary joined +#' object on shared features, filter to remove 0 values, run PCA, then harmony +#' integration, before performing the label transfer from `y` to `x` on the +#' integrated harmony embedding space. Additional params that can be used with +#' this method are:\cr +#' +#' * `source_cell_ids` - character. subset of `y` cells to use +#' * `target_cell_ids` - character. subset of `x` cells to use +#' * `expression_values` - character. expression values in `x` and `y` to use +#' to generate combined space. Default = `"raw"` +#' * `use_hvf` - logical. whether to calculate highly variable features to use +#' for PCA calculation. Default = `TRUE`, but setting `FALSE` is recommended if +#' any of `x` or `y` has roughly 1000 features or fewer +#' * `plot_join_labels` - logical. Whether to plot source labels and final +#' labels in the joine object UMAP. +#' * `normalize_params` - named list. Additional params to pass to +#' `normalizeGiotto()` if desired. +#' * `pca_params` - named list. Additional params to pass to `runPCA()` if +#' desired. +#' * `integration_params` - named list. Additional params to pass to +#' `runGiottoHarmony()` if desired. +#' * `plot_params` - named list. Additional params to pass to `plotUMAP()` if +#' desired. Only relevant when `plot_join_labels = TRUE` +#' * `verbose` - verbosity +#' #' @examples #' g <- GiottoData::loadGiottoMini("visium") #' id_subset <- sample(spatIDs(g), 300) @@ -3372,24 +3405,33 @@ setGeneric( .lab_transfer_harmony <- function(x, y, + source_cell_ids = NULL, + target_cell_ids = NULL, expression_values = "raw", dimensions_to_use = 1:10, spat_unit = NULL, feat_type = NULL, - filter_params = list( - expression_threshold = 1, - feat_det_in_min_cells = 1, - min_det_feats_per_cell = 10 - ), - normalize_params = list(), use_hvf = TRUE, + plot_join_labels = FALSE, + normalize_params = list(), pca_params = list(), integration_params = list(), + plot_params = list(), verbose = NULL, ... # passes to labelTransfer ) { # NSE vars cell_ID <- transfer <- transfer_prob <- NULL + + .check_plot_output <- function(pparam) { + direct_setting <- plot_params[[pparam]] + if (!is.null(direct_setting)) return(direct_setting) + any(instructions(x, pparam), instructions(y, pparam)) + } + + .show_plot <- .check_plot_output("show_plot") + .return_plot <- .check_plot_output("return_plot") + .save_plot <- .check_plot_output("save_plot") # turn off lower level updates options("giotto.update_param" = FALSE) @@ -3457,12 +3499,12 @@ setGeneric( xdata, verbose = FALSE) yj <- setGiotto(giotto(instructions = dummy_instrs, initialize = FALSE), ydata, verbose = FALSE) - - # join on intersected feats - j <- joinGiottoObjects( - list(xj[ufids], yj[ufids]), - gobject_names = c("x", "y") - ) + + xj <- subsetGiotto(xj, feat_ids = ufids, cell_ids = target_cell_ids) + yj <- subsetGiotto(yj, feat_ids = ufids, cell_ids = source_cell_ids) + + # join on intersected feats and specified cell_IDs + j <- joinGiottoObjects(list(xj, yj), gobject_names = c("x", "y")) # cleanup rm(y, xj, yj, xdata, ydata, ymeta, dummy_sl_x, dummy_sl_y, dummy_instrs) @@ -3529,6 +3571,65 @@ setGeneric( by_column = TRUE, column_cell_ID = "cell_ID" ) + + # plot outputs + if (!any(.save_plot, .return_plot, .show_plot) && plot_join_labels) { + return(x) # return early if plotting not needed + } + + vmsg(.v = verbose, "7. plot_join_labels = TRUE: Running UMAP...") + + j <- runUMAP(j, + dim_reduction_to_use = "harmony", + dim_reduction_name = "harmony", + name = "harmony_umap", + dimensions_to_use = dimensions_to_use + ) + + plotlabs <- unique(res[[tname]]) + default_colors <- getRainbowColors( + n = length(plotlabs), slim = c(0.5, 1), vlim = c(0.3, 1) + ) + names(default_colors) <- plotlabs + + plot_params$gobject <- j + plot_params$dim_reduction_name <- "harmony_umap" + plot_params$color_as_factor <- TRUE + plot_params$point_size <- plot_params$point_size %null% 0.5 + plot_params$point_border_stroke <- plot_params$point_border_stroke %null% 0 + plot_params$cell_color_code <- + plot_params$cell_color_code %null% default_colors + + p1_params <- p2_params <- plot_params + + p1_params$cell_color <- transfer_args$labels + p1_params$select_cells <- spatIDs(j, subset = list_ID == "y") + p1_params$other_point_size <- p1_params$other_point_size %null% 0.3 + p1_params$show_plot <- FALSE + p1_params$return_plot <- TRUE + p1_params$title <- "source labels" + + p2_params$cell_color <- tname + p2_params$show_plot <- FALSE + p2_params$return_plot <- TRUE + p2_params$title <- "final labels" + + plot_list <- list(label_source_plot = do.call(plotUMAP, p1_params), + label_final_plot = do.call(plotUMAP, p2_params)) + + if (.show_plot) { + print(plot_grid(plotlist = plot_list)) + } + if (.save_plot) { + plot_output_handler(x, plot_list[[1]], + save_plot = .save_plot, + default_save_name = "transferLabels_source", + ) + } + if (.return_plot) { + x <- c(list(gobject = x), plot_list) + } + return(x) } diff --git a/man/labelTransfer.Rd b/man/labelTransfer.Rd index e1d13ce8b..31da8a1eb 100644 --- a/man/labelTransfer.Rd +++ b/man/labelTransfer.Rd @@ -55,7 +55,8 @@ voting} \item{name}{metadata column in target to apply the full set of labels to} \item{integration_method}{character. Integration method to use when -transferring labels. Options are "none" (default) and "harmony".} +transferring labels. Options are "none" (default) and "harmony". See section +below for more info and params.} \item{prob}{output knn probabilities together with label predictions} @@ -86,7 +87,11 @@ for x (1) and y (2). Setting defaults with \code{activeFeatType()} may be easier IDs from \code{source_cell_ids} are always included as well.} } \value{ -object \code{x} with new transferred labels added to metadata +object \code{x} with new transferred labels added to metadata. If +running on \code{x} and \code{y} objects, \code{integration_method = "harmony"}, +\code{plot_join_labels = TRUE}, and \code{return_plot = TRUE} is set, output will +be instead a named list of \code{gobject} (updated \code{x}), and \code{label_source_plot} +and \code{label_target_plot} \code{ggplot2} objects } \description{ When two sets of data share an embedding space, transfer the labels from @@ -111,6 +116,36 @@ labels to the remaining cells in the target Giotto object. It can also be used to transfer labels from one set of annotated data to another dataset based on expression similarity after joining and integrating. } +\section{integration_method}{ +When running \code{labelTranfer()} on two \code{giotto} objects, an integration +pipeline can also be run to align the two datasets together before the +transfer. \code{integration_method = "harmony"} will make a temporary joined +object on shared features, filter to remove 0 values, run PCA, then harmony +integration, before performing the label transfer from \code{y} to \code{x} on the +integrated harmony embedding space. Additional params that can be used with +this method are:\cr +\itemize{ +\item \code{source_cell_ids} - character. subset of \code{y} cells to use +\item \code{target_cell_ids} - character. subset of \code{x} cells to use +\item \code{expression_values} - character. expression values in \code{x} and \code{y} to use +to generate combined space. Default = \code{"raw"} +\item \code{use_hvf} - logical. whether to calculate highly variable features to use +for PCA calculation. Default = \code{TRUE}, but setting \code{FALSE} is recommended if +any of \code{x} or \code{y} has roughly 1000 features or fewer +\item \code{plot_join_labels} - logical. Whether to plot source labels and final +labels in the joine object UMAP. +\item \code{normalize_params} - named list. Additional params to pass to +\code{normalizeGiotto()} if desired. +\item \code{pca_params} - named list. Additional params to pass to \code{runPCA()} if +desired. +\item \code{integration_params} - named list. Additional params to pass to +\code{runGiottoHarmony()} if desired. +\item \code{plot_params} - named list. Additional params to pass to \code{plotUMAP()} if +desired. Only relevant when \code{plot_join_labels = TRUE} +\item \code{verbose} - verbosity +} +} + \examples{ g <- GiottoData::loadGiottoMini("visium") id_subset <- sample(spatIDs(g), 300) From faf11e153da4bb0f1706b182513b7a0db6355604 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Dec 2024 02:35:04 -0500 Subject: [PATCH 12/16] chore: reexport dotplot --- R/suite_reexports.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/suite_reexports.R b/R/suite_reexports.R index 905811ab7..833d0b6c6 100644 --- a/R/suite_reexports.R +++ b/R/suite_reexports.R @@ -471,6 +471,8 @@ GiottoClass::writeGiottoLargeImage #' @export GiottoVisuals::addGiottoImageToSpatPlot #' @export +GiottoVisuals::dotPlot +#' @export GiottoVisuals::dimCellPlot #' @export GiottoVisuals::dimCellPlot2D From fbee521563cef809c8b2b14bb36eede2090bbe47 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Dec 2024 02:55:19 -0500 Subject: [PATCH 13/16] chore: update news --- DESCRIPTION | 2 +- NEWS.md | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 9596ed514..9b8ba061e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -38,7 +38,7 @@ Imports: ggraph, ggplot2 (>= 3.1.1), GiottoUtils (>= 0.2.2), - GiottoVisuals (>= 0.2.6), + GiottoVisuals (>= 0.2.10), igraph (>= 1.2.4.1), Matrix (>= 1.6-2), MatrixGenerics, diff --git a/NEWS.md b/NEWS.md index cc8301f61..b1d5eb507 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,24 @@ +# Giotto 4.1.6 (2024/12/09) + +## Bug fixes +* `doScrubletDetect()` seed setting + +## Enhancements +* `labelTransfer()` now has `integration_method = "harmony"` for label transferring with an integration pipeline. See ?labelTransfer and the `integration_method` section. +* `importXenium()` `load_transcripts()` can now return a `data.table` rather than the `giottoPoints` representation + +## New +* `.varexp()` internal for calculating SVD variance determined with support for partial SVDs +* `.cumvar()` internal for calculating cumulative variance explained +* re-export of `dotPlot()` from GiottoVisuals + +## Changes +* GiottoClass req raised to 0.4.5 +* GiottoUtils req raised to 0.2.2 +* GiottoVisuals req raised to 0.2.10 + + # Giotto 4.1.5 (2024/11/08) ## Enhancements From 74dd669252ced2d917054c9d5052df9d0b3de5ae Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Dec 2024 03:02:32 -0500 Subject: [PATCH 14/16] chore: docs --- DESCRIPTION | 2 +- NAMESPACE | 2 ++ man/reexports.Rd | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 9b8ba061e..a869dc843 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: Giotto Title: Spatial Single-Cell Transcriptomics Toolbox -Version: 4.1.5 +Version: 4.1.6 Authors@R: c( person("Ruben", "Dries", email = "rubendries@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-7650-7754")), diff --git a/NAMESPACE b/NAMESPACE index 8aca099c2..2a8b3001f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -180,6 +180,7 @@ export(doLouvainSubCluster) export(doRandomWalkCluster) export(doSNNCluster) export(doScrubletDetect) +export(dotPlot) export(estimateAutomatedImageRegistrationWithSIFT) export(estimateImageBg) export(exportGiottoViewer) @@ -751,6 +752,7 @@ importFrom(GiottoVisuals,dimGenePlot3D) importFrom(GiottoVisuals,dimPlot) importFrom(GiottoVisuals,dimPlot2D) importFrom(GiottoVisuals,dimPlot3D) +importFrom(GiottoVisuals,dotPlot) importFrom(GiottoVisuals,getColors) importFrom(GiottoVisuals,giottoSankeyPlan) importFrom(GiottoVisuals,plotHeatmap) diff --git a/man/reexports.Rd b/man/reexports.Rd index f9575eb02..15e96008b 100644 --- a/man/reexports.Rd +++ b/man/reexports.Rd @@ -223,6 +223,7 @@ \alias{updateGiottoPolygonObject} \alias{writeGiottoLargeImage} \alias{addGiottoImageToSpatPlot} +\alias{dotPlot} \alias{dimCellPlot} \alias{dimCellPlot2D} \alias{dimFeatPlot2D} @@ -301,6 +302,6 @@ below to see their documentation. \item{GiottoUtils}{\code{\link[GiottoUtils:pipe]{\%>\%}}, \code{\link[GiottoUtils]{getDistinctColors}}, \code{\link[GiottoUtils]{getRainbowColors}}} - \item{GiottoVisuals}{\code{\link[GiottoVisuals]{addGiottoImageToSpatPlot}}, \code{\link[GiottoVisuals]{dimCellPlot}}, \code{\link[GiottoVisuals:dimCellPlot]{dimCellPlot2D}}, \code{\link[GiottoVisuals]{dimFeatPlot2D}}, \code{\link[GiottoVisuals]{dimFeatPlot3D}}, \code{\link[GiottoVisuals:dimFeatPlot3D]{dimGenePlot3D}}, \code{\link[GiottoVisuals]{dimPlot}}, \code{\link[GiottoVisuals:dimPlot]{dimPlot2D}}, \code{\link[GiottoVisuals:dimPlot]{dimPlot3D}}, \code{\link[GiottoVisuals]{getColors}}, \code{\link[GiottoVisuals]{giottoSankeyPlan}}, \code{\link[GiottoVisuals]{plotHeatmap}}, \code{\link[GiottoVisuals]{plotMetaDataCellsHeatmap}}, \code{\link[GiottoVisuals]{plotMetaDataHeatmap}}, \code{\link[GiottoVisuals]{plotPCA}}, \code{\link[GiottoVisuals]{plotPCA_2D}}, \code{\link[GiottoVisuals]{plotPCA_3D}}, \code{\link[GiottoVisuals]{plotStatDelaunayNetwork}}, \code{\link[GiottoVisuals]{plotTSNE}}, \code{\link[GiottoVisuals]{plotTSNE_2D}}, \code{\link[GiottoVisuals]{plotTSNE_3D}}, \code{\link[GiottoVisuals]{plotUMAP}}, \code{\link[GiottoVisuals]{plotUMAP_2D}}, \code{\link[GiottoVisuals]{plotUMAP_3D}}, \code{\link[GiottoVisuals]{sankeyLabel}}, \code{\link[GiottoVisuals:sankeyLabel]{sankeyLabel<-}}, \code{\link[GiottoVisuals]{sankeyPlot}}, \code{\link[GiottoVisuals]{sankeyRelate}}, \code{\link[GiottoVisuals:sankeyRelate]{sankeyRelate<-}}, \code{\link[GiottoVisuals]{sankeySet}}, \code{\link[GiottoVisuals]{sankeySetAddresses}}, \code{\link[GiottoVisuals]{showClusterDendrogram}}, \code{\link[GiottoVisuals]{showClusterHeatmap}}, \code{\link[GiottoVisuals]{showColorInstructions}}, \code{\link[GiottoVisuals]{showSaveParameters}}, \code{\link[GiottoVisuals]{spatCellPlot}}, \code{\link[GiottoVisuals:spatCellPlot]{spatCellPlot2D}}, \code{\link[GiottoVisuals]{spatDeconvPlot}}, \code{\link[GiottoVisuals]{spatDimCellPlot}}, \code{\link[GiottoVisuals]{spatDimCellPlot2D}}, \code{\link[GiottoVisuals]{spatDimFeatPlot2D}}, \code{\link[GiottoVisuals]{spatDimFeatPlot3D}}, \code{\link[GiottoVisuals:spatDimFeatPlot3D]{spatDimGenePlot3D}}, \code{\link[GiottoVisuals]{spatDimPlot}}, \code{\link[GiottoVisuals:spatDimPlot]{spatDimPlot2D}}, \code{\link[GiottoVisuals]{spatDimPlot3D}}, \code{\link[GiottoVisuals]{spatFeatPlot2D}}, \code{\link[GiottoVisuals]{spatFeatPlot2D_single}}, \code{\link[GiottoVisuals]{spatFeatPlot3D}}, \code{\link[GiottoVisuals:spatFeatPlot3D]{spatGenePlot3D}}, \code{\link[GiottoVisuals]{spatInSituPlotDensity}}, \code{\link[GiottoVisuals]{spatInSituPlotHex}}, \code{\link[GiottoVisuals]{spatInSituPlotPoints}}, \code{\link[GiottoVisuals]{spatNetwDistributions}}, \code{\link[GiottoVisuals]{spatNetwDistributionsDistance}}, \code{\link[GiottoVisuals]{spatNetwDistributionsKneighbors}}, \code{\link[GiottoVisuals]{spatPlot}}, \code{\link[GiottoVisuals:spatPlot]{spatPlot2D}}, \code{\link[GiottoVisuals:spatPlot]{spatPlot3D}}, \code{\link[GiottoVisuals]{subsetSankeySet}}, \code{\link[GiottoVisuals]{violinPlot}}} + \item{GiottoVisuals}{\code{\link[GiottoVisuals]{addGiottoImageToSpatPlot}}, \code{\link[GiottoVisuals]{dimCellPlot}}, \code{\link[GiottoVisuals:dimCellPlot]{dimCellPlot2D}}, \code{\link[GiottoVisuals]{dimFeatPlot2D}}, \code{\link[GiottoVisuals]{dimFeatPlot3D}}, \code{\link[GiottoVisuals:dimFeatPlot3D]{dimGenePlot3D}}, \code{\link[GiottoVisuals]{dimPlot}}, \code{\link[GiottoVisuals:dimPlot]{dimPlot2D}}, \code{\link[GiottoVisuals:dimPlot]{dimPlot3D}}, \code{\link[GiottoVisuals]{dotPlot}}, \code{\link[GiottoVisuals]{getColors}}, \code{\link[GiottoVisuals]{giottoSankeyPlan}}, \code{\link[GiottoVisuals]{plotHeatmap}}, \code{\link[GiottoVisuals]{plotMetaDataCellsHeatmap}}, \code{\link[GiottoVisuals]{plotMetaDataHeatmap}}, \code{\link[GiottoVisuals]{plotPCA}}, \code{\link[GiottoVisuals]{plotPCA_2D}}, \code{\link[GiottoVisuals]{plotPCA_3D}}, \code{\link[GiottoVisuals]{plotStatDelaunayNetwork}}, \code{\link[GiottoVisuals]{plotTSNE}}, \code{\link[GiottoVisuals]{plotTSNE_2D}}, \code{\link[GiottoVisuals]{plotTSNE_3D}}, \code{\link[GiottoVisuals]{plotUMAP}}, \code{\link[GiottoVisuals]{plotUMAP_2D}}, \code{\link[GiottoVisuals]{plotUMAP_3D}}, \code{\link[GiottoVisuals]{sankeyLabel}}, \code{\link[GiottoVisuals:sankeyLabel]{sankeyLabel<-}}, \code{\link[GiottoVisuals]{sankeyPlot}}, \code{\link[GiottoVisuals]{sankeyRelate}}, \code{\link[GiottoVisuals:sankeyRelate]{sankeyRelate<-}}, \code{\link[GiottoVisuals]{sankeySet}}, \code{\link[GiottoVisuals]{sankeySetAddresses}}, \code{\link[GiottoVisuals]{showClusterDendrogram}}, \code{\link[GiottoVisuals]{showClusterHeatmap}}, \code{\link[GiottoVisuals]{showColorInstructions}}, \code{\link[GiottoVisuals]{showSaveParameters}}, \code{\link[GiottoVisuals]{spatCellPlot}}, \code{\link[GiottoVisuals:spatCellPlot]{spatCellPlot2D}}, \code{\link[GiottoVisuals]{spatDeconvPlot}}, \code{\link[GiottoVisuals]{spatDimCellPlot}}, \code{\link[GiottoVisuals]{spatDimCellPlot2D}}, \code{\link[GiottoVisuals]{spatDimFeatPlot2D}}, \code{\link[GiottoVisuals]{spatDimFeatPlot3D}}, \code{\link[GiottoVisuals:spatDimFeatPlot3D]{spatDimGenePlot3D}}, \code{\link[GiottoVisuals]{spatDimPlot}}, \code{\link[GiottoVisuals:spatDimPlot]{spatDimPlot2D}}, \code{\link[GiottoVisuals]{spatDimPlot3D}}, \code{\link[GiottoVisuals]{spatFeatPlot2D}}, \code{\link[GiottoVisuals]{spatFeatPlot2D_single}}, \code{\link[GiottoVisuals]{spatFeatPlot3D}}, \code{\link[GiottoVisuals:spatFeatPlot3D]{spatGenePlot3D}}, \code{\link[GiottoVisuals]{spatInSituPlotDensity}}, \code{\link[GiottoVisuals]{spatInSituPlotHex}}, \code{\link[GiottoVisuals]{spatInSituPlotPoints}}, \code{\link[GiottoVisuals]{spatNetwDistributions}}, \code{\link[GiottoVisuals]{spatNetwDistributionsDistance}}, \code{\link[GiottoVisuals]{spatNetwDistributionsKneighbors}}, \code{\link[GiottoVisuals]{spatPlot}}, \code{\link[GiottoVisuals:spatPlot]{spatPlot2D}}, \code{\link[GiottoVisuals:spatPlot]{spatPlot3D}}, \code{\link[GiottoVisuals]{subsetSankeySet}}, \code{\link[GiottoVisuals]{violinPlot}}} }} From d4f3e6f9a39e6c907c79543b99b46bede01f53b1 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Dec 2024 03:05:42 -0500 Subject: [PATCH 15/16] chore: docs --- NAMESPACE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NAMESPACE b/NAMESPACE index e8799628d..cf94c401c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -181,8 +181,8 @@ export(doMesmerSegmentation) export(doRandomWalkCluster) export(doSNNCluster) export(doScrubletDetect) -export(dotPlot) export(doStardistSegmentation) +export(dotPlot) export(estimateAutomatedImageRegistrationWithSIFT) export(estimateImageBg) export(exportGiottoViewer) From 402b4c979bc4c2fef9dcf7f0dff1261fe80c28a1 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Dec 2024 03:07:55 -0500 Subject: [PATCH 16/16] Update NEWS.md --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index b1d5eb507..1fa9f3c82 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,7 @@ * `importXenium()` `load_transcripts()` can now return a `data.table` rather than the `giottoPoints` representation ## New +* `doMesmerSegmentation()` and `doStardistSegmentation()` segmentation wrappers * `.varexp()` internal for calculating SVD variance determined with support for partial SVDs * `.cumvar()` internal for calculating cumulative variance explained * re-export of `dotPlot()` from GiottoVisuals