Skip to content

Commit

Permalink
Merge pull request #11 from jumpingrivers/data-dir
Browse files Browse the repository at this point in the history
Data directory
  • Loading branch information
KieranODrake authored Feb 8, 2024
2 parents 1e7c80c + 347cf49 commit 412f8e9
Show file tree
Hide file tree
Showing 37 changed files with 3,498 additions and 320 deletions.
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
^renv$
^renv\.lock$
^tfpbrowser\.Rproj$
^\.Rproj\.user$
.lintr
Expand Down
1 change: 1 addition & 0 deletions .Rprofile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
source("renv/activate.R")
55 changes: 52 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,55 @@
.Rproj.user
# {shinytest2}: Ignore new debug snapshots for `$expect_values()`
*_.new.png

# Prevent the in-repo small example dataset being over-written with production data
inst/app/www/data/

# History files
.Rhistory
.Rapp.history

# Session Data files
.RData
.RDataTmp

# User-specific files
.Ruserdata
# {shinytest2}: Ignore new debug snapshots for `$expect_values()`
*_.new.png

# Example code in package build process
*-Ex.R

# Output files from R CMD build
/*.tar.gz

# Output files from R CMD check
/*.Rcheck/

# RStudio files
.Rproj.user/

# produced vignettes
vignettes/*.html
vignettes/*.pdf

# OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
.httr-oauth

# knitr and R markdown default cache directories
*_cache/
/cache/

# Temporary files created by R markdown
*.utf8.md
*.knit.md

# R Environment Variables
.Renviron

# pkgdown site
docs/

# translation temp files
po/*~

# RStudio Connect folder
rsconnect/
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ Suggests:
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.2
RoxygenNote: 7.2.3
4 changes: 0 additions & 4 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
# Generated by roxygen2: do not edit by hand

export("%>%")
export(create_all_node_lookups)
export(empty_treeview)
export(get_cluster_ID)
export(get_sequences_lookup)
export(run_app)
export(update_data)
importFrom(magrittr,"%>%")
importFrom(rlang,.data)
importFrom(rlang,.env)
13 changes: 10 additions & 3 deletions R/add_ext_resources.R
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
#' Add external resources to the shiny app
#'
#' Function is internally used to add external
#' resources inside the Shiny application.
add_ext_resources = function() {
#' Function is internally used to add external resources inside the Shiny application.
#'
#' @param data_dir The (server-side) file-path for the directory containing the data for
#' presentation. This should contain a `scanner_output` subdirectory, which will be mounted as
#' /data/scanner_output/ in the browser.

add_ext_resources = function(data_dir) {
shiny::addResourcePath(
"www", system.file("app/www", package = "tfpbrowser", mustWork = TRUE)
)
shiny::addResourcePath(
"data/scanner_output", file.path(data_dir, "scanner_output")
)
shiny::tags$head(
shinyjs::useShinyjs(),
shiny::tags$link(rel = "stylesheet", type = "text/css", href = "www/tfpbrowser-style.css")
Expand Down
58 changes: 42 additions & 16 deletions R/app_server.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,34 @@
#' @param input,output,session Internal parameters for `{shiny}`.
#' @noRd
app_server = function(input, output, session) {
data_dir = get_data_dir()

# Update the available treeviews & mutations
shiny::observe({
new_choices = c(
c("None" = ""),
available_treeview(data_dir = data_dir)
)
shiny::updateSelectInput(
session = session,
inputId = "widgetChoice",
choices = new_choices
)
})

shiny::observe({
mutation_set = available_mutations(data_dir = data_dir)
shiny::updateSelectInput(
session = session,
inputId = "mutationChoice",
choices = mutation_set
)
})

# Load treeview -----------------------------------------------------------
imported_ggtree = shiny::reactive({
shiny::req(input$widgetChoice)
filename = get_filename(input$widgetChoice)
filename = get_filename(input$widgetChoice, data_dir)
readRDS(filename)
})

Expand Down Expand Up @@ -64,19 +87,18 @@ app_server = function(input, output, session) {

# disable dropdown unless mutation treeview
shiny::observe({
shiny::req(input$widgetChoice)
choice = ifelse(input$widgetChoice != "", input$widgetChoice, "")
# toggle mutation dropdown
shinyjs::toggleState(id = "mutationChoice",
condition = input$widgetChoice == "tree-mutations.rds")
shinyjs::toggleElement(id = "mutationChoice",
condition = choice == "tree-mutations.rds")

Check warning on line 93 in R/app_server.R

View workflow job for this annotation

GitHub Actions / lint

file=R/app_server.R,line=93,col=25,[indentation_linter] Hanging indent should be 27 spaces but is 25 spaces.
# toggle sequence dropdown
shinyjs::toggleState(id = "sequenceChoice",
condition = input$widgetChoice == "tree-sequences.rds")
shinyjs::toggleElement(id = "sequenceChoice",
condition = choice == "tree-sequences.rds")

Check warning on line 96 in R/app_server.R

View workflow job for this annotation

GitHub Actions / lint

file=R/app_server.R,line=96,col=25,[indentation_linter] Hanging indent should be 27 spaces but is 25 spaces.
# select input for sequences
if (input$widgetChoice == "tree-sequences.rds") {
avail_seqs = data.table::as.data.table(available_sequences())
if (choice == "tree-sequences.rds") {
avail_seqs = data.table::as.data.table(available_sequences(data_dir))
names(avail_seqs) = "Sequences"
shiny::updateSelectizeInput(inputId = "sequenceChoice",
label = "Select sequence",
shiny::updateSelectInput(inputId = "sequenceChoice",
choices = avail_seqs

Check warning on line 102 in R/app_server.R

View workflow job for this annotation

GitHub Actions / lint

file=R/app_server.R,line=102,col=34,[indentation_linter] Indentation should be 8 spaces but is 34 spaces.
)

Check warning on line 103 in R/app_server.R

View workflow job for this annotation

GitHub Actions / lint

file=R/app_server.R,line=103,col=34,[indentation_linter] Indentation should be 6 spaces but is 34 spaces.
}
Expand All @@ -85,7 +107,7 @@ app_server = function(input, output, session) {
# get selected nodes from mutation choice
shiny::observeEvent(input$mutationChoice, {

nodeChoice = selected_mut_nodes(input$mutationChoice)
nodeChoice = selected_mut_nodes(input$mutationChoice, data_dir)

# the 'node' column contains integers that define the IDs for graph-nodes in the htmlwidget
node_map = imported_ggtree()$data[c("cluster_id", "node")]
Expand All @@ -107,7 +129,7 @@ app_server = function(input, output, session) {
# get selected nodes from sequence choice
shiny::observeEvent(input$sequenceChoice, {

nodeChoice = selected_seq_nodes(input$sequenceChoice)
nodeChoice = selected_seq_nodes(input$sequenceChoice, data_dir)

# the 'node' column contains integers that define the IDs for graph-nodes in the htmlwidget
node_map = imported_ggtree()$data[c("cluster_id", "node")]
Expand All @@ -131,7 +153,8 @@ app_server = function(input, output, session) {
shiny::req(input$widgetChoice)
shiny::req(input$treeview_selected)
get_selected_cluster_id(widgetChoice = input$widgetChoice,
treeviewSelected = utils::tail(input$treeview_selected, 1))
treeviewSelected = utils::tail(input$treeview_selected, 1),
data_dir = data_dir)
}) %>%
shiny::bindCache(input$widgetChoice, input$treeview_selected)

Expand All @@ -154,19 +177,22 @@ app_server = function(input, output, session) {
# Tables Tab --------------------------------------------------------------
tablesServer(
"table1",
cluster_choice = selected_cluster_id
cluster_choice = selected_cluster_id,
data_dir = data_dir
)

# Plots Tab ----------------------------------------------------------
plotsServer(
"plot1",
cluster_choice = selected_cluster_id
cluster_choice = selected_cluster_id,
data_dir = data_dir
)

# RDS Tab ----------------------------------------------------------
rdsServer(
"rds1",
cluster_choice = selected_cluster_id
cluster_choice = selected_cluster_id,
data_dir = data_dir
)

} # end server function
72 changes: 44 additions & 28 deletions R/app_ui.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#' @param request Internal parameter for `{shiny}`.
#' @noRd
app_ui = function(request) {
data_dir <- get_data_dir()

Check warning on line 6 in R/app_ui.R

View workflow job for this annotation

GitHub Actions / lint

file=R/app_ui.R,line=6,col=12,[undesirable_operator_linter] Operator `<-` is undesirable. Use =, not <-, for assignment.

shiny::tagList(

shinyjs::useShinyjs(),
Expand All @@ -12,7 +14,7 @@ app_ui = function(request) {
# title
title = place_title_logo(),

header = add_ext_resources(),
header = add_ext_resources(data_dir),
# theme
theme = bslib::bs_theme(version = 4,
bootswatch = "minty",
Expand Down Expand Up @@ -57,34 +59,48 @@ app_ui = function(request) {

# Bottom row - show tree (static html output from tfpscanner)
shiny::fluidRow(

shiny::column(12,

# choose type of treeview
shiny::radioButtons(inputId = "widgetChoice",
label = "Select treeview",
choices = c(c("None" = ""), available_treeview()),
inline = TRUE),

# choose type of mutation
shiny::selectizeInput(inputId = "mutationChoice",
label = "Select mutation",
choices = available_mutations()),

# choose type of sequence
shiny::selectizeInput(inputId = "sequenceChoice",
label = "Select sequence",
choices = NULL),

# markdown files to add description
shiny::uiOutput("tree_md_files"),

# show treeview widget
shiny::wellPanel(
ggiraph::girafeOutput("treeview"),
style = "background: white; height: 1800px;",
),
shiny::br()
id="view-container",
shiny::div(id="view-selection",
htmltools::tags$details(
id="sidebar-toggle",
open="open",
`aria-role`="button",
`aria-label`="Toggle sidebar visibility",
htmltools::tags$summary(
shiny::span(">>"),
shiny::span("<<")
)
),
# choose type of treeview
shiny::selectInput(inputId = "widgetChoice",
label = "View",
choices = c("None" = ""),
selectize = FALSE),

# choose type of mutation
shiny::selectInput(inputId = "mutationChoice",
label = "Mutation",
choices = character(0),
selectize = FALSE),

# choose type of sequence
shiny::selectInput(inputId = "sequenceChoice",
label = "Sequence",
choices = NULL,
selectize = FALSE),
),
shiny::div(id="view-graphic",
# markdown files to add description
shiny::uiOutput("tree_md_files"),

# show treeview widget
shiny::wellPanel(
ggiraph::girafeOutput("treeview"),
style = "background: white; height: 1800px;",
),
shiny::br()
)
)
) # end fluid row
), # end "data" page
Expand Down
15 changes: 15 additions & 0 deletions R/config.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#' Obtain the optionally-specified data directory for the app
#'
#' The user can specify a data-directory by specifying the environment variable `APP_DATA_DIR`.
#' When given, this directory must have subdirectories: `mutations`, `scanner_output`, `sequences`,
#' `treeview`.
#' When not specified, data will be taken from the package-embedded directory `/app/www/data`.
#'
#' @return Scalar string. The data-directory for use in the app.

get_data_dir <- function() {
Sys.getenv(
"APP_DATA_DIR",
system.file("app", "www", "data", package = "tfpbrowser")
)
}
25 changes: 15 additions & 10 deletions R/module_plots.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ plotsUI = function(id) {
#' Plots tab Server
#' @param id ID for shiny module namespacing
#' @param cluster_choice which cluster to display the data for
#' @param data_dir The data directory for the app.
#' @noRd
plotsServer = function(id, cluster_choice) {
plotsServer = function(id, cluster_choice, data_dir) {
shiny::moduleServer(id, function(input, output, session) {
ns = session$ns # nolint

Expand All @@ -28,7 +29,7 @@ plotsServer = function(id, cluster_choice) {

# all available plots
all_files = shiny::reactive({
return(get_all_files(cluster_choice()))
return(get_all_files(cluster_choice(), data_dir = data_dir))
}) %>%
shiny::bindCache(cluster_choice())

Expand All @@ -47,19 +48,25 @@ plotsServer = function(id, cluster_choice) {
choices = all_images)
})

# get plot file
# the path to the plot, from the server's perspective
plot_file = shiny::reactive({
shiny::req(cluster_choice())
plot_file = system.file("app", "www", "data", "scanner_output",
cluster_choice(), input$plot_type,
package = "tfpbrowser")
plot_file = file.path(data_dir, "scanner_output", cluster_choice(), input$plot_type)
return(plot_file)
}) %>%
shiny::bindCache(cluster_choice(), input$plot_type)

# the path to the plot, from the browser's perspective
plot_url = shiny::reactive({
shiny::req(plot_file())

plot_subpath <- fs::path_rel(plot_file(), data_dir)
glue::glue("data/{plot_subpath}")
})

# check if plots available
plot_avail = shiny::reactive({
src = fs::path_rel(plot_file(), system.file("app", package = "tfpbrowser"))
src = plot_url()
if (length(src) != 0) {
return(grepl(".png", tolower(src)))
} else {
Expand All @@ -70,9 +77,7 @@ plotsServer = function(id, cluster_choice) {
# display plot if available
output$display_plot = shiny::renderUI({
if (plot_avail()) {
shiny::img(src = fs::path_rel(plot_file(),
system.file("app", package = "tfpbrowser")),
width = "400px")
shiny::img(src = plot_url(), width = "400px")
} else {
shiny::p("No plots available.", style = "color: red; text-align: left")
}
Expand Down
Loading

0 comments on commit 412f8e9

Please sign in to comment.