#' @title Detect the spatial community of each cell
#'
#' @description Function to detect the spatial community of each cell as
#' proposed by \href{https://www.nature.com/articles/s41586-019-1876-x}{
#' Jackson et al., The single-cell pathology landscape of breast cancer, Nature,
#' 2020}. Each cell is clustered based on its interactions as defined by a
#' spatial object graph.
#'
#' @param object a \code{SingleCellExperiment} or \code{SpatialExperiment}
#' object
#' @param colPairName single character indicating the \code{colPair(object)}
#' entry containing the neighbor information.
#' @param size_threshold single positive numeric that specifies the minimum
#' number of cells per community. Defaults to 0.
#' @param group_by single character indicating that spatial community
#' detection will be performed separately for all unique entries to
#' \code{colData(object)[,group_by]}.
#' @param name single character specifying the name of the output saved in
#' \code{colData(object)}. Defaults to "spatial_community".
#' @param cluster_fun single character specifying the function to use for
#' community detection. Options are all strings that contain the suffix of an
#' \code{igraph} community detection algorithm (e.g. "walktrap").
#' Defaults to "louvain".
#' @param BPPARAM a \code{\link[BiocParallel]{BiocParallelParam-class}} object
#' defining how to parallelize computations. Applicable when \code{group_by} is
#' specified and defaults to \code{SerialParam()}.
#' For reproducibility between runs, we recommend defining \code{RNGseed} in the
#' \code{\link[BiocParallel]{BiocParallelParam-class}} object.
#'
#' @section Spatial community detection procedure:
#' 1. Create an igraph object from the edge list stored in
#' \code{colPair(object, colPairName)}.
#'
#' 2. Perform community detection using the specified \code{cluster_fun} algorithm.
#'
#' 3. Store the community IDs in a vector and replace all communities with
#' a size smaller than \code{size_threshold} by NA.
#'
#' Optional steps: Specify \code{group_by} to perform spatial community
#' detection separately for all unique entries to \code{colData(object)[,group_by]}
#' e.g. for tumor and non-tumor cells.
#'
#' @return returns an object of \code{class(object)} containing a new column
#' entry to \code{colData(object)[[name]]}.
#'
#' @examples
#' library(cytomapper)
#' library(BiocParallel)
#' data(pancreasSCE)
#'
#' sce <- buildSpatialGraph(pancreasSCE, img_id = "ImageNb",
#' type = "expansion",
#' name = "neighborhood",
#' threshold = 20)
#'
#' ## Detect spatial community
#' set.seed(22)
#' sce <- detectCommunity(sce,
#' colPairName = "neighborhood",
#' size_threshold = 10)
#'
#' plotSpatial(sce,
#' img_id = "ImageNb",
#' node_color_by = "spatial_community",
#' scales = "free")
#'
#' ## Detect spatial community - specify group_by
#' sce <- detectCommunity(sce,
#' colPairName = "neighborhood",
#' group_by = "CellType",
#' size_threshold = 10,
#' BPPARAM = SerialParam(RNGseed = 22))
#'
#' plotSpatial(sce,
#' img_id = "ImageNb",
#' node_color_by = "spatial_community",
#' scales = "free")
#'
#' @author Lasse Meyer (\email{lasse.meyer@@uzh.ch})
#'
#' @references
#' \href{https://www.nature.com/articles/s41586-019-1876-x}{
#' Jackson et al., The single-cell pathology landscape of breast cancer,
#' Nature, 2020}
#'
#' @importFrom SingleCellExperiment colData
#' @importFrom BiocParallel bplapply
#' @importFrom igraph membership sizes
#' @export
detectCommunity <- function(object,
colPairName,
size_threshold = 0,
group_by = NULL,
name = "spatial_community",
cluster_fun = "louvain",
BPPARAM = SerialParam()){
.valid.detectCommunity.input(object, colPairName, size_threshold, group_by, name, cluster_fun)
if (!is.null(group_by)) {
cur_list <- bplapply(unique(colData(object)[,group_by]), function(x){
cur_object <- object[,colData(object)[,group_by] == x]
cl_comm <- .detectCommunity_function(cur_object, colPairName, cluster_fun)
comm <- paste0(x,"_",membership(cl_comm))
names(comm) <- colnames(cur_object)
if (size_threshold != 0){
comm[membership(cl_comm) %in% which(sizes(cl_comm) < size_threshold)] <- NA
}
return(comm)
}, BPPARAM = BPPARAM)
comm <- unlist(cur_list, use.names = TRUE)
} else {
cur_object <- object
cl_comm <- .detectCommunity_function(cur_object, colPairName, cluster_fun)
comm <- as.character(membership(cl_comm))
names(comm) <- colnames(object)
if (size_threshold != 0){
comm[membership(cl_comm) %in% which(sizes(cl_comm) < size_threshold)] <- NA
}
}
colData(object)[[name]] <- comm[colnames(object)]
return(object)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.