#' Create ligand receptor matrices from a Seurat Object
#'
#' @param input_object Seurat object to create ligand receptor matrices from
#'
#' @param metadata_grouping Grouping variable in the Seurat object metadata used
#' to define the groups of cells. Default is "cell_types".
#'
#' @param ligand_receptor_pairs Data.frame of ligands, receptors and
#' interactions in the format of ramilowski_pairs provided by this package.
#' Defaults is "ramilowski_pairs".
#'
#' @return Generates a list, with the first element being the mean expression of
#' ligands in rows and cell groups in columns and the second element being the
#' mean expression of receptors in rows and cell groups in columns.
#'
#' @keywords internal
#' @noRd
create_expression_matrices <- function(input_object,
metadata_grouping,
ligand_receptor_pairs,
number_cells_required,
min_expression,
max_expression
) {
# Define cells to keep
cell_types_keep <- names(table(input_object[[metadata_grouping]]))[table(input_object[[metadata_grouping]])>number_cells_required]
# Filter cells
input_filtered <- input_object[,input_object[[metadata_grouping]][,1] %in% cell_types_keep]
# Filter genes
ligs.recs.all <- unique(c(unique(as.character(ligand_receptor_pairs$ligand)),
unique(as.character(ligand_receptor_pairs$receptor))))
ligs.recs.use <- ligs.recs.all[ligs.recs.all %in% rownames(input_filtered)]
overall.lig.rec <- Seurat::GetAssayData(input_filtered,slot="counts",assay="RNA")[ligs.recs.use,]
ligs.keep <- apply(overall.lig.rec,1,sum)[apply(overall.lig.rec,1,sum)>min_expression &
apply(overall.lig.rec,1,sum)<max_expression]
input_filtered <- input_filtered[names(ligs.keep),]
# Split object
input_filtered_split <- Seurat::SplitObject(input_filtered,split=metadata_grouping)
expr_ligs <- do.call(cbind,lapply(input_filtered_split,function(x) {
expr <- Seurat::GetAssayData(x,assay="RNA",slot="data")
apply(expr[rownames(expr) %in% ligand_receptor_pairs$ligand,],1,mean)
}))
expr_recs <- do.call(cbind,lapply(input_filtered_split,function(x) {
expr <- Seurat::GetAssayData(x,assay="RNA",slot="data")
apply(expr[rownames(expr) %in% ligand_receptor_pairs$receptor,],1,mean)
}))
return(list(expr_ligs,expr_recs))
}
#' Assess joint means between ligands and receptors across cell types
#'
#' @param ligand_mean_dataframe Mean expression values for ligands across cells
#' from a given condition
#'
#' @param receptor_mean_dataframe Mean expression values for receptors across
#' cells from a given condition
#'
#' @param ligand_receptor_pairs Data.frame of ligands, receptors and
#' interactions in the format of ramilowski_pairs provided by this package
#'
#' @param number_cell_types The number of unique cell types in a given sample
#' or condition. This will be used to assess ligand and receptor interactions
#' across cell types.
#'
#' @return Generates a tibble containing joint means for ligand receptor
#' interaction pairs across cell types.
#'
#' @importFrom magrittr %>%
#' @importFrom dplyr mutate
#' @importFrom tibble as_tibble
#' @importFrom dplyr recode
#'
#' @keywords internal
#' @noRd
ligand_receptor_means <- function(ligand_mean_dataframe,receptor_mean_dataframe,ligand_receptor_pairs) {
# Bind variables
Var1 <- Var2 <- interaction_pairs <- NULL
# Determine number of cell types
number_cell_types <- ncol(ligand_mean_dataframe)
lig.rec.pairs <- vector("list",length=nrow(ligand_receptor_pairs))
for (i in 1:nrow(ligand_receptor_pairs)) {
lig.use <- as.character(ligand_receptor_pairs[i,"ligand"])
rec.use <- as.character(ligand_receptor_pairs[i,"receptor"])
lig.status <- !lig.use %in% rownames(ligand_mean_dataframe)
rec.status <- !rec.use %in% rownames(receptor_mean_dataframe)
if (any(lig.status,rec.status)) {
lig.rec.pairs[[i]] <- NA
} else {
comparisons <- expand.grid(seq(1:number_cell_types),seq(1:number_cell_types))
all.lig.rec <- vector("list")
test.frame <- data.frame(ligand_mean_dataframe[lig.use,],receptor_mean_dataframe[rec.use,])
for (q in 1:nrow(comparisons)) {
all.lig.rec[[q]] <- mean(c(test.frame[comparisons[q,1],1],test.frame[comparisons[q,2],2]))
}
lig.rec.pairs[[i]] <- data.frame(do.call(rbind,all.lig.rec))
colnames(lig.rec.pairs[[i]])[1] <- paste(lig.use,rec.use,sep="_")
}
}
interact.frame <- do.call(cbind,lig.rec.pairs)
remove.cols <- apply(interact.frame,2,function(x) any(is.na(x)))
interact.frame <- interact.frame[,-which(remove.cols)]
remove.cols2 <- apply(interact.frame,2,function(x) all(x==0))
interact.frame <- interact.frame[,!remove.cols2]
level.key <- colnames(ligand_mean_dataframe)
names(level.key) <- seq(1,number_cell_types,1)
new.names <- comparisons %>%
data.frame() %>%
mutate(Var1=recode(Var1,!!!level.key)) %>%
mutate(Var2=recode(Var2,!!!level.key))
rownames(interact.frame) <- paste(new.names[,1],new.names[,2],sep="_")
as_tibble(interact.frame,rownames="interaction_pairs")
}
#' Assess joint means between scrambled interaction pairs for
#' ligands and receptors across cell types
#'
#' @param ligand_receptor_means Tibble generated by ligand_receptor_means
#' function. Used to generate create a joint expression weighting for ligand
#' receptor pairs.
#'
#' @param ligand_mean_dataframe Mean expression values for ligands across cells
#' from a given condition
#'
#' @param receptor_mean_dataframe Mean expression values for receptors across
#' cells from a given condition
#'
#' @param ligand_receptor_pairs Data.frame of ligands, receptors and
#' interactions in the format of ramilowski_pairs provided by this package
#'
#' @param scramble_times Number of times to random pair ligands and receptors to
#' generate a background distribution.
#'
#' @return Generates a tibble containing joint resulting from scrambling ligand
#' and receptor pairs.
#'
#' @importFrom magrittr %>%
#' @importFrom dplyr mutate
#' @importFrom tidyr gather
#' @importFrom tibble as_tibble
#' @importFrom dplyr left_join
#' @importFrom stats sd
#'
#' @keywords internal
#' @noRd
ligand_receptor_scramble <- function(ligand_receptor_means_tib,ligand_mean_dataframe,receptor_mean_dataframe,ligand_receptor_pairs,scramble_times) {
# Bind variables
interaction_pairs <- scram_mean <- scram_sd <- NULL
# Determine number of cell types
number_cell_types <- ncol(ligand_mean_dataframe)
ligs.from.interact <- sapply(strsplit(colnames(ligand_receptor_means_tib)[2:ncol(ligand_receptor_means_tib)],split="_"),function(x) x[[1]])
recs.from.interact <- sapply(strsplit(colnames(ligand_receptor_means_tib)[2:ncol(ligand_receptor_means_tib)],split="_"),function(x) x[[2]])
lig.rec.pairs.scram.mean <- lig.rec.pairs.scram.sd <- vector("list")
for (i in 1:length(ligs.from.interact)) {
lig.use <- ligs.from.interact[i]
rec.use <- recs.from.interact[i]
comparisons <- expand.grid(seq(1:number_cell_types),seq(1:number_cell_types))
scram.iter <- vector("list",length=scramble_times)
for (q in 1:scramble_times) {
scramble.index <- sample(1:(number_cell_types^2),(number_cell_types^2))
comparisons <- comparisons[scramble.index,]
all.lig.rec <- vector("list")
test.frame <- data.frame(ligand_mean_dataframe[lig.use,],receptor_mean_dataframe[rec.use,])
for (z in 1:nrow(comparisons)) {
all.lig.rec[[z]] <- mean(c(test.frame[comparisons[z,1],1],test.frame[comparisons[z,2],2]))
}
scram.iter[[q]] <- data.frame(do.call(rbind,all.lig.rec))
}
bound.scram.iter <- do.call(cbind,scram.iter)
lig.rec.pairs.scram.mean[[i]] <- data.frame(scram_mean=apply(bound.scram.iter,1,mean))
colnames(lig.rec.pairs.scram.mean[[i]]) <- paste(lig.use,rec.use,sep="_")
lig.rec.pairs.scram.sd[[i]] <- data.frame(scram_sd=apply(bound.scram.iter,1,sd))
colnames(lig.rec.pairs.scram.sd[[i]]) <- paste(lig.use,rec.use,sep="_")
}
interact.frame.scram.mean <- do.call(cbind,lig.rec.pairs.scram.mean)
interact.frame.scram.sd <- do.call(cbind,lig.rec.pairs.scram.sd)
rownames(interact.frame.scram.mean) <- rownames(interact.frame.scram.sd) <- ligand_receptor_means_tib$interaction_pairs
interact.mean.scram <- as_tibble(interact.frame.scram.mean,rownames="interaction_pairs")
interact.sd.scram <- as_tibble(interact.frame.scram.sd,rownames="interaction_pairs")
interact.mean.scram.g <- interact.mean.scram %>%
gather("interaction","scram_mean",-interaction_pairs)
interact.sd.scram.g <- interact.sd.scram %>%
gather("interaction","scram_sd",-interaction_pairs)
left_join(interact.mean.scram.g,interact.sd.scram.g,by=c("interaction_pairs","interaction"))
}
#' Assess statistical significance of ligand/receptor interactions within an
#' individual group of samples
#'
#' @param ligand_receptor_means Tibble generated by ligand_receptor_means
#' function. Used to generate create a joint expression weighting for ligand
#' receptor pairs.
#'
#' @param ligand_receptor_scramble Tibble generated by ligand_receptor_scramble
#' function. Used to generate scrambled values to test statistical signifiance
#' of the strength of interactions.
#'
#' @return Generates a tibble containing joint resulting from scrambling ligand
#' and receptor pairs.
#'
#' @importFrom magrittr %>%
#' @importFrom dplyr mutate
#' @importFrom tidyr gather
#' @importFrom dplyr left_join
#'
#' @keywords internal
#' @noRd
ligand_receptor_stats <- function(ligand_receptor_means_tib,ligand_receptor_scramble) {
# Bind variables
value <- interaction_pairs <- scram_mean <- scram_sd <- NULL
interact.tib.g <- ligand_receptor_means_tib %>%
gather("interaction","value",-interaction_pairs)
overall.lig.rec <- left_join(interact.tib.g,ligand_receptor_scramble,by=c("interaction_pairs","interaction"))
overall.lig.rec %>%
mutate(p_val=1-stats::pnorm(value,mean=scram_mean,sd=scram_sd)) %>%
mutate(cell_type1=sapply(strsplit(interaction_pairs,split="_"),function(x) x[[1]])) %>%
mutate(cell_type2=sapply(strsplit(interaction_pairs,split="_"),function(x) x[[2]])) %>%
mutate(scram_mean=ifelse(scram_mean==0,0.1,scram_mean)) %>%
mutate(interact_ratio=value/scram_mean)
}
#' Create a data.frame of ligand receptor interactions and cell types to parse
#' across replicate samples
#'
#' @param interaction_stats Tibble from celltalk function, usually filtered to
#' the top significant ligand and receptor interactions of interest
#'
#' @return A data.frame with each row corresponding to a cell type specific
#' ligand/receptor interaction
#'
#' @importFrom magrittr %>%
#' @importFrom dplyr mutate
#' @importFrom rlang .data
#'
#' @keywords internal
#' @noRd
id_interactions <- function(interactions_stats) {
interactions_stats %>%
mutate(ligand=sapply(strsplit(interaction,split="_"),function(x) x[[1]])) %>%
mutate(receptor=sapply(strsplit(interaction,split="_"),function(x) x[[2]])) %>%
dplyr::select(.data$cell_type1,.data$cell_type2,.data$ligand,.data$receptor) %>%
data.frame()
}
#' Extract sample group replicates from seurat object
#'
#' @param seurat_object Seurat object containing expression data acorss all
#' samples and cells
#'
#' @param sample_group Name of the meta.data column in a Seurat object that
#' has the name of the sample group
#'
#' @return A character vector with the names of each sample group replicated
#' the proper number of times
#'
#' @keywords internal
#' @noRd
extract_sample_group_replicates <- function(seurat_object,sample_groups,sample_replicates) {
sample_group_frame <- seurat_object@meta.data %>%
dplyr::select(dplyr::all_of(sample_groups),dplyr::all_of(sample_replicates)) %>%
dplyr::distinct()
rownames(sample_group_frame) <- NULL
return(sample_group_frame)
}
#' Create a data.frame of ligand and receptors across cell types from individual
#' replicate samples
#'
#' @param ligand Ligand from a ligand/receptor interaction
#'
#' @param receptor Receptor from a ligand/receptor interaction
#'
#' @param cell_type1 Cell type expressing the ligand of interest
#'
#' @param cell_type2 Cell type expressing the receptor of interest
#'
#' @param sample_replicates Name of metadata slot containing the names of the
#' individual replicate samples in a sample group
#'
#' @param sample_group Seruat object containing expression data for the ligand
#' receptor pair of interest and replicate samples in meta.data
#'
#' @importFrom rlang .data
#'
#' @return Generates a tibble containing the joint ligand receptor means across
#' individual replicate samples in a sample group
#'
#' @keywords internal
#' @noRd
cell_type_lig_rec_frame <- function(interactions_compare,seurat_object,sample_replicates,sample_groups,metadata_grouping) {
replicate_types <- NULL
lig_rec_use <- unique(c(interactions_compare$ligand,interactions_compare$receptor))
cell_types_use <- unique(c(interactions_compare$cell_type1,interactions_compare$cell_type2))
expr_dat <- Seurat::GetAssayData(seurat_object,slot="data",assay="RNA") %>%
as.matrix() %>%
t() %>%
as_tibble(.data,rownames="cell_barcodes")
meta_dat <- seurat_object@meta.data %>%
as_tibble(.data,rownames="cell_barcodes")
expr_meta <- left_join(expr_dat,meta_dat,by="cell_barcodes") %>%
mutate(replicate_types=paste(.data[[sample_groups]],.data[[metadata_grouping]],.data[[sample_replicates]],sep=","))
unique_names <- names(table(expr_meta$replicate_types))
expr_meta_list <- expr_meta %>%
group_split(replicate_types)
names(expr_meta_list) <- unique_names
expr_meta_list <- expr_meta_list[sapply(expr_meta_list,nrow)>1]
mean_lig_rec <- lapply(expr_meta_list,function(x) {
apply(x[,lig_rec_use],2,mean)
})
mean_lig_rec_frame <- do.call(rbind,mean_lig_rec) %>% data.frame()
mean_lig_rec_frame$sample_groups <- sapply(strsplit(rownames(mean_lig_rec_frame),split=","),function(x)
x[[1]])
mean_lig_rec_frame$cell_types <- sapply(strsplit(rownames(mean_lig_rec_frame),split=","),function(x)
x[[2]])
mean_lig_rec_frame$sample_replicates <- as.factor(sapply(strsplit(rownames(mean_lig_rec_frame),split=","),function(x)
x[[3]]))
mean_lig_rec_frame
}
#' Create a cell type and ligand/receptor specific tibble across sample
#' groups
#'
#' @param replicate_scores_frame Data.frame containing ligand and receptor
#' interactions across cell types. This is the output from the
#' cell_type_lig_rec_frame function.
#'
#' @param interactions_compare Cell type specific ligand/receptor interaction
#' pairs to evaluate. This is the output from id_interactions.
#' @param extracted_sample_groups Vector containing the replicated names of the
#' sample groups. This is the output from extract_sample_group_replicates.
#'
#' @return Generates a tibble containing the joint ligand receptor means across
#' individual replicate samples in a sample group
#'
#' @keywords internal
#' @noRd
cell_type_ligand_receptor_score <- function(replicate_scores_frame,
interactions_compare,
extracted_sample_groups,
sample_replicates,
sample_groups) {
cell_types <- NULL
interaction_scores <- list()
for (i in 1:nrow(interactions_compare)) {
ligand <- interactions_compare[i,"ligand"]
receptor <- interactions_compare[i,"receptor"]
sample1 <- replicate_scores_frame %>%
select(all_of(ligand),cell_types,sample_replicates,sample_groups) %>%
filter(cell_types==interactions_compare[i,"cell_type1"])
colnames(sample1)[c(3,4)] <- c(sample_replicates,sample_groups)
sample1 <- suppressMessages(left_join(extracted_sample_groups,sample1,by=c(.data[[sample_groups]],.data[[sample_replicates]])))
sample1[is.na(sample1[,ligand]),ligand] <- 0
sample1[is.na(sample1[,"cell_types"]),"cell_types"] <- sample1$cell_types[1]
sample2 <- replicate_scores_frame %>%
select(all_of(receptor),cell_types,sample_replicates,sample_groups) %>%
filter(cell_types==interactions_compare[i,"cell_type2"])
colnames(sample2)[c(3,4)] <- c(sample_replicates,sample_groups)
sample2 <- suppressMessages(left_join(extracted_sample_groups,sample2,by=c(.data[[sample_groups]],.data[[sample_replicates]])))
sample2[is.na(sample2[,receptor]),receptor] <- 0
sample2[is.na(sample2[,"cell_types"]),"cell_types"] <- sample2$cell_types[1]
sample_score <- data.frame((sample1[,3] + sample2[,3]) / 2,
sample_groups=sample1[,sample_groups],
cell_type1=interactions_compare[i,"cell_type1"],
cell_type2=interactions_compare[i,"cell_type2"],
ligand=interactions_compare[i,"ligand"],
receptor=interactions_compare[i,"receptor"])
colnames(sample_score)[1] <- "scores"
interaction_scores[[i]] <- sample_score
}
do.call(rbind,interaction_scores)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.