--- title: "Meta-analysis Testing" output: html_document --- ```{r} # Load required libraries library(SingleCellExperiment) library(Seurat) library(tidyverse) library(MetaNeighbor) ``` ```{r eval = FALSE} # Load the Seurat objects hSeurat <- readRDS("hSeurat_annotated.rds") vtSeurat <- readRDS("vtSeurat2_annotated.rds") # Convert to SCE objects hSCE <- as.SingleCellExperiment(hSeurat) vtSCE <- as.SingleCellExperiment(vtSeurat) # Create my_data mydata <- list(hSCE = hSCE, vtSCE = vtSCE) # Check whether the gene information align between the two datasets lapply(mydata, function(x) head(rownames(x), 3)) # cell-type information is labeled identically in all datasets lapply(mydata, function(x) colnames(colData(x))) # add the cell type information onto a new column name called "cell type" mydata$hSCE$"cell type" <- mydata$hSCE$ident mydata$vtSCE$"cell type" <- mydata$vtSCE$ident # Check that count matrices stored in the assays slot, have identical names lapply(mydata, function(x) names(assays(x))) # Create a merged dataset by using mergeSCE, which takes a list of SCE objects # as an input and outputs a single SCE object fused_data <- mergeSCE(mydata) dim(fused_data) dim(hSCE) dim(vtSCE) head(colData(fused_data)) # To avoid having to recreate the merged object, save the R object to a file # by using R's RDS format. saveRDS(fused_data, "merged_2_datasets.rds") ``` We notice that the fused data contains the cells from both datasets, as the # of columns is the sum of the two datasets. ```{r} # Load RDS file two_datasets <- readRDS("merged_2_datasets.rds") # To obtain a cursory overview of cell-type composition by study, we cross-tabulate cell-type annotations by study IDs table(two_datasets$"cell type", two_datasets$study_id) # It is okay to have identical cell type names at this stage. ``` : Hierarchical cell-type replicability analysis ```{r, fig.height = 8, fig.width = 10} # Picking the highly variable genes global_hvgs <- variableGenes(dat = two_datasets, exp_labels = two_datasets$study_id) length(global_hvgs) # MetaNeighborUS returns a cell-type-by-cell-type matrix containing cell-type similarities. # This fast version should always be used on large datasets but can also be run on smaller datasets. aurocs <- MetaNeighborUS(var_genes = global_hvgs, dat = two_datasets, study_id = two_datasets$study_id, cell_type = two_datasets$"cell type", fast_version = TRUE) # Apparently, we can use this line of code as well. MetaNeighbor::ggPlotHeatmap(aurocs, label_size = 10) # To identify pairs of replicable cell types, run the following function top_hits <- topHits(aurocs, dat = two_datasets, study_id = two_datasets$study_id, cell_type = two_datasets$"cell type", threshold = 0.9) top_hits ``` ```{r fig.height = 8, fig.width = 10} # When there is a clear structure in the data, we can refine AUROCs by # splitting the data. level1_split <- splitClusters(aurocs, k = 2) level1_split first_split <- level1_split[[1]] first_split # Repeat the MetaNeighbor analysis on immune cells only full_labels <- makeClusterName(two_datasets$study_id, two_datasets$`cell type`) subdata <- two_datasets[, full_labels %in% first_split] dim(subdata) # To focus on variability specific to endocrine cells, re-pick highly variable genes var_genes <- variableGenes(dat = subdata, exp_labels = subdata$study_id) # recompute cell-type similarities and visualize AUROCs aurocs <- MetaNeighborUS(var_genes = var_genes, dat = subdata, fast_version = TRUE, study_id = subdata$study_id, cell_type = subdata$"cell type") plotHeatmap(aurocs, cex = 0.7) # Continue to zoom in as long as there are at least two cell types per dataset. # Repeat steps 13-16 level2_split <- splitClusters(aurocs, k = 3) level2_split my_split <- level2_split[[2]] my_split subdata <- two_datasets[, full_labels %in% my_split] var_genes <- variableGenes(dat = subdata, exp_labels = subdata$study_id) length(var_genes) aurocs <- MetaNeighborUS(var_genes = var_genes, dat = subdata, fast_version = TRUE, study_id = subdata$study_id, cell_type = subdata$"cell type") plotHeatmap(aurocs, cex = 1) ``` However, if we use one-vs-best AUROCs, MetaNeighbor can automatically identify the two closest matching cell types in each target dataset. ```{r fig.height = 8, fig.width = 10} best_hits <- MetaNeighborUS(var_genes = global_hvgs, dat = two_datasets, study_id = two_datasets$study_id, cell_type = two_datasets$"cell type", fast_version = TRUE, one_vs_best = TRUE, symmetric_output = FALSE) plotHeatmap(best_hits, cex = 0.5) ``` ```{r} # Extracting cell types as meta-clusters mclusters <- extractMetaClusters(best_hits, threshold = 0.7) mcsummary <- scoreMetaClusters(mclusters, best_hits) # scoreMetaClusters() function provides a good summary of meta-clusters # Visualize the number of robust cell types, the replicability structure # can be summarized as an Upset plot with plotUpset() plotUpset(mclusters) # Save the output as pdf. pdf("meta_clusters.pdf") plotMetaClusters(mclusters, best_hits) while (!is.null(dev.list())) dev.off() ``` ```{r fig.height = 6, fig.width = 8} cluster_graph <- makeClusterGraph(best_hits, low_threshold = 0.3) plotClusterGraph(cluster_graph, two_datasets$study_id, two_datasets$"cell type", size_factor = 3) # We can focus on a cluster of interest (coi). # Take a closer look at 'hSCE|Dendritic cell', query its closest neighbors in the graph with extendClusterSet() and then zoom in on its subgraph with subsetClusterGraph() coi <- "hSCE|Dendritic cell" coi <- extendClusterSet(cluster_graph, initial_set = coi, max_neighbor_distance = 2) subgraph <- subsetClusterGraph(cluster_graph, coi) plotClusterGraph(subgraph, two_datasets$study_id, two_datasets$"cell type", size_factor = 5) ```