Nothing
#' Use quanTIseq to Deconvolute a Gene Expression Matrix
#'
#' @description
#' Deconvolutes gene expression data to estimate immune cell fractions using
#' the quanTIseq method. Source code from https://github.com/FFinotello/quanTIseq.
#'
#' @references
#' F. Finotello, C. Mayer, C. Plattner, G. Laschober, D. Rieder,
#' H. Hackl, A. Krogsdam, W. Posch, D. Wilflingseder, S. Sopper, M. Jsselsteijn,
#' D. Johnsons, Y. Xu, Y. Wang, M. E. Sanders, M. V. Estrada, P.
#' Ericsson-Gonzalez, J. Balko, N. F. de Miranda, Z. Trajanoski.
#' "quanTIseq: quantifying immune contexture of human tumors".
#' bioRxiv 223180. https://doi.org/10.1101/223180.
#'
#' @param mix.mat Data frame or matrix. Gene expression matrix with gene symbols
#' on the first column and sample IDs on the first row. Expression data must
#' be on non-log scale (TPM for RNA-seq or expression values for microarrays).
#' @param arrays Logical. Whether expression data are from microarrays.
#' Default is FALSE. If TRUE, the rmgenes parameter is set to "none".
#' @param signame Character. Name of the signature matrix. Currently only
#' "TIL10" is available. Default is "TIL10".
#' @param tumor Logical. Whether expression data are from tumor samples.
#' If TRUE, signature genes with high expression in tumor samples are removed.
#' Default is FALSE.
#' @param mRNAscale Logical. Whether cell fractions must be scaled to account
#' for cell-type-specific mRNA content. Default is TRUE.
#' @param method Character. Deconvolution method: "hampel", "huber", "bisquare"
#' for robust regression, or "lsei" for constrained least squares.
#' Default is "lsei".
#' @param rmgenes Character. Genes to remove: "unassigned" (default), "default",
#' "none", or "path".
#'
#' @return Data frame with cell fractions for each sample.
#'
#' @export
#' @author Finotello F, et al. (adapted for IOBR)
#'
#' @examples
#' \dontrun{
#' quantiseq_data <- load_data("quantiseq_data")
#' if (!is.null(quantiseq_data)) {
#' common_genes <- rownames(quantiseq_data$TIL10_signature)
#' tpm_matrix <- as.data.frame(matrix(
#' abs(rnorm(length(common_genes) * 2, mean = 5, sd = 2)),
#' nrow = length(common_genes), ncol = 2
#' ))
#' rownames(tpm_matrix) <- common_genes
#' colnames(tpm_matrix) <- paste0("Sample", 1:2)
#' results <- deconvolute_quantiseq.default(mix.mat = tpm_matrix)
#' if (!is.null(results)) head(results)
#' }
#' }
deconvolute_quantiseq.default <- function(mix.mat,
arrays = FALSE,
signame = "TIL10",
tumor = FALSE,
mRNAscale = TRUE,
method = c("lsei", "hampel", "huber", "bisquare"),
rmgenes = "unassigned") {
if (is.null(mix.mat)) return(NULL)
method <- rlang::arg_match(method)
if (nrow(mix.mat) == 0) {
cli::cli_abort("{.arg mix.mat} cannot be empty.")
}
cli::cli_alert_info("Running quanTIseq deconvolution module")
if (rmgenes == "unassigned" && arrays) {
rmgenes <- "none"
} else if (rmgenes == "unassigned" && !arrays) {
rmgenes <- "default"
}
listsig <- c("TIL10")
quantiseq_ref <- load_data("quantiseq_data")
if (is.null(quantiseq_ref)) return(NULL)
if (signame %in% listsig) {
sig.mat <- quantiseq_ref$TIL10_signature
mRNA <- quantiseq_ref$TIL10_mRNA_scaling
lrmgenes <- quantiseq_ref$TIL10_rmgenes
} else {
sig.mat.file <- paste0(signame, "_signature.txt")
sig.mat <- read.table(sig.mat.file, header = TRUE, sep = "\t", row.names = 1)
mRNA.file <- paste0(signame, "_mRNA_scaling.txt")
mRNA <- read.table(mRNA.file, sep = "\t", header = FALSE, stringsAsFactors = FALSE)
}
if (!is.numeric(mix.mat[[1, 1]])) {
cli::cli_abort(c(
"Wrong input format for the mixture matrix!",
"i" = "Please follow the instructions in the documentation."
))
}
if (mRNAscale) {
colnames(mRNA) <- c("celltype", "scaling")
mRNA <- as.vector(as.matrix(mRNA$scaling[match(colnames(sig.mat), mRNA$celltype)]))
} else {
mRNA <- rep(1, ncol(sig.mat))
}
cli::cli_alert_info("Gene expression normalization and re-annotation (arrays: {arrays})")
mix.mat <- fixMixture(mix.mat, arrays = arrays)
if (rmgenes != "none") {
if (signame %in% listsig) {
n1 <- nrow(sig.mat)
sig.mat <- sig.mat[!rownames(sig.mat) %in% lrmgenes, , drop = FALSE]
n2 <- nrow(sig.mat)
cli::cli_alert_info("Removing {n1 - n2} noisy genes")
}
}
if (tumor) {
if (signame %in% listsig) {
abgenes <- quantiseq_ref$TIL10_TCGA_aberrant_immune_genes
n1 <- nrow(sig.mat)
sig.mat <- sig.mat[!rownames(sig.mat) %in% abgenes, , drop = FALSE]
n2 <- nrow(sig.mat)
cli::cli_alert_info("Removing {n1 - n2} genes with high expression in tumors")
}
}
ns <- nrow(sig.mat)
us <- length(intersect(rownames(sig.mat), rownames(mix.mat)))
perc <- round(us * 100 / ns, digits = 2)
cli::cli_alert_info("Signature genes found in data set: {us}/{ns} ({perc}%)")
cli::cli_alert_info("Mixture deconvolution (method: {method})")
results1 <- quanTIseq(sig.mat, mix.mat, scaling = mRNA, method = method)
if ("Tregs" %in% colnames(sig.mat) && "T.cells.CD4" %in% colnames(sig.mat) &&
method == "lsei") {
minTregs <- 0.02
i <- which(colnames(sig.mat) == "T.cells.CD4")
results2 <- quanTIseq(sig.mat[, -i], mix.mat, scaling = mRNA[-i], method = method)
ind <- which(results1[, "Tregs"] < minTregs)
if (length(ind) > 0) {
results1[ind, "Tregs"] <- (results2[ind, "Tregs"] + results1[ind, "Tregs"]) / 2
results1[ind, "T.cells.CD4"] <- pmax(
0, results1[ind, "T.cells.CD4"] - (results2[ind, "Tregs"] + results1[ind, "Tregs"]) / 2
)
}
}
results <- results1
results <- results / apply(results, 1, sum)
cli::cli_alert_success("Deconvolution successful!")
results <- data.frame(results)
results <- cbind(rownames(results), results)
colnames(results)[1] <- "Sample"
results
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.