| Title: | Cell Type Deconvolution of Spatial Transcriptomics with Dampened Weighted Least Squares |
|---|---|
| Description: | Estimates the cell type composition of each spot of a spatial transcriptomics experiment from a single-cell reference, following spatialDWLS (Dong and Yuan 2021, <doi:10.1186/s13059-021-02362-7>), which builds on dampened weighted least squares (DWLS; Tsoucas et al. 2019, <doi:10.1038/s41467-019-10802-z>). Spots are solved in two rounds: candidate cell types are chosen per cluster by enrichment, then each spot is re-solved against the types present in it. Works on dense or sparse matrices, in parallel through 'BiocParallel', and over windows of spots for expression stores that do not fit in memory. |
| Authors: | Rui Dong [aut] (original spatialDWLS method and implementation), Guo-Cheng Yuan [aut], Ruben Dries [aut, cre] (ORCID: <https://orcid.org/0000-0001-7650-7754>), Jiaji George Chen [ctb] (package and website) |
| Maintainer: | Ruben Dries <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.1 |
| Built: | 2026-10-16 17:42:35 UTC |
| Source: | https://github.com/drieslab/spatialDWLS |
Runs both rounds of spatialDWLS on an expression matrix. Each spot's result is a composition: the proportions of a solved spot sum to one.
dwls( expr, sign_matrix, clusters, n_cell = 50, cutoff = 2, logbase = 2, na_as_zero = FALSE, BPPARAM = NULL, chunk_size = 256L )dwls( expr, sign_matrix, clusters, n_cell = 50, cutoff = 2, logbase = 2, na_as_zero = FALSE, BPPARAM = NULL, chunk_size = 256L )
expr |
log-scaled, normalised expression: features (rows) by spots
(columns), as a base |
sign_matrix |
mean expression per cell type: signature features (rows)
by cell type (columns), on the reverse-logged scale, e.g. from
|
clusters |
cluster of every spot. Either named by spot ID (matched
against |
n_cell |
numeric. expected number of cells per spot. In round 2 a cell
type is kept for a spot only when its round-1 proportion is at least
|
cutoff |
numeric. PAGE enrichment z-score a cell type must reach in at least one spot of a cluster to be a candidate for that cluster. The two highest-scoring types are always candidates. |
logbase |
numeric. log base of |
na_as_zero |
logical. spots that cannot be solved (no signal on the
signature features) are |
BPPARAM |
a |
chunk_size |
integer. spots per parallel task. |
a numeric matrix, cell types (rows) by spots (columns).
dwls_stream() for expression read in windows.
set.seed(1) genes <- paste0("g", 1:30) sig <- matrix(1, 30, 3, dimnames = list(genes, c("A", "B", "C"))) sig[1:10, "A"] <- sig[11:20, "B"] <- sig[21:30, "C"] <- 40 # 20 spots mixing A and B, 20 spots of C alone mix <- cbind(rbind(a <- runif(20, 0.3, 0.7), 1 - a, 0), matrix(c(0, 0, 1), 3, 20)) counts <- matrix(rpois(30 * 40, sig %*% mix * 5), 30, dimnames = list(genes, paste0("s", 1:40))) clusters <- rep(c("mixed", "pure"), each = 20) prop <- dwls(log2(counts + 1), sig, clusters, n_cell = 5) round(prop[, c(1:3, 21:23)], 2)set.seed(1) genes <- paste0("g", 1:30) sig <- matrix(1, 30, 3, dimnames = list(genes, c("A", "B", "C"))) sig[1:10, "A"] <- sig[11:20, "B"] <- sig[21:30, "C"] <- 40 # 20 spots mixing A and B, 20 spots of C alone mix <- cbind(rbind(a <- runif(20, 0.3, 0.7), 1 - a, 0), matrix(c(0, 0, 1), 3, 20)) counts <- matrix(rpois(30 * 40, sig %*% mix * 5), 30, dimnames = list(genes, paste0("s", 1:40))) clusters <- rep(c("mixed", "pure"), each = 20) prop <- dwls(log2(counts + 1), sig, clusters, n_cell = 5) round(prop[, c(1:3, 21:23)], 2)
Mean expression per cell type over the signature features: the reference
dwls() expects.
dwls_signature(expr, sign_gene, cell_type)dwls_signature(expr, sign_gene, cell_type)
expr |
single-cell expression, features (rows) by cells (columns).
Pass the scale the spots will be solved on, i.e. normalised and not
logged ( |
sign_gene |
character. signature features, e.g. cell type markers.
Features missing from |
cell_type |
cell type of each column of |
a numeric matrix, signature features (rows) by cell type
(columns, in order of first appearance in cell_type).
set.seed(1) x <- matrix(rpois(200, 3), 20, 10, dimnames = list(paste0("g", 1:20), paste0("c", 1:10))) dwls_signature(x, sign_gene = paste0("g", 1:5), cell_type = rep(c("A", "B"), each = 5))set.seed(1) x <- matrix(rpois(200, 3), 20, 10, dimnames = list(paste0("g", 1:20), paste0("c", 1:10))) dwls_signature(x, sign_gene = paste0("g", 1:5), cell_type = rep(c("A", "B"), each = 5))
The spatialDWLS driver for expression backends that read spots in windows,
such as an on-disk store. dwls() calls it with a single window.
The reader is called once per window in each of four passes: cluster and feature means, PAGE z-scores, the cluster round of solves and the spot round. Only the signature features are ever requested, and no more than one window is held at a time (apart from the cell types x spots result).
dwls_stream( read_window, n_windows, feat_ids, clusters, sign_matrix, n_cell = 50, cutoff = 2, logbase = 2, na_as_zero = FALSE, BPPARAM = NULL, chunk_size = 256L )dwls_stream( read_window, n_windows, feat_ids, clusters, sign_matrix, n_cell = 50, cutoff = 2, logbase = 2, na_as_zero = FALSE, BPPARAM = NULL, chunk_size = 256L )
read_window |
|
n_windows |
integer. number of windows. |
feat_ids |
character. every feature the backend holds; the signature is restricted to these. |
clusters |
cluster of every spot, named by spot ID. Extra entries are ignored. |
sign_matrix |
mean expression per cell type: signature features (rows)
by cell type (columns), on the reverse-logged scale, e.g. from
|
n_cell |
numeric. expected number of cells per spot. In round 2 a cell
type is kept for a spot only when its round-1 proportion is at least
|
cutoff |
numeric. PAGE enrichment z-score a cell type must reach in at least one spot of a cluster to be a candidate for that cluster. The two highest-scoring types are always candidates. |
logbase |
numeric. log base of |
na_as_zero |
logical. spots that cannot be solved (no signal on the
signature features) are |
BPPARAM |
a |
chunk_size |
integer. spots per parallel task. |
a numeric matrix, cell types (rows) by spots (columns), spots in window order.
set.seed(1) genes <- paste0("g", 1:30) sig <- matrix(1, 30, 3, dimnames = list(genes, c("A", "B", "C"))) sig[1:10, "A"] <- sig[11:20, "B"] <- sig[21:30, "C"] <- 40 mix <- cbind(rbind(a <- runif(20, 0.3, 0.7), 1 - a, 0), matrix(c(0, 0, 1), 3, 20)) expr <- log2(matrix(rpois(30 * 40, sig %*% mix * 5), 30, dimnames = list(genes, paste0("s", 1:40))) + 1) clusters <- setNames(rep(c("mixed", "pure"), each = 20), colnames(expr)) # read the spots ten at a time windows <- split(colnames(expr), rep(1:4, each = 10)) prop <- dwls_stream( read_window = function(i, features) expr[features, windows[[i]]], n_windows = length(windows), feat_ids = rownames(expr), clusters = clusters, sign_matrix = sig, n_cell = 5 ) all.equal(prop, dwls(expr, sig, clusters, n_cell = 5))set.seed(1) genes <- paste0("g", 1:30) sig <- matrix(1, 30, 3, dimnames = list(genes, c("A", "B", "C"))) sig[1:10, "A"] <- sig[11:20, "B"] <- sig[21:30, "C"] <- 40 mix <- cbind(rbind(a <- runif(20, 0.3, 0.7), 1 - a, 0), matrix(c(0, 0, 1), 3, 20)) expr <- log2(matrix(rpois(30 * 40, sig %*% mix * 5), 30, dimnames = list(genes, paste0("s", 1:40))) + 1) clusters <- setNames(rep(c("mixed", "pure"), each = 20), colnames(expr)) # read the spots ten at a time windows <- split(colnames(expr), rep(1:4, each = 10)) prop <- dwls_stream( read_window = function(i, features) expr[features, windows[[i]]], n_windows = length(windows), feat_ids = rownames(expr), clusters = clusters, sign_matrix = sig, n_cell = 5 ) all.equal(prop, dwls(expr, sig, clusters, n_cell = 5))