From dbc5390c118b1c1c2a5b1dee69a71b7cdeef9c33 Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Wed, 17 Jul 2019 15:18:14 -0400 Subject: [PATCH 1/3] reorg Dockerfile --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index b96e970..d30723b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,9 +23,9 @@ ARG SHINY_APP_IDLE_TIMEOUT=0 RUN sed -i "s/directory_index on;/app_idle_timeout ${SHINY_APP_IDLE_TIMEOUT};/g" /etc/shiny-server/shiny-server.conf RUN rm -r /srv/shiny-server/* && mkdir -p /srv/shiny-server/epiTAD/data -COPY VERSION /srv/shiny-server/epiTAD +COPY data/ /srv/shiny-server/epiTAD/data/ +COPY www/ /srv/shiny-server/epiTAD/www/ COPY global.R /srv/shiny-server/epiTAD COPY ui.R /srv/shiny-server/epiTAD COPY server.R /srv/shiny-server/epiTAD -COPY data/ /srv/shiny-server/epiTAD/data/ -COPY www/ /srv/shiny-server/epiTAD/www/ +COPY VERSION /srv/shiny-server/epiTAD From 5fdd14c0c5ff923ca12078d36519dc0644f6fdf1 Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Wed, 17 Jul 2019 15:18:45 -0400 Subject: [PATCH 2/3] Remove choice of particular BioMart mirror This was causing problems where "useast" wasn't connecting and the app wasn't able to start. May need to revisit in the future. --- global.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.R b/global.R index b6fc981..d4d2284 100644 --- a/global.R +++ b/global.R @@ -21,7 +21,7 @@ logger <- function(...) { # Global Data logger("Connecting to BioMart: ensembl, hsapiens_gene_ensemble") -ensembl54 <- useEnsembl("ensembl", dataset = "hsapiens_gene_ensembl",mirror = "useast") +ensembl54 <- useEnsembl("ensembl", dataset = "hsapiens_gene_ensembl") logger("Loading cached HiC Data") load("data/hicData.Rdata") From 92c4a28b8be70e17533c00a77c7051cdc545db8d Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Wed, 17 Jul 2019 15:20:18 -0400 Subject: [PATCH 3/3] Add caching of data queries and plots --- Dockerfile | 2 +- server.R | 742 ++++++++++++++++++++++++----------------------------- 2 files changed, 334 insertions(+), 410 deletions(-) diff --git a/Dockerfile b/Dockerfile index d30723b..17d9014 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ RUN Rscript -e "BiocManager::install(c('haploR', 'HiTC', 'Sushi', 'biomaRt'))" \ RUN Rscript -e "install.packages(c('writexl', 'plotly', 'shinyWidgets'))" \ && rm -rf /tmp/downloaded_packages/ /tmp/*.rds -RUN Rscript -e "install.packages(c('ggpubr'))" \ +RUN Rscript -e "install.packages(c('ggpubr', 'digest'))" \ && rm -rf /tmp/downloaded_packages/ /tmp/*.rds ARG SHINY_APP_IDLE_TIMEOUT=0 diff --git a/server.R b/server.R index 0cafd65..4404bb9 100644 --- a/server.R +++ b/server.R @@ -1,4 +1,6 @@ SNP_QUERY_ERROR <- "The queried SNP may not be valid. Please check your input." +options("epitad.cachedir" = file.path(tempdir(), "epitad")) +dir.create(getOption("epitad.cachedir"), recursive = TRUE, showWarnings = FALSE) epitad_datatable <- function( x, @@ -33,6 +35,298 @@ epitad_datatable <- function( ) } +query_regulomedb <- function(snp_list) { + shiny::validate(shiny::need( + !is.null(snp_list) && snp_list != "", + "Please enter a valid SNP or file containing SNP IDs" + )) + + input_hash <- digest::digest(snp_list) + + cache_dir <- getOption("epitad.cachedir", getwd()) + cache_file <- file.path(cache_dir, paste0("regulome_", input_hash, ".rds")) + if (file.exists(cache_file)) { + message("Loading cached query results from: ", cache_file) + return(readRDS(cache_file)) + } + + x <- queryRegulome(query = snp_list) + if (!"score" %in% names(x$res.table)) { + # Got a bad response from RegulomeDB + regulome_error_msg <- + if (any(grepl("Server error", paste0(x$res.table[[1]])))) { + "An error occurred on the RegulomeDB server, please try again." + } else { + "An error occurred while querying RegulomeDB, please try again." + } + shiny::validate(need(FALSE, regulome_error_msg)) + } + shiny::validate(need(nrow(x$res.table) > 0, SNP_QUERY_ERROR)) + x <- as.data.frame(x$res.table) + x$score <- as.character(x$score) + x$score_anno <- NA + + for (i in seq_len(nrow(x))) { + x$score_anno[i] <- switch( + x$score[i], + "1a" = "eQTL + TF binding + matched TF motif + matched DNase Footprint + DNase peak", + "1b" = "eQTL + TF binding + any motif + DNase Footprint + DNase peak", + "1c" = "eQTL + TF binding + matched TF motif + DNase peak", + "1d" = "eQTL + TF binding + any motif + DNase peak", + "1e" = "eQTL + TF binding + matched TF motif", + "1f" = "eQTL + TF binding / DNase peak", + "2a" = "TF binding + matched TF motif + matched DNase Footprint + DNase peak", + "2b" = "TF binding + any motif + DNase Footprint + DNase peak", + "2c" = "TF binding + matched TF motif + DNase peak", + "3a" = "TF binding + any motif + DNase peak", + "3b" = "TF binding + matched TF motif", + "4" = "TF binding + DNase peak", + "5" = "TF binding or DNase peak", + "Other" + ) + } + + message("Saving query results to: ", cache_file) + saveRDS(x, cache_file) + x +} + +safely <- function(.f, error_msg = NULL, quiet = FALSE) { + function(...) { + tryCatch( + list(result = .f(...), error = NULL), + error = function(e) { + if (!quiet) message("Error: ", e$message) + + list(result = NULL, error = if (is.null(error_msg)) e$message else error_msg) + }, + interrupt = function(e) { + stop("Terminated by user", call. = FALSE) + } + ) + } +} + +safe_queryHaploreg <- function(...) { + # safe_queryHaploreg(query = snps, ldThresh = as.numeric(input$value), ldPop = input$pop) + input_hash <- digest::digest(list(...)) + + cache_dir <- getOption("epitad.cachedir", getwd()) + cache_file <- file.path(cache_dir, paste0("haploreg_", input_hash, ".rds")) + if (file.exists(cache_file)) { + message("Loading cached query results from: ", cache_file) + return(readRDS(cache_file)) + } + + s_queryHaploreg <- safely(queryHaploreg) + x <- s_queryHaploreg(...) + + if (is.null(x$error)) { + message("Saving query results to: ", cache_file) + saveRDS(x, cache_file) + } + + x +} + + +cached_mega_plot <- function(...) { + args <- list(...) + if (is.null(names(args)) || any(names(args) == "")) { + stop("Arguments to cached_mega_plot() must be named") + } + + args_hash <- digest::digest(args) + cache_dir <- getOption("epitad.cachedir", getwd()) + cache_file <- file.path(cache_dir, paste0("plot_", args_hash, ".rds")) + if (file.exists(cache_file)) { + message("Loading cached plots from: ", cache_file) + return(readRDS(cache_file)) + } + + gg <- do.call("mega_plot", args) + message("Saving plot cache to: ", cache_file) + saveRDS(gg, cache_file) + gg +} + + +mega_plot <- function(ld, genes, minBP, maxBP, plot_color, show_genes = TRUE) { + chrX <- max(ld$chr, na.rm = TRUE) + hic_dat <- extractRegion(hiC[[paste0("chr", chrX, "chr", chrX)]], + chr = paste0("chr", chrX), + from = minBP, to = maxBP + ) + hic_matrix <- as.matrix(intdata(hic_dat)) + tads <- as.data.frame(tads_imr90) + + # ---- Mega Plot: create plot ---- + + ## create dataframe for plotting triangular heatmap + # determine number of bins + nbins <- nrow(hic_matrix) + stepsize <- abs(minBP - maxBP) / (2 * nbins) + + # scale + vec <- hic_matrix + vec[which(vec < 0)] <- 0 + vec[which(vec > 28)] <- 28 + breaks <- seq(0, 28, length.out = 100) + cols_num <- c(0:length(breaks) + 1) + cols_vec <- cut(vec, c(-Inf, breaks, Inf), labels = cols_num) + hicmcol <- matrix(as.numeric(as.character(cols_vec)), nrow = nrow(hic_matrix)) + + # make an empty tibble + tmp <- tibble(x = numeric(), y = numeric(), f = numeric(), g = character(), v = numeric()) + + for (i in (1:nrow(hic_matrix))) { + y <- -.5 + + x <- minBP + (i * 2 * stepsize) - (stepsize * 2) + for (j in (i:ncol(hic_matrix))) { + x <- x + stepsize + y <- y + .5 + + poly_dat <- tibble( + x = c(x - stepsize, x, x + stepsize, x), + y = c(y, y + .5, y, y - .5), + f = hicmcol[i, j], + g = paste0("bin_", i, "_", j), + v = hic_matrix[i, j] + ) + + tmp <- bind_rows(tmp, poly_dat) + } + } + rm(i, j) + + # Mega Plot: Base plot themes ---- + theme_blank <- + theme( + axis.line = element_blank(), + axis.text.x = element_blank(), + axis.text.y = element_blank(), + axis.ticks = element_blank(), + axis.title.x = element_blank(), + panel.background = element_blank(), + panel.border = element_blank(), + panel.grid.major = element_blank(), + panel.grid.minor = element_blank(), + plot.background = element_blank() + ) + + theme_blank_no_legend <- theme_blank + theme(legend.position = "none") + + gg <- list() + + # Mega Plot: HiC Plot ---- + gg$phic <- ggplot(tmp, aes(x = x, y = y, text = paste0("Raw value: ", v))) + + geom_polygon(aes(fill = f, group = g)) + + scale_fill_gradientn(colors = plot_color(n = 100), name = "Score") + + coord_cartesian(xlim = c(minBP, maxBP)) + + ylim(0, (nbins * 0.5) + 1) + + ylab("HIC Intensities") + + theme_blank + + theme( + legend.justification = c(1, 1), legend.position = c(1, 1), + ) + + # Mega Plot: Gene Plot ---- + gg$pgene <- ggplot(genes) + + geom_rect( + mapping = aes(xmin = Start, xmax = End, + ymin = 0.1, ymax = 0.9, + lwd = 30, + text = paste0( + "Symbol: ", Symbol, "
", + "Start: ", Start, "
", + "End: ", End + )), + fill = plot_color(n = nrow(genes)), + alpha = 0.7 + ) + + if (show_genes) { + gg$pgene <- gg$pgene + + geom_text( + aes(x = (Start + End) / 2, + y = rep(c(1.05, -0.05), length.out = nrow(genes)), + label = Symbol + ), + color = plot_color(n = nrow(genes)), size = 3 + ) + } + + gg$pgene <- gg$pgene + + coord_cartesian(xlim = c(minBP, maxBP)) + + ylim(-0.2, 1.2) + + guides(fill = FALSE, alpha = FALSE, size = FALSE) + + ylab("Genes") + + theme_blank_no_legend + + # Mega Plot: SNP Plot ---- + gg$psnp <- ggplot(ld) + + if (nrow(ld[ld$is_query_snp == 0, ]) >= 1) { + gg$psnp <- gg$psnp + + geom_segment( + aes(x = pos_hg38, y = 0, + xend = pos_hg38, yend = 1, + text = paste0( + "rsID: ", rsID, "
", + "Position: ", pos_hg38, "
", + "Ref/Alt: ", ref, "/", alt + ) + ), + subset(ld, is_query_snp == 0), + color = "grey" + ) + } + + gg$psnp <- gg$psnp + + geom_segment(aes( + x = pos_hg38, y = 0, + xend = pos_hg38, yend = 1, + text = paste0( + "rsID: ", rsID, "
", + "Position: ", pos_hg38, "
", + "Ref/Alt: ", ref, "/", alt + ) + ), + subset(ld, is_query_snp == 1), + color = plot_color(n = nrow(ld[ld$is_query_snp == 1, ])) + ) + + coord_cartesian(xlim = c(minBP, maxBP)) + + ylim(0, 1) + + guides(colour = FALSE, size = FALSE) + + ylab("SNPs") + + theme_blank_no_legend + + # Mega Plot: TAD Plot ---- + gg$ptad <- ggplot(tads) + + geom_rect( + aes(xmin = start, xmax = end, + ymin = 0.1, ymax = 0.9, + alpha = 0.7, + lwd = 30, + text = paste0(chrX, ":", start, "-", end) + ), + subset(tads, tads$seqnames == paste0("chr", chrX)), + fill = plot_color(n = nrow(tads[tads$seqnames == paste0("chr", chrX), ])) + ) + + coord_cartesian(xlim = c(minBP, maxBP)) + + ylim(0, 1) + + guides(fill = FALSE, alpha = FALSE, size = FALSE) + + labs(x = "BP", y = "TADs") + + theme_blank_no_legend + + theme( + axis.line.x = element_line(color = "black"), + axis.ticks.x = element_line(color = "black"), + ) + + gg +} + function(input, output, session) { # Enable bookmarking button and update URL on bookmark setBookmarkExclude("file1") @@ -43,45 +337,27 @@ function(input, output, session) { DT:::DT2BSClass(c("stripe", "hover", "compact", "cell-border")) - sample <- eventReactive(input$update1, { + snp_input_file <- eventReactive(input$update1, { samplefile <- input$file1 if (is.null(samplefile)) { return() } - sample1 <- read.table(file = samplefile$datapath, sep = "\t", header = FALSE, stringsAsFactors = FALSE) + read.table(file = samplefile$datapath, sep = "\t", header = FALSE, stringsAsFactors = FALSE) }) - safely <- function(.f, error_msg = NULL, quiet = FALSE) { - function(...) { - tryCatch( - list(result = .f(...), error = NULL), - error = function(e) { - if (!quiet) message("Error: ", e$message) - - list(result = NULL, error = if (is.null(error_msg)) e$message else error_msg) - }, - interrupt = function(e) { - stop("Terminated by user", call. = FALSE) - } - ) - } - } - - safe_queryHaploreg <- safely(queryHaploreg) - # A flag to trigger recalc of other UI elements when query button is hit r_trigger_queried <- reactiveVal(FALSE) dat <- eventReactive(input$update1, { if (input$snpList == "") { - dat <- sample() + req(snp_input_file()) + dat <- snp_input_file() snps <- dat[, 1] - x <- safe_queryHaploreg(query = snps, ldThresh = as.numeric(input$value), ldPop = input$pop) } else { snps <- as.character(unlist(strsplit(input$snpList, ","))) snps <- trimws(snps) - x <- safe_queryHaploreg(query = snps, ldThresh = input$value, ldPop = input$pop) } + x <- safe_queryHaploreg(query = snps, ldThresh = as.numeric(input$value), ldPop = input$pop) shiny::validate(need(is.null(x$error), SNP_QUERY_ERROR)) r_trigger_queried(!r_trigger_queried()) if (is.null(x$error)) { @@ -106,58 +382,25 @@ function(input, output, session) { }) dat2 <- eventReactive(input$update1, { + shiny::validate(shiny::need( + (!is.null(input$snpList) && input$snpList != "") || !is.null(snp_input_file()), + "Please enter a SNP ID or a file containing SNP IDs" + )) + if (input$snpList == "") { - dat <- sample() + req(snp_input_file()) + dat <- snp_input_file() snps <- dat[, 1] - x <- queryRegulome(query = snps) - x <- as.data.frame(x$res.table) - x$score <- as.character(x$score) - x$score_anno <- NA } else { snps <- as.character(unlist(strsplit(input$snpList, ","))) snps <- trimws(snps) - x <- queryRegulome(query = snps) - if (!"score" %in% names(x$res.table)) { - # Got a bad response from RegulomeDB - regulome_error_msg <- - if (any(grepl("Server error", paste0(x$res.table[[1]])))) { - "An error occurred on the RegulomeDB server, please try again." - } else { - "An error occurred while querying RegulomeDB, please try again." - } - shiny::validate(need(FALSE, regulome_error_msg)) - } - shiny::validate(need(nrow(x$res.table) > 0, SNP_QUERY_ERROR)) - x <- as.data.frame(x$res.table) - x$score <- as.character(x$score) - x$score_anno <- NA } - - for (i in seq_len(nrow(x))) { - x$score_anno[i] <- switch( - x$score[i], - "1a" = "eQTL + TF binding + matched TF motif + matched DNase Footprint + DNase peak", - "1b" = "eQTL + TF binding + any motif + DNase Footprint + DNase peak", - "1c" = "eQTL + TF binding + matched TF motif + DNase peak", - "1d" = "eQTL + TF binding + any motif + DNase peak", - "1e" = "eQTL + TF binding + matched TF motif", - "1f" = "eQTL + TF binding / DNase peak", - "2a" = "TF binding + matched TF motif + matched DNase Footprint + DNase peak", - "2b" = "TF binding + any motif + DNase Footprint + DNase peak", - "2c" = "TF binding + matched TF motif + DNase peak", - "3a" = "TF binding + any motif + DNase peak", - "3b" = "TF binding + matched TF motif", - "4" = "TF binding + DNase peak", - "5" = "TF binding or DNase peak", - "Other" - ) - } - x + query_regulomedb(snps) }) snps <- eventReactive(input$update1, { if (input$snpList == "") { - dat <- sample() + dat <- snp_input_file() snps <- dat[, 1] return(snps) } @@ -374,191 +617,31 @@ function(input, output, session) { # Mega Plot --------------------------------------------------------------- output$megaPlot <- renderPlotly({ - # ---- Mega Plot: pull in needed data pieces ---- ld <- dat() - chrX <- max(ld$chr, na.rm = TRUE) minBP <- values$tmp_min maxBP <- values$tmp_max - hic_dat <- extractRegion(hiC[[paste0("chr", chrX, "chr", chrX)]], - chr = paste0("chr", chrX), - from = minBP, to = maxBP + shiny::validate( + need( + maxBP - minBP < 5000000, + "Please choose SNPs or adjust the BP range so that SNPs are within 5,000,000 BP." + ) ) - hic_matrix <- as.matrix(intdata(hic_dat)) genes <- genes() colnames(genes) <- c("Symbol", "Start", "End") - tads <- as.data.frame(tads_imr90) - - # ---- Mega Plot: create plot ---- - - ## create dataframe for plotting triangular heatmap - # determine number of bins - nbins <- nrow(hic_matrix) - stepsize <- abs(minBP - maxBP) / (2 * nbins) - - # scale - vec <- hic_matrix - vec[which(vec < 0)] <- 0 - vec[which(vec > 28)] <- 28 - breaks <- seq(0, 28, length.out = 100) - cols_num <- c(0:length(breaks) + 1) - cols_vec <- cut(vec, c(-Inf, breaks, Inf), labels = cols_num) - hicmcol <- matrix(as.numeric(as.character(cols_vec)), nrow = nrow(hic_matrix)) - - # make an empty tibble - tmp <- tibble(x = numeric(), y = numeric(), f = numeric(), g = character(), v = numeric()) - - for (i in (1:nrow(hic_matrix))) { - y <- -.5 - - x <- minBP + (i * 2 * stepsize) - (stepsize * 2) - for (j in (i:ncol(hic_matrix))) { - x <- x + stepsize - y <- y + .5 - - poly_dat <- tibble( - x = c(x - stepsize, x, x + stepsize, x), - y = c(y, y + .5, y, y - .5), - f = hicmcol[i, j], - g = paste0("bin_", i, "_", j), - v = hic_matrix[i, j] - ) - - tmp <- bind_rows(tmp, poly_dat) - } - } - rm(i, j) - - # Mega Plot: Base plot themes ---- - theme_blank <- - theme( - axis.line = element_blank(), - axis.text.x = element_blank(), - axis.text.y = element_blank(), - axis.ticks = element_blank(), - axis.title.x = element_blank(), - panel.background = element_blank(), - panel.border = element_blank(), - panel.grid.major = element_blank(), - panel.grid.minor = element_blank(), - plot.background = element_blank() - ) - - theme_blank_no_legend <- theme_blank + theme(legend.position = "none") - - # Mega Plot: HiC Plot ---- - phic <- ggplot(tmp, aes(x = x, y = y, text = paste0("Raw value: ", v))) + - geom_polygon(aes(fill = f, group = g)) + - scale_fill_gradientn(colors = plot_color()(n = 100), name = "Score") + - coord_cartesian(xlim = c(minBP, maxBP)) + - ylim(0, (nbins * 0.5) + 1) + - ylab("HIC Intensities") + - theme_blank + - theme( - legend.justification = c(1, 1), legend.position = c(1, 1), - ) - - # Mega Plot: Gene Plot ---- - pgene <- ggplot(genes) + - geom_rect( - mapping = aes(xmin = Start, xmax = End, - ymin = 0.1, ymax = 0.9, - lwd = 30, - text = paste0( - "Symbol: ", Symbol, "
", - "Start: ", Start, "
", - "End: ", End - )), - fill = plot_color()(n = nrow(genes)), - alpha = 0.7 - ) - - if (input$showgenes %% 2 == 0) { - pgene <- pgene + - geom_text( - aes(x = (Start + End) / 2, - y = rep(c(1.05, -0.05), length.out = nrow(genes)), - label = Symbol - ), - color = plot_color()(n = nrow(genes)), size = 3 - ) - } - - pgene <- pgene + - coord_cartesian(xlim = c(minBP, maxBP)) + - ylim(-0.2, 1.2) + - guides(fill = FALSE, alpha = FALSE, size = FALSE) + - ylab("Genes") + - theme_blank_no_legend - - # Mega Plot: SNP Plot ---- - psnp <- ggplot(ld) - - if (nrow(ld[ld$is_query_snp == 0, ]) >= 1) { - psnp <- psnp + - geom_segment( - aes(x = pos_hg38, y = 0, - xend = pos_hg38, yend = 1, - text = paste0( - "rsID: ", rsID, "
", - "Position: ", pos_hg38, "
", - "Ref/Alt: ", ref, "/", alt - ) - ), - subset(ld, is_query_snp == 0), - color = "grey" - ) - } - - psnp <- psnp + - geom_segment(aes( - x = pos_hg38, y = 0, - xend = pos_hg38, yend = 1, - text = paste0( - "rsID: ", rsID, "
", - "Position: ", pos_hg38, "
", - "Ref/Alt: ", ref, "/", alt - ) - ), - subset(ld, is_query_snp == 1), - color = plot_color()(n = nrow(ld[ld$is_query_snp == 1, ])) - ) + - coord_cartesian(xlim = c(minBP, maxBP)) + - ylim(0, 1) + - guides(colour = FALSE, size = FALSE) + - ylab("SNPs") + - theme_blank_no_legend - - # Mega Plot: TAD Plot ---- - ptad <- ggplot(tads) + - geom_rect( - aes(xmin = start, xmax = end, - ymin = 0.1, ymax = 0.9, - alpha = 0.7, - lwd = 30, - text = paste0(chrX, ":", start, "-", end) - ), - subset(tads, tads$seqnames == paste0("chr", chrX)), - fill = plot_color()(n = nrow(tads[tads$seqnames == paste0("chr", chrX), ])) - ) + - coord_cartesian(xlim = c(minBP, maxBP)) + - ylim(0, 1) + - guides(fill = FALSE, alpha = FALSE, size = FALSE) + - labs(x = "BP", y = "TADs") + - theme_blank_no_legend + - theme( - axis.line.x = element_line(color = "black"), - axis.ticks.x = element_line(color = "black"), - ) - + gg <- cached_mega_plot( + ld = ld, genes = genes, minBP = minBP, maxBP = maxBP, + plot_color = plot_color(), + show_genes = input$showgenes %% 2 == 0 + ) # Mega Plot: Compose Final Plot - p1 <- ggplotly(phic, tooltip = "text") - p2 <- hide_legend(ggplotly(pgene, tooltip = "text")) - p3 <- hide_legend(ggplotly(psnp, tooltip = "text")) - p4 <- hide_legend(ggplotly(ptad, tooltip = "text")) + p1 <- ggplotly(gg$phic, tooltip = "text") + p2 <- hide_legend(ggplotly(gg$pgene, tooltip = "text")) + p3 <- hide_legend(ggplotly(gg$psnp, tooltip = "text")) + p4 <- hide_legend(ggplotly(gg$ptad, tooltip = "text")) megap <- subplot(p1, p2, p3, p4, nrows = 4, heights = c(0.65, 0.15, 0.1, 0.1), @@ -572,188 +655,29 @@ function(input, output, session) { }, content = function(file) { pdf(file) - # ---- Mega Plot: pull in needed data pieces ---- ld <- dat() - chrX <- max(ld$chr, na.rm = TRUE) minBP <- values$tmp_min maxBP <- values$tmp_max - hic_dat <- extractRegion(hiC[[paste0("chr", chrX, "chr", chrX)]], - chr = paste0("chr", chrX), - from = minBP, to = maxBP + shiny::validate( + need( + maxBP - minBP < 5000000, + "Please choose SNPs or adjust the BP range so that SNPs are within 5,000,000 BP." + ) ) - hic_matrix <- as.matrix(intdata(hic_dat)) genes <- genes() colnames(genes) <- c("Symbol", "Start", "End") - tads <- as.data.frame(tads_imr90) - - # ---- Mega Plot: create plot ---- - - ## create dataframe for plotting triangular heatmap - # determine number of bins - nbins <- nrow(hic_matrix) - stepsize <- abs(minBP - maxBP) / (2 * nbins) - - # scale - vec <- hic_matrix - vec[which(vec < 0)] <- 0 - vec[which(vec > 28)] <- 28 - breaks <- seq(0, 28, length.out = 100) - cols_num <- c(0:length(breaks) + 1) - cols_vec <- cut(vec, c(-Inf, breaks, Inf), labels = cols_num) - hicmcol <- matrix(as.numeric(as.character(cols_vec)), nrow = nrow(hic_matrix)) - - # make an empty tibble - tmp <- tibble(x = numeric(), y = numeric(), f = numeric(), g = character(), v = numeric()) - - for (i in (1:nrow(hic_matrix))) { - y <- -.5 - - x <- minBP + (i * 2 * stepsize) - (stepsize * 2) - for (j in (i:ncol(hic_matrix))) { - x <- x + stepsize - y <- y + .5 - - poly_dat <- tibble( - x = c(x - stepsize, x, x + stepsize, x), - y = c(y, y + .5, y, y - .5), - f = hicmcol[i, j], - g = paste0("bin_", i, "_", j), - v = hic_matrix[i, j] - ) - - tmp <- bind_rows(tmp, poly_dat) - } - } - rm(i, j) - - # Mega Plot: Base plot themes ---- - theme_blank <- - theme( - axis.line = element_blank(), - axis.text.x = element_blank(), - axis.text.y = element_blank(), - axis.ticks = element_blank(), - axis.title.x = element_blank(), - panel.background = element_blank(), - panel.border = element_blank(), - panel.grid.major = element_blank(), - panel.grid.minor = element_blank(), - plot.background = element_blank() - ) - - theme_blank_no_legend <- theme_blank + theme(legend.position = "none") - - # Mega Plot: HiC Plot ---- - phic <- ggplot(tmp, aes(x = x, y = y, text = paste0("Raw value: ", v))) + - geom_polygon(aes(fill = f, group = g)) + - scale_fill_gradientn(colors = plot_color()(n = 100), name = "Score") + - coord_cartesian(xlim = c(minBP, maxBP)) + - ylim(0, (nbins * 0.5) + 1) + - ylab("HIC Intensities") + - theme_blank + - theme( - legend.justification = c(1, 1), legend.position = c(1, 1), - ) - - # Mega Plot: Gene Plot ---- - pgene <- ggplot(genes) + - geom_rect( - mapping = aes(xmin = Start, xmax = End, - ymin = 0.1, ymax = 0.9, - lwd = 30, - text = paste0( - "Symbol: ", Symbol, "
", - "Start: ", Start, "
", - "End: ", End - )), - fill = plot_color()(n = nrow(genes)), - alpha = 0.7 - ) - - if (input$showgenes %% 2 == 0) { - pgene <- pgene + - geom_text( - aes(x = (Start + End) / 2, - y = rep(c(1.05, -0.05), length.out = nrow(genes)), - label = Symbol - ), - color = plot_color()(n = nrow(genes)), size = 3 - ) - } - - pgene <- pgene + - coord_cartesian(xlim = c(minBP, maxBP)) + - ylim(-0.2, 1.2) + - guides(fill = FALSE, alpha = FALSE, size = FALSE) + - ylab("Genes") + - theme_blank_no_legend - - # Mega Plot: SNP Plot ---- - psnp <- ggplot(ld) - - if (nrow(ld[ld$is_query_snp == 0, ]) >= 1) { - psnp <- psnp + - geom_segment( - aes(x = pos_hg38, y = 0, - xend = pos_hg38, yend = 1, - text = paste0( - "rsID: ", rsID, "
", - "Position: ", pos_hg38, "
", - "Ref/Alt: ", ref, "/", alt - ) - ), - subset(ld, is_query_snp == 0), - color = "grey" - ) - } - - psnp <- psnp + - geom_segment(aes( - x = pos_hg38, y = 0, - xend = pos_hg38, yend = 1, - text = paste0( - "rsID: ", rsID, "
", - "Position: ", pos_hg38, "
", - "Ref/Alt: ", ref, "/", alt - ) - ), - subset(ld, is_query_snp == 1), - color = plot_color()(n = nrow(ld[ld$is_query_snp == 1, ])) - ) + - coord_cartesian(xlim = c(minBP, maxBP)) + - ylim(0, 1) + - guides(colour = FALSE, size = FALSE) + - ylab("SNPs") + - theme_blank_no_legend - - # Mega Plot: TAD Plot ---- - ptad <- ggplot(tads) + - geom_rect( - aes(xmin = start, xmax = end, - ymin = 0.1, ymax = 0.9, - alpha = 0.7, - lwd = 30, - text = paste0(chrX, ":", start, "-", end) - ), - subset(tads, tads$seqnames == paste0("chr", chrX)), - fill = plot_color()(n = nrow(tads[tads$seqnames == paste0("chr", chrX), ])) - ) + - coord_cartesian(xlim = c(minBP, maxBP)) + - ylim(0, 1) + - guides(fill = FALSE, alpha = FALSE, size = FALSE) + - labs(x = "BP", y = "TADs") + - theme_blank_no_legend + - theme( - axis.line.x = element_line(color = "black"), - axis.ticks.x = element_line(color = "black"), - ) + gg <- cached_mega_plot( + ld = ld, genes = genes, minBP = minBP, maxBP = maxBP, + plot_color = plot_color(), + show_genes = input$showgenes %% 2 == 0 + ) # Mega Plot: Compose Final Plot - final <- ggarrange(phic,pgene,psnp,ptad, + final <- ggarrange(gg$phic, gg$pgene, gg$psnp, gg$ptad, ncol = 1, nrow = 4,heights = c(6.5,1.5, 1, 1)) print(final)