From 9defa26c144c763ed4617ee9d0da78c425007f22 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 26 Mar 2018 15:29:04 -0400 Subject: [PATCH 01/65] now disabling all inputs during run --- apps/LOLAweb/app.R | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 041da0b..ed5ad05 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -277,7 +277,21 @@ server <- function(input, output, session) { }) observeEvent(input$run, { - + + # disable runLOLA button while processing + shinyjs::disable("run") + shinyjs::disable("userset") + shinyjs::disable("universe") + shinyjs::disable("loladb") + shinyjs::disable("button_userset_example") + shinyjs::disable("refgenome") + shinyjs::disable("defaultuniverse") + shinyjs::disable("useruniverse") + shinyjs::disable("checkbox") + shinyjs::disable("button_userset_upload") + shinyjs::disable("defaultuserset") + + withCallingHandlers({ shinyjs::html(id = "messages", html = "") shinyjs::html(id = "gear", html = "", add = FALSE) @@ -503,6 +517,19 @@ server <- function(input, output, session) { instruction = { cipher }, noload = TRUE) + # re-enable runLOLA button while processing + shinyjs::enable("run") + shinyjs::enable("userset") + shinyjs::enable("universe") + shinyjs::enable("loladb") + shinyjs::enable("button_userset_example") + shinyjs::enable("refgenome") + shinyjs::enable("defaultuniverse") + shinyjs::enable("useruniverse") + shinyjs::enable("checkbox") + shinyjs::enable("button_userset_upload") + shinyjs::enable("defaultuserset") + return(res) From ad48de142c33fc54a851b8661253672386dfab29 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 26 Mar 2018 15:44:37 -0400 Subject: [PATCH 02/65] disabling other elements when viewing cached result --- apps/LOLAweb/app.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index ed5ad05..128e82d 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -595,7 +595,9 @@ server <- function(input, output, session) { shinyjs::disable("defaultuniverse") shinyjs::disable("useruniverse") shinyjs::disable("checkbox") - + shinyjs::disable("button_userset_upload") + shinyjs::disable("defaultuserset") + # show results message on run tab shinyjs::show("noinputmsg") From 137dc1e144acf2a2f3f2cbbfcd46e2a123ed9296 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 26 Mar 2018 16:58:24 -0400 Subject: [PATCH 03/65] more robust disabling of inputs --- apps/LOLAweb/app.R | 46 ++++++-------------------------------- apps/LOLAweb/www/style.css | 7 +++++- 2 files changed, 13 insertions(+), 40 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 128e82d..44d4032 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -92,9 +92,11 @@ ui <- list( actionButton("run", "RUN LOLA", class = "runLOLA"), - HTML("
Sample Results
") + HTML("") ), - class = "headerBox"), + # class = "headerBox", id = "runInputs"), + id = "runInputs"), + fluidRow( column(2, htmlOutput("gear")), @@ -279,18 +281,7 @@ server <- function(input, output, session) { observeEvent(input$run, { # disable runLOLA button while processing - shinyjs::disable("run") - shinyjs::disable("userset") - shinyjs::disable("universe") - shinyjs::disable("loladb") - shinyjs::disable("button_userset_example") - shinyjs::disable("refgenome") - shinyjs::disable("defaultuniverse") - shinyjs::disable("useruniverse") - shinyjs::disable("checkbox") - shinyjs::disable("button_userset_upload") - shinyjs::disable("defaultuserset") - + shinyjs::runjs("$('#runInputs').addClass('disabledinputs');") withCallingHandlers({ shinyjs::html(id = "messages", html = "") @@ -517,19 +508,6 @@ server <- function(input, output, session) { instruction = { cipher }, noload = TRUE) - # re-enable runLOLA button while processing - shinyjs::enable("run") - shinyjs::enable("userset") - shinyjs::enable("universe") - shinyjs::enable("loladb") - shinyjs::enable("button_userset_example") - shinyjs::enable("refgenome") - shinyjs::enable("defaultuniverse") - shinyjs::enable("useruniverse") - shinyjs::enable("checkbox") - shinyjs::enable("button_userset_upload") - shinyjs::enable("defaultuserset") - return(res) @@ -586,18 +564,8 @@ server <- function(input, output, session) { rawdat_res$run_sum <- res$run_sum # disable all buttons in header when query is good - shinyjs::disable("run") - shinyjs::disable("userset") - shinyjs::disable("universe") - shinyjs::disable("loladb") - shinyjs::disable("button_userset_example") - shinyjs::disable("refgenome") - shinyjs::disable("defaultuniverse") - shinyjs::disable("useruniverse") - shinyjs::disable("checkbox") - shinyjs::disable("button_userset_upload") - shinyjs::disable("defaultuserset") - + shinyjs::runjs("$('#runInputs').addClass('disabledinputs');") + # show results message on run tab shinyjs::show("noinputmsg") diff --git a/apps/LOLAweb/www/style.css b/apps/LOLAweb/www/style.css index 92404bc..b51f68d 100644 --- a/apps/LOLAweb/www/style.css +++ b/apps/LOLAweb/www/style.css @@ -9,7 +9,7 @@ } -.headerBox { +#runInputs { min-height: 20px; padding: 19px; margin-bottom: 20px; @@ -29,4 +29,9 @@ #button_userset_upload { margin-top: 20px; +} + +.disabledinputs { + pointer-events: none; + opacity: 0.4; } \ No newline at end of file From 7c1a896c42bb458984ef592f3198579061317e63 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Tue, 27 Mar 2018 12:01:10 -0400 Subject: [PATCH 04/65] no longer hardcoding db names by refgenome choice --- apps/LOLAweb/app.R | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 44d4032..586c934 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -343,15 +343,13 @@ server <- function(input, output, session) { output$loladbs <- renderUI({ - if(input$refgenome == "mm10") { - - selectInput("loladb", label = "", choices = c("Core")) - - } else { - - selectInput("loladb", label = "", choices = c("Core", "LOLAJaspar", "LOLARoadmap")) - - } + fl <- grep(input$refgenome, + list.files("reference", recursive = TRUE), + value = TRUE) + + dbs <- unique(gsub("(.*?)(/.*)", "\\1", fl)) + + selectInput("loladb", label = "", choices = dbs) }) From c781ab027683ce2216894248668711f8fa2a6a51 Mon Sep 17 00:00:00 2001 From: nem2p Date: Thu, 29 Mar 2018 11:55:36 -0400 Subject: [PATCH 05/65] Deployment test --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 89e3475..68f9017 100644 --- a/docker/README.md +++ b/docker/README.md @@ -17,7 +17,7 @@ ## Reference Data -See the [LOLAweb documentation](https://github.com/databio/LOLAweb/tree/master/apps/LOLAweb) for retrieving reference data. +See the [LOLAweb documentation](https://github.com/databio/LOLAweb/tree/master/apps/LOLAweb) for downloading reference data. ## `run` the LOLAweb container locally with reference data: From 8e509328aefe9f3e06f07f9039da0d0c1440e514 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Fri, 6 Apr 2018 10:01:33 -0400 Subject: [PATCH 06/65] first pass at interactive scatterplot and tabset layout for results --- apps/LOLAweb/app.R | 116 ++++++++++++++++++++++++++--------------- apps/LOLAweb/scratch.R | 79 ++++++++++++++++++++++++---- 2 files changed, 143 insertions(+), 52 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 586c934..3e0299b 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -12,6 +12,7 @@ library(simpleCache) library(sodium) library(shinyBS) library(GenomicDistributions) +library(plotly) setCacheDir("cache") @@ -104,37 +105,35 @@ ui <- list( htmlOutput("messages")) )), tabPanel("Results", - fluidRow(div(HTML("
Results is currently empty.
To generate result output, visit Run or view sample results.
"), id = "noresultsmsg") - ), + fluidRow(div(HTML("
Results is currently empty.
To generate result output, visit Run or view sample results.
"), id = "noresultsmsg") + ), + fluidRow( + column(10, + tags$h4(htmlOutput("link")), + shinyjs::hidden(htmlOutput("gear2")) + ) + ), + fluidRow(column(2, + shinyjs::hidden( + tags$div( + h4("Display Options", + actionLink("infodisplay", "", icon = icon("question-circle-o"))), + id = "infodisplay_div" + )), + uiOutput("slider_rank"), + uiOutput("slider_oddsratio"), + uiOutput("slider_support"), + uiOutput("slider_pvalue"), + uiOutput("select_collection"), + uiOutput("select_sort"), + uiOutput("select_userset")), + column(10, + # shinyjs::hidden( + tabsetPanel(type = "tabs", + tabPanel("Scatterplot", + plotlyOutput("scatter")), + tabPanel("Histograms", fluidRow( - column(2, - shinyjs::hidden( - tags$div( - h4("Display Options", - actionLink("infodisplay", "", icon = icon("question-circle-o"))), - id = "infodisplay_div" - ) - ), - uiOutput("slider_rank"), - uiOutput("slider_oddsratio"), - uiOutput("slider_support"), - uiOutput("slider_pvalue"), - uiOutput("select_collection"), - uiOutput("select_sort"), - uiOutput("select_userset"), - conditionalPanel(condition = "output.res", - h4("Run Summary"), - tableOutput("run_sum"), style = "font-size:10px;") - ), - column(10, - tags$h4(htmlOutput("link")), - shinyjs::hidden( - tags$div( - h2("LOLA Results", - actionLink("infoplot", "", icon = icon("question-circle-o"))), - id = "infoplot_div")), - shinyjs::hidden(htmlOutput("gear2")) - ), column(5, conditionalPanel(condition = "output.res", h4("Odds Ratio"), @@ -155,7 +154,11 @@ ui <- list( downloadButton("pvalue_plot_dl", label = "Download Plot", class = "dt-button")), - plotOutput("pvalue_plot"), + plotOutput("pvalue_plot") + ) + ) + ), + tabPanel("Distribution", conditionalPanel(condition = "output.res", h4("Distribution over genome"), downloadButton("distrib_plot_dl", @@ -167,12 +170,19 @@ ui <- list( downloadButton("dist_plot_dl", label = "Download Plot", class = "dt-button")), - plotOutput("dist_plot") - ) - ), - fluidRow( - column(DT::dataTableOutput("res"), width = 12) - ) + plotOutput("dist_plot")), + tabPanel("Run Summary", + conditionalPanel(condition = "output.res", + h4("Run Summary"), + tableOutput("run_sum"), style = "font-size:18px;") + ), + id = "result-tabs") + # ) + ) + ), + fluidRow( + column(DT::dataTableOutput("res"), width = 12) + ) ), tabPanel("About", includeHTML("about.html") @@ -600,6 +610,7 @@ server <- function(input, output, session) { } else { shinyjs::hide("gear2") + # shinyjs::show("result-tabs") } @@ -717,15 +728,15 @@ server <- function(input, output, session) { data.frame( x = - c("Start ", - "End ", - "Elapsed", - "Cache ", + c("Start Time ", + "End Time ", + "Elapsed Time ", + "Cache ID ", "Regions ", "Genome ", "Universe ", "Database ", - "Commit "), + "LOLAweb Commit Used "), y = c(as.character(rawdat_res$run_sum$start_time), as.character(rawdat_res$run_sum$end_time), @@ -741,6 +752,27 @@ server <- function(input, output, session) { }, spacing = "s", colnames = FALSE, align = "l") + output$scatter <- renderPlotly({ + + req(input$select_collection_i) + + q <- + ggplot(dat(), aes(pValueLog, oddsRatio, size = log(support), + text = paste0("Collection: ", + collection, + "\n", + "Description: ", + axis_label))) + + geom_point() + + xlab("P Value Log") + + ylab("Odds Ratio") + + geom_blank(aes(text = collection)) + + theme_ns() + + ggplotly(q) + + }) + # call plot output$oddsratio_plot <- renderPlot({ diff --git a/apps/LOLAweb/scratch.R b/apps/LOLAweb/scratch.R index 117a602..3b2da0f 100644 --- a/apps/LOLAweb/scratch.R +++ b/apps/LOLAweb/scratch.R @@ -266,17 +266,76 @@ x <- system.time({ }) -userSet = readBed(file = "lola_vignette_data/setB_100.bed") -dbPath = "reference/Core/hg38/" -regionDB = loadRegionDB(dbLocation=dbPath) -userUniverse = readBed("universes/hg38/tiles.hg38.5000.bed") -userUniverse = read.table(file = "universes/hg38/tiles.hg38.5000.bed", header = F) -colnames(userUniverse) <- c('chr','start','end','id','score','strand') -userUniverse <- with(userUniverse, GRanges(chr, IRanges(start+1, end), strand, score, id=id)) +##### ggplotly -userSetsRedefined = redefineUserSets(userSet, userUniverse) +# userSet = readBed(file = "lola_vignette_data/setB_100.bed") +# dbPath = "reference/Core/hg19/" +# regionDB = loadRegionDB(dbLocation=dbPath) +# +# userUniverse = readBed("universes/hg19/tiles1000.hg19.bed") +# # userUniverse = read.table(file = "universes/hg38/tiles.hg38.5000.bed", header = F) +# # colnames(userUniverse) <- c('chr','start','end','id','score','strand') +# # userUniverse <- with(userUniverse, GRanges(chr, IRanges(start+1, end), strand, score, id=id)) +# +# userSetsRedefined = redefineUserSets(userSet, userUniverse) +# +# +# resRedefined = runLOLA(userSetsRedefined, userUniverse, regionDB, cores=1) +library(sodium) -resRedefined = runLOLA(userSetsRedefined, userUniverse, regionDB, cores=1) - \ No newline at end of file +keyphrase <- "486TQ3MHFJPU2D9" +loadCaches(keyphrase, assignToVariable = "cipher", loadEnvir = globalenv(), cacheDir = "cache") + +cipher <- get("cipher", envir = globalenv()) + +# keyphrase +key <- hash(charToRaw(keyphrase)) + +dat <- data_decrypt(cipher, key) + +res <- unserialize(dat) + +res$resRedefined$id <- paste(res$resRedefined$description, res$resRedefined$dbSet, sep = "_") +res$resRedefined$axis_label <- strtrim(res$resRedefined$description, 50) + +library(magrittr) + +p <- + res$resRedefined %>% + filter(maxRnk < 90) %>% + arrange(desc(meanRnk)) %>% + # ggplot(aes(description, eval(parse(text = "meanRnk")), oddsRatio, fill = userSet, group = id)) + + ggplot(aes(reorder(axis_label, eval(parse(text = "meanRnk"))), rev(oddsRatio), fill = userSet, group = id)) + + # ggplot(aes(reorder(axis_label, eval(parse(text = "maxRnk"))), oddsRatio, fill = userSet, group = id)) + + geom_bar(stat = "identity", position = "dodge") + + xlab("Description") + + ylab("Odds Ratio") + + coord_flip() + + theme_ns() + +library(plotly) + +ggplotly(p) + + +q <- + res$resRedefined %>% + filter(maxRnk < 100) %>% + arrange(desc(meanRnk)) %>% + ggplot(aes(pValueLog, oddsRatio, size = log(support), + text = paste0("Collection: ", + collection, + "\n", + "Description: ", + axis_label))) + + geom_point() + + xlab("P Value Log") + + ylab("Odds Ratio") + + # coord_flip() + + geom_blank(aes(text = collection)) + + theme_ns() + + theme(legend.position = "right") + +ggplotly(q, tooltip = c("x", "y", "size", "text")) From 825b20a4a37f9f76d98d697e9c14b0282e8b8c8a Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Fri, 6 Apr 2018 13:36:40 -0400 Subject: [PATCH 07/65] now putting data table in its own tab --- apps/LOLAweb/app.R | 19 +++++++------------ apps/LOLAweb/scratch.R | 5 ++++- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 3e0299b..61b526a 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -135,11 +135,10 @@ ui <- list( tabPanel("Histograms", fluidRow( column(5, - conditionalPanel(condition = "output.res", h4("Odds Ratio"), downloadButton("oddsratio_plot_dl", label = "Download Plot", - class = "dt-button")), + class = "dt-button"), plotOutput("oddsratio_plot"), conditionalPanel(condition = "output.res", h4("Support"), @@ -149,39 +148,35 @@ ui <- list( plotOutput("support_plot") ), column(5, - conditionalPanel(condition = "output.res", h4("P Value"), downloadButton("pvalue_plot_dl", label = "Download Plot", - class = "dt-button")), + class = "dt-button"), plotOutput("pvalue_plot") ) ) ), tabPanel("Distribution", - conditionalPanel(condition = "output.res", h4("Distribution over genome"), downloadButton("distrib_plot_dl", label = "Download Plot", - class = "dt-button")), + class = "dt-button"), plotOutput("distrib_plot"), - conditionalPanel(condition = "output.res", h4("Distance to TSS"), downloadButton("dist_plot_dl", label = "Download Plot", - class = "dt-button")), + class = "dt-button"), plotOutput("dist_plot")), + tabPanel("Table", + column(DT::dataTableOutput("res"), width = 12) + ), tabPanel("Run Summary", conditionalPanel(condition = "output.res", h4("Run Summary"), tableOutput("run_sum"), style = "font-size:18px;") ), id = "result-tabs") - # ) ) - ), - fluidRow( - column(DT::dataTableOutput("res"), width = 12) ) ), tabPanel("About", diff --git a/apps/LOLAweb/scratch.R b/apps/LOLAweb/scratch.R index 3b2da0f..b518233 100644 --- a/apps/LOLAweb/scratch.R +++ b/apps/LOLAweb/scratch.R @@ -336,6 +336,9 @@ q <- # coord_flip() + geom_blank(aes(text = collection)) + theme_ns() + - theme(legend.position = "right") + theme(legend.position = "bottom") ggplotly(q, tooltip = c("x", "y", "size", "text")) + +ggplotly(q, tooltip = c("x", "y", "size")) %>% + layout(showlegend = TRUE, legendgroup = "size") From 0ab7e189b6511369185baaafb0b3f71f5fc74526 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 9 Apr 2018 18:00:56 -0400 Subject: [PATCH 08/65] cleaning up some old code --- apps/LOLAweb/app.R | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 61b526a..bd273aa 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -397,9 +397,6 @@ server <- function(input, output, session) { for (i in 1:length(input$userset[,1])) { - # userSet <- read.table(input$userset[[i, 'datapath']], header = F) - # colnames(userSet) <- c('chr','start','end','id','score','strand') - # userSet <- with(userSet, GRanges(chr, IRanges(start+1, end), strand, score, id=id)) userSet = readBed(input$userset[[i, 'datapath']]) userSets[[i]] <- userSet @@ -415,10 +412,6 @@ server <- function(input, output, session) { datapath <- paste0("userSets/", input$defaultuserset) - # userSet = read.table(file = datapath, header = F) - # colnames(userSet) <- c('chr','start','end','id','score','strand') - # userSet <- with(userSet, GRanges(chr, IRanges(start+1, end), strand, score, id=id)) - userSet = readBed(datapath) userSets[[1]] <- userSet @@ -440,15 +433,12 @@ server <- function(input, output, session) { datapath <- paste0("universes/", input$refgenome, "/", input$defaultuniverse) - # userUniverse = read.table(file = datapath, header = F) userUniverse = readBed(file = datapath) universename <- input$defaultuniverse } - # colnames(userUniverse) <- c('chr','start','end','id','score','strand') - # userUniverse <- with(userUniverse, GRanges(chr, IRanges(start+1, end), strand, score, id=id)) userSetsRedefined = redefineUserSets(userSets, userUniverse) From d2eb3ffedabf4265eaa8f69e657349c3e5d57266 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 9 Apr 2018 19:02:05 -0400 Subject: [PATCH 09/65] now hiding tabset panel initially on result page --- apps/LOLAweb/app.R | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index bd273aa..6aade2f 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -128,7 +128,8 @@ ui <- list( uiOutput("select_sort"), uiOutput("select_userset")), column(10, - # shinyjs::hidden( + shinyjs::hidden( + div( tabsetPanel(type = "tabs", tabPanel("Scatterplot", plotlyOutput("scatter")), @@ -174,9 +175,9 @@ ui <- list( conditionalPanel(condition = "output.res", h4("Run Summary"), tableOutput("run_sum"), style = "font-size:18px;") - ), - id = "result-tabs") - ) + ) + ), + id = "result-tabs"))) ) ), tabPanel("About", @@ -569,11 +570,15 @@ server <- function(input, output, session) { selected = "Results") shinyjs::show("gear2") - + shinyjs::show("result-tabs") + + # show help text for results sliders and plots shinyjs::show("infoplot_div") shinyjs::show("infodisplay_div") shinyjs::show("run_sum") + + } else { @@ -595,8 +600,7 @@ server <- function(input, output, session) { } else { shinyjs::hide("gear2") - # shinyjs::show("result-tabs") - + } }) @@ -754,6 +758,8 @@ server <- function(input, output, session) { geom_blank(aes(text = collection)) + theme_ns() + plot_render$state <- TRUE + ggplotly(q) }) @@ -763,8 +769,6 @@ server <- function(input, output, session) { req(input$select_sort_i) - plot_render$state <- TRUE - plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) }) From e1743678dbb8d466eced6aea64b56e575b311b6b Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 9 Apr 2018 19:47:27 -0400 Subject: [PATCH 10/65] histograms are now interactive --- apps/LOLAweb/app.R | 88 +++++++++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 6aade2f..ebdcbba 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -136,24 +136,25 @@ ui <- list( tabPanel("Histograms", fluidRow( column(5, - h4("Odds Ratio"), - downloadButton("oddsratio_plot_dl", - label = "Download Plot", - class = "dt-button"), - plotOutput("oddsratio_plot"), - conditionalPanel(condition = "output.res", - h4("Support"), - downloadButton("support_plot_dl", - label = "Download Plot", - class = "dt-button")), - plotOutput("support_plot") + # h4("Odds Ratio"), + # downloadButton("oddsratio_plot_dl", + # label = "Download Plot", + # class = "dt-button"), + # plotOutput("oddsratio_plot"), + plotlyOutput("oddsratio_plot"), + # conditionalPanel(condition = "output.res", + # h4("Support"), + # downloadButton("support_plot_dl", + # label = "Download Plot", + # class = "dt-button")), + plotlyOutput("support_plot") ), column(5, - h4("P Value"), - downloadButton("pvalue_plot_dl", - label = "Download Plot", - class = "dt-button"), - plotOutput("pvalue_plot") + # h4("P Value"), + # downloadButton("pvalue_plot_dl", + # label = "Download Plot", + # class = "dt-button"), + plotlyOutput("pvalue_plot") ) ) ), @@ -764,15 +765,28 @@ server <- function(input, output, session) { }) + # # call plot + # output$oddsratio_plot <- renderPlot({ + # + # req(input$select_sort_i) + # + # plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) + # + # }) + # call plot - output$oddsratio_plot <- renderPlot({ + output$oddsratio_plot <- renderPlotly({ req(input$select_sort_i) - plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) - + p <- plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) + + ggplotly(p) %>% + layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) + }) + # download handler output$oddsratio_plot_dl <- downloadHandler( filename = function() { paste("oddsratio", @@ -799,11 +813,22 @@ server <- function(input, output, session) { }) - output$support_plot <- renderPlot({ + # output$support_plot <- renderPlot({ + # + # req(input$select_sort_i) + # + # plot_input(dat(), "support", "Support", input$select_sort_i) + # + # }) + + output$support_plot <- renderPlotly({ req(input$select_sort_i) - plot_input(dat(), "support", "Support", input$select_sort_i) + p <- plot_input(dat(), "support", "Support", input$select_sort_i) + + ggplotly(p) %>% + layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) }) @@ -835,12 +860,24 @@ server <- function(input, output, session) { }) - output$pvalue_plot <- renderPlot({ + # output$pvalue_plot <- renderPlot({ + # + # req(input$select_sort_i) + # + # plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) + # + # + # }) + + output$pvalue_plot <- renderPlotly({ req(input$select_sort_i) plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) + ggplotly(p) %>% + layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) + }) @@ -865,13 +902,14 @@ server <- function(input, output, session) { } output$distrib_plot <- renderPlot({ - + req(input$select_sort_i) - + distrib_plot_input() - + }) + # feature distance plot dist_plot_input <- function() { From 690502788c2071cb3cc23a3cb5a670bc59aab44c Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Tue, 10 Apr 2018 16:20:13 -0400 Subject: [PATCH 11/65] added genomic distribution partition plot and made histograms full layout --- apps/LOLAweb/app.R | 92 +++++++++++++++++++++++++++++++++--------- apps/LOLAweb/scratch.R | 22 +++++++++- 2 files changed, 93 insertions(+), 21 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index ebdcbba..760603e 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -134,8 +134,8 @@ ui <- list( tabPanel("Scatterplot", plotlyOutput("scatter")), tabPanel("Histograms", - fluidRow( - column(5, + # fluidRow( + # column(10, # h4("Odds Ratio"), # downloadButton("oddsratio_plot_dl", # label = "Download Plot", @@ -147,28 +147,41 @@ ui <- list( # downloadButton("support_plot_dl", # label = "Download Plot", # class = "dt-button")), - plotlyOutput("support_plot") - ), - column(5, + plotlyOutput("support_plot"), + # ), + # column(5, # h4("P Value"), # downloadButton("pvalue_plot_dl", # label = "Download Plot", # class = "dt-button"), plotlyOutput("pvalue_plot") - ) - ) + # ) + # ) ), tabPanel("Distribution", - h4("Distribution over genome"), - downloadButton("distrib_plot_dl", - label = "Download Plot", - class = "dt-button"), - plotOutput("distrib_plot"), - h4("Distance to TSS"), - downloadButton("dist_plot_dl", - label = "Download Plot", - class = "dt-button"), - plotOutput("dist_plot")), + fluidRow( + column(10, + h4("Distribution over genome"), + downloadButton("distrib_plot_dl", + label = "Download Plot", + class = "dt-button"), + plotOutput("distrib_plot")) + ), + fluidRow( + column(5, + h4("Distance to TSS"), + downloadButton("dist_plot_dl", + label = "Download Plot", + class = "dt-button"), + plotOutput("dist_plot")), + column(5, + h4("Genomic Partitions"), + downloadButton("part_plot_dl", + label = "Download Plot", + class = "dt-button"), + plotOutput("part_plot")) + ) + ), tabPanel("Table", column(DT::dataTableOutput("res"), width = 12) ), @@ -470,6 +483,8 @@ server <- function(input, output, session) { # calculate distances to TSSs TSSDist = TSSDistance(userSets, input$refgenome) + # distribution of overlaps for a query set to genomic partitions + gp = genomicPartitions(userSets, input$refgenome) }) @@ -490,7 +505,8 @@ server <- function(input, output, session) { res = list(resRedefined = resRedefined, genDist = genDist, TSSDist = TSSDist, - run_sum = run_sum) + run_sum = run_sum, + gp = gp) # caching # need to call keyphrase from reactive above because it is used to construct link @@ -556,6 +572,8 @@ server <- function(input, output, session) { rawdat_res$TSSDist <- res$TSSDist + rawdat_res$gp <- res$gp + rawdat_res$run_sum <- res$run_sum # disable all buttons in header when query is good @@ -586,6 +604,7 @@ server <- function(input, output, session) { rawdat_res$rawdat <- rawdat_nocache()$resRedefined rawdat_res$genDist <- rawdat_nocache()$genDist rawdat_res$TSSDist <- rawdat_nocache()$TSSDist + rawdat_res$gp <- rawdat_nocache()$gp rawdat_res$run_sum <- rawdat_nocache()$run_sum } @@ -873,7 +892,7 @@ server <- function(input, output, session) { req(input$select_sort_i) - plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) + p <- plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) ggplotly(p) %>% layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) @@ -926,6 +945,32 @@ server <- function(input, output, session) { dist_plot_input() }) + + # partitions plot + part_plot_input <- function() { + + gp <- rawdat_res$gp + + if(is.null(gp)) { + + NULL + + } else { + + plotPartitions(gp) + + } + + + } + + output$part_plot <- renderPlot({ + + req(input$select_sort_i) + + part_plot_input() + + }) # download handler output$distrib_plot_dl <- downloadHandler( @@ -946,6 +991,15 @@ server <- function(input, output, session) { } ) + output$part_plot_dl <- downloadHandler( + filename = function() { paste("paritions", + ".pdf", + sep="") }, + content = function(file) { + ggsave(file, plot = part_plot_input(), device = "pdf") + } + ) + # data table diff --git a/apps/LOLAweb/scratch.R b/apps/LOLAweb/scratch.R index b518233..e75a1a0 100644 --- a/apps/LOLAweb/scratch.R +++ b/apps/LOLAweb/scratch.R @@ -126,11 +126,26 @@ query = read.table(file = "lola_vignette_data/setC_complete.bed", header = F) colnames(query) = c('chr','start','end','id','score','strand') query = with(query, GRanges(chr, IRanges(start+1, end), strand, score, id=id)) -x = genomicDistribution(query, "hg19") +query = readBed("lola_vignette_data/setC_complete.bed") + +x = aggregateOverGenomeBins(query, "hg19") # Then, plot the result: -plotGenomicDist(x) +p <- + plotGenomeAggregate(x) + +ggplotly(p) + +y <- + TSSDistance(query, "hg19") + +q <- + plotFeatureDist(y) +ggplotly(q) + +gp = genomicPartitions(query, "hg19") +plotPartitions(gp) EnsDb = loadEnsDb("hg19") @@ -342,3 +357,6 @@ ggplotly(q, tooltip = c("x", "y", "size", "text")) ggplotly(q, tooltip = c("x", "y", "size")) %>% layout(showlegend = TRUE, legendgroup = "size") + + + From e3aaef7c2306318ceada30cdcfb32eeac349e493 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Wed, 11 Apr 2018 15:36:09 -0400 Subject: [PATCH 12/65] changed sample results cache link --- apps/LOLAweb/app.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 760603e..a492056 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -93,7 +93,7 @@ ui <- list( actionButton("run", "RUN LOLA", class = "runLOLA"), - HTML("") + HTML("") ), # class = "headerBox", id = "runInputs"), id = "runInputs"), @@ -105,7 +105,7 @@ ui <- list( htmlOutput("messages")) )), tabPanel("Results", - fluidRow(div(HTML("
Results is currently empty.
To generate result output, visit Run or view sample results.
"), id = "noresultsmsg") + fluidRow(div(HTML("
Results is currently empty.
To generate result output, visit Run or view sample results.
"), id = "noresultsmsg") ), fluidRow( column(10, From 22c88ccbae521c4aad3ae151d778567ab61a7460 Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 12 Apr 2018 14:05:41 -0400 Subject: [PATCH 13/65] Add universe docs --- apps/LOLAweb/about.html | 23 +- apps/LOLAweb/universe_selection.svg | 1407 +++++++++++++++++++++++++++ 2 files changed, 1429 insertions(+), 1 deletion(-) create mode 100644 apps/LOLAweb/universe_selection.svg diff --git a/apps/LOLAweb/about.html b/apps/LOLAweb/about.html index 0f19ab5..c2c330d 100644 --- a/apps/LOLAweb/about.html +++ b/apps/LOLAweb/about.html @@ -6,6 +6,7 @@ @@ -26,10 +27,30 @@

How do I use LOLAweb?

Hit "Run LOLA" and watch the magic happen! The results will be displayed as an interactive interface letting you sort and filter the top hits. The schematic below demonstrates the whole process:

- LOLAweb worfklow + LOLAweb workflow
+

What universe should I choose?

+ +

One of the key questions when you run LOLA is what your background set, or "universe" is. The universe is a bit open-ended, and it's reasonable to try a few different things. Changing the universe isn't right or wrong, it just changes the question you are asking. The universe set is tested for overlap with the database, and the counts are used in the contingency tables that determine significance for your user sets. The reason this is important is that if you have some regions which were never really possible to end up in a region set of interest, it's unfair to penalize your regions for not overlapping those regions in the database, changing the results of the significance test.

+ + + +

Let's imagine you've done an experiment where you're testing how some epigenomic signal (say, H3K27ac or DNA methylation) responds to a perturbation. You end up with a set of genomic regions that were covered by your assay, along with two subsets of interest: those that increased, and those that decreased in signal (see figure).

+ +

In this case, one approach is to think of this as two user query sets: one for each subset of regions that change. Now, what should your universe be? Well, you have a few options. Let's go through 4 common universe choices see what they mean about the significance test you're performing. The four choices move in increasing order of specificity: + +

Choice 1: genome tiles. LOLAweb lets you choose tiling regions of various sizes. These tiles are little better than generic splits of the genome because they at least account for reference assembly gaps. But otherwise, this is a pretty basic background set which doesn't restrict the question at all. This would be a useful universe to choose if you are not sure what to expect, and your experiment could have included any genomic region as output. The result will tell you what database region sets are enriched in your query sets generally, across the whole genome.

+ +

Choice 2: any regulatory elements. A bit more restricted universe set is the set of active regulatory elements. LOLAweb includes a manually curated universe set that was derived by merging all of the DNAse hypersensitivity data from over 100 cell types from the ENCODE project. This set will restrict your significance test to only active regulatory elements, so it's a reasonable background set if you're looking at ChIP-seq data or some other active signal, but may not be relevant for every experiment type. In practice, we find this to be a useful first pass test for many experiments. Relative to the tiling approach, this, for example, won't penalize your overlap test for not overlapping a database region that's hidden away in a heterochromatic region. It yields which database region sets are enriched in your query set, but only considering active parts of the genome. An advantage of this approach is that it's easy: we've already defined that set for you and you can just select it. A disadvantage is that you're restricted to elements that were covered in the considered cell types (although, offsetting that is the point that really specialized stuff is less likely to be in the database, anyway).

+ +

Choice 3: all regions covered. Probably a better choice (though requiring a bit more work) is to derive the universe from your actual data. The natural choice would be to use the set of regions your experiment actually covered. You can think of this universe as the set of regions you tested for possible inclusion in your user sets; or, in other words, it is the restricted background set of regions that were tested, including everything in your regions of interest as well as those that were tested but did not get included. If you can easily come up with such a test for your problem, this is a really good choice for background universe. The resulting test will give you overlaps with database regions without penalizing for areas that weren't even covered in your experiment anyway. This asks: what's special about my regions that increased, versus all the regions that didn't?

+ +

Choice 4: changing regions only Finally, you could make a very restrictive universe by just combining your two region sets of interest. In this case, it would be the set of regions that either increased or decreased. The result of this test will give you the enrichment of the increased regions relative to changing regions. This is a subtly different question to ask than using the set of all covered regions (choice 3). It assumes that we're only interested in regions that change, then we ask the question: what's special about the ones that increased?

+ +

In the case of DNA methylation: all regions that had reasonable coverage of methylation reads are your universe, and those that were either highly methylated or lowly methylated (or differentially methylated) would be your subsets of interest. It's the set including all genes that had enough reads that they could have been differentially methylated, even if they weren't.

+

Can I share my LOLAweb results with others?

Yes! Once you run your region sets through LOLAweb, you are redirected to a web page unique to your data. It will look something like this:

diff --git a/apps/LOLAweb/universe_selection.svg b/apps/LOLAweb/universe_selection.svg new file mode 100644 index 0000000..10df12d --- /dev/null +++ b/apps/LOLAweb/universe_selection.svg @@ -0,0 +1,1407 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + Subset that increased + Subset that decreased + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Regions with signal + 1. Tiles + 3. All regions covered + + + + + + + + + + + + + + + + + + + + 4. Changing regions only + + + + + + + + + + + + + + 2. Any regulatory elements + + + + + + + + + + + + + + + + + + + + + + + + + + + + Universe options + Experimental data + + From 72569039fa9e92db3261c87659950abc0639d11a Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 12 Apr 2018 14:15:04 -0400 Subject: [PATCH 14/65] Add dockerhub link --- docker/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/README.md b/docker/README.md index 68f9017..1e2ca0e 100644 --- a/docker/README.md +++ b/docker/README.md @@ -14,6 +14,8 @@ ```docker pull databio/lolaweb``` +The image itself is hosted at dockerhub: https://hub.docker.com/r/databio/lolaweb/ + ## Reference Data From bd731f05ddb732f5f314cb7a7bf27b7bfb3ab2db Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Thu, 12 Apr 2018 14:43:39 -0400 Subject: [PATCH 15/65] download plot text now says PDF; reverting to static histograms --- apps/LOLAweb/app.R | 138 +++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 67 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index a492056..d05b17d 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -135,27 +135,32 @@ ui <- list( plotlyOutput("scatter")), tabPanel("Histograms", # fluidRow( - # column(10, - # h4("Odds Ratio"), - # downloadButton("oddsratio_plot_dl", - # label = "Download Plot", - # class = "dt-button"), - # plotOutput("oddsratio_plot"), - plotlyOutput("oddsratio_plot"), + column(5, + div( + h4("Odds Ratio"), + downloadButton("oddsratio_plot_dl", + label = "PDF", + class = "dt-button"), + style ="display:inline-block;"), + plotOutput("oddsratio_plot"), + # plotlyOutput("oddsratio_plot"), # conditionalPanel(condition = "output.res", - # h4("Support"), - # downloadButton("support_plot_dl", - # label = "Download Plot", - # class = "dt-button")), - plotlyOutput("support_plot"), - # ), - # column(5, - # h4("P Value"), - # downloadButton("pvalue_plot_dl", - # label = "Download Plot", - # class = "dt-button"), - plotlyOutput("pvalue_plot") - # ) + h4("Support"), + downloadButton("support_plot_dl", + label = "PDF", + class = "dt-button"), + # plotlyOutput("support_plot"), + plotOutput("support_plot") + + ), + column(5, + h4("P Value"), + downloadButton("pvalue_plot_dl", + label = "PDF", + class = "dt-button"), + # plotlyOutput("pvalue_plot") + plotOutput("pvalue_plot") + ) # ) ), tabPanel("Distribution", @@ -163,7 +168,7 @@ ui <- list( column(10, h4("Distribution over genome"), downloadButton("distrib_plot_dl", - label = "Download Plot", + label = "PDF", class = "dt-button"), plotOutput("distrib_plot")) ), @@ -171,13 +176,13 @@ ui <- list( column(5, h4("Distance to TSS"), downloadButton("dist_plot_dl", - label = "Download Plot", + label ="PDF", class = "dt-button"), plotOutput("dist_plot")), column(5, h4("Genomic Partitions"), downloadButton("part_plot_dl", - label = "Download Plot", + label = "PDF", class = "dt-button"), plotOutput("part_plot")) ) @@ -438,7 +443,6 @@ server <- function(input, output, session) { if(input$checkbox) { - # userUniverse = read.table(file = input$useruniverse$datapath, header = F) userUniverse = readBed(file = input$useruniverse$datapath) @@ -784,27 +788,27 @@ server <- function(input, output, session) { }) + # call plot + output$oddsratio_plot <- renderPlot({ + + req(input$select_sort_i) + + plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) + + }) + # # call plot - # output$oddsratio_plot <- renderPlot({ + # output$oddsratio_plot <- renderPlotly({ # # req(input$select_sort_i) # - # plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) - # + # p <- plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) + # + # ggplotly(p) %>% + # layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) + # # }) - - # call plot - output$oddsratio_plot <- renderPlotly({ - - req(input$select_sort_i) - - p <- plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) - - ggplotly(p) %>% - layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) - - }) - + # # download handler output$oddsratio_plot_dl <- downloadHandler( @@ -832,25 +836,25 @@ server <- function(input, output, session) { }) - # output$support_plot <- renderPlot({ + output$support_plot <- renderPlot({ + + req(input$select_sort_i) + + plot_input(dat(), "support", "Support", input$select_sort_i) + + }) + + # output$support_plot <- renderPlotly({ # # req(input$select_sort_i) # - # plot_input(dat(), "support", "Support", input$select_sort_i) + # p <- plot_input(dat(), "support", "Support", input$select_sort_i) + # + # ggplotly(p) %>% + # layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) # # }) - output$support_plot <- renderPlotly({ - - req(input$select_sort_i) - - p <- plot_input(dat(), "support", "Support", input$select_sort_i) - - ggplotly(p) %>% - layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) - - }) - # download handler output$support_plot_dl <- downloadHandler( filename = function() { paste("support", @@ -879,27 +883,27 @@ server <- function(input, output, session) { }) - # output$pvalue_plot <- renderPlot({ + output$pvalue_plot <- renderPlot({ + + req(input$select_sort_i) + + plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) + + + }) + + # output$pvalue_plot <- renderPlotly({ # # req(input$select_sort_i) # - # plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) + # p <- plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) + # + # ggplotly(p) %>% + # layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) # # # }) - output$pvalue_plot <- renderPlotly({ - - req(input$select_sort_i) - - p <- plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) - - ggplotly(p) %>% - layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) - - - }) - output$pvalue_plot_dl <- downloadHandler( filename = function() { paste("pvalue", ".pdf", From a3e32a3947e6a33aaf39d173d2d4bce3f7c3e90b Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 12 Apr 2018 14:45:10 -0400 Subject: [PATCH 16/65] ignore links to external data --- .gitignore | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index a30dd77..7396acd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ inst/doc apps/LOLAweb/cache/* *.bed apps/LOLAweb/lola_vignette_data/*.bed -apps/LOLAweb/universes/* -apps/LOLAweb/reference/ -apps/LOLAwebuserSets/* +apps/LOLAweb/universes +apps/LOLAweb/reference +apps/LOLAweb/cache +apps/LOLAweb/shinylog +apps/LOLAweb/results +apps/LOLAweb/userSets From 6fc96df7dae003b6b323059e35a6b1c72844df6c Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 12 Apr 2018 14:45:23 -0400 Subject: [PATCH 17/65] fix universe figure --- apps/LOLAweb/about.html | 9 +++++---- apps/LOLAweb/{ => www}/universe_selection.svg | 0 2 files changed, 5 insertions(+), 4 deletions(-) rename apps/LOLAweb/{ => www}/universe_selection.svg (100%) diff --git a/apps/LOLAweb/about.html b/apps/LOLAweb/about.html index c2c330d..d5440ee 100644 --- a/apps/LOLAweb/about.html +++ b/apps/LOLAweb/about.html @@ -6,7 +6,7 @@ @@ -31,11 +31,12 @@

How do I use LOLAweb?


-

What universe should I choose?

+ +

What universe should I choose?

One of the key questions when you run LOLA is what your background set, or "universe" is. The universe is a bit open-ended, and it's reasonable to try a few different things. Changing the universe isn't right or wrong, it just changes the question you are asking. The universe set is tested for overlap with the database, and the counts are used in the contingency tables that determine significance for your user sets. The reason this is important is that if you have some regions which were never really possible to end up in a region set of interest, it's unfair to penalize your regions for not overlapping those regions in the database, changing the results of the significance test.

- +

Let's imagine you've done an experiment where you're testing how some epigenomic signal (say, H3K27ac or DNA methylation) responds to a perturbation. You end up with a set of genomic regions that were covered by your assay, along with two subsets of interest: those that increased, and those that decreased in signal (see figure).

@@ -47,7 +48,7 @@

How do I use LOLAweb?

Choice 3: all regions covered. Probably a better choice (though requiring a bit more work) is to derive the universe from your actual data. The natural choice would be to use the set of regions your experiment actually covered. You can think of this universe as the set of regions you tested for possible inclusion in your user sets; or, in other words, it is the restricted background set of regions that were tested, including everything in your regions of interest as well as those that were tested but did not get included. If you can easily come up with such a test for your problem, this is a really good choice for background universe. The resulting test will give you overlaps with database regions without penalizing for areas that weren't even covered in your experiment anyway. This asks: what's special about my regions that increased, versus all the regions that didn't?

-

Choice 4: changing regions only Finally, you could make a very restrictive universe by just combining your two region sets of interest. In this case, it would be the set of regions that either increased or decreased. The result of this test will give you the enrichment of the increased regions relative to changing regions. This is a subtly different question to ask than using the set of all covered regions (choice 3). It assumes that we're only interested in regions that change, then we ask the question: what's special about the ones that increased?

+

Choice 4: changing regions only Finally, you could make a very restrictive universe by just combining your two region sets of interest. In this case, it would be the set of regions that either increased or decreased. The result of this test will give you the enrichment of the increased regions relative to changing regions. This is a subtly different question to ask than using the set of all covered regions (choice 3). The LOLA R package provides an easy way to do this with the buildRestrictedUniverse function, and you can accomplish the same thing with the radio button on LOLAweb. It assumes that we're only interested in regions that change, then we ask the question: what's special about the ones that increased?

In the case of DNA methylation: all regions that had reasonable coverage of methylation reads are your universe, and those that were either highly methylated or lowly methylated (or differentially methylated) would be your subsets of interest. It's the set including all genes that had enough reads that they could have been differentially methylated, even if they weren't.

diff --git a/apps/LOLAweb/universe_selection.svg b/apps/LOLAweb/www/universe_selection.svg similarity index 100% rename from apps/LOLAweb/universe_selection.svg rename to apps/LOLAweb/www/universe_selection.svg From 6b52fdbba571ccf98e564c09832bf1e8b16d1558 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Thu, 12 Apr 2018 15:02:18 -0400 Subject: [PATCH 18/65] now disabling all plotly buttons on scatterplot --- apps/LOLAweb/app.R | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index d05b17d..99d8182 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -784,8 +784,9 @@ server <- function(input, output, session) { plot_render$state <- TRUE - ggplotly(q) - + ggplotly(q) %>% + config(displayModeBar = F) + # config(collaborate = FALSE, displaylogo=FALSE) }) # call plot From 16261e9bc5c12620d48a1ca2da1582e78137fdfa Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 12 Apr 2018 15:07:31 -0400 Subject: [PATCH 19/65] restyle footnote --- apps/LOLAweb/app.R | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index a492056..79ee927 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -198,10 +198,17 @@ ui <- list( includeHTML("about.html") ), footer = div(HTML( - paste0("
Powered by SOMRC
A Project of the Sheffield Lab
Source code on Github
Try it yourself with Docker", - "
LOLAweb commit ", lw_version, "
") + paste0("
+ Built by the Sheffield Computational Biology Lab and SOMRC at UVA.
View source code on GitHub or run it locally with Docker", "
LOLAweb version: ", lw_version, + "
") ), - align = "right", style = " bottom:0; width:100%; height:10px; padding: 10px; padding-bottom:20px; z-index: 1000;"), + align = "center", style = " bottom:0; width:100%; height:10px; padding: 10px; padding-bottom:20px; z-index: 1000;"), id = "mainmenu" ) ) @@ -213,7 +220,13 @@ server <- function(input, output, session) { addPopover(session=session, id="infouserset", title="User Sets", - content="

The User Set is your set of genomic regions that you want to test for overlap with the database. Upload a file in BED format (really, it just needs the first 3 columns: chr, start, and end). You can also drag and drop multiple files and they will be analyzed simultaneously!

", + content="

The User Set is your set of genomic regions that you + want to test for overlap with the database. Upload a file in BED format (really, it just needs the first 3 columns: + chr, start, and end). You can also drag and drop multiple files and + they will be analyzed simultaneously! +

", placement = "bottom", trigger = "click", options = NULL) @@ -221,7 +234,17 @@ server <- function(input, output, session) { addPopover(session=session, id="infouniverse", title="Universes", - content="

The universe is your background set of regions. You should think of the universe as the set of regions you tested for possible inclusion in your user sets; or, in other words, it is the restricted background set of regions that were tested, including everything in your regions of interest as well as those that did not get included. We recommend you upload a universe that is specific to the query set, but we also provide a few basic region sets (like tiling regions, or the set of all active DNaseI hypersensitive elements from the ENCODE project). The choice of universe can have a drastic affect on the results of the analysis, so it may also be worth running LOLA few times with different universe sets. For further information, there are more details in the LOLA documentation.

", + content="

The universe is your background set of regions. You + should think of the universe as the set of regions you tested for + possible inclusion in your user sets. We recommend you upload a + universe that is specific to the query set, but we also provide a + few basic region sets (like tiling regions, or the set of all + active DNaseI hypersensitive elements from the ENCODE project). The + choice of universe can have a drastic affect on the results of the + analysis, so it may also be worth running LOLA few times with + different universe sets. For further information, there are more + details on the About tab. +

", placement = "bottom", trigger = "click", options = NULL) @@ -231,7 +254,14 @@ server <- function(input, output, session) { id="infodb", title="Region Databases", # html for content with JS at the bottom to close popup - content="

We have provided a few different general-purpose databases. We recommend starting with the Core database, but there are also a few other more specific options if you want to extend your analysis. Further details about what is contained in each database can be found in the documentation on LOLA region databases.

", + content="

We have provided a few different general-purpose + databases. We recommend starting with the Core database, but there + are also a few other more specific options if you want to extend + your analysis. Further details about what is contained in each + database can be found in the documentation on + LOLA region databases. +

", placement = "bottom", trigger = "click", options = NULL) From c0f97e8447b46942bfa7694ad1a47b547a49555c Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Thu, 12 Apr 2018 15:30:16 -0400 Subject: [PATCH 20/65] restricting refgenome to hg19 when example user set is toggled --- apps/LOLAweb/app.R | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 99d8182..512f978 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -60,7 +60,8 @@ ui <- list( h3("#1 Upload regions of interest", actionLink("infouserset", "", icon = icon("question-circle-o"))) ), - selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10")), + # selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10")), + uiOutput("refgenome"), shinyjs::hidden(selectInput("defaultuserset", label = "Select pre-loaded region set", choices = list.files("userSets"))), @@ -365,6 +366,19 @@ server <- function(input, output, session) { }) + output$refgenome <- renderUI({ + + if(input$defaultuserset == "setB_100.bed" & exampleuserset$toggle) { + + selectInput("refgenome", label = "Reference genome", choices = "hg19") + + } else { + + selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10")) + + } + }) + output$loladbs <- renderUI({ From 5d48e5b840fd281054ceb3aef5df7471459680fb Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Thu, 12 Apr 2018 15:49:17 -0400 Subject: [PATCH 21/65] now limiting histograms to 50 results at most --- apps/LOLAweb/misc.R | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/LOLAweb/misc.R b/apps/LOLAweb/misc.R index 8eec926..a4e8416 100644 --- a/apps/LOLAweb/misc.R +++ b/apps/LOLAweb/misc.R @@ -12,6 +12,11 @@ plot_input <- function(res, metric, ylabel, sortcol) { # conditional for inverting rank sorting + if(nrow(res) > 50) { + + res <- head(res,50) + } + if(grepl("rnk", sortcol, ignore.case = TRUE)) { # need to order data frame by sort col if it's a rank From e40205f525bce021005ce1fda72c8bf04eca90c2 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Thu, 12 Apr 2018 15:51:43 -0400 Subject: [PATCH 22/65] adding comment re histogram limit --- apps/LOLAweb/misc.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/LOLAweb/misc.R b/apps/LOLAweb/misc.R index a4e8416..5723bbd 100644 --- a/apps/LOLAweb/misc.R +++ b/apps/LOLAweb/misc.R @@ -10,13 +10,13 @@ round_top <- function(x,n) { plot_input <- function(res, metric, ylabel, sortcol) { - # conditional for inverting rank sorting - + # limit to 50 results for histograms so they don't get too dense if(nrow(res) > 50) { res <- head(res,50) } + # conditional for inverting rank sorting if(grepl("rnk", sortcol, ignore.case = TRUE)) { # need to order data frame by sort col if it's a rank From f75b3a7565a2ea5161a1f10cc968dba7b1459381 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Thu, 12 Apr 2018 17:53:24 -0400 Subject: [PATCH 23/65] universe method now selected via radio button; for > 1 user set you can build universe --- apps/LOLAweb/app.R | 99 +++++++++++++++++++++++++++++++++--------- apps/LOLAweb/scratch.R | 15 ++++--- 2 files changed, 88 insertions(+), 26 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 512f978..fed44fb 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -73,17 +73,19 @@ ui <- list( shinyjs::hidden( actionButton("button_userset_upload", "Browse for data to upload") - ) + ), + textOutput("testn") ), column(4, tags$div( h3("#2 Select background universe", actionLink("infouniverse", "", icon = icon("question-circle-o"))) ), - uiOutput("universe"), - checkboxInput("checkbox", - label = "Check here to upload your own universe", - value = FALSE) + uiOutput("universe_opts"), + uiOutput("universe") + # checkboxInput("checkbox", + # label = "Check here to upload your own universe", + # value = FALSE) ), column(4, tags$div( @@ -145,7 +147,6 @@ ui <- list( style ="display:inline-block;"), plotOutput("oddsratio_plot"), # plotlyOutput("oddsratio_plot"), - # conditionalPanel(condition = "output.res", h4("Support"), downloadButton("support_plot_dl", label = "PDF", @@ -377,9 +378,9 @@ server <- function(input, output, session) { selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10")) } + }) - output$loladbs <- renderUI({ fl <- grep(input$refgenome, @@ -392,14 +393,34 @@ server <- function(input, output, session) { }) + output$universe_opts <- renderUI({ + + if(nfiles$n > 1) { + + radioButtons("universe_opts", "Universe", + choiceValues = c("default", "user", "build"), + choiceNames = c("Use default universe", "Upload universe", "Build universe with user sets")) + + } else { + + radioButtons("universe_opts", "Universe", + choiceValues = c("default", "user"), + choiceNames = c("Use default universe", "Upload universe")) + + } + + }) + output$universe <- renderUI({ + + req(input$universe_opts) - if(input$checkbox) { + if(input$universe_opts == "user") { fileInput("useruniverse", "Choose universe file", accept = c(".bed")) - } else { + } else if (input$universe_opts == "default") { selectInput("defaultuniverse", label = "Select pre-loaded universe", @@ -423,6 +444,7 @@ server <- function(input, output, session) { run_time <- system.time({ + # user set(s) userSets <- list() if(!exampleuserset$toggle) { @@ -454,34 +476,59 @@ server <- function(input, output, session) { names(userSets) = input$defaultuserset } - - if(input$checkbox) { - - userUniverse = readBed(file = input$useruniverse$datapath) + + # universe + + # if(input$checkbox) { + # + # userUniverse = readBed(file = input$useruniverse$datapath) + # + # + # universename <- input$useruniverse$datapath + # + # } else { + # + # datapath <- paste0("universes/", input$refgenome, "/", input$defaultuniverse) + # + # userUniverse = readBed(file = datapath) + # + # + # universename <- input$defaultuniverse + # + # } + + if(input$universe_opts == "user") { + userUniverse <- readBed(file = input$useruniverse$datapath) universename <- input$useruniverse$datapath - - } else { - + + } else if (input$universe_opts == "default") { + datapath <- paste0("universes/", input$refgenome, "/", input$defaultuniverse) - - userUniverse = readBed(file = datapath) - + userUniverse <- readBed(file = datapath) + universename <- input$defaultuniverse + } else if (input$universe_opts == "build") { + + userUniverse <- buildRestrictedUniverse(userSets) + + universename <- paste0(c(names(userSets), "universe"), collapse = "_") + } userSetsRedefined = redefineUserSets(userSets, userUniverse) - # load region data for each reference genome + # set up path to databases for given reference genome dbPath = paste("reference", input$loladb, input$refgenome, sep = "/" ) - + + # load region data for the given reference genome regionDB = loadRegionDB(dbLocation=dbPath) # garbage collection @@ -561,6 +608,16 @@ server <- function(input, output, session) { }) + # capture the number of user sets that are being uploaded + # use this to toggle radio buttons for building a universe + nfiles <- reactiveValues(n = 0) + + observe({ + + nfiles$n <- length(input$userset[,1]) + + }) + plot_render <- reactiveValues(state = FALSE) observe({ diff --git a/apps/LOLAweb/scratch.R b/apps/LOLAweb/scratch.R index e75a1a0..d4f9af4 100644 --- a/apps/LOLAweb/scratch.R +++ b/apps/LOLAweb/scratch.R @@ -284,19 +284,24 @@ x <- system.time({ ##### ggplotly -# userSet = readBed(file = "lola_vignette_data/setB_100.bed") -# dbPath = "reference/Core/hg19/" -# regionDB = loadRegionDB(dbLocation=dbPath) +userSet = readBed(file = "lola_vignette_data/setB_100.bed") +userSet2 = readBed(file = "lola_vignette_data/setC_100.bed") + +restrictedUniverse <- buildRestrictedUniverse(GRangesList(userSet, userSet2)) +data("sample_input", package="LOLA") # load userSets + +dbPath = "reference/Core/hg19/" +regionDB = loadRegionDB(dbLocation=dbPath) # # userUniverse = readBed("universes/hg19/tiles1000.hg19.bed") # # userUniverse = read.table(file = "universes/hg38/tiles.hg38.5000.bed", header = F) # # colnames(userUniverse) <- c('chr','start','end','id','score','strand') # # userUniverse <- with(userUniverse, GRanges(chr, IRanges(start+1, end), strand, score, id=id)) # -# userSetsRedefined = redefineUserSets(userSet, userUniverse) +userSetsRedefined = redefineUserSets(GRangesList(userSet, userSet2), restrictedUniverse) # # -# resRedefined = runLOLA(userSetsRedefined, userUniverse, regionDB, cores=1) +resRedefined = runLOLA(userSetsRedefined, restrictedUniverse, regionDB, cores=1) library(sodium) From 9ff91610da87bfb75e77b680c4c573623fe1d94a Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Thu, 12 Apr 2018 21:44:03 -0400 Subject: [PATCH 24/65] updates to scatterplot --- apps/LOLAweb/app.R | 54 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 3e0b7e1..73b3ff9 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -135,6 +135,14 @@ ui <- list( div( tabsetPanel(type = "tabs", tabPanel("Scatterplot", + shinyjs::hidden( + div( + h4("Scatter Plot"), + downloadButton("scatterplot_dl", + label = "PDF", + class = "dt-button"), + id = "scatterhead" + )), plotlyOutput("scatter")), tabPanel("Histograms", # fluidRow( @@ -725,6 +733,7 @@ server <- function(input, output, session) { } else { shinyjs::hide("gear2") + shinyjs::show("scatterhead") } @@ -866,30 +875,47 @@ server <- function(input, output, session) { }, spacing = "s", colnames = FALSE, align = "l") - output$scatter <- renderPlotly({ - - req(input$select_collection_i) + + scatterplot_input <- function() { - q <- - ggplot(dat(), aes(pValueLog, oddsRatio, size = log(support), - text = paste0("Collection: ", - collection, - "\n", - "Description: ", - axis_label))) + - geom_point() + + ggplot(dat(), aes(pValueLog, oddsRatio, size = log(support), + text = paste0("Collection: ", + collection, + "\n", + "Description: ", + axis_label))) + + geom_point(aes(col = userSet)) + xlab("P Value Log") + ylab("Odds Ratio") + + scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio), max(rawdat_res$rawdat$oddsRatio))) + + scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog), max(rawdat_res$rawdat$pValueLog))) + geom_blank(aes(text = collection)) + theme_ns() + } + + output$scatter <- renderPlotly({ + + req(input$select_collection_i) + plot_render$state <- TRUE - ggplotly(q) %>% - config(displayModeBar = F) - # config(collaborate = FALSE, displaylogo=FALSE) + ggplotly(scatterplot_input()) %>% + config(displayModeBar = FALSE) + }) + # download handler + output$scatterplot_dl <- downloadHandler( + filename = function() { paste("scatter", + ".pdf", + sep="") }, + content = function(file) { + ggsave(file, plot = scatterplot_input() + , device = "pdf") + } + ) + # call plot output$oddsratio_plot <- renderPlot({ From 2e8379d79165cff1686e3a4a26d17c65e3d94374 Mon Sep 17 00:00:00 2001 From: nsheff Date: Fri, 13 Apr 2018 09:36:10 -0400 Subject: [PATCH 25/65] wrap long messages --- apps/LOLAweb/app.R | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 73b3ff9..9f4706b 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -48,7 +48,10 @@ ui <- list( ), fluidRow( shinyjs::hidden(div(HTML("
- All Run inputs are disabled while LOLAweb has results loaded.
Navigate to Results to view current result output.
To execute a new run, reload LOLAweb.
"), id = "noinputmsg")) + All Run inputs are disabled while LOLAweb has results + loaded.
Navigate to Results to view current result + output.
To execute a new run, reload + LOLAweb."), id = "noinputmsg")) ), fluidRow( @@ -286,7 +289,10 @@ server <- function(input, output, session) { id="infocollection", title="Collections", # html for content with JS at the bottom to close popup - content="

LOLA databases are made up of one or more sub-collections of region set. Using this drop-down, you can filter your plots and tables to show only the results from one of these collections at a time.

", + content="

LOLA databases are made up of one or more sub- + collections of region set. Using this drop-down, you can filter + your plots and tables to show only the results from one of these + collections at a time.

", placement = "bottom", trigger = "click", options = NULL) @@ -296,7 +302,17 @@ server <- function(input, output, session) { id="infoplot", title="LOLA Results", # html for content with JS at the bottom to close popup - content="

These barplots show the highest-ranking region sets from the database. The higher scores indicate more overlap with your query set. The results are scored using 3 statistics: Support is the raw number of regions that overlapped between your query set and the database set. LogPVal and LogOdds are the results of a Fisher's exact test scoring the significance of that overlap.

We rank each region set from the database for each of these 3 scores, and you can see the raw scores and the ranks in the table below. You can also see the maximum and mean ranks across all 3 categories.

", + content="

These barplots show the highest-ranking region sets + from the database. The higher scores indicate more overlap with + your query set. The results are scored using 3 statistics: Support + is the raw number of regions that overlapped between your query set + and the database set. LogPVal and LogOdds are the results of a + Fisher's exact test scoring the significance of that + overlap.

We rank each region set from the database for each + of these 3 scores, and you can see the raw scores and the ranks in + the table below. You can also see the maximum and mean ranks across + all 3 categories. +

", placement = "bottom", trigger = "click", options = NULL) From c2ec8d136ed99df6c6259b46e06abef0f2b07687 Mon Sep 17 00:00:00 2001 From: nsheff Date: Fri, 13 Apr 2018 12:41:26 -0400 Subject: [PATCH 26/65] Convert hard-coded folders into variables. See #50 --- apps/LOLAweb/app.R | 21 ++++++++++----------- apps/LOLAweb/misc.R | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 9f4706b..749338f 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -14,8 +14,7 @@ library(shinyBS) library(GenomicDistributions) library(plotly) -setCacheDir("cache") - +setCacheDir(cacheDir) # get lolaweb version lw_version <- system(command = "git rev-parse HEAD | cut -c1-9", intern = TRUE) @@ -67,7 +66,7 @@ ui <- list( uiOutput("refgenome"), shinyjs::hidden(selectInput("defaultuserset", label = "Select pre-loaded region set", - choices = list.files("userSets"))), + choices = list.files(exampleDir))), fileInput("userset", "Choose BED file(s)", multiple = TRUE, accept = c(".bed")), @@ -438,7 +437,7 @@ server <- function(input, output, session) { output$loladbs <- renderUI({ fl <- grep(input$refgenome, - list.files("reference", recursive = TRUE), + list.files(dbDir, recursive = TRUE), value = TRUE) dbs <- unique(gsub("(.*?)(/.*)", "\\1", fl)) @@ -478,7 +477,7 @@ server <- function(input, output, session) { selectInput("defaultuniverse", label = "Select pre-loaded universe", - choices = list.files(paste0("universes/", input$refgenome))) + choices = list.files(paste0(universeDir, input$refgenome))) } @@ -520,7 +519,7 @@ server <- function(input, output, session) { message("Loading example data") - datapath <- paste0("userSets/", input$defaultuserset) + datapath <- paste0(exampleDir, input$defaultuserset) userSet = readBed(datapath) userSets[[1]] <- userSet @@ -559,7 +558,7 @@ server <- function(input, output, session) { } else if (input$universe_opts == "default") { - datapath <- paste0("universes/", input$refgenome, "/", input$defaultuniverse) + datapath <- paste0(universeDir, input$refgenome, "/", input$defaultuniverse) userUniverse <- readBed(file = datapath) @@ -576,7 +575,7 @@ server <- function(input, output, session) { userSetsRedefined = redefineUserSets(userSets, userUniverse) # set up path to databases for given reference genome - dbPath = paste("reference", + dbPath = paste(dbDir, input$loladb, input$refgenome, sep = "/" @@ -647,7 +646,7 @@ server <- function(input, output, session) { observe({ - cachenames <- tools::file_path_sans_ext(list.files("cache")) + cachenames <- tools::file_path_sans_ext(list.files(cacheDir)) if(length(query()) != 0 && !query()[[1]] %in% cachenames) { @@ -676,7 +675,7 @@ server <- function(input, output, session) { observe({ - cachenames <- tools::file_path_sans_ext(list.files("cache")) + cachenames <- tools::file_path_sans_ext(list.files(cacheDir)) if(length(query()) != 0 && query()[[1]] %in% cachenames) { @@ -684,7 +683,7 @@ server <- function(input, output, session) { env <- new.env() - simpleCache(keyphrase, assignToVariable = "cipher", loadEnvir = environment(), cacheDir = "cache") + simpleCache(keyphrase, assignToVariable = "cipher", loadEnvir = environment(), cacheDir=cacheDir) cipher <- get("cipher", envir = env) diff --git a/apps/LOLAweb/misc.R b/apps/LOLAweb/misc.R index 5723bbd..22a1979 100644 --- a/apps/LOLAweb/misc.R +++ b/apps/LOLAweb/misc.R @@ -38,4 +38,35 @@ plot_input <- function(res, metric, ylabel, sortcol) { coord_flip() + theme_ns() -} \ No newline at end of file +} + + +# This function just wraps the base Sys.gentenv function to provide a default +# value for the case that the environment variable is not specified. +getEnv = function(envVar, default="") { + var = Sys.getenv(envVar) + if (var == "") { + return(default) + } else { + return(var) + } +} + + + +# Set up cache dir based on environment variable +localDir = getEnv("LWLOCAL", "/data/lola/") +cacheDir = paste0(localDir, "cache/") +logDir = paste0(localDir, "shinylog/") +resultsDir = paste0(localDir, "results/") + + +refDir = getEnv("LWREF", "/mnt/q/shefflab/LOLAweb/") + +dbDir = paste0(refDir, "databases/") +universeDir = paste0(refDir, "universes/") +exampleDir = paste0(refDir, "examples/") +message("Local dir: ", localDir) +message("Reference data dir: ", refDir) +message("universe dir: ", universeDir) +message("dbDir data dir: ", dbDir) From 427c744c5694f54379e98ef1136cfa268cda776e Mon Sep 17 00:00:00 2001 From: nsheff Date: Fri, 13 Apr 2018 12:55:33 -0400 Subject: [PATCH 27/65] Some scatterplot style tweaks --- apps/LOLAweb/app.R | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 749338f..065e90b 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -899,11 +899,12 @@ server <- function(input, output, session) { "\n", "Description: ", axis_label))) + - geom_point(aes(col = userSet)) + - xlab("P Value Log") + - ylab("Odds Ratio") + + geom_point(aes(col=userSet), alpha=.75) + + xlab("Log(P value)") + + ylab("Odds ratio") + scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio), max(rawdat_res$rawdat$oddsRatio))) + scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog), max(rawdat_res$rawdat$pValueLog))) + + scale_size_continuous(range = c(0.5,4)) + geom_blank(aes(text = collection)) + theme_ns() From e936848e29e16360b2d046228ab95ea48e04ed61 Mon Sep 17 00:00:00 2001 From: Nathan Sheffield Date: Fri, 13 Apr 2018 13:57:55 -0400 Subject: [PATCH 28/65] Update docker-compose.yml --- docker/swarm/docker-compose.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docker/swarm/docker-compose.yml b/docker/swarm/docker-compose.yml index 60e0582..a13f405 100644 --- a/docker/swarm/docker-compose.yml +++ b/docker/swarm/docker-compose.yml @@ -9,10 +9,8 @@ services: ports: - "80" volumes: - - /data/lola/reference:/srv/shiny-server/LOLAweb/apps/LOLAweb/reference - - /data/lola/universes:/srv/shiny-server/LOLAweb/apps/LOLAweb/universes - - /data/lola/userSets:/srv/shiny-server/LOLAweb/apps/LOLAweb/userSets - - /data/lola/cache:/srv/shiny-server/LOLAweb/apps/LOLAweb/cache + - /data/lola:/data/lola + - /mnt/q/shefflab/LOLAweb:/mnt/q/shefflab/LOLAweb - /data/lola/shinylog:/var/log/shiny-server deploy: mode: replicated From c1fc5d8a987de5e7d0f216a437f701c52c495486 Mon Sep 17 00:00:00 2001 From: Nathan Sheffield Date: Fri, 13 Apr 2018 14:01:29 -0400 Subject: [PATCH 29/65] revert commit --- docker/swarm/docker-compose.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docker/swarm/docker-compose.yml b/docker/swarm/docker-compose.yml index a13f405..60e0582 100644 --- a/docker/swarm/docker-compose.yml +++ b/docker/swarm/docker-compose.yml @@ -9,8 +9,10 @@ services: ports: - "80" volumes: - - /data/lola:/data/lola - - /mnt/q/shefflab/LOLAweb:/mnt/q/shefflab/LOLAweb + - /data/lola/reference:/srv/shiny-server/LOLAweb/apps/LOLAweb/reference + - /data/lola/universes:/srv/shiny-server/LOLAweb/apps/LOLAweb/universes + - /data/lola/userSets:/srv/shiny-server/LOLAweb/apps/LOLAweb/userSets + - /data/lola/cache:/srv/shiny-server/LOLAweb/apps/LOLAweb/cache - /data/lola/shinylog:/var/log/shiny-server deploy: mode: replicated From bb34fec5174432e7ef1ae715b7bb9a0823d26670 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Fri, 13 Apr 2018 15:38:55 -0400 Subject: [PATCH 30/65] updating Dockerfile so prod doesn't pull dev app code --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index f146a37..1f34f74 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -8,7 +8,7 @@ COPY shiny-server.sh /usr/bin/shiny-server.sh # get the code WORKDIR /srv/shiny-server -RUN git clone -b dev https://github.com/databio/LOLAweb.git +RUN git clone https://github.com/databio/LOLAweb.git # add dir for cache RUN mkdir LOLAweb/cache From 911588378b82504eaf8fa51f4acc49d80bf7e972 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 16 Apr 2018 11:44:13 -0400 Subject: [PATCH 31/65] displaying button and h4 inline for plot headers --- apps/LOLAweb/app.R | 14 ++++++-------- apps/LOLAweb/www/style.css | 8 ++++++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 065e90b..9597123 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -139,7 +139,7 @@ ui <- list( tabPanel("Scatterplot", shinyjs::hidden( div( - h4("Scatter Plot"), + h4("Scatter Plot", class ="plot_header"), downloadButton("scatterplot_dl", label = "PDF", class = "dt-button"), @@ -149,15 +149,13 @@ ui <- list( tabPanel("Histograms", # fluidRow( column(5, - div( - h4("Odds Ratio"), + h4("Odds Ratio", class = "plot_header"), downloadButton("oddsratio_plot_dl", label = "PDF", class = "dt-button"), - style ="display:inline-block;"), plotOutput("oddsratio_plot"), # plotlyOutput("oddsratio_plot"), - h4("Support"), + h4("Support", class = "plot_header"), downloadButton("support_plot_dl", label = "PDF", class = "dt-button"), @@ -166,7 +164,7 @@ ui <- list( ), column(5, - h4("P Value"), + h4("P Value", class = "plot_header"), downloadButton("pvalue_plot_dl", label = "PDF", class = "dt-button"), @@ -186,13 +184,13 @@ ui <- list( ), fluidRow( column(5, - h4("Distance to TSS"), + h4("Distance to TSS", class = "plot_header"), downloadButton("dist_plot_dl", label ="PDF", class = "dt-button"), plotOutput("dist_plot")), column(5, - h4("Genomic Partitions"), + h4("Genomic Partitions", class = "plot_header"), downloadButton("part_plot_dl", label = "PDF", class = "dt-button"), diff --git a/apps/LOLAweb/www/style.css b/apps/LOLAweb/www/style.css index b51f68d..ba94293 100644 --- a/apps/LOLAweb/www/style.css +++ b/apps/LOLAweb/www/style.css @@ -32,6 +32,10 @@ } .disabledinputs { - pointer-events: none; - opacity: 0.4; + pointer-events: none; + opacity: 0.4; +} + +.plot_header { + display: inline-block; } \ No newline at end of file From 849acc51534f3df54cd8f4be7e1ce45dc1699815 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 16 Apr 2018 11:47:25 -0400 Subject: [PATCH 32/65] one more 'plot_header' class --- apps/LOLAweb/app.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 9597123..540022b 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -176,7 +176,7 @@ ui <- list( tabPanel("Distribution", fluidRow( column(10, - h4("Distribution over genome"), + h4("Distribution over genome", class = "plot_header"), downloadButton("distrib_plot_dl", label = "PDF", class = "dt-button"), From 7605fea5141d341455659a26c9b3fe12bae7e517 Mon Sep 17 00:00:00 2001 From: nem2p Date: Mon, 16 Apr 2018 11:58:35 -0400 Subject: [PATCH 33/65] Update pip as needed for Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d3187b3..2a4e029 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ services: - docker before_install: + - pip install --upgrade pip - pip install --user awscli - export PATH=$PATH:$HOME/.local/bin - echo $DOCKER_PASSWORD | docker login -u "$DOCKER_USERNAME" --password-stdin From b332069d93eb5ac5ba3e85d2b81f9488c8053c94 Mon Sep 17 00:00:00 2001 From: nem2p Date: Mon, 16 Apr 2018 12:21:02 -0400 Subject: [PATCH 34/65] Pip update fix --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2a4e029..51054b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ services: - docker before_install: - - pip install --upgrade pip + - sudo install --upgrade pip - pip install --user awscli - export PATH=$PATH:$HOME/.local/bin - echo $DOCKER_PASSWORD | docker login -u "$DOCKER_USERNAME" --password-stdin From c4ef13d98bf3bd7be59166d88b8aab9323909bfb Mon Sep 17 00:00:00 2001 From: nem2p Date: Mon, 16 Apr 2018 12:22:53 -0400 Subject: [PATCH 35/65] Forgot pip --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 51054b9..6cd267b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ services: - docker before_install: - - sudo install --upgrade pip + - sudo pip install --upgrade pip - pip install --user awscli - export PATH=$PATH:$HOME/.local/bin - echo $DOCKER_PASSWORD | docker login -u "$DOCKER_USERNAME" --password-stdin From c63d8fe6f1d93bd27e4a735893d8518902da3c6e Mon Sep 17 00:00:00 2001 From: nsheff Date: Mon, 16 Apr 2018 12:30:35 -0400 Subject: [PATCH 36/65] add mm9; examples msg --- apps/LOLAweb/app.R | 2 +- apps/LOLAweb/misc.R | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 540022b..f410e45 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -426,7 +426,7 @@ server <- function(input, output, session) { } else { - selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10")) + selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10", "mm9")) } diff --git a/apps/LOLAweb/misc.R b/apps/LOLAweb/misc.R index 22a1979..ee6485f 100644 --- a/apps/LOLAweb/misc.R +++ b/apps/LOLAweb/misc.R @@ -70,3 +70,4 @@ message("Local dir: ", localDir) message("Reference data dir: ", refDir) message("universe dir: ", universeDir) message("dbDir data dir: ", dbDir) +message("exampleDir dir: ", exampleDir) From 6ecb5a6ba4bfe79e606fef57faf1955783e1f377 Mon Sep 17 00:00:00 2001 From: nsheff Date: Mon, 16 Apr 2018 14:29:19 -0400 Subject: [PATCH 37/65] Add some debug printouts --- apps/LOLAweb/app.R | 3 ++- apps/LOLAweb/misc.R | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index f410e45..12aeec1 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -647,7 +647,8 @@ server <- function(input, output, session) { cachenames <- tools::file_path_sans_ext(list.files(cacheDir)) if(length(query()) != 0 && !query()[[1]] %in% cachenames) { - + message("Cachenames: ", cachenames) + message("cacheDir: ", cacheDir) showModal(modalDialog( title = "Bad Request", HTML(paste0("The cache '", diff --git a/apps/LOLAweb/misc.R b/apps/LOLAweb/misc.R index ee6485f..64fc341 100644 --- a/apps/LOLAweb/misc.R +++ b/apps/LOLAweb/misc.R @@ -67,6 +67,7 @@ dbDir = paste0(refDir, "databases/") universeDir = paste0(refDir, "universes/") exampleDir = paste0(refDir, "examples/") message("Local dir: ", localDir) +message("Cache dir: ", cacheDir) message("Reference data dir: ", refDir) message("universe dir: ", universeDir) message("dbDir data dir: ", dbDir) From ff7eadb92f25e6e5a7d901cf94f90854a738f330 Mon Sep 17 00:00:00 2001 From: nsheff Date: Mon, 16 Apr 2018 15:55:00 -0400 Subject: [PATCH 38/65] Use Sys.glob instead of list.files speed up list of large databases by not recursing deep into file structure needlessly. Fix #75 --- apps/LOLAweb/app.R | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 12aeec1..6d88483 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -433,12 +433,14 @@ server <- function(input, output, session) { }) output$loladbs <- renderUI({ - - fl <- grep(input$refgenome, - list.files(dbDir, recursive = TRUE), - value = TRUE) - - dbs <- unique(gsub("(.*?)(/.*)", "\\1", fl)) + message("timetest1") + #fl <- grep(input$refgenome, + # list.files("/ext/qumulo/LOLAweb/databases", pattern="*/hg19", recursive = TRUE), + # value = TRUE) + #dbs <- unique(gsub("(.*?)(/.*)", "\\1", fl)) + fl = Sys.glob(paste0(dbDir, "/*/", input$refgenome)) + dbs = gsub(paste0(dbDir, "/(.*)/", input$refgenome), "\\1", fl) + message("timetest2") selectInput("loladb", label = "", choices = dbs) From 7faf7aa669fca4d92f75596601d3fff0023aa3ed Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 16 Apr 2018 18:45:38 -0400 Subject: [PATCH 39/65] now showing example data options dynamically by refgenome --- apps/LOLAweb/app.R | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 6d88483..acfde55 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -64,9 +64,11 @@ ui <- list( ), # selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10")), uiOutput("refgenome"), - shinyjs::hidden(selectInput("defaultuserset", - label = "Select pre-loaded region set", - choices = list.files(exampleDir))), + # shinyjs::hidden(selectInput("defaultuserset", + # label = "Select pre-loaded region set", + # choices = list.files(exampleDir))), + shinyjs::hidden( + uiOutput("defaultuserset")), fileInput("userset", "Choose BED file(s)", multiple = TRUE, accept = c(".bed")), @@ -420,15 +422,15 @@ server <- function(input, output, session) { output$refgenome <- renderUI({ - if(input$defaultuserset == "setB_100.bed" & exampleuserset$toggle) { - - selectInput("refgenome", label = "Reference genome", choices = "hg19") - - } else { + # if(input$defaultuserset == "setB_100.bed" & exampleuserset$toggle) { + # + # selectInput("refgenome", label = "Reference genome", choices = "hg19") + # + # } else { selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10", "mm9")) - } + # } }) @@ -446,6 +448,14 @@ server <- function(input, output, session) { }) + output$defaultuserset <- renderUI({ + + selectInput("defaultuserset", + label = "Select pre-loaded region set", + choices = list.files(paste0(exampleDir, "/", input$refgenome))) + + }) + output$universe_opts <- renderUI({ if(nfiles$n > 1) { @@ -519,7 +529,7 @@ server <- function(input, output, session) { message("Loading example data") - datapath <- paste0(exampleDir, input$defaultuserset) + datapath <- paste0(exampleDir, input$refgenome, "/", input$defaultuserset) userSet = readBed(datapath) userSets[[1]] <- userSet From a37f5448b4253d64f7570867b6ab435eadbb13c8 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Mon, 16 Apr 2018 18:49:12 -0400 Subject: [PATCH 40/65] misc cleanup of code --- apps/LOLAweb/app.R | 82 +--------------------------------------------- 1 file changed, 1 insertion(+), 81 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index acfde55..91a2c4d 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -62,11 +62,7 @@ ui <- list( h3("#1 Upload regions of interest", actionLink("infouserset", "", icon = icon("question-circle-o"))) ), - # selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10")), uiOutput("refgenome"), - # shinyjs::hidden(selectInput("defaultuserset", - # label = "Select pre-loaded region set", - # choices = list.files(exampleDir))), shinyjs::hidden( uiOutput("defaultuserset")), fileInput("userset", "Choose BED file(s)", @@ -87,9 +83,6 @@ ui <- list( ), uiOutput("universe_opts"), uiOutput("universe") - # checkboxInput("checkbox", - # label = "Check here to upload your own universe", - # value = FALSE) ), column(4, tags$div( @@ -102,7 +95,6 @@ ui <- list( class = "runLOLA"), HTML("") ), - # class = "headerBox", id = "runInputs"), id = "runInputs"), fluidRow( @@ -149,19 +141,16 @@ ui <- list( )), plotlyOutput("scatter")), tabPanel("Histograms", - # fluidRow( column(5, h4("Odds Ratio", class = "plot_header"), downloadButton("oddsratio_plot_dl", label = "PDF", class = "dt-button"), plotOutput("oddsratio_plot"), - # plotlyOutput("oddsratio_plot"), h4("Support", class = "plot_header"), downloadButton("support_plot_dl", label = "PDF", class = "dt-button"), - # plotlyOutput("support_plot"), plotOutput("support_plot") ), @@ -170,10 +159,8 @@ ui <- list( downloadButton("pvalue_plot_dl", label = "PDF", class = "dt-button"), - # plotlyOutput("pvalue_plot") plotOutput("pvalue_plot") ) - # ) ), tabPanel("Distribution", fluidRow( @@ -421,28 +408,15 @@ server <- function(input, output, session) { }) output$refgenome <- renderUI({ - - # if(input$defaultuserset == "setB_100.bed" & exampleuserset$toggle) { - # - # selectInput("refgenome", label = "Reference genome", choices = "hg19") - # - # } else { selectInput("refgenome", label = "Reference genome", choices = c("hg19", "hg38", "mm10", "mm9")) - # } - }) output$loladbs <- renderUI({ - message("timetest1") - #fl <- grep(input$refgenome, - # list.files("/ext/qumulo/LOLAweb/databases", pattern="*/hg19", recursive = TRUE), - # value = TRUE) - #dbs <- unique(gsub("(.*?)(/.*)", "\\1", fl)) + fl = Sys.glob(paste0(dbDir, "/*/", input$refgenome)) dbs = gsub(paste0(dbDir, "/(.*)/", input$refgenome), "\\1", fl) - message("timetest2") selectInput("loladb", label = "", choices = dbs) @@ -542,24 +516,6 @@ server <- function(input, output, session) { # universe - # if(input$checkbox) { - # - # userUniverse = readBed(file = input$useruniverse$datapath) - # - # - # universename <- input$useruniverse$datapath - # - # } else { - # - # datapath <- paste0("universes/", input$refgenome, "/", input$defaultuniverse) - # - # userUniverse = readBed(file = datapath) - # - # - # universename <- input$defaultuniverse - # - # } - if(input$universe_opts == "user") { userUniverse <- readBed(file = input$useruniverse$datapath) @@ -952,19 +908,6 @@ server <- function(input, output, session) { }) - # # call plot - # output$oddsratio_plot <- renderPlotly({ - # - # req(input$select_sort_i) - # - # p <- plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) - # - # ggplotly(p) %>% - # layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) - # - # }) - # - # download handler output$oddsratio_plot_dl <- downloadHandler( filename = function() { paste("oddsratio", @@ -999,17 +942,6 @@ server <- function(input, output, session) { }) - # output$support_plot <- renderPlotly({ - # - # req(input$select_sort_i) - # - # p <- plot_input(dat(), "support", "Support", input$select_sort_i) - # - # ggplotly(p) %>% - # layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) - # - # }) - # download handler output$support_plot_dl <- downloadHandler( filename = function() { paste("support", @@ -1047,18 +979,6 @@ server <- function(input, output, session) { }) - # output$pvalue_plot <- renderPlotly({ - # - # req(input$select_sort_i) - # - # p <- plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) - # - # ggplotly(p) %>% - # layout(legend = list(orientation = "h", x = -0.5, y =-0.25)) - # - # - # }) - output$pvalue_plot_dl <- downloadHandler( filename = function() { paste("pvalue", ".pdf", From 3f05b6a3dbfea14c6311785b49a4012427e35b3f Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Tue, 17 Apr 2018 17:19:20 -0400 Subject: [PATCH 41/65] made legend horizontal and removed title --- apps/LOLAweb/app.R | 10 ++++++++-- apps/LOLAweb/scratch.R | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 91a2c4d..f158abf 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -873,7 +873,8 @@ server <- function(input, output, session) { scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog), max(rawdat_res$rawdat$pValueLog))) + scale_size_continuous(range = c(0.5,4)) + geom_blank(aes(text = collection)) + - theme_ns() + theme_ns() + + guides(size = FALSE) } @@ -884,7 +885,12 @@ server <- function(input, output, session) { plot_render$state <- TRUE ggplotly(scatterplot_input()) %>% - config(displayModeBar = FALSE) + config(displayModeBar = FALSE) %>% + layout( + legend = list(orientation = "h", + x = 0.44, + y = -0.2, + title = "")) }) diff --git a/apps/LOLAweb/scratch.R b/apps/LOLAweb/scratch.R index d4f9af4..5b69860 100644 --- a/apps/LOLAweb/scratch.R +++ b/apps/LOLAweb/scratch.R @@ -355,12 +355,12 @@ q <- ylab("Odds Ratio") + # coord_flip() + geom_blank(aes(text = collection)) + - theme_ns() + - theme(legend.position = "bottom") + theme_ns() ggplotly(q, tooltip = c("x", "y", "size", "text")) -ggplotly(q, tooltip = c("x", "y", "size")) %>% +x <- + ggplotly(q, tooltip = c("x", "y", "size")) %>% layout(showlegend = TRUE, legendgroup = "size") From d31fa1eca9a0f3dea491fd1be135b27a7576bed8 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Wed, 18 Apr 2018 14:40:16 -0400 Subject: [PATCH 42/65] ignoring NA values in pvalue log and odds ratio while setting scatterplot axes --- apps/LOLAweb/app.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index f158abf..3618f46 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -869,8 +869,8 @@ server <- function(input, output, session) { geom_point(aes(col=userSet), alpha=.75) + xlab("Log(P value)") + ylab("Odds ratio") + - scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio), max(rawdat_res$rawdat$oddsRatio))) + - scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog), max(rawdat_res$rawdat$pValueLog))) + + scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), max(rawdat_res$rawdat$oddsRatio, na.rm = TRUE))) + + scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog, na.rm = TRUE), max(rawdat_res$rawdat$pValueLog, na.rm = TRUE))) + scale_size_continuous(range = c(0.5,4)) + geom_blank(aes(text = collection)) + theme_ns() + From c34c1a062afcffe214f7c8f98cdc0efe047db29f Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 19 Apr 2018 08:53:34 -0400 Subject: [PATCH 43/65] add universes html page test --- apps/LOLAweb/www/universes.html | 65 +++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 apps/LOLAweb/www/universes.html diff --git a/apps/LOLAweb/www/universes.html b/apps/LOLAweb/www/universes.html new file mode 100644 index 0000000..d5dc34d --- /dev/null +++ b/apps/LOLAweb/www/universes.html @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + LOLA + + + +
+

Universes

+ + +

What universe should I choose?

+ +

One of the key questions when you run LOLA is what your background set, or "universe" is. The universe is a bit open-ended, and it's reasonable to try a few different things. Changing the universe isn't right or wrong, it just changes the question you are asking. The universe set is tested for overlap with the database, and the counts are used in the contingency tables that determine significance for your user sets. The reason this is important is that if you have some regions which were never really possible to end up in a region set of interest, it's unfair to penalize your regions for not overlapping those regions in the database, changing the results of the significance test.

+ + + +

Let's imagine you've done an experiment where you're testing how some epigenomic signal (say, H3K27ac or DNA methylation) responds to a perturbation. You end up with a set of genomic regions that were covered by your assay, along with two subsets of interest: those that increased, and those that decreased in signal (see figure).

+ +

In this case, one approach is to think of this as two user query sets: one for each subset of regions that change. Now, what should your universe be? Well, you have a few options. Let's go through 4 common universe choices see what they mean about the significance test you're performing. The four choices move in increasing order of specificity: + +

Choice 1: genome tiles. LOLAweb lets you choose tiling regions of various sizes. These tiles are little better than generic splits of the genome because they at least account for reference assembly gaps. But otherwise, this is a pretty basic background set which doesn't restrict the question at all. This would be a useful universe to choose if you are not sure what to expect, and your experiment could have included any genomic region as output. The result will tell you what database region sets are enriched in your query sets generally, across the whole genome.

+ +

Choice 2: any regulatory elements. A bit more restricted universe set is the set of active regulatory elements. LOLAweb includes a manually curated universe set that was derived by merging all of the DNAse hypersensitivity data from over 100 cell types from the ENCODE project. This set will restrict your significance test to only active regulatory elements, so it's a reasonable background set if you're looking at ChIP-seq data or some other active signal, but may not be relevant for every experiment type. In practice, we find this to be a useful first pass test for many experiments. Relative to the tiling approach, this, for example, won't penalize your overlap test for not overlapping a database region that's hidden away in a heterochromatic region. It yields which database region sets are enriched in your query set, but only considering active parts of the genome. An advantage of this approach is that it's easy: we've already defined that set for you and you can just select it. A disadvantage is that you're restricted to elements that were covered in the considered cell types (although, offsetting that is the point that really specialized stuff is less likely to be in the database, anyway).

+ +

Choice 3: all regions covered. Probably a better choice (though requiring a bit more work) is to derive the universe from your actual data. The natural choice would be to use the set of regions your experiment actually covered. You can think of this universe as the set of regions you tested for possible inclusion in your user sets; or, in other words, it is the restricted background set of regions that were tested, including everything in your regions of interest as well as those that were tested but did not get included. If you can easily come up with such a test for your problem, this is a really good choice for background universe. The resulting test will give you overlaps with database regions without penalizing for areas that weren't even covered in your experiment anyway. This asks: what's special about my regions that increased, versus all the regions that didn't?

+ +

Choice 4: changing regions only Finally, you could make a very restrictive universe by just combining your two region sets of interest. In this case, it would be the set of regions that either increased or decreased. The result of this test will give you the enrichment of the increased regions relative to changing regions. This is a subtly different question to ask than using the set of all covered regions (choice 3). The LOLA R package provides an easy way to do this with the buildRestrictedUniverse function, and you can accomplish the same thing with the radio button on LOLAweb. It assumes that we're only interested in regions that change, then we ask the question: what's special about the ones that increased?

+ +

In the case of DNA methylation: all regions that had reasonable coverage of methylation reads are your universe, and those that were either highly methylated or lowly methylated (or differentially methylated) would be your subsets of interest. It's the set including all genes that had enough reads that they could have been differentially methylated, even if they weren't.

+
+ + + + From 321acd81c6c893ee610d8a5f053663806acb09b0 Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 19 Apr 2018 09:48:39 -0400 Subject: [PATCH 44/65] major docs update - switch from html to md - add info on databases - add more howtos --- apps/LOLAweb/about.html | 39 ++++++++ apps/LOLAweb/about.md | 215 ++++++++++++++++++++++++++++++++++++++++ apps/LOLAweb/app.R | 10 +- 3 files changed, 259 insertions(+), 5 deletions(-) create mode 100644 apps/LOLAweb/about.md diff --git a/apps/LOLAweb/about.html b/apps/LOLAweb/about.html index d5440ee..0428854 100644 --- a/apps/LOLAweb/about.html +++ b/apps/LOLAweb/about.html @@ -7,6 +7,7 @@
  • What is LOLAweb?
  • How do I use LOLAweb?
  • What universe should I choose?
  • +
  • What database should I choose?
  • Can I share my LOLAweb results with others?
  • How long are LOLAweb results kept?
  • @@ -52,6 +53,44 @@

    What universe should I choose?

    In the case of DNA methylation: all regions that had reasonable coverage of methylation reads are your universe, and those that were either highly methylated or lowly methylated (or differentially methylated) would be your subsets of interest. It's the set including all genes that had enough reads that they could have been differentially methylated, even if they weren't.

    +
    + + +

    What database should I choose?

    + + LOLAweb provides access to a few curated databases we have put together for you. If you want to run LOLAweb on a custom database, that's also possible, but you'd have to download the app and run it locally. We provide docker containers that make this easy. Alternatively, the LOLA R package can work with custom databases and may be simpler, if you don't want to deal with a containerized setup or running your own local shiny server. + + But because databases are too large , with LOLAwebWhen you select a reference + + Current contents of LOLA core: + + * hg19/hg38 + 1. Transcription Factor binding sites from [ENCODE](http://hgdownload.cse.ucsc.edu/goldenPath/hg19/encodeDCC/wgEncodeAwgTfbsUniform/) + 2. Tissue clustered DNase hypersensitive sites from [Sheffield et al. (2013)](http://dnase.genome.duke.edu) + 3. [Codex database](http://codex.stemcells.cam.ac.uk/) + 4. A collection of UCSC feature tables (like CpG islands) + 5. Cistrome database from [Cistrome](http://dx.doi.org/10.1186/gb-2011-12-8-r83) + 6. Epigenome databases from [Cistrome](http://dx.doi.org/10.1186/gb-2011-12-8-r83) + * mm10 + 1. [Codex database](http://codex.stemcells.cam.ac.uk/) + 2. Cistrome database + 3. Encode TFBS + + + Current contents of LOLA Extended: + + * hg19/hg38 + 1. Roadmap epigenomics regions + 2. JASPAR motif matches + + +
    + +

    Can I use a custom database with LOLAweb?

    +

    Yes, you can, but you'll have to run LOLAweb locally. Luckily, we make this easy. LOLAweb provides access to a few curated databases we have put together for you. If you want to run LOLAweb on a custom database, that's also possible, but you'd have to download the app and run it locally. We provide docker containers that make this easy. Alternatively, the LOLA R package can work with custom databases and may be simpler, if you don't want to deal with a containerized setup or running your own local shiny server.

    + +
    +

    Can I share my LOLAweb results with others?

    Yes! Once you run your region sets through LOLAweb, you are redirected to a web page unique to your data. It will look something like this:

    diff --git a/apps/LOLAweb/about.md b/apps/LOLAweb/about.md new file mode 100644 index 0000000..225d7f1 --- /dev/null +++ b/apps/LOLAweb/about.md @@ -0,0 +1,215 @@ + + + +- [What is LOLAweb?](#what) +- [How do I use LOLAweb?](#how-to-use) +- [How do I cite LOLAweb?](#how-to-cite) +- [What universe should I choose?](#uni) +- [What database should I choose?](#database) +- [Can I use a custom database with LOLAweb?](#customdb) +- [How do I run LOLAweb locally?](#run-locally) +- [Can I share my LOLAweb results with others?](#share-results) +- [How long are LOLAweb results kept?](#results-kept) +- [What other resources are available for LOLAweb?](#other-resources) + +---------------------------------------- + + +### What is LOLAweb? + +LOLAweb is a web server and interactive results viewer for enrichment of overlap +between a query region set (a bed file) and a database of region sets. It +provides an interactive result explorer to visualize the highest ranked +enrichments from the database. LOLAweb is a web interface to the LOLA R package. + +-------------------------------------------------------------------------------- + + +### How do I use LOLAweb? + +Using LOLAweb is as easy as 1-2-3. First, all you really need is a bed file +(with at least 3 columns: chromosome, start, and end) identifying regions of +interest. These could be the result of a differential ChIP-seq or ATAC-seq +experiment, or anything, really. Upload that file by dragging it into the first +query box. You'll need to indicate which reference assembly your file subscribes +to. + +Second, choose a universe. If you have a set of background regions, upload them +here; otherwise, choose one of our built-in universe sets. + +Finally, choose a database. We offer a few options; just start with the default +Core database at first, but feel free to look around. If you want, you can +always use a custom database by running either LOLAweb or LOLA locally. + +Hit "Run LOLA" and watch the magic happen! The results will be displayed as an +interactive interface letting you sort and filter the top hits. The schematic +below demonstrates the whole process: + +LOLAweb workflow + +-------------------------------------------------------------------------------- + + +### What universe should I choose? + +One of the key questions when you run LOLA is what your background set, or +"universe" is. The universe is a bit open-ended, and it's reasonable to try a +few different things. Changing the universe isn't right or wrong, it just +changes the question you are asking. The universe set is tested for overlap with +the database, and the counts are used in the contingency tables that determine +significance for your user sets. The reason this is important is that if you +have some regions which were never really possible to end up in a region set of +interest, it's unfair to penalize your regions for not overlapping those regions +in the database, changing the results of the significance test. + + + +Let's imagine you've done an experiment where you're testing how some epigenomic +signal (say, H3K27ac or DNA methylation) responds to a perturbation. You end up +with a set of genomic regions that were covered by your assay, along with two +subsets of interest: those that increased, and those that decreased in signal +(see figure). + +In this case, one approach is to think of this as two user query sets: one for +each subset of regions that change. Now, what should your universe be? Well, you +have a few options. Let's go through 4 common universe choices see what they +mean about the significance test you're performing. The four choices move in +increasing order of specificity: + +Choice 1: genome tiles. LOLAweb lets you choose tiling regions of various +sizes. These tiles are little better than generic splits of the genome because +they at least account for reference assembly gaps. But otherwise, this is a +pretty basic background set which doesn't restrict the question at all. This +would be a useful universe to choose if you are not sure what to expect, and +your experiment could have included any genomic region as output. The result +will tell you what database region sets are enriched in your query sets +generally, across the whole genome. + +Choice 2: any regulatory elements. A bit more restricted universe set is +the set of active regulatory elements. LOLAweb includes a manually curated +universe set that was derived by merging all of the DNAse hypersensitivity data +from over 100 cell types from the ENCODE project. This set will restrict your +significance test to only active regulatory elements, so it's a reasonable +background set if you're looking at ChIP-seq data or some other active signal, +but may not be relevant for every experiment type. In practice, we find this to +be a useful first pass test for many experiments. Relative to the tiling +approach, this, for example, won't penalize your overlap test for not +overlapping a database region that's hidden away in a heterochromatic region. It +yields which database region sets are enriched in your query set, but only +considering active parts of the genome. An advantage of this approach is that +it's easy: we've already defined that set for you and you can just select it. A +disadvantage is that you're restricted to elements that were covered in the +considered cell types (although, offsetting that is the point that really +specialized stuff is less likely to be in the database, anyway). + +Choice 3: all regions covered. Probably a better choice (though requiring +a bit more work) is to derive the universe from your actual data. The natural +choice would be to use the set of regions your experiment actually covered. You +can think of this universe as the set of regions you tested for possible +inclusion in your user sets; or, in other words, it is the restricted background +set of regions that were tested, including everything in your regions of +interest as well as those that were tested but did not get included. If you can +easily come up with such a test for your problem, this is a really good choice +for background universe. The resulting test will give you overlaps with database +regions without penalizing for areas that weren't even covered in your +experiment anyway. This asks: what's special about my regions that increased, +versus all the regions that didn't? + +Choice 4: changing regions only Finally, you could make a very +restrictive universe by just combining your two region sets of interest. In this +case, it would be the set of regions that either increased or decreased. The +result of this test will give you the enrichment of the increased regions +relative to changing regions. This is a subtly different question to ask +than using the set of all covered regions (choice 3). The LOLA R package +provides an easy way to do this with the buildRestrictedUniverse +function, and you can accomplish the same thing with the radio button on +LOLAweb. It assumes that we're only interested in regions that change, then we +ask the question: what's special about the ones that increased? + +In the case of DNA methylation: all regions that had reasonable coverage of +methylation reads are your universe, and those that were either highly +methylated or lowly methylated (or differentially methylated) would be your +subsets of interest. It's the set including all genes that had enough reads that +they could have been differentially methylated, even if they weren't. + +-------------------------------------------------------------------------------- + + + +### What database should I choose? + +LOLAweb provides access to a few curated databases we have put together for you. +If you want to run LOLAweb on a custom database, that's also possible, but you'd +have to download the app and run it locally. When you select a genome assembly, +LOLAweb will automatically populate the database dropdown menu with all +available databases for the chosen assembly. Here are the contents of the +databases currently available to LOLAweb users: + +**LOLA Core**: + +* hg19/hg38 + 1. Transcription Factor binding sites from [ENCODE](http://hgdownload.cse.ucsc.edu/goldenPath/hg19/encodeDCC/wgEncodeAwgTfbsUniform/) + 2. Tissue clustered DNase hypersensitive sites from [Sheffield et al. (2013)](http://dnase.genome.duke.edu) + 3. [Codex database](http://codex.stemcells.cam.ac.uk/) + 4. A collection of UCSC feature tables (like CpG islands) + 5. Cistrome database from [Cistrome](http://dx.doi.org/10.1186/gb-2011-12-8-r83) + 6. Epigenome databases from [Cistrome](http://dx.doi.org/10.1186/gb-2011-12-8-r83) +* mm10 + 1. [Codex database](http://codex.stemcells.cam.ac.uk/) + 2. Cistrome database + 3. Transcription Factor binding sites from ENCODE +* mm9 + A `liftOver` version of the `mm10` database. + +**LOLA Roadmap**: + +* hg19/hg38 + All files downloaded from the Roadmap Epigenomics project. + +**LOLA Jaspar**: +* hg19/hg38 + We scanned the genome assembly for motif matches to every motif in the JASPAR + database. Each motif has an entry in the database with all its matches. This + enables you to do a type of simple motif enrichment analysis to see if your + regions significantly overlap the set of motif matches for any known motifs. + + +-------------------------------------------------------------------------------- + + +### Can I use a custom database with LOLAweb? + +Yes, you can, but you'll have to run LOLAweb locally because it's not practical +to let users upload an entire database. Luckily, we've containerized LOLAweb, so +it's relatively easy to run it locally. Alternatively, the LOLA R package can +work with custom databases and may be simpler, if you don't want to deal with a +containerized setup or running your own local shiny server. + +-------------------------------------------------------------------------------- + + +### Can I share my LOLAweb results with others? +Yes! Once you run your region sets through LOLAweb, you are redirected to a web +page unique to your data. It will look something like this: + +
    http://lolaweb.databio.org/?key=VWQN3ZC5HFD92EK
    + +This link can be sent to other users to share your findings. We do not store +your original data or any identifying information about who submitted it. + +-------------------------------------------------------------------------------- + + +### How long are LOLAweb results kept? + +LOLAweb results are stored on our servers for one year, then automatically deleted. + +-------------------------------------------------------------------------------- + + +### How do I run LOLAweb locally? + +blah.blahl. \ No newline at end of file diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 3618f46..8dc479d 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -198,17 +198,17 @@ ui <- list( id = "result-tabs"))) ) ), - tabPanel("About", - includeHTML("about.html") + tabPanel("AboutMD", + includeMarkdown("about.md") ), footer = div(HTML( paste0("
    Built by the Sheffield Computational Biology Lab and SOMRC at UVA.
    View source code on GitHub or run it locally with SOMRC at UVA.
    View source code on GitHub or run it locally with Docker", "
    LOLAweb version: our docker image", "
    LOLAweb version: ", lw_version, "
    ") ), From 2a7a3aea0496d7aef4b33492d20d9378bbd4e57e Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 19 Apr 2018 11:42:07 -0400 Subject: [PATCH 45/65] update docker instructions --- docker/README.md | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/docker/README.md b/docker/README.md index 1e2ca0e..6935530 100644 --- a/docker/README.md +++ b/docker/README.md @@ -17,29 +17,43 @@ The image itself is hosted at dockerhub: https://hub.docker.com/r/databio/lolaweb/ -## Reference Data +## Container volumes and reference data -See the [LOLAweb documentation](https://github.com/databio/LOLAweb/tree/master/apps/LOLAweb) for downloading reference data. +LOLAweb needs access to a few folders where it can store results or logs, or access necessary files like the database. To handle this, we've set up the app to look for two shell environment variables: +* **$LWREF**, for LOLAweb reference data, which may be read-only +* **$LWLOCAL**, where local results can be written. -## `run` the LOLAweb container locally with reference data: +To get the LOLAweb container to work, you need to set these environment variables (for example, in your `.bashrc` or `.profile` file. + +### LWREF + +LOLAweb will look at the value in `LWREF` for the reference data. This folder should have subfolders called `databases`, `universes`, and `examples`. In each of these subfolders are another layer of subfolders for genome assemblies. See the [LOLAweb documentation](https://github.com/databio/LOLAweb/tree/master/apps/LOLAweb) for downloading reference data. + +### LWLOCAL + +LOLAweb looks for `$LWLOCAL` to have two subfolders: `cache`, and `shinylogs`. This is where the app will write results and log files. + +## Run the LOLAweb container locally with reference data: docker run -d \ -p 80:80 \ - -v /data/lola/reference:/srv/shiny-server/LOLAweb/apps/LOLAweb/reference \ - -v /data/lola/universes:/srv/shiny-server/LOLAweb/apps/LOLAweb/universes \ - -v /data/lola/userSets:/srv/shiny-server/LOLAweb/apps/LOLAweb/userSets \ - -v /data/lola/cache:/srv/shiny-server/LOLAweb/apps/LOLAweb/cache \ - -v /data/lola/shinylog:/var/log/shiny-server \ + --volume ${LWLOCAL}:${LWLOCAL} \ + --volume ${LWREF}:${LWREF} \ + -e LWREF=$LWREF \ + -e LWLOCAL=$LWLOCAL \ databio/lolaweb -The first four volumes are for reference data and result sets. The final volume is a unified log directory, allowing admins to view logs generated by the Shiny application. - Open a browser to: ``` http://localhost/LOLAweb/apps/LOLAweb ``` -## Run LOLAweb in a Docker Swarm: +## Running a dev container + +You could also run the `dev` version of the container by just changing `databio/lolaweb` to `databio/lolaweb:dev`. This will pull the dev tagged image from dockerhub. + + +## Running multiple LOLAweb containers simultaneously with Docker Swarm: -Docker Swarm is a technique for running multiple instances of the same container. [Read more](swarm/README.md) about how to set up your own swarm. +For the typical use case of an individual user, a single running container will suffice. But if you need to set up an enterprise-level LOLAweb server that can handle concurrent users, we've also made that easy by using docker swarm. This is how we run the main LOLAweb servers, and you could do the same thing if you want your own local implementation. Docker Swarm is a technique for running multiple instances of the same container. [Read more](swarm/README.md) about how to set up your own swarm. From 8ced2d74036f6e22bbc0becb0ca085958ac97ba4 Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 19 Apr 2018 13:29:38 -0400 Subject: [PATCH 46/65] update docs --- apps/LOLAweb/about.md | 66 +++++++++++++++++++++++++++++++------------ apps/LOLAweb/app.R | 2 +- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/apps/LOLAweb/about.md b/apps/LOLAweb/about.md index 225d7f1..d962865 100644 --- a/apps/LOLAweb/about.md +++ b/apps/LOLAweb/about.md @@ -5,12 +5,12 @@ - [How do I use LOLAweb?](#how-to-use) - [How do I cite LOLAweb?](#how-to-cite) - [What universe should I choose?](#uni) -- [What database should I choose?](#database) +- [What is in the LOLAweb region set databases?](#database) - [Can I use a custom database with LOLAweb?](#customdb) - [How do I run LOLAweb locally?](#run-locally) - [Can I share my LOLAweb results with others?](#share-results) - [How long are LOLAweb results kept?](#results-kept) -- [What other resources are available for LOLAweb?](#other-resources) +- [What can I find more information or support?](#other-resources) ---------------------------------------- @@ -20,9 +20,8 @@ LOLAweb is a web server and interactive results viewer for enrichment of overlap between a query region set (a bed file) and a database of region sets. It provides an interactive result explorer to visualize the highest ranked -enrichments from the database. LOLAweb is a web interface to the LOLA R package. +enrichments from the database. LOLAweb is a web interface to the [LOLA R +package](http://bioconductor.org/packages/LOLA/). -------------------------------------------------------------------------------- @@ -51,6 +50,13 @@ below demonstrates the whole process: -------------------------------------------------------------------------------- + +### How do I cite LOLAweb? + +LOLAweb is pending publication. + +-------------------------------------------------------------------------------- + ### What universe should I choose? @@ -139,14 +145,16 @@ they could have been differentially methylated, even if they weren't. -### What database should I choose? +### What is in the LOLAweb region set databases? LOLAweb provides access to a few curated databases we have put together for you. -If you want to run LOLAweb on a custom database, that's also possible, but you'd -have to download the app and run it locally. When you select a genome assembly, -LOLAweb will automatically populate the database dropdown menu with all -available databases for the chosen assembly. Here are the contents of the -databases currently available to LOLAweb users: +You can also [run LOLAweb on a custom database](#customdb), if you want. But the +online version provides a few useful databases that will suffice for the +majority of users. + +When you select a genome assembly, LOLAweb will automatically populate the +database dropdown menu with all available databases for the chosen assembly. +Here are the contents of the databases currently available to LOLAweb users: **LOLA Core**: @@ -184,9 +192,19 @@ databases currently available to LOLAweb users: Yes, you can, but you'll have to run LOLAweb locally because it's not practical to let users upload an entire database. Luckily, we've containerized LOLAweb, so -it's relatively easy to run it locally. Alternatively, the LOLA R package can -work with custom databases and may be simpler, if you don't want to deal with a -containerized setup or running your own local shiny server. +it's relatively easy to run it locally. Alternatively, the [LOLA R +package](http://bioconductor.org/packages/LOLA/) can work with custom databases +and may be simpler, if you don't want to deal with a containerized setup or +running your own local shiny server. But if you do want to run LOLAweb locally, +check out *[how to run LOLAweb locally](#run-locally)*. + +-------------------------------------------------------------------------------- + + +### How do I run LOLAweb locally? + +You'll need to be familiar with [Docker](http://docker.com). You can find the Docker container for LOLAweb at [Dockerhub (https://hub.docker.com/r/databio/lolaweb/)](https://hub.docker.com/r/databio/lolaweb/). Instructions for run a local LOLAweb instance are here: https://github.com/databio/LOLAweb/tree/master/docker + -------------------------------------------------------------------------------- @@ -207,9 +225,21 @@ your original data or any identifying information about who submitted it. LOLAweb results are stored on our servers for one year, then automatically deleted. --------------------------------------------------------------------------------- + +### Where can I find more information or support? + +Here are + +- [LOLAweb Issue tracker](https://github.com/databio/LOLAweb/issues) - please use this for support requests for LOLAweb. +- [LOLAweb GitHub source code](https://github.com/databio/LOLAweb) +- [Dockerhub docker image](https://hub.docker.com/r/databio/lolaweb/) +- Manuscript (pending) +- [LOLA R package at Bioconductor](http://bioconductor.org/packages/LOLA/) +- [LOLA R package source code at GitHub](https://github.com/nsheff/LOLA) +- [LOLA R package documentation](http://code.databio.org/LOLA) +- [Published Bioinformatics paper describing LOLA](http://dx.doi.org/10.1093/bioinformatics/btv612) +- [Region set databases and vignette data](http://cloud.databio.org) + + - -### How do I run LOLAweb locally? -blah.blahl. \ No newline at end of file diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 8dc479d..564c2d0 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -198,7 +198,7 @@ ui <- list( id = "result-tabs"))) ) ), - tabPanel("AboutMD", + tabPanel("About", includeMarkdown("about.md") ), footer = div(HTML( From d9d45fa85b43d3c68eaf9c88ba194fddd9ce14c2 Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 19 Apr 2018 15:28:31 -0400 Subject: [PATCH 47/65] restyle master slider --- apps/LOLAweb/about.md | 41 +++++++++++++++++++++++++++++++------- apps/LOLAweb/app.R | 3 +-- apps/LOLAweb/www/style.css | 28 +++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/apps/LOLAweb/about.md b/apps/LOLAweb/about.md index d962865..ce301e2 100644 --- a/apps/LOLAweb/about.md +++ b/apps/LOLAweb/about.md @@ -1,7 +1,7 @@ -- [What is LOLAweb?](#what) +- [What is LOLAweb and what is it used for?](#what) - [How do I use LOLAweb?](#how-to-use) - [How do I cite LOLAweb?](#how-to-cite) - [What universe should I choose?](#uni) @@ -15,7 +15,7 @@ ---------------------------------------- -### What is LOLAweb? +### What is LOLAweb and what is it used for? LOLAweb is a web server and interactive results viewer for enrichment of overlap between a query region set (a bed file) and a database of region sets. It @@ -23,6 +23,8 @@ provides an interactive result explorer to visualize the highest ranked enrichments from the database. LOLAweb is a web interface to the [LOLA R package](http://bioconductor.org/packages/LOLA/). +LOLA web is useful for exploring enrichment of genomic ranges. Frequently, we uncover sets of genomic regions as relevant for some particular biological scenario. For example, they may be binding sites of a given transcription + -------------------------------------------------------------------------------- @@ -70,6 +72,19 @@ have some regions which were never really possible to end up in a region set of interest, it's unfair to penalize your regions for not overlapping those regions in the database, changing the results of the significance test. +LOLAweb provides 3 basic options. These options are briefly introduced here, and +then details on how to decide are provided below: + +**Use pre-loaded universe**: Here you can select from a series of universes we +have already created for you. These universes vary based on the reference genome +assembly you have chosen. They may include tiling regions (which). LOLAweb +includes a manually curated universe set that was derived by merging all of the +DNAse hypersensitivity data from over 100 cell types from the ENCODE project. + +**Build restricted universe**: + +** + @@ -135,11 +150,20 @@ function, and you can accomplish the same thing with the radio button on LOLAweb. It assumes that we're only interested in regions that change, then we ask the question: what's special about the ones that increased? -In the case of DNA methylation: all regions that had reasonable coverage of -methylation reads are your universe, and those that were either highly -methylated or lowly methylated (or differentially methylated) would be your -subsets of interest. It's the set including all genes that had enough reads that -they could have been differentially methylated, even if they weren't. + +### How could I define my own universe? + +If you want complete control over the question you're asking, the best thing to do is define your own universe. How to do this depends on the particular data you're looking at. Here we outline a few guidelines for common data types to get you started in how to think about the universe: + +**DNA methylation data**: all regions that had reasonable coverage of methylation +reads are your universe, and those that were either highly methylated or lowly +methylated (or differentially methylated) would be your subsets of interest. +It's the set of CpGs including all CpGs that had enough reads that they could +have been differentially methylated, even if they weren't. The universe could be +quite different for RRBS (reduced representation bisulfite sequencing) vs. WGBS +(whole-genome bisulfite sequencing). + +**Chip-seq data**: -------------------------------------------------------------------------------- @@ -184,6 +208,9 @@ Here are the contents of the databases currently available to LOLAweb users: enables you to do a type of simple motif enrichment analysis to see if your regions significantly overlap the set of motif matches for any known motifs. +You can also download these databases and explore them yourself at +http://cloud.databio.org. + -------------------------------------------------------------------------------- diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 564c2d0..5bba657 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -778,9 +778,8 @@ server <- function(input, output, session) { output$slider_rank <- renderUI({ req(rawdat_res$rawdat) - sliderInput("slider_rank_i", - "Max Rank Cutoff", + "Max Rank Cutoff (master slider)", min = min(rawdat_res$rawdat$maxRnk, na.rm = TRUE), max = max(rawdat_res$rawdat$maxRnk, na.rm = TRUE), value = quantile(rawdat_res$rawdat$maxRnk, probs = 20/nrow(rawdat_res$rawdat))) diff --git a/apps/LOLAweb/www/style.css b/apps/LOLAweb/www/style.css index ba94293..9fd1768 100644 --- a/apps/LOLAweb/www/style.css +++ b/apps/LOLAweb/www/style.css @@ -38,4 +38,30 @@ .plot_header { display: inline-block; -} \ No newline at end of file +} + +.js-irs-1 .irs-bar { +border-top-color: #411; +border-bottom-color: #411; +} + +.js-irs-1 .irs-bar-edge { +border-color: #411; +} + +.js-irs-1 .irs-single, .js-irs-1 .irs-bar-edge, .js-irs-1 .irs-bar { +background: #722; +} + +/*.js-irs-1 .irs-bar { +border-top-color: #10d010; +border-bottom-color: #10d010; +} + +.js-irs-1 .irs-bar-edge { +border-color: #10d010; +} + +.js-irs-1 .irs-single, .js-irs-1 .irs-bar-edge, .js-irs-1 .irs-bar { +background: #0a0; +}*/ \ No newline at end of file From b2d6c7326cb5bf295ec6e7fe3e1c2ac1d0bbc8bb Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 19 Apr 2018 15:30:22 -0400 Subject: [PATCH 48/65] plot styles --- apps/LOLAweb/app.R | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 5bba657..a63d017 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -133,16 +133,16 @@ ui <- list( tabPanel("Scatterplot", shinyjs::hidden( div( - h4("Scatter Plot", class ="plot_header"), + h4("Scatterplot", class ="plot_header"), downloadButton("scatterplot_dl", label = "PDF", class = "dt-button"), id = "scatterhead" )), plotlyOutput("scatter")), - tabPanel("Histograms", + tabPanel("Barplots", column(5, - h4("Odds Ratio", class = "plot_header"), + h4("Odds ratio", class = "plot_header"), downloadButton("oddsratio_plot_dl", label = "PDF", class = "dt-button"), @@ -818,7 +818,7 @@ server <- function(input, output, session) { req(rawdat_res$rawdat) sliderInput("slider_oddsratio_i", - "Odds Ratio Cutoff", + "Odds ratio cutoff", min = round(min(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), 3), max = round(max(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), 3), value = round(min(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), 3)) @@ -832,15 +832,15 @@ server <- function(input, output, session) { data.frame( x = - c("Start Time ", - "End Time ", - "Elapsed Time ", + c("Start time ", + "End time ", + "Elapsed time ", "Cache ID ", "Regions ", "Genome ", "Universe ", "Database ", - "LOLAweb Commit Used "), + "LOLAweb commit used "), y = c(as.character(rawdat_res$run_sum$start_time), as.character(rawdat_res$run_sum$end_time), @@ -866,7 +866,7 @@ server <- function(input, output, session) { "Description: ", axis_label))) + geom_point(aes(col=userSet), alpha=.75) + - xlab("Log(P value)") + + xlab("log(p value)") + ylab("Odds ratio") + scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), max(rawdat_res$rawdat$oddsRatio, na.rm = TRUE))) + scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog, na.rm = TRUE), max(rawdat_res$rawdat$pValueLog, na.rm = TRUE))) + @@ -909,7 +909,7 @@ server <- function(input, output, session) { req(input$select_sort_i) - plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) + plot_input(dat(), "oddsRatio", "Odds ratio", input$select_sort_i) }) @@ -919,7 +919,7 @@ server <- function(input, output, session) { ".pdf", sep="") }, content = function(file) { - ggsave(file, plot = plot_input(dat(), "oddsRatio", "Odds Ratio", input$select_sort_i) + ggsave(file, plot = plot_input(dat(), "oddsRatio", "Odds ratio", input$select_sort_i) , device = "pdf") } ) @@ -932,7 +932,7 @@ server <- function(input, output, session) { req(rawdat_res$rawdat) sliderInput("slider_support_i", - "Support Cutoff", + "Support cutoff", min = round(min(rawdat_res$rawdat$support, na.rm=TRUE), 3), max = round(max(rawdat_res$rawdat$support, na.rm=TRUE), 3), value = round(min(rawdat_res$rawdat$support, na.rm=TRUE), 3)) @@ -979,7 +979,7 @@ server <- function(input, output, session) { req(input$select_sort_i) - plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) + plot_input(dat(), "pValueLog", "log(p value)", input$select_sort_i) }) @@ -989,7 +989,7 @@ server <- function(input, output, session) { ".pdf", sep="") }, content = function(file) { - ggsave(file, plot = plot_input(dat(), "pValueLog", "P Value (log scale)", input$select_sort_i) + ggsave(file, plot = plot_input(dat(), "pValueLog", "log(p value)", input$select_sort_i) , device = "pdf") } ) From d4b9344c1966d84c74dc7d0f7b4f1baa63be43db Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Thu, 19 Apr 2018 15:49:08 -0400 Subject: [PATCH 49/65] scatterplot now handles infinite log pvalues --- apps/LOLAweb/app.R | 179 ++++++++++++++++++++++++++++++++++++----- apps/LOLAweb/misc.R | 16 +++- apps/LOLAweb/scratch.R | 35 +++++--- 3 files changed, 201 insertions(+), 29 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 3618f46..d7b0bbb 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -557,7 +557,7 @@ server <- function(input, output, session) { userUniverse, regionDB, cores=4) - + # need to make sure user set is discrete even if coded as number resRedefined$userSet = as.character(resRedefined$userSet) @@ -860,21 +860,164 @@ server <- function(input, output, session) { scatterplot_input <- function() { - ggplot(dat(), aes(pValueLog, oddsRatio, size = log(support), - text = paste0("Collection: ", - collection, - "\n", - "Description: ", - axis_label))) + - geom_point(aes(col=userSet), alpha=.75) + - xlab("Log(P value)") + - ylab("Odds ratio") + - scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), max(rawdat_res$rawdat$oddsRatio, na.rm = TRUE))) + - scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog, na.rm = TRUE), max(rawdat_res$rawdat$pValueLog, na.rm = TRUE))) + - scale_size_continuous(range = c(0.5,4)) + - geom_blank(aes(text = collection)) + - theme_ns() + - guides(size = FALSE) + # dat <- dat()[!is.infinite(dat()$pValueLog) & !is.infinite(dat()$oddsRatio),] + # + # p <- + # ggplot(dat, aes(pValueLog, oddsRatio, + # text = paste0("Collection: ", + # collection, + # "\n", + # "Description: ", + # axis_label))) + + # geom_point(aes(col=userSet, size = log(support)), alpha=.75) + + # xlab("Log(P value)") + + # ylab("Odds ratio") + + # scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), max(rawdat_res$rawdat$oddsRatio, na.rm = TRUE))) + + # scale_x_continuous(limits = c(min(inf.omit(rawdat_res$rawdat$pValueLog), na.rm = TRUE)), max(inf.omit(rawdat_res$rawdat$pValueLog), na.rm = TRUE)) + + # scale_size_continuous(range = c(0.5,4)) + + # geom_blank(aes(text = collection)) + + # theme_ns() + + # guides(size = FALSE) + # + # if (any(is.infinite(dat()$pValueLog))) { + # + # inflogpval <- dat()[is.infinite(dat()$pValueLog),] + # inflogpval$pValueLog <- -1e-6 + # + # p <- p + geom_point(aes(pValueLog, oddsRatio), col = "black", pch="O", alpha = 0.75, data = inflogpval) + # + # } + # + # if (any(is.infinite(dat()$oddsRatio))) { + # + # infor <- dat()[is.infinite(dat()$oddsRatio),] + # infor$oddsRatio <- -1e-6 + # + # p <- p + geom_point(col = "black", pch="O", alpha = 0.75, data = infor) + # + # p + # + # } + # + # p + + # conditions for handling infinite log pvalues (i.e. pval = 0 due to perfect overlap ) + noinfres <- dat()[!is.infinite(dat()$pValueLog),] + + inflogpval <- dat()[is.infinite(dat()$pValueLog),] + inflogpval$pValueLog <- max(inf.omit(rawdat_res$rawdat$pValueLog))+1 + + # case when all the rows have infinite pvalues + if (all(is.infinite(dat()$pValueLog))) { + + p <- + ggplot() + + geom_point(aes(pValueLog, oddsRatio, + # need to construct custom text since the value is fudged + text = paste0( + "Log P Value: ", + "Infinite", + "\n", + "Odds Ratio: ", + oddsRatio, + "\n", + "Support: ", + support, + "\n", + "Collection: ", + collection, + "\n", + "Description: ", + axis_label)), + col = "black", + pch = "O", + alpha = 0.75, data = inflogpval) + + # ... when some have infinite values + } else if (any(is.infinite(dat()$pValueLog))) { + + p <- + ggplot() + + geom_point(aes(pValueLog, oddsRatio, + # need to construct custom text since the value is fudged + text = paste0( + "Log P Value: ", + "Infinite", + "\n", + "Odds Ratio: ", + oddsRatio, + "\n", + "Support: ", + support, + "\n", + "Collection: ", + collection, + "\n", + "Description: ", + axis_label)), + col = "black", + pch = "O", + alpha = 0.75, data = inflogpval) + + geom_point(aes(pValueLog, + oddsRatio, + text = paste0( + "Log P Value: ", + pValueLog, + "\n", + "Odds Ratio: ", + oddsRatio, + "\n", + "Support: ", + support, + "\n", + "Collection: ", + collection, + "\n", + "Description: ", + axis_label), + col=userSet, + size = log(support)), + alpha=.75, + data = noinfres) + + # ... when none have infinite values + } else { + + p <- + ggplot() + + geom_point(aes(pValueLog, + oddsRatio, + text = paste0( + "Log P Value: ", + pValueLog, + "\n", + "Odds Ratio: ", + oddsRatio, + "\n", + "Support: ", + support, + "\n", + "Collection: ", + collection, + "\n", + "Description: ", + axis_label), + col=userSet, + size = log(support)), + alpha=.75, + data = noinfres) + + } + + p + + xlab("Log(P value)") + + ylab("Odds ratio") + + scale_size_continuous(range = c(0.5,4)) + + scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio), max(rawdat_res$rawdat$oddsRatio))) + + scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog), max(inf.omit(rawdat_res$rawdat$pValueLog))+1)) + + guides(size = FALSE) + + theme_ns() + } @@ -884,7 +1027,7 @@ server <- function(input, output, session) { plot_render$state <- TRUE - ggplotly(scatterplot_input()) %>% + ggplotly(scatterplot_input(), tooltip = "text") %>% config(displayModeBar = FALSE) %>% layout( legend = list(orientation = "h", @@ -970,7 +1113,7 @@ server <- function(input, output, session) { sliderInput("slider_pvalue_i", "P Value Cutoff", min = round(min(rawdat_res$rawdat$pValueLog, na.rm=TRUE), 3), - max = round(max(rawdat_res$rawdat$pValueLog, na.rm=TRUE), 3), + max = round(max(inf.omit(rawdat_res$rawdat$pValueLog), na.rm=TRUE), 3), value = round(min(rawdat_res$rawdat$pValueLog, na.rm=TRUE), 3)) diff --git a/apps/LOLAweb/misc.R b/apps/LOLAweb/misc.R index 64fc341..c0b7bd4 100644 --- a/apps/LOLAweb/misc.R +++ b/apps/LOLAweb/misc.R @@ -6,6 +6,20 @@ round_top <- function(x,n) { } +# infinite value omission + +inf.omit <- function(x) { + + if(any(is.infinite(x))) { + + x <- x[!is.infinite(x)] + + } + + x + +} + # plot input plot_input <- function(res, metric, ylabel, sortcol) { @@ -15,7 +29,7 @@ plot_input <- function(res, metric, ylabel, sortcol) { res <- head(res,50) } - + # conditional for inverting rank sorting if(grepl("rnk", sortcol, ignore.case = TRUE)) { diff --git a/apps/LOLAweb/scratch.R b/apps/LOLAweb/scratch.R index 5b69860..69913a2 100644 --- a/apps/LOLAweb/scratch.R +++ b/apps/LOLAweb/scratch.R @@ -305,7 +305,7 @@ resRedefined = runLOLA(userSetsRedefined, restrictedUniverse, regionDB, cores=1) library(sodium) -keyphrase <- "486TQ3MHFJPU2D9" +keyphrase <- "9B1MPF7WEGYCZJ4" loadCaches(keyphrase, assignToVariable = "cipher", loadEnvir = globalenv(), cacheDir = "cache") cipher <- get("cipher", envir = globalenv()) @@ -324,7 +324,7 @@ library(magrittr) p <- res$resRedefined %>% - filter(maxRnk < 90) %>% + filter(maxRnk < 200) %>% arrange(desc(meanRnk)) %>% # ggplot(aes(description, eval(parse(text = "meanRnk")), oddsRatio, fill = userSet, group = id)) + ggplot(aes(reorder(axis_label, eval(parse(text = "meanRnk"))), rev(oddsRatio), fill = userSet, group = id)) + @@ -340,28 +340,43 @@ library(plotly) ggplotly(p) +noinfres <- res$resRedefined[!is.infinite(res$resRedefined$pValueLog),] + +# data with infinite pvalue log values +inflogpval <- res$resRedefined[is.infinite(res$resRedefined$pValueLog),] +inflogpval$pValueLog <- -1e-6 + +# data with +infor <- + q <- - res$resRedefined %>% - filter(maxRnk < 100) %>% + # res$resRedefined %>% + # mutate(pValueLog = ifelse(is.infinite(pValueLog), -1e-6, pValueLog)) %>% + noinfres %>% + filter(maxRnk < 1000) %>% arrange(desc(meanRnk)) %>% - ggplot(aes(pValueLog, oddsRatio, size = log(support), + ggplot(aes(pValueLog, oddsRatio), text = paste0("Collection: ", collection, "\n", "Description: ", - axis_label))) + - geom_point() + + axis_label)) + + geom_point(aes(size = log(support))) + xlab("P Value Log") + ylab("Odds Ratio") + # coord_flip() + geom_blank(aes(text = collection)) + + geom_point(col = "red", pch="O", alpha = 0.25, data = inflogpval) + theme_ns() -ggplotly(q, tooltip = c("x", "y", "size", "text")) +q + +ggplotly(q, tooltip = c("x")) x <- ggplotly(q, tooltip = c("x", "y", "size")) %>% layout(showlegend = TRUE, legendgroup = "size") - - +x +infcheck <- apply(res$resRedefined[,c("pValueLog", "oddsRatio")], 2, function(x) !is.infinite(x)) +res$resRedefined[infcheck[,1],] From dfdea72671b5b9c9728cdc709c570728624044e3 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Thu, 19 Apr 2018 17:57:53 -0400 Subject: [PATCH 50/65] now handling infinite odds ratios as well --- apps/LOLAweb/app.R | 146 +++++++++++++++++++++-------------------- apps/LOLAweb/scratch.R | 3 +- 2 files changed, 78 insertions(+), 71 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 96c359a..cccb934 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -820,7 +820,7 @@ server <- function(input, output, session) { sliderInput("slider_oddsratio_i", "Odds ratio cutoff", min = round(min(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), 3), - max = round(max(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), 3), + max = round(max(inf.omit(rawdat_res$rawdat$oddsRatio), na.rm = TRUE), 3), value = round(min(rawdat_res$rawdat$oddsRatio, na.rm = TRUE), 3)) }) @@ -860,79 +860,97 @@ server <- function(input, output, session) { scatterplot_input <- function() { # conditions for handling infinite log pvalues (i.e. pval = 0 due to perfect overlap ) - noinfres <- dat()[!is.infinite(dat()$pValueLog),] + # also accounting for infinite oddsRatio + noinfres <- dat()[!is.infinite(dat()$pValueLog) & !is.infinite(dat()$oddsRatio),] inflogpval <- dat()[is.infinite(dat()$pValueLog),] inflogpval$pValueLog <- max(inf.omit(rawdat_res$rawdat$pValueLog))+1 - # case when all the rows have infinite pvalues + infor <- dat()[is.infinite(dat()$oddsRatio),] + infor$oddsRatio <- -1e-6 + + infvals <- rbind(inflogpval, infor) + + # case when all the rows have infinite values if (all(is.infinite(dat()$pValueLog))) { p <- ggplot() + geom_point(aes(pValueLog, oddsRatio, # need to construct custom text since the value is fudged - text = paste0( - "Log P Value: ", - "Infinite", - "\n", - "Odds Ratio: ", - oddsRatio, - "\n", - "Support: ", - support, - "\n", - "Collection: ", - collection, - "\n", - "Description: ", - axis_label)), + text = paste0("Log P Value: ", "Infinite", "\n", "Odds Ratio: ", oddsRatio, "\n", "Support: ", support, "\n", "Collection: ",collection, "\n", "Description: ", axis_label)), col = "black", pch = "O", alpha = 0.75, data = inflogpval) - # ... when some have infinite values - } else if (any(is.infinite(dat()$pValueLog))) { + } else if (all(is.infinite(dat()$oddsRatio))) { + p <- + ggplot() + + geom_point(aes(pValueLog, oddsRatio, + # need to construct custom text since the value is fudged + text = paste0("Log P Value: ", pValueLog, "\n", "Odds Ratio: ", "NA", "\n", "Support: ", support, "\n", "Collection: ",collection, "\n", "Description: ", axis_label)), + col = "black", + pch = "O", + alpha = 0.75, data = infor) + + # ... when some have infinite values + } else if (any(is.infinite(dat()$pValueLog)) & !any(is.infinite(dat()$oddsRatio))) { + + p <- + ggplot() + + geom_point(aes(pValueLog, oddsRatio, + # need to construct custom text since the value is fudged + text = paste0("Log P Value: ", "Infinite", "\n", "Odds Ratio: ", oddsRatio, "\n", "Support: ", support, "\n", "Collection: ",collection, "\n", "Description: ", axis_label)), + col = "black", + pch = "O", + alpha = 0.75, data = inflogpval) + + geom_point(aes(pValueLog, + oddsRatio, + text = paste0("Log (p value): ", pValueLog, "\n", "Odds ratio: ", oddsRatio, "\n", "Support: ", support, "\n", "Collection: ", collection, "\n", "Description: ", axis_label), + col=userSet, + size = log(support)), + alpha=.75, + data = noinfres) + + # ... when some have infinite values + } else if (!any(is.infinite(dat()$pValueLog)) & any(is.infinite(dat()$oddsRatio))) { + + p <- + ggplot() + + geom_point(aes(pValueLog, oddsRatio, + # need to construct custom text since the value is fudged + text = paste0("Log P Value: ", pValueLog, "\n", "Odds Ratio: ", "NA", "\n", "Support: ", support, "\n", "Collection: ",collection, "\n", "Description: ", axis_label)), + col = "black", + pch = "O", + alpha = 0.75, data = infor) + + geom_point(aes(pValueLog, + oddsRatio, + text = paste0("Log (p value): ", pValueLog, "\n", "Odds ratio: ", oddsRatio, "\n", "Support: ", support, "\n", "Collection: ", collection, "\n", "Description: ", axis_label), + col=userSet, + size = log(support)), + alpha=.75, + data = noinfres) + + # ... when some have infinite values + } else if (any(is.infinite(dat()$pValueLog)) & any(is.infinite(dat()$oddsRatio))) { p <- ggplot() + geom_point(aes(pValueLog, oddsRatio, # need to construct custom text since the value is fudged - text = paste0( - "Log P Value: ", - "Infinite", - "\n", - "Odds Ratio: ", - oddsRatio, - "\n", - "Support: ", - support, - "\n", - "Collection: ", - collection, - "\n", - "Description: ", - axis_label)), + text = paste0("Log P Value: ", "Infinite", "\n", "Odds Ratio: ", oddsRatio, "\n", "Support: ", support, "\n", "Collection: ", collection, "\n", "Description: ", axis_label)), col = "black", pch = "O", alpha = 0.75, data = inflogpval) + + geom_point(aes(pValueLog, oddsRatio, + # need to construct custom text since the value is fudged + text = paste0( "Log P Value: ", pValueLog, "\n", "Odds Ratio: ", "NA", "\n", "Support: ", support, "\n", "Collection: ", collection, "\n", "Description: ", axis_label)), + col = "black", + pch = "O", + alpha = 0.75, data = infor) + geom_point(aes(pValueLog, oddsRatio, - text = paste0( - "Log P Value: ", - pValueLog, - "\n", - "Odds Ratio: ", - oddsRatio, - "\n", - "Support: ", - support, - "\n", - "Collection: ", - collection, - "\n", - "Description: ", - axis_label), + text = paste0("Log (p value): ",pValueLog,"\n","Odds ratio: ", oddsRatio, "\n", "Support: ", support, "\n", "Collection: ", collection,"\n", "Description: ", axis_label), col=userSet, size = log(support)), alpha=.75, @@ -945,34 +963,22 @@ server <- function(input, output, session) { ggplot() + geom_point(aes(pValueLog, oddsRatio, - text = paste0( - "Log P Value: ", - pValueLog, - "\n", - "Odds Ratio: ", - oddsRatio, - "\n", - "Support: ", - support, - "\n", - "Collection: ", - collection, - "\n", - "Description: ", - axis_label), + text = paste0("Log (p value): ",pValueLog,"\n","Odds ratio: ", oddsRatio, "\n", "Support: ", support, "\n", "Collection: ", collection,"\n", "Description: ", axis_label), col=userSet, size = log(support)), alpha=.75, - data = noinfres) + data = noinfres) } p + - xlab("log(p value)") + - ylab("Odds ratio") + + xlab("log(p value)") + + ylab("Odds ratio") + scale_size_continuous(range = c(0.5,4)) + - scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio), max(rawdat_res$rawdat$oddsRatio))) + - scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog), max(inf.omit(rawdat_res$rawdat$pValueLog))+1)) + + scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio)-1, + max(inf.omit(rawdat_res$rawdat$oddsRatio)))) + + scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog), + max(inf.omit(rawdat_res$rawdat$pValueLog))+1)) + guides(size = FALSE) + theme_ns() diff --git a/apps/LOLAweb/scratch.R b/apps/LOLAweb/scratch.R index 69913a2..ec16f2c 100644 --- a/apps/LOLAweb/scratch.R +++ b/apps/LOLAweb/scratch.R @@ -305,7 +305,8 @@ resRedefined = runLOLA(userSetsRedefined, restrictedUniverse, regionDB, cores=1) library(sodium) -keyphrase <- "9B1MPF7WEGYCZJ4" +# keyphrase <- "9B1MPF7WEGYCZJ4" +keyphrase <- "NHKZSD5B64EOLY1" loadCaches(keyphrase, assignToVariable = "cipher", loadEnvir = globalenv(), cacheDir = "cache") cipher <- get("cipher", envir = globalenv()) From 1693fce5b50e8257722cbc767a9cf9fbf9866f83 Mon Sep 17 00:00:00 2001 From: nem2p Date: Fri, 20 Apr 2018 11:11:19 -0400 Subject: [PATCH 51/65] Updates to documentation - ENV vars and VOLs --- README.md | 2 +- docker/swarm/README.md | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f18ca85..d7bfb2e 100644 --- a/README.md +++ b/README.md @@ -9,4 +9,4 @@ LOLAweb is implemented as an interactive Shiny app. You can run this app locally ## Dockerfile -We have also produced a Dockerfile and host an image on dockerhub (`databio/lolaweb`). You can read how to run LOLAweb locally in a docker container by reading the [instructions in the docker folder](docker/). +We have also produced a Dockerfile and published an image on Docker Hub (`databio/lolaweb`). You can read how to run LOLAweb locally in a docker container by reading the [instructions in the docker folder](docker/). diff --git a/docker/swarm/README.md b/docker/swarm/README.md index 997c16c..f6f74ec 100644 --- a/docker/swarm/README.md +++ b/docker/swarm/README.md @@ -37,11 +37,12 @@ services: ports: - "80" volumes: - - /data/lola/reference:/srv/shiny-server/LOLAweb/apps/LOLAweb/reference - - /data/lola/universes:/srv/shiny-server/LOLAweb/apps/LOLAweb/universes - - /data/lola/userSets:/srv/shiny-server/LOLAweb/apps/LOLAweb/userSets - - /data/lola/cache:/srv/shiny-server/LOLAweb/apps/LOLAweb/cache + - /data/lola:/data/lola + - /mnt/network-share/LOLAweb:/mnt/network-share/LOLAweb/ - /data/lola/shinylog:/var/log/shiny-server + environment: + - LWREF=/mnt/network-share/LOLAweb/ + - LWLOCAL=/data/lola/ deploy: mode: replicated replicas: 4 @@ -86,11 +87,12 @@ networks: Take note of a few important elements of this YAML file: - The `lolaweb` containers run on an internal overlay network, via port 80. -- Each container mounts four local volumes to read LOLA reference data. +- Each container mounts three local volumes to read LOLA reference data and universes, and to write logs to a common directory. +- Each container also launches with two ENV variables used by LOLAweb: [LWREF](../README.md#lwref) and [LWLOCAL](../README.md#lwlocal). - The swarm runs 4 replicas of the `lolaweb` container, each capped at 12GB of memory. -- The Shiny containers are labeled with additional information passed to the Træfik load balancer. +- Shiny containers are labeled with additional information passed to the Træfik load balancer. - Træfik listens on the overlay network port 80, and is published to the host network over port 80. Port 8080 provides a monitoring interface if so desired. -- One replica of the Træfik load balancer runs in that service, capped at 10MB of memory. +- One replica of the Træfik load balancer runs as a part of that service, capped at 10MB of memory. Notice that it is "placed" on a specific Docker swarm node. - Træfik mounts and monitors the Docker socket file in order to automatically update anytime the swarm behind it is updated. ## Container Images From 0dd6f5aba1343e3efde078f14200b46ec054cbe6 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Fri, 20 Apr 2018 14:10:25 -0400 Subject: [PATCH 52/65] square scatter plot --- apps/LOLAweb/app.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index cccb934..5958017 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -977,8 +977,10 @@ server <- function(input, output, session) { scale_size_continuous(range = c(0.5,4)) + scale_y_continuous(limits = c(min(rawdat_res$rawdat$oddsRatio)-1, max(inf.omit(rawdat_res$rawdat$oddsRatio)))) + + # expand = expand_scale(mult = c(0,0))) + scale_x_continuous(limits = c(min(rawdat_res$rawdat$pValueLog), - max(inf.omit(rawdat_res$rawdat$pValueLog))+1)) + + max(inf.omit(rawdat_res$rawdat$pValueLog))+5)) + + # expand = expand_scale(mult = c(0,0))) + guides(size = FALSE) + theme_ns() @@ -993,6 +995,8 @@ server <- function(input, output, session) { ggplotly(scatterplot_input(), tooltip = "text") %>% config(displayModeBar = FALSE) %>% layout( + height = 500, + width = 500, legend = list(orientation = "h", x = 0.44, y = -0.2, From bbe85b4cd1b8c397737d7d897f1bc4693456bb55 Mon Sep 17 00:00:00 2001 From: nsheff Date: Thu, 19 Apr 2018 15:41:10 -0400 Subject: [PATCH 53/65] case styles, notes --- apps/LOLAweb/app.R | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 5958017..e46d96e 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -162,7 +162,10 @@ ui <- list( plotOutput("pvalue_plot") ) ), - tabPanel("Distribution", + tabPanel("Genomic distribution", + HTML("These plots come from the + GenomicDistributions + package."), fluidRow( column(10, h4("Distribution over genome", class = "plot_header"), @@ -179,7 +182,7 @@ ui <- list( class = "dt-button"), plotOutput("dist_plot")), column(5, - h4("Genomic Partitions", class = "plot_header"), + h4("Genomic partitions", class = "plot_header"), downloadButton("part_plot_dl", label = "PDF", class = "dt-button"), @@ -189,9 +192,9 @@ ui <- list( tabPanel("Table", column(DT::dataTableOutput("res"), width = 12) ), - tabPanel("Run Summary", + tabPanel("Run summary", conditionalPanel(condition = "output.res", - h4("Run Summary"), + h4("Run summary"), tableOutput("run_sum"), style = "font-size:18px;") ) ), @@ -779,7 +782,7 @@ server <- function(input, output, session) { req(rawdat_res$rawdat) sliderInput("slider_rank_i", - "Max Rank Cutoff (master slider)", + "Max rank cutoff (master slider)", min = min(rawdat_res$rawdat$maxRnk, na.rm = TRUE), max = max(rawdat_res$rawdat$maxRnk, na.rm = TRUE), value = quantile(rawdat_res$rawdat$maxRnk, probs = 20/nrow(rawdat_res$rawdat))) From 93c2094d9853488120a3f0f2d895568179f10b26 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Fri, 20 Apr 2018 15:51:53 -0400 Subject: [PATCH 54/65] trying a slightly bigger size for square scatterplot --- apps/LOLAweb/app.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index e46d96e..899d957 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -998,8 +998,8 @@ server <- function(input, output, session) { ggplotly(scatterplot_input(), tooltip = "text") %>% config(displayModeBar = FALSE) %>% layout( - height = 500, - width = 500, + height = 600, + width = 600, legend = list(orientation = "h", x = 0.44, y = -0.2, From 8be1f2cdc1f5a6f7f506e3e67c16b29a84014546 Mon Sep 17 00:00:00 2001 From: nsheff Date: Fri, 20 Apr 2018 16:18:37 -0400 Subject: [PATCH 55/65] Some small docs updates --- apps/LOLAweb/about.md | 25 ++++++++++++++++++++++++- apps/LOLAweb/app.R | 12 ++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/apps/LOLAweb/about.md b/apps/LOLAweb/about.md index ce301e2..82da238 100644 --- a/apps/LOLAweb/about.md +++ b/apps/LOLAweb/about.md @@ -5,7 +5,9 @@ - [How do I use LOLAweb?](#how-to-use) - [How do I cite LOLAweb?](#how-to-cite) - [What universe should I choose?](#uni) +- [How could I define my own universe?](#custom-universe) - [What is in the LOLAweb region set databases?](#database) +- [What are the example query sets?](#examples) - [Can I use a custom database with LOLAweb?](#customdb) - [How do I run LOLAweb locally?](#run-locally) - [Can I share my LOLAweb results with others?](#share-results) @@ -25,6 +27,7 @@ package](http://bioconductor.org/packages/LOLA/). LOLA web is useful for exploring enrichment of genomic ranges. Frequently, we uncover sets of genomic regions as relevant for some particular biological scenario. For example, they may be binding sites of a given transcription +[...] -------------------------------------------------------------------------------- @@ -55,7 +58,9 @@ below demonstrates the whole process: ### How do I cite LOLAweb? -LOLAweb is pending publication. +LOLAweb is pending publication. In the interim, please cite the LOLA R package: + +[...] -------------------------------------------------------------------------------- @@ -85,6 +90,8 @@ DNAse hypersensitivity data from over 100 cell types from the ENCODE project. ** +[...] + @@ -150,7 +157,9 @@ function, and you can accomplish the same thing with the radio button on LOLAweb. It assumes that we're only interested in regions that change, then we ask the question: what's special about the ones that increased? +-------------------------------------------------------------------------------- + ### How could I define my own universe? If you want complete control over the question you're asking, the best thing to do is define your own universe. How to do this depends on the particular data you're looking at. Here we outline a few guidelines for common data types to get you started in how to think about the universe: @@ -211,6 +220,20 @@ Here are the contents of the databases currently available to LOLAweb users: You can also download these databases and explore them yourself at http://cloud.databio.org. +-------------------------------------------------------------------------------- + + +### What are the example query sets? + +**lamina.bed**. This is a set of regions that are identified as being attached +to the nuclear periphery. + +**ewing_DHS.bed**. This is a very small example of some DNase hypersensitivity sites +that are specific to Ewing sarcoma, a rare pediatric cancer. This is the example +set used in the LOLA vignettes and the data were from Sheffield et al. (2017). + +**mesenchymal_DHS.bed**. This example set is derived from ENCODE DNase hypersensitivity data + -------------------------------------------------------------------------------- diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index e46d96e..47bd047 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -159,9 +159,17 @@ ui <- list( downloadButton("pvalue_plot_dl", label = "PDF", class = "dt-button"), - plotOutput("pvalue_plot") + plotOutput("pvalue_plot"), HTML("These barplots depict the + top-ranking database region sets. The sort order for all 3 plots + is determined by the sort column selected in the Display Options + panel. At most, 50 region sets will be displayed. Entries with + multiple small bars represent multiple database replicates with + the same descriptive label. Further details on each comparison + can be found in the Table tab. ") ) ), + + tabPanel("Genomic distribution", HTML("These plots come from the GenomicDistributions @@ -439,7 +447,7 @@ server <- function(input, output, session) { radioButtons("universe_opts", "Universe", choiceValues = c("default", "user", "build"), - choiceNames = c("Use default universe", "Upload universe", "Build universe with user sets")) + choiceNames = c("Use pre-loaded universe", "Upload universe", "Build universe with user sets")) } else { From 39676a26246dd07a6eb81751cdb6d21695f8df43 Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Fri, 20 Apr 2018 22:59:05 -0400 Subject: [PATCH 56/65] including disabled version of build restricted universe button --- apps/LOLAweb/app.R | 17 +++++++++++++---- apps/LOLAweb/disabler.R | 18 ++++++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 899d957..3cfca40 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -2,6 +2,7 @@ options(shiny.maxRequestSize=100*1024^2) source("themes.R") source("misc.R") +source("disabler.R") library(shiny) library(LOLA) @@ -42,6 +43,13 @@ ui <- list( # javascript for redirect to results view tags$script("Shiny.addCustomMessageHandler('redirect', function(result_url) {window.location = result_url;});"), + # tags$script('Shiny.addCustomMessageHandler("jsCode", + # function(message) { + # console.log(message) + # eval(message.code); + # } + # ); + # '), tags$link(rel="shortcut icon", href="favicon.ico") ), @@ -438,14 +446,15 @@ server <- function(input, output, session) { if(nfiles$n > 1) { radioButtons("universe_opts", "Universe", - choiceValues = c("default", "user", "build"), + choiceValues = c("default", "user", "build"), choiceNames = c("Use default universe", "Upload universe", "Build universe with user sets")) } else { - radioButtons("universe_opts", "Universe", - choiceValues = c("default", "user"), - choiceNames = c("Use default universe", "Upload universe")) + # radioButtons("universe_opts", "Universe", + # choiceValues = c("default", "user", "build"), + # choiceNames = list("Use default universe", "Upload universe", tags$div("Build universe with user sets", style = "pointer-events:none; opacity: 0.4;"))) + HTML(disabledbutton) } diff --git a/apps/LOLAweb/disabler.R b/apps/LOLAweb/disabler.R index 909c879..437aa65 100644 --- a/apps/LOLAweb/disabler.R +++ b/apps/LOLAweb/disabler.R @@ -1,16 +1,22 @@ -disabledbutton <- "
    - +disabledbutton <- "
    +
    +
    +
    +
    From e2e29acbe6876b3df379552bc674a2a38fceee3e Mon Sep 17 00:00:00 2001 From: VP Nagraj Date: Fri, 20 Apr 2018 23:03:18 -0400 Subject: [PATCH 57/65] changing 'default' to 'pre-loaded' in universe label --- apps/LOLAweb/app.R | 3 --- apps/LOLAweb/disabler.R | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 3225f58..9bac689 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -459,9 +459,6 @@ server <- function(input, output, session) { } else { - # radioButtons("universe_opts", "Universe", - # choiceValues = c("default", "user", "build"), - # choiceNames = list("Use default universe", "Upload universe", tags$div("Build universe with user sets", style = "pointer-events:none; opacity: 0.4;"))) HTML(disabledbutton) } diff --git a/apps/LOLAweb/disabler.R b/apps/LOLAweb/disabler.R index 437aa65..08666b9 100644 --- a/apps/LOLAweb/disabler.R +++ b/apps/LOLAweb/disabler.R @@ -4,7 +4,7 @@ disabledbutton <- "
    From 4f258381669dde550618cdc48be57d5c5a6f4c28 Mon Sep 17 00:00:00 2001 From: nem2p Date: Mon, 23 Apr 2018 11:11:57 -0400 Subject: [PATCH 58/65] Updating docker documentation for ENV --- README.md | 4 ++-- docker/README.md | 7 ++++--- docker/swarm/README.md | 12 ++++++------ docker/swarm/docker-compose.yml | 11 ++++++----- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index d7bfb2e..167053f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,6 @@ This repository contains two components: 1) the shiny [app source code](apps/LOL LOLAweb is implemented as an interactive Shiny app. You can run this app locally by following the [instructions in the appfolder](apps/LOLAweb/). -## Dockerfile +## Docker -We have also produced a Dockerfile and published an image on Docker Hub (`databio/lolaweb`). You can read how to run LOLAweb locally in a docker container by reading the [instructions in the docker folder](docker/). +We have also produced a Dockerfile and published an image on Docker Hub (`databio/lolaweb`). Learn how to run LOLAweb locally in a docker container by reading the [instructions in the docker folder](docker/). diff --git a/docker/README.md b/docker/README.md index 6935530..441e662 100644 --- a/docker/README.md +++ b/docker/README.md @@ -38,10 +38,11 @@ LOLAweb looks for `$LWLOCAL` to have two subfolders: `cache`, and `shinylogs`. T docker run -d \ -p 80:80 \ - --volume ${LWLOCAL}:${LWLOCAL} \ - --volume ${LWREF}:${LWREF} \ -e LWREF=$LWREF \ -e LWLOCAL=$LWLOCAL \ + --volume ${LWLOCAL}:${LWLOCAL} \ + --volume ${LWREF}:${LWREF} \ + --volume ${LWLOCAL}/shinylog:/var/log/shiny-server databio/lolaweb Open a browser to: @@ -51,7 +52,7 @@ http://localhost/LOLAweb/apps/LOLAweb ## Running a dev container -You could also run the `dev` version of the container by just changing `databio/lolaweb` to `databio/lolaweb:dev`. This will pull the dev tagged image from dockerhub. +You could also run the `dev` version of the container by pulling `databio/lolaweb:dev`. This will retrieve the dev tagged image from dockerhub. ## Running multiple LOLAweb containers simultaneously with Docker Swarm: diff --git a/docker/swarm/README.md b/docker/swarm/README.md index f6f74ec..c87f0da 100644 --- a/docker/swarm/README.md +++ b/docker/swarm/README.md @@ -36,13 +36,13 @@ services: - net ports: - "80" - volumes: - - /data/lola:/data/lola - - /mnt/network-share/LOLAweb:/mnt/network-share/LOLAweb/ - - /data/lola/shinylog:/var/log/shiny-server environment: - - LWREF=/mnt/network-share/LOLAweb/ - - LWLOCAL=/data/lola/ + - LWREF=$LWREF + - LWLOCAL=$LWLOCAL + volumes: + - ${LWLOCAL}:${LWLOCAL} + - ${LWREF}:${LWREF} + - ${LWLOCAL}/shinylog:/var/log/shiny-server deploy: mode: replicated replicas: 4 diff --git a/docker/swarm/docker-compose.yml b/docker/swarm/docker-compose.yml index 60e0582..ed4a3d1 100644 --- a/docker/swarm/docker-compose.yml +++ b/docker/swarm/docker-compose.yml @@ -8,12 +8,13 @@ services: - net ports: - "80" + environment: + - LWREF=$LWREF + - LWLOCAL=$LWLOCAL volumes: - - /data/lola/reference:/srv/shiny-server/LOLAweb/apps/LOLAweb/reference - - /data/lola/universes:/srv/shiny-server/LOLAweb/apps/LOLAweb/universes - - /data/lola/userSets:/srv/shiny-server/LOLAweb/apps/LOLAweb/userSets - - /data/lola/cache:/srv/shiny-server/LOLAweb/apps/LOLAweb/cache - - /data/lola/shinylog:/var/log/shiny-server + - ${LWLOCAL}:${LWLOCAL} + - ${LWREF}:${LWREF} + - ${LWLOCAL}/shinylog:/var/log/shiny-server deploy: mode: replicated replicas: 4 From 9ca0140fc37338797755a4097ad0464f61850b30 Mon Sep 17 00:00:00 2001 From: nsheff Date: Mon, 23 Apr 2018 13:48:48 -0400 Subject: [PATCH 59/65] update docs, text size (see #78) --- apps/LOLAweb/about.md | 82 ++++++++++++++++++++++++++++++++----------- apps/LOLAweb/app.R | 68 ++++++++++++++++++++--------------- apps/LOLAweb/misc.R | 17 +++++---- 3 files changed, 113 insertions(+), 54 deletions(-) diff --git a/apps/LOLAweb/about.md b/apps/LOLAweb/about.md index 82da238..bd18820 100644 --- a/apps/LOLAweb/about.md +++ b/apps/LOLAweb/about.md @@ -3,6 +3,7 @@ - [What is LOLAweb and what is it used for?](#what) - [How do I use LOLAweb?](#how-to-use) +- [How does LOLAweb evaluate overlap?](#overlap-evaluation) - [How do I cite LOLAweb?](#how-to-cite) - [What universe should I choose?](#uni) - [How could I define my own universe?](#custom-universe) @@ -20,12 +21,25 @@ ### What is LOLAweb and what is it used for? LOLAweb is a web server and interactive results viewer for enrichment of overlap -between a query region set (a bed file) and a database of region sets. It -provides an interactive result explorer to visualize the highest ranked +between a user-provided query region set (a bed file) and a database of region +sets. It provides an interactive result explorer to visualize the highest ranked enrichments from the database. LOLAweb is a web interface to the [LOLA R package](http://bioconductor.org/packages/LOLA/). -LOLA web is useful for exploring enrichment of genomic ranges. Frequently, we uncover sets of genomic regions as relevant for some particular biological scenario. For example, they may be binding sites of a given transcription +LOLA web is useful for exploring enrichment of genomic ranges. Frequently, we +uncover sets of genomic regions as relevant for some particular biological +scenario. For example, they may be binding sites of a given transcription, +regions that change in methylation or histone modification signals after some +perturbation, regions that specify differences between two species or cell +states, and so on. From the way we've found the regions, we know something about +them, but we'd now like to know if anything else is known about these particular +regions. Have other experiments uncovered them as important for something? Have +they been highlighted in a large-scale project in some other related cell type? + +This is where LOLAweb can help. We test the query regions for overlap with +thousands of existing database region sets. By ranking the overlap, we can see +which existing datasets are most similar to the new query set. This enables us +to tie previous knowledge to our new genomic regions. [...] -------------------------------------------------------------------------------- @@ -55,12 +69,24 @@ below demonstrates the whole process: -------------------------------------------------------------------------------- + +### How does LOLAweb evaluate overlap? + +LOLA uses three summary statistics to assess the degree of overlap: 1) the P-value and 2) odds ratio from a Fisher's exact test, and 3) the raw number of overlapping regions. Each of these statistics emphasizes a different aspect of the comparison; for example, the number of overlapping regions emphasizes sheer volume of overlapping regions but does not correct for significance, while the odds ratio emphasizes relative enrichment but can be dominated by sets with small numbers of regions. To come up with an aggregate score that shares strengths of each of these statistics, LOLA ranks each pairwise comparison for each of these three statistics independently, and then calculates a combined rank for each region set by assigning it the worst (max) rank among these three. To rank highly in the combined rank, then, requires that a comparison do reasonably well on all three measures, because the worst score is taken. In our experience, this process prioritizes biologically relevant associations and eliminates spurious relationships [@Sheffield2016; @Assenov2014]. + +LOLA evaluates overlaps by comparing the query region set to each database region set and calculates the number of overlapping regions for each pairwise comparison. **The number of overlaps is called the Support** for that relationship. Along with a similar calculation for the universe region set, LOLA uses the number of overlaps and non-overlaps to build a contingency table, and then uses a Fisher's exact test to assess the significance of the overlap. After computing these statistics for each comparison, LOLA ranks each database region set and provides a ranked summary of the top database sets. This procedure effectively pulls out the region sets in the database that are most similar to the query region set. + +[ ... this section needs editing] + +-------------------------------------------------------------------------------- ### How do I cite LOLAweb? LOLAweb is pending publication. In the interim, please cite the LOLA R package: -[...] +N. C. Sheffield and C. Bock, “LOLA: enrichment analysis for genomic region sets and regulatory elements in R and Bioconductor,” Bioinformatics, vol. 32, no. 4, pp. 587–589, Oct. 2016. + +[http://dx.doi.org/10.1093/bioinformatics/btv612](http://dx.doi.org/10.1093/bioinformatics/btv612) -------------------------------------------------------------------------------- @@ -162,17 +188,30 @@ ask the question: what's special about the ones that increased? ### How could I define my own universe? -If you want complete control over the question you're asking, the best thing to do is define your own universe. How to do this depends on the particular data you're looking at. Here we outline a few guidelines for common data types to get you started in how to think about the universe: - -**DNA methylation data**: all regions that had reasonable coverage of methylation -reads are your universe, and those that were either highly methylated or lowly -methylated (or differentially methylated) would be your subsets of interest. -It's the set of CpGs including all CpGs that had enough reads that they could -have been differentially methylated, even if they weren't. The universe could be -quite different for RRBS (reduced representation bisulfite sequencing) vs. WGBS -(whole-genome bisulfite sequencing). - -**Chip-seq data**: +If you want complete control over the question you're asking, the best thing to +do is define your own universe. How to do this depends on the particular data +you're looking at. Here we outline a few guidelines for common data types to get +you started in how to think about the universe: + +**DNA methylation data**: You universe could be all regions that had reasonable +coverage of methylation reads, and your user sets could be those that were either +highly methylated or lowly methylated (or differentially methylated). The universe is the set of CpGs that had +enough reads that they could have been differentially methylated, even if they +weren't. The universe could be quite different for RRBS (reduced representation +bisulfite sequencing) vs. WGBS (whole-genome bisulfite sequencing) protocols. + +**Chip-seq data**: The universe could be the set of 1kb tiles that were covered +by an Input experiment. This test would show where ChIP peaks are generally +enriched relative to the whole genome, and will likely show enrichment in active +areas generally. Alternatively, the universe could be the union of all +transcription factor binding sites from large-scale projects like ENCODE, or the +pre- loaded set of active DNase hypersensitive sites. This universe would test +the enrichment of your ChIP peaks relative to other ChIP peaks, which will be +more likely to highlight cell-type differences. Finally, perhaps you have +differential peaks between two conditions. In this case, you could build a +*restricted* universe of just peaks covered by these two experiments. This test +would then show you how your increasing peaks are enriched relative only to +peaks in this one cell type. -------------------------------------------------------------------------------- @@ -223,16 +262,19 @@ http://cloud.databio.org. -------------------------------------------------------------------------------- -### What are the example query sets? +### What are the example user query sets? **lamina.bed**. This is a set of regions that are identified as being attached to the nuclear periphery. -**ewing_DHS.bed**. This is a very small example of some DNase hypersensitivity sites -that are specific to Ewing sarcoma, a rare pediatric cancer. This is the example -set used in the LOLA vignettes and the data were from Sheffield et al. (2017). +**ewing_DHS.bed**. This is a very small example of some DNase hypersensitivity +sites that are specific to Ewing sarcoma, a rare pediatric cancer. This is the +example set used in the LOLA vignettes and the data were from Sheffield et al. +(2017). -**mesenchymal_DHS.bed**. This example set is derived from ENCODE DNase hypersensitivity data +**mesenchymal_DHS.bed**. This example set is derived from ENCODE DNase +hypersensitivity data. It was derived by taking DNase hypersensitive sites with +high scores in mesenchymal cell types and low scores in all other cell types -------------------------------------------------------------------------------- diff --git a/apps/LOLAweb/app.R b/apps/LOLAweb/app.R index 9bac689..98e2180 100644 --- a/apps/LOLAweb/app.R +++ b/apps/LOLAweb/app.R @@ -155,7 +155,7 @@ ui <- list( label = "PDF", class = "dt-button"), plotOutput("oddsratio_plot"), - h4("Support", class = "plot_header"), + h4("Support (overlap count)", class = "plot_header"), downloadButton("support_plot_dl", label = "PDF", class = "dt-button"), @@ -242,13 +242,19 @@ server <- function(input, output, session) { # user sets addPopover(session=session, id="infouserset", - title="User Sets", - content="

    The User Set is your set of genomic regions that you - want to test for overlap with the database. Upload a file in BED format (really, it just needs the first 3 columns: - chr, start, and end). You can also drag and drop multiple files and - they will be analyzed simultaneously! + title="User query sets", + content="

    The regions of interest, also called the user query + set, is your set of genomic regions that you want to test for + overlap with the database. Upload a file in BED + format (really, it just needs the first 3 columns: chr, start, + and end). You can also drag and drop multiple files and they will + be analyzed simultaneously!

    + +

    You can also load example data for each reference genome. + Details about what regions are in these examples are on the About + tab. +

    ", placement = "bottom", trigger = "click", @@ -256,18 +262,22 @@ server <- function(input, output, session) { # universes addPopover(session=session, id="infouniverse", - title="Universes", - content="

    The universe is your background set of regions. You + title="Background universe", + content="

    The universe set is your background set of regions. You should think of the universe as the set of regions you tested for - possible inclusion in your user sets. We recommend you upload a - universe that is specific to the query set, but we also provide a - few basic region sets (like tiling regions, or the set of all - active DNaseI hypersensitive elements from the ENCODE project). The - choice of universe can have a drastic affect on the results of the - analysis, so it may also be worth running LOLA few times with - different universe sets. For further information, there are more - details on the About tab. -

    ", + possible inclusion in your user sets. You have 3 options: 1) we + provide a few pre-loaded region sets (like tiling regions, or the + set of all active DNaseI hypersensitive elements from the ENCODE + project) that can be useful for many analyses. 2), you can upload + your own universe, which lets you tailor the analysis to the query + set; 3) if you upload more than 1 query set, we can build a + universe by merging all of the uploaded query sets. The choice of + universe can have a drastic affect on the results of the analysis, + it may be worth running LOLA few times with different universe + sets. For further information, there are more details on the + About tab.

    ", placement = "bottom", trigger = "click", options = NULL) @@ -275,16 +285,18 @@ server <- function(input, output, session) { # region dbs addPopover(session=session, id="infodb", - title="Region Databases", + title="Region databases", # html for content with JS at the bottom to close popup content="

    We have provided a few different general-purpose - databases. We recommend starting with the Core database, but there - are also a few other more specific options if you want to extend - your analysis. Further details about what is contained in each - database can be found in the documentation on - LOLA region databases. -

    ", + databases. We recommend starting with the Core database, which + contains data from the ENCODE project, the cistrome project, and + other public data sources. We also provide databases containing + Roadmap Epigenomics data and motif searches using motifs from the + JASPAR motif database. Further details about what is contained in + each database can be found on the About tab.