|
| 1 | +--- |
| 2 | +title: "Joint Pertub-seq perturbations analysis" |
| 3 | +output: |
| 4 | + md_document: |
| 5 | + variant: markdown_github |
| 6 | +date: "`r format(Sys.time(), '%d %B, %Y')`" |
| 7 | +--- |
| 8 | + |
| 9 | +```{r setup, include=FALSE} |
| 10 | +knitr::opts_chunk$set(echo = TRUE) |
| 11 | +setwd("/Users/dujinhong/Documents/study/Kathryn Roeder/Project/causarray/causarray/docs/source/tutorial") |
| 12 | +``` |
| 13 | + |
| 14 | + |
| 15 | +The original data of Jin et al 2020 can be downloaded from the Broad single cell portal (https://singlecell.broadinstitute.org/single_cell/study/SCP1184). |
| 16 | +Here, we just use a subset of the data to demonstrate the workflow of the analysis. |
| 17 | + |
| 18 | + |
| 19 | + |
| 20 | +```{r} |
| 21 | +library(Seurat) |
| 22 | +library(caret) |
| 23 | +
|
| 24 | +sc.seurat <- readRDS("perturbseq-exneu.rds") |
| 25 | +
|
| 26 | +Y <- data.frame(t(sc.seurat[['RNA']]$counts)) # cell-by-gene matrix |
| 27 | +metadata <- sc.seurat@meta.data |
| 28 | +
|
| 29 | +perturb <- metadata |
| 30 | +colnames(perturb) <- gsub("Perturbation", "trt_", colnames(perturb)) |
| 31 | +perturb$trt_ <- relevel(as.factor(perturb$trt_), ref = "GFP") |
| 32 | +dmy <- dummyVars(" ~ trt_", data = perturb) |
| 33 | +A <- data.frame(predict(dmy, newdata = perturb))[,-1] # cell-by-trt matrix |
| 34 | +``` |
| 35 | + |
| 36 | +For running causarray, we require the following inputs: |
| 37 | + |
| 38 | +- `Y`: the cell-by-gene gene expression matrix. |
| 39 | +- `A`: the cell-by-condition binary matrix of the perturbation/treatment conditions. |
| 40 | +- `X, X_A`: (optional) the cell-by-covariate matrix of the covariates of interest for outcome and propensity models. |
| 41 | + |
| 42 | +Here, `Y` and `A` can be dataframes. |
| 43 | + |
| 44 | + |
| 45 | + |
| 46 | +Use R package `reticulate` to load the Python package `causarray`. |
| 47 | + |
| 48 | +```{r} |
| 49 | +require(reticulate) |
| 50 | +Sys.setenv(PYTHONUNBUFFERED = TRUE) |
| 51 | +use_condaenv('causarray') |
| 52 | +causarray <- import("causarray") |
| 53 | +cat(causarray$`__version__`) |
| 54 | +
|
| 55 | +# (Y, A) should be either data.frame or matrix |
| 56 | +# optional covariates can be provided as matrices |
| 57 | +dat <- causarray$prep_causarray_data(Y, A) |
| 58 | +names(dat) <- c("Y", "A", "X", "X_A") |
| 59 | +list2env(dat, .GlobalEnv) |
| 60 | +``` |
| 61 | + |
| 62 | + |
| 63 | +We first apply gcate to estimate unmeasured confounders. |
| 64 | + |
| 65 | +```{r} |
| 66 | +r <- 10 |
| 67 | +res_gate <- causarray$fit_gcate(Y, X, A, r, verbose=TRUE) # a list of results from 2 stages optimization |
| 68 | +U <- res_gate[[2]]$U |
| 69 | +``` |
| 70 | + |
| 71 | +Next, we apply causarray to estimate the causal effects of perturbations on gene expression. |
| 72 | + |
| 73 | +```{r} |
| 74 | +offsets <- log(res_gate[[2]][['kwargs_glm']][['size_factor']]) # use the precomputed size factors |
| 75 | +res <- causarray$LFC(Y, cbind(X, U), A, cbind(X_A, U), offset=offsets, verbose=TRUE) |
| 76 | +``` |
| 77 | + |
| 78 | +```{r} |
| 79 | +names(res) <- c("df_res", "estimation") |
| 80 | +list2env(res, .GlobalEnv) |
| 81 | +``` |
| 82 | + |
| 83 | + |
| 84 | +```{r, fig.width=12, fig.height=6} |
| 85 | +library(dplyr) |
| 86 | +library(ggplot2) |
| 87 | +
|
| 88 | +# Filter the results for significant discoveries |
| 89 | +significant_discoveries <- df_res[df_res$padj < 0.1, ] |
| 90 | +
|
| 91 | +# Count the number of discoveries for each perturbation condition |
| 92 | +discovery_counts <- as.data.frame(table(significant_discoveries$trt)) |
| 93 | +colnames(discovery_counts) <- c('Perturbation', 'Count') |
| 94 | +
|
| 95 | +# Order the discovery_counts by Count in descending order |
| 96 | +discovery_counts <- discovery_counts %>% arrange(desc(Count)) |
| 97 | +
|
| 98 | +# Set the factor levels of Perturbation to ensure ggplot respects the order |
| 99 | +discovery_counts$Perturbation <- factor(discovery_counts$Perturbation, levels = discovery_counts$Perturbation) |
| 100 | +
|
| 101 | +# Plot the number of discoveries for each perturbation condition |
| 102 | +ggplot(discovery_counts, aes(x = Perturbation, y = Count)) + |
| 103 | + geom_bar(stat = "identity", fill = "royalblue") + theme(axis.text.x = element_text(angle = 90, hjust = 1)) + |
| 104 | + ggtitle('Number of Discoveries (padj < 0.1) for Each Perturbation Condition') + |
| 105 | + xlab('Perturbation Condition') + |
| 106 | + ylab('Number of Discoveries') |
| 107 | +``` |
0 commit comments