From 193d0b6bec71934fb8fed12d4d0f44927c4936b5 Mon Sep 17 00:00:00 2001 From: Federico Marini Date: Wed, 2 Oct 2024 17:05:45 +0200 Subject: [PATCH 1/7] yolo'ing the sets of changes done to have the runr up n running - so far uses a propagation of a parameter --- R/iSEEindex.R | 349 +++++++++++++++------------ R/iSEEindexResource-class.R | 32 +-- R/landing_page.R | 180 +++++++------- R/observers.R | 31 ++- R/utils-datasets.R | 146 +++++------ man/iSEEindex.Rd | 63 ++++- tests/testthat/test-observers.R | 2 +- tests/testthat/test-utils-datasets.R | 2 +- 8 files changed, 451 insertions(+), 354 deletions(-) diff --git a/R/iSEEindex.R b/R/iSEEindex.R index 6a3d95d..597b3d2 100644 --- a/R/iSEEindex.R +++ b/R/iSEEindex.R @@ -96,6 +96,7 @@ #' info on the versions of the `iSEEindex` and `iSEE` packages. #' @param body.header UI element to display \emph{above} the main landing page body. #' @param body.footer UI element to display \emph{below} the main landing page body. +#' @param already_se_object TODO #' #' @return An [iSEE::iSEE()] app with a custom landing page using a [BiocFileCache()] to cache a selection of data sets. #' @@ -107,17 +108,9 @@ #' @importFrom utils packageVersion #' #' @examples -#' ## -#' # BiocFileCache ---- -#' ## -#' -#' library(BiocFileCache) +#' library("BiocFileCache") #' bfc <- BiocFileCache(cache = tempdir()) #' -#' ## -#' # iSEEindex ---- -#' ## -#' #' dataset_fun <- function() { #' x <- yaml::read_yaml(system.file(package = "iSEEindex", "example.yaml")) #' x$datasets @@ -133,46 +126,18 @@ #' if (interactive()) { #' shiny::runApp(app, port = 1234) #' } -iSEEindex <- function(bfc, FUN.datasets, FUN.initial = NULL, default.add = TRUE, default.position = c("first", "last"), app.title = NULL, body.header = NULL, body.footer = NULL) { - stopifnot(is(bfc, "BiocFileCache")) - if (is.null(FUN.initial)) { - FUN.initial <- function() NULL - } - - if (is.null(app.title)) { - app.title <- sprintf("iSEEindex - v%s | powered by iSEE - v%s", - packageVersion("iSEEindex"), - packageVersion("iSEE")) - } - - iSEE( - landingPage=.landing_page(bfc, FUN.datasets, FUN.initial, default.add, default.position, body.header, body.footer), - appTitle = app.title - ) -} - -#' @examples -#' ## -#' # BiocFileCache ---- -#' ## #' -#' library(BiocFileCache) -#' bfc <- BiocFileCache(cache = tempdir()) -#' -#' ## -#' # iSEEindex ---- -#' ## +#' ## Alternatively, with the example based on using runr calls #' -#' dataset_fun <- function() { +#' dataset_fun_tonsils <- function() { #' x <- yaml::read_yaml( -#' system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") +#' system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") #' ) #' x$datasets #' } -#' -#' initial_fun <- function() { +#' initial_fun_tonsils <- function() { #' x <- yaml::read_yaml( -#' system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") +#' system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") #' ) #' x$initial #' } @@ -180,16 +145,13 @@ iSEEindex <- function(bfc, FUN.datasets, FUN.initial = NULL, default.add = TRUE, #' library("shiny") #' header_tonsils <- fluidRow( #' shinydashboard::box( -#' width = 12, -#' collapsible = TRUE, -#' collapsed = TRUE, +#' width = 12, collapsible = TRUE, collapsed = TRUE, #' title = "How to explore the Tonsil Atlas datasets", #' includeMarkdown( #' system.file("tonsils_example", "header_tonsils.md", package = "iSEEindex") #' ) #' ) #' ) -#' #' footer_tonsils <- fluidRow( #' shinydashboard::box( #' width = 12, @@ -199,46 +161,141 @@ iSEEindex <- function(bfc, FUN.datasets, FUN.initial = NULL, default.add = TRUE, #' ) #' ) #' -#' app <- iSEEindex_runr(bfc, dataset_fun, initial_fun, -#' default.add = TRUE, -#' default.position = "last", -#' app.title = "iSEE ❤️ Tonsil Data Atlas", -#' body.header = header_tonsils, -#' body.footer = footer_tonsils) +#' app_tonsils <- iSEEindex(bfc, +#' dataset_fun_tonsils, +#' initial_fun_tonsils, +#' default.add = TRUE, +#' default.position = "last", +#' app.title = "iSEE ❤️ Tonsil Data Atlas", +#' body.header = header_tonsils, +#' body.footer = footer_tonsils, +#' already_se_object = TRUE) #' #' if (interactive()) { -#' shiny::runApp(app, port = 1234) +#' shiny::runApp(app_tonsils, port = 5678) #' } -iSEEindex_runr <- function(bfc, - FUN.datasets, - FUN.initial = NULL, - default.add = TRUE, default.position = c("first", "last"), - app.title = NULL, - body.header = NULL, - body.footer = NULL) { - stopifnot(is(bfc, "BiocFileCache")) - if (is.null(FUN.initial)) { - FUN.initial <- function() NULL - } +iSEEindex <- function(bfc, + FUN.datasets, + FUN.initial = NULL, + default.add = TRUE, + default.position = c("first", "last"), + app.title = NULL, + body.header = NULL, + body.footer = NULL, + already_se_object = FALSE) { + stopifnot(is(bfc, "BiocFileCache")) + if (is.null(FUN.initial)) { + FUN.initial <- function() NULL + } - if (is.null(app.title)) { - app.title <- sprintf("iSEEindex - v%s", - packageVersion("iSEEindex")) - } else { - app.title <- app.title - } + if (is.null(app.title)) { + app.title <- sprintf("iSEEindex - v%s | powered by iSEE - v%s", + packageVersion("iSEEindex"), + packageVersion("iSEE")) + } - iSEE( - landingPage=.landing_page_runr(bfc, - FUN.datasets, - FUN.initial, - default.add, default.position, - body.header, - body.footer), - appTitle = app.title - ) + iSEE( + landingPage = .landing_page(bfc, + FUN.datasets, + FUN.initial, + default.add, + default.position, + body.header, + body.footer, + already_se_object = already_se_object + ), + appTitle = app.title + ) } +#### #' @examples +#### #' ## +#### #' ## +#### #' +#### #' library(BiocFileCache) +#### #' bfc <- BiocFileCache(cache = tempdir()) +#### #' +#### #' ## +#### #' ## +#### #' +#### #' dataset_fun <- function() { +#### #' x <- yaml::read_yaml( +#### #' system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") +#### #' ) +#### #' x$datasets +#### #' } +#### #' +#### #' initial_fun <- function() { +#### #' x <- yaml::read_yaml( +#### #' system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") +#### #' ) +#### #' x$initial +#### #' } +#### #' +#### #' library("shiny") +#### #' header_tonsils <- fluidRow( +#### #' shinydashboard::box( +#### #' width = 12, +#### #' collapsible = TRUE, +#### #' collapsed = TRUE, +#### #' title = "How to explore the Tonsil Atlas datasets", +#### #' includeMarkdown( +#### #' system.file("tonsils_example", "header_tonsils.md", package = "iSEEindex") +#### #' ) +#### #' ) +#### #' ) +#### #' +#### #' footer_tonsils <- fluidRow( +#### #' shinydashboard::box( +#### #' width = 12, +#### #' includeMarkdown( +#### #' system.file("tonsils_example", "footer_tonsils.md", package = "iSEEindex") +#### #' ) +#### #' ) +#### #' ) +#### #' +#### #' app <- iSEEindex_runr(bfc, dataset_fun, initial_fun, +#### #' default.add = TRUE, +#### #' default.position = "last", +#### #' app.title = "iSEE ❤️ Tonsil Data Atlas", +#### #' body.header = header_tonsils, +#### #' body.footer = footer_tonsils) +#### #' +#### #' if (interactive()) { +#### #' shiny::runApp(app, port = 1234) +#### #' } +#### # iSEEindex_runr <- function(bfc, +#### # FUN.datasets, +#### # FUN.initial = NULL, +#### # default.add = TRUE, +#### # default.position = c("first", "last"), +#### # app.title = NULL, +#### # body.header = NULL, +#### # body.footer = NULL) { +#### # stopifnot(is(bfc, "BiocFileCache")) +#### # if (is.null(FUN.initial)) { +#### # FUN.initial <- function() NULL +#### # } +#### # +#### # if (is.null(app.title)) { +#### # app.title <- sprintf("iSEEindex - v%s", +#### # packageVersion("iSEEindex")) +#### # } else { +#### # app.title <- app.title +#### # } +#### # +#### # iSEE( +#### # landingPage=.landing_page(bfc, +#### # FUN.datasets, +#### # FUN.initial, +#### # default.add, default.position, +#### # body.header, +#### # body.footer, +#### # already_se_object = TRUE), +#### # appTitle = app.title +#### # ) +#### # } + #' Prepare and Launch the Main App. @@ -258,10 +315,11 @@ iSEEindex_runr <- function(bfc, #' #' @param FUN A function to initialize the \pkg{iSEE} observer #' architecture. Refer to [iSEE::createLandingPage()] for more details. -#' @param bfc An [BiocFileCache()] object. +#' @param bfc A [BiocFileCache()] object. #' @param session The Shiny session object from the server function. #' @param pObjects An environment containing global parameters generated in the #' landing page. +#' @param already_se_object TODO propagated #' #' @return A `NULL` value is invisibly returned. #' @@ -273,7 +331,7 @@ iSEEindex_runr <- function(bfc, #' @importFrom shinyjs enable #' #' @rdname INTERNAL_launch_isee -.launch_isee <- function(FUN, bfc, session, pObjects) { +.launch_isee <- function(FUN, bfc, session, pObjects, already_se_object) { # nocov start dataset_id <- pObjects[[.dataset_selected_id]] which_dataset <- which(pObjects$datasets_table[[.datasets_id]] == dataset_id) @@ -284,7 +342,8 @@ iSEEindex_runr <- function(bfc, withProgress(message = sprintf("Loading '%s'", dataset_title), value = 0, max = 2, { incProgress(1, detail = "(Down)loading object") - se2 <- try(.load_sce(bfc, dataset_id, dataset_metadata)) + se2 <- try(.load_sce(bfc, dataset_id, dataset_metadata, + already_se_object = already_se_object)) incProgress(1, detail = "Launching iSEE app") if (is(se2, "try-error")) { showNotification("Invalid SummarizedExperiment supplied.", type="error") @@ -338,70 +397,62 @@ iSEEindex_runr <- function(bfc, -.launch_isee_runr <- function(FUN, bfc, session, pObjects) { - # nocov start - dataset_id <- pObjects[[.dataset_selected_id]] - which_dataset <- which(pObjects$datasets_table[[.datasets_id]] == dataset_id) - # TODO: refactor as function that takes data set identifier and returns uri - dataset_metadata <- as.list(pObjects$datasets_table[which_dataset, , drop=FALSE]) - # TODO: refactor as function that takes data set identifier and returns title - dataset_title <- pObjects$datasets_table[which_dataset, .datasets_title, drop=TRUE] - withProgress(message = sprintf("Loading '%s'", dataset_title), - value = 0, max = 2, { - incProgress(1, detail = "(Down)loading object") - - - # se2 <- try(.load_sce_runr(bfc, dataset_id, dataset_metadata)) - se2 <- try(.load_sce_runr(bfc, dataset_id, dataset_metadata)) - - - - - - incProgress(1, detail = "Launching iSEE app") - if (is(se2, "try-error")) { - showNotification("Invalid SummarizedExperiment supplied.", type="error") - } else { - if (is.null(pObjects$initial_table)) { - initial <- NULL - tour <- NULL - } else { - initial_id <- pObjects[[.ui_initial]] - which_initial <- which( - pObjects$initial_table[[.initial_config_id]] == initial_id & - pObjects$initial_table[[.initial_datasets_id]] == dataset_id - ) - initial_metadata <- as.list(pObjects$initial_table[which_initial, , drop = FALSE]) - initial_message <- capture.output( - init <- try(.parse_initial(bfc, dataset_id, initial_id, initial_metadata)), - type = "message") - initial <- init$initial - tour <- init$tour - } - if (is(init, "try-error")) { - showModal(modalDialog( - title = "Invalid initial state", - p("An error occured while evaluating the script:"), - markdown(paste0(c("```", initial_message, "```"), collapse = "\n")), - p("Contact the app maintainer for further help."), - footer = NULL, - size = "l", - easyClose = TRUE - )) - return(NULL) - } - FUN(SE=se2, INITIAL=initial, TOUR=tour) - shinyjs::enable(iSEE:::.generalOrganizePanels) # organize panels - shinyjs::enable(iSEE:::.generalLinkGraph) # link graph - shinyjs::enable(iSEE:::.generalExportOutput) # export content - shinyjs::enable(iSEE:::.generalCodeTracker) # tracked code - shinyjs::enable(iSEE:::.generalPanelSettings) # panel settings - shinyjs::enable(iSEE:::.generalVignetteOpen) # open vignette - shinyjs::enable(iSEE:::.generalSessionInfo) # session info - shinyjs::enable(iSEE:::.generalCitationInfo) # citation info - } - }, session = session) - - invisible(NULL) - # nocov end -} +# .launch_isee_runr <- function(FUN, bfc, session, pObjects) { +# # nocov start +# dataset_id <- pObjects[[.dataset_selected_id]] +# which_dataset <- which(pObjects$datasets_table[[.datasets_id]] == dataset_id) +# # TODO: refactor as function that takes data set identifier and returns uri +# dataset_metadata <- as.list(pObjects$datasets_table[which_dataset, , drop=FALSE]) +# # TODO: refactor as function that takes data set identifier and returns title +# dataset_title <- pObjects$datasets_table[which_dataset, .datasets_title, drop=TRUE] +# withProgress(message = sprintf("Loading '%s'", dataset_title), +# value = 0, max = 2, { +# incProgress(1, detail = "(Down)loading object") +# se2 <- try(.load_sce(bfc, dataset_id, dataset_metadata, already_se_object = TRUE)) +# incProgress(1, detail = "Launching iSEE app") +# if (is(se2, "try-error")) { +# showNotification("Invalid SummarizedExperiment supplied.", type="error") +# } else { +# if (is.null(pObjects$initial_table)) { +# initial <- NULL +# tour <- NULL +# } else { +# initial_id <- pObjects[[.ui_initial]] +# which_initial <- which( +# pObjects$initial_table[[.initial_config_id]] == initial_id & +# pObjects$initial_table[[.initial_datasets_id]] == dataset_id +# ) +# initial_metadata <- as.list(pObjects$initial_table[which_initial, , drop = FALSE]) +# initial_message <- capture.output( +# init <- try(.parse_initial(bfc, dataset_id, initial_id, initial_metadata)), +# type = "message") +# initial <- init$initial +# tour <- init$tour +# } +# if (is(init, "try-error")) { +# showModal(modalDialog( +# title = "Invalid initial state", +# p("An error occured while evaluating the script:"), +# markdown(paste0(c("```", initial_message, "```"), collapse = "\n")), +# p("Contact the app maintainer for further help."), +# footer = NULL, +# size = "l", +# easyClose = TRUE +# )) +# return(NULL) +# } +# FUN(SE=se2, INITIAL=initial, TOUR=tour) +# shinyjs::enable(iSEE:::.generalOrganizePanels) # organize panels +# shinyjs::enable(iSEE:::.generalLinkGraph) # link graph +# shinyjs::enable(iSEE:::.generalExportOutput) # export content +# shinyjs::enable(iSEE:::.generalCodeTracker) # tracked code +# shinyjs::enable(iSEE:::.generalPanelSettings) # panel settings +# shinyjs::enable(iSEE:::.generalVignetteOpen) # open vignette +# shinyjs::enable(iSEE:::.generalSessionInfo) # session info +# shinyjs::enable(iSEE:::.generalCitationInfo) # citation info +# } +# }, session = session) +# +# invisible(NULL) +# # nocov end +# } diff --git a/R/iSEEindexResource-class.R b/R/iSEEindexResource-class.R index 9ac6559..2c7caf5 100644 --- a/R/iSEEindexResource-class.R +++ b/R/iSEEindexResource-class.R @@ -376,29 +376,21 @@ iSEEindexRunrResource <- function(x) { #' @export setMethod("precache", "iSEEindexRunrResource", - function(x, bfc, id, ...) - { - # Trim 'runr://' from the original URI and evaluate the R call, - # check that the value is an existing filepath and pass to BiocFileCache, - # which will manage the caching. - # Use action="copy" to leave the original file untouched. - call_string <- sub("runr://", "", x@uri) - env <- new.env() - - # fpath not needed per se, we should have a "valid r call and that is it" - - object_path <- eval(parse(text = call_string)) - - - # fpath <- eval(parse(text = call_string), envir = env) - # stopifnot(file.exists(fpath)) - # object_path <- bfcadd(x = bfc, rname = id, fpath = fpath, action = "copy", ...) - + function(x, bfc, id, ...) +{ + # Trim 'runr://' from the original URI and evaluate the R call, + # We expect already that an SE object will be returned + call_string <- sub("runr://", "", x@uri) + # fpath not needed per se, we should have a "valid r call and that is it" + # this time it is called object, as it is already returning that + object <- eval(parse(text = call_string)) + ## "we have to believe" that this is already somehow cached e.g. via + ## Bioc data packages using the cache, and many times it is so - return(object_path) - }) + return(object) +}) diff --git a/R/landing_page.R b/R/landing_page.R index 236261e..a507561 100644 --- a/R/landing_page.R +++ b/R/landing_page.R @@ -11,6 +11,7 @@ #' in the Shiny `selectizeInput()`. #' @param body.header UI element to display \emph{above} the main landing page body. #' @param body.footer UI element to display \emph{below} the main landing page body. +#' @param already_se_object TODO to be propagated #' #' @return A `function` that defines UI elements and observers for the #' landing page of the app. @@ -24,7 +25,14 @@ #' @importFrom shinyjs disable #' #' @rdname INTERNAL_landing_page -.landing_page <- function(bfc, FUN.datasets, FUN.initial, default.add = TRUE, default.position = c("first", "last"), body.header = NULL, body.footer = NULL) { +.landing_page <- function(bfc, + FUN.datasets, + FUN.initial, + default.add = TRUE, + default.position = c("first", "last"), + body.header = NULL, + body.footer = NULL, + already_se_object) { default.position <- match.arg(default.position) # datasets datasets_available_list <- FUN.datasets() @@ -95,7 +103,7 @@ .create_observers(input, session, pObjects, rObjects, FUN.initial, default.add, default.position) - .create_launch_observers(FUN, bfc, input, session, pObjects) + .create_launch_observers(FUN, bfc, input, session, pObjects, already_se_object = already_se_object) .render_datasets_table(output, pObjects, rObjects) @@ -110,91 +118,89 @@ - - -.landing_page_runr <- function(bfc, FUN.datasets, FUN.initial, default.add = TRUE, default.position = c("first", "last"), body.header = NULL, body.footer = NULL) { - default.position <- match.arg(default.position) - # datasets - datasets_available_list <- FUN.datasets() - .check_datasets_list(datasets_available_list) - datasets_available_table <- .datasets_to_dataframe(datasets_available_list) - # initial configurations - initial_available_list <- FUN.initial() - .check_initial_list(initial_available_list) - initial_available_table <- .initial_to_dataframe(initial_available_list, datasets_available_table[[.datasets_id]]) - # landing page function (return value) - function (FUN, input, output, session) { - # nocov start - output$allPanels <- renderUI({ - tagList( - body.header, - fluidRow( - column(width = 7L, - shinydashboard::box(title = "Available Data Sets", - collapsible = FALSE, width = NULL, - selectizeInput(.ui_dataset_columns, label = "Show columns:", - choices = setdiff(colnames(datasets_available_table), c(.datasets_id, .datasets_uri, .datasets_description)), - selected = c(.datasets_title), - multiple = TRUE, - options = list(plugins=list('remove_button', 'drag_drop'))), - DTOutput(.ui_dataset_table) - )), - column(width = 5L, - shinydashboard::tabBox(id = .ui_box_dataset, title = "Selected dataset", - side = "left", - width = NULL, - tabPanel("Info", - uiOutput(.ui_markdown_overview)), - tabPanel("Configure and launch", - fluidRow( - column(width = 10L, - selectizeInput(.ui_initial, label = "Initial settings:", - choices = character(0))), - column(width = 2L, - br(), - actionButton(.ui_launch_button, label="Launch!", - style="color: #ffffff; background-color: #0092AC; border-color: #2e6da4")) - ), - uiOutput(.ui_initial_overview)) - ) - ) - ), - body.footer - ) # tagList - }) # renderUI - - ## Disable navbar buttons that are not linked to any observer yet - shinyjs::disable(iSEE:::.generalOrganizePanels) # organize panels - shinyjs::disable(iSEE:::.generalLinkGraph) # link graph - shinyjs::disable(iSEE:::.generalExportOutput) # export content - shinyjs::disable(iSEE:::.generalCodeTracker) # tracked code - shinyjs::disable(iSEE:::.generalPanelSettings) # panel settings - shinyjs::disable(iSEE:::.generalVignetteOpen) # open vignette - shinyjs::disable(iSEE:::.generalSessionInfo) # session info - shinyjs::disable(iSEE:::.generalCitationInfo) # citation info - - pObjects <- .create_persistent_objects( - datasets_available_table, - initial_available_table) - rObjects <- reactiveValues( - rerender_datasets=1L, - rerender_overview=1L, - rerender_initial=1L) - - .create_observers(input, session, pObjects, rObjects, FUN.initial, default.add, default.position) - - .create_launch_observers_runr(FUN, bfc, input, session, pObjects) - - .render_datasets_table(output, pObjects, rObjects) - - .render_markdown_overview(output, pObjects, rObjects) - - .render_initial_overview(output, pObjects, rObjects) - - invisible(NULL) - # nocov end - } -} +# .landing_page_runr <- function(bfc, FUN.datasets, FUN.initial, default.add = TRUE, default.position = c("first", "last"), body.header = NULL, body.footer = NULL) { +# default.position <- match.arg(default.position) +# # datasets +# datasets_available_list <- FUN.datasets() +# .check_datasets_list(datasets_available_list) +# datasets_available_table <- .datasets_to_dataframe(datasets_available_list) +# # initial configurations +# initial_available_list <- FUN.initial() +# .check_initial_list(initial_available_list) +# initial_available_table <- .initial_to_dataframe(initial_available_list, datasets_available_table[[.datasets_id]]) +# # landing page function (return value) +# function (FUN, input, output, session) { +# # nocov start +# output$allPanels <- renderUI({ +# tagList( +# body.header, +# fluidRow( +# column(width = 7L, +# shinydashboard::box(title = "Available Data Sets", +# collapsible = FALSE, width = NULL, +# selectizeInput(.ui_dataset_columns, label = "Show columns:", +# choices = setdiff(colnames(datasets_available_table), c(.datasets_id, .datasets_uri, .datasets_description)), +# selected = c(.datasets_title), +# multiple = TRUE, +# options = list(plugins=list('remove_button', 'drag_drop'))), +# DTOutput(.ui_dataset_table) +# )), +# column(width = 5L, +# shinydashboard::tabBox(id = .ui_box_dataset, title = "Selected dataset", +# side = "left", +# width = NULL, +# tabPanel("Info", +# uiOutput(.ui_markdown_overview)), +# tabPanel("Configure and launch", +# fluidRow( +# column(width = 10L, +# selectizeInput(.ui_initial, label = "Initial settings:", +# choices = character(0))), +# column(width = 2L, +# br(), +# actionButton(.ui_launch_button, label="Launch!", +# style="color: #ffffff; background-color: #0092AC; border-color: #2e6da4")) +# ), +# uiOutput(.ui_initial_overview)) +# ) +# ) +# ), +# body.footer +# ) # tagList +# }) # renderUI +# +# ## Disable navbar buttons that are not linked to any observer yet +# shinyjs::disable(iSEE:::.generalOrganizePanels) # organize panels +# shinyjs::disable(iSEE:::.generalLinkGraph) # link graph +# shinyjs::disable(iSEE:::.generalExportOutput) # export content +# shinyjs::disable(iSEE:::.generalCodeTracker) # tracked code +# shinyjs::disable(iSEE:::.generalPanelSettings) # panel settings +# shinyjs::disable(iSEE:::.generalVignetteOpen) # open vignette +# shinyjs::disable(iSEE:::.generalSessionInfo) # session info +# shinyjs::disable(iSEE:::.generalCitationInfo) # citation info +# +# pObjects <- .create_persistent_objects( +# datasets_available_table, +# initial_available_table) +# rObjects <- reactiveValues( +# rerender_datasets=1L, +# rerender_overview=1L, +# rerender_initial=1L) +# +# .create_observers(input, session, pObjects, rObjects, FUN.initial, default.add, default.position) +# +# .create_launch_observers(FUN, bfc, input, session, pObjects, already_se_object = TRUE) +# +# .render_datasets_table(output, pObjects, rObjects) +# +# .render_markdown_overview(output, pObjects, rObjects) +# +# .render_initial_overview(output, pObjects, rObjects) +# +# invisible(NULL) +# # nocov end +# } +# } diff --git a/R/observers.R b/R/observers.R index 86eaff8..79e4f12 100644 --- a/R/observers.R +++ b/R/observers.R @@ -65,17 +65,22 @@ #' @param FUN A function to initialize the \pkg{iSEE} observer #' architecture. Refer to [iSEE::createLandingPage()] for more details. +#' #' @param bfc A [BiocFileCache()] object. #' landing page. +#' @param input TODO +#' @param session TODO +#' @param pObjects TODO +#' @param already_se_object TODO #' #' @importFrom shiny observeEvent #' #' @rdname INTERNAL_create_observers -.create_launch_observers <- function(FUN, bfc, input, session, pObjects) { +.create_launch_observers <- function(FUN, bfc, input, session, pObjects, already_se_object) { # nocov start observeEvent(input[[.ui_launch_button]], { - .launch_isee(FUN, bfc, session, pObjects) + .launch_isee(FUN, bfc, session, pObjects, already_se_object = already_se_object) }, ignoreNULL=TRUE, ignoreInit=TRUE) # nocov end @@ -83,15 +88,15 @@ } - -.create_launch_observers_runr <- function(FUN, bfc, input, session, pObjects) { - - # nocov start - observeEvent(input[[.ui_launch_button]], { - .launch_isee_runr(FUN, bfc, session, pObjects) - }, ignoreNULL=TRUE, ignoreInit=TRUE) - # nocov end - - invisible(NULL) -} +# +# .create_launch_observers_runr <- function(FUN, bfc, input, session, pObjects) { +# +# # nocov start +# observeEvent(input[[.ui_launch_button]], { +# .launch_isee(FUN, bfc, session, pObjects, already_se_object = TRUE) +# }, ignoreNULL=TRUE, ignoreInit=TRUE) +# # nocov end +# +# invisible(NULL) +# } diff --git a/R/utils-datasets.R b/R/utils-datasets.R index 59ab4ba..8eced35 100644 --- a/R/utils-datasets.R +++ b/R/utils-datasets.R @@ -8,6 +8,7 @@ #' @param bfc A [BiocFileCache()] object. #' @param id A data set identifier as a character scalar. #' @param metadata Named list of metadata. See individual resource classes for required and optional metadata. +#' @param already_se_object Logical, TODO - shall we default this to FALSE? #' #' @return #' For `.load_sce()`, a [SingleCellExperiment()] object. @@ -28,66 +29,82 @@ #' #' ## Usage --- #' -#' iSEEindex:::.load_sce(bfc, id, metadata) +#' iSEEindex:::.load_sce(bfc, id, metadata, already_se_object = FALSE) #' -.load_sce <- function(bfc, id, metadata) { - bfc_result <- bfcquery(bfc, id, field = "rname", exact = TRUE) - # nocov start - if (nrow(bfc_result) == 0) { - uri_object <- .metadata_to_object(metadata) - object_path <- precache(uri_object, bfc, id) +#' ## Alternatively, using the runr approach +#' id_tonsil <- "demo_load_sce_tonsil" +#' metadata <- list( +#' uri="runr://HCATonsilData::HCATonsilData(assayType = 'RNA', cellType = 'epithelial')" +#' ) +#' iSEEindex:::.load_sce(bfc, id, metadata, already_se_object = TRUE) +.load_sce <- function(bfc, + id, + metadata, + already_se_object) { + if (!already_se_object) { + bfc_result <- bfcquery(bfc, id, field = "rname", exact = TRUE) + # nocov start + if (nrow(bfc_result) == 0) { + uri_object <- .metadata_to_object(metadata) + object_path <- precache(uri_object, bfc, id) + } else { + object_path <- bfc[[bfc_result$rid]] + } + # nocov end + object <- readRDS(object_path) + object <- .convert_to_sce(object) } else { - object_path <- bfc[[bfc_result$rid]] + # if providing directly an SE object, e.g. via data packages... + uri_object <- .metadata_to_object(metadata) + + object <- precache(uri_object, bfc, id) + object <- .convert_to_sce(object) } - # nocov end - object <- readRDS(object_path) - object <- .convert_to_sce(object) object } -#' @examples -#' -#' library(BiocFileCache) -#' bfc <- BiocFileCache(tempdir()) -#' id <- "demo_load_sce_tonsil" -#' metadata <- list(uri="runr://HCATonsilData::HCATonsilData(assayType = 'RNA', cellType = 'epithelial')") -#' -#' ## Usage --- -#' -#' iSEEindex:::.load_sce_runr(bfc, id, metadata) -.load_sce_runr <- function(bfc, id, metadata) { - bfc_result <- bfcquery(bfc, id, field = "rname", exact = TRUE) - # nocov start - # if (nrow(bfc_result) == 0) { - # uri_object <- .metadata_to_object(metadata) - # object_path <- precache(uri_object, bfc, id) - # } else { - # object_path <- bfc[[bfc_result$rid]] - # } - - - uri_object <- .metadata_to_object_runr(metadata) - - object_call <- precache(uri_object, bfc, id) - # if (nrow(bfc_result) == 0) { - # uri_object <- .metadata_to_object(metadata) - # object_path <- precache(uri_object, bfc, id) - # } else { - # object_path <- bfc[[bfc_result$rid]] - # } - - - # nocov end - # object <- readRDS(object_path) - - object <- object_call - - object <- .convert_to_sce(object) - object -} +### #' @examples +### #' +### #' library(BiocFileCache) +### #' bfc <- BiocFileCache(tempdir()) +### #' id <- "demo_load_sce_tonsil" +### #' metadata <- list(uri="runr://HCATonsilData::HCATonsilData(assayType = 'RNA', cellType = 'epithelial')") +### #' +### #' ## Usage --- +### #' +### #' iSEEindex:::.load_sce_runr(bfc, id, metadata) +# .load_sce_runr <- function(bfc, id, metadata) { +# bfc_result <- bfcquery(bfc, id, field = "rname", exact = TRUE) +# # nocov start +# # if (nrow(bfc_result) == 0) { +# # uri_object <- .metadata_to_object(metadata) +# # object_path <- precache(uri_object, bfc, id) +# # } else { +# # object_path <- bfc[[bfc_result$rid]] +# # } +# +# uri_object <- .metadata_to_object(metadata) +# +# object_call <- precache(uri_object, bfc, id) +# # if (nrow(bfc_result) == 0) { +# # uri_object <- .metadata_to_object(metadata) +# # object_path <- precache(uri_object, bfc, id) +# # } else { +# # object_path <- bfc[[bfc_result$rid]] +# # } +# +# +# # nocov end +# # object <- readRDS(object_path) +# +# object <- object_call +# +# object <- .convert_to_sce(object) +# object +# } @@ -135,6 +152,11 @@ #' )) #' iSEEindex:::.metadata_to_object(list(uri="s3://your-bucket/your-prefix/file.rds")) #' iSEEindex:::.metadata_to_object(list(uri="s3://your-bucket/your-prefix/file.rds")) +#' iSEEindex:::.metadata_to_object( +#' list( +#' uri="runr://HCATonsilData::HCATonsilData(assayType = 'RNA', cellType = 'epithelial')" +#' ) +#' ) .metadata_to_object <- function(x) { scheme <- urltools::url_parse(x[[.datasets_uri]])$scheme scheme_titled <- str_to_title(scheme) @@ -152,28 +174,6 @@ } -#' @examples -#' iSEEindex:::.metadata_to_object(list(uri="runr://HCATonsilData::HCATonsilData(assayType = 'RNA', cellType = 'epithelial')")) -.metadata_to_object_runr <- function(x) { - scheme <- urltools::url_parse(x[[.datasets_uri]])$scheme - scheme_titled <- str_to_title(scheme) - target_class <- sprintf("iSEEindex%sResource", scheme_titled) - constructor.FUN <- try({ - get(target_class) - }, silent = TRUE) - if (is(constructor.FUN, "try-error")) { - stop( - sprintf("No constructor function available for scheme '%s'. ", scheme), - sprintf("Consider implementing the constructor function '%s()'.", target_class) - ) - } - constructor.FUN(x) -} - - - - - #' Check Validity of Data Sets Metadata #' diff --git a/man/iSEEindex.Rd b/man/iSEEindex.Rd index e1eb505..f3842e3 100644 --- a/man/iSEEindex.Rd +++ b/man/iSEEindex.Rd @@ -12,7 +12,8 @@ iSEEindex( default.position = c("first", "last"), app.title = NULL, body.header = NULL, - body.footer = NULL + body.footer = NULL, + already_se_object = FALSE ) } \arguments{ @@ -39,6 +40,8 @@ info on the versions of the \code{iSEEindex} and \code{iSEE} packages.} \item{body.header}{UI element to display \emph{above} the main landing page body.} \item{body.footer}{UI element to display \emph{below} the main landing page body.} + +\item{already_se_object}{TODO} } \value{ An \code{\link[iSEE:iSEE]{iSEE::iSEE()}} app with a custom landing page using a \code{\link[=BiocFileCache]{BiocFileCache()}} to cache a selection of data sets. @@ -126,17 +129,9 @@ The individual sub-lists may also contain additional optional named metadata spe } \examples{ -## -# BiocFileCache ---- -## - -library(BiocFileCache) +library("BiocFileCache") bfc <- BiocFileCache(cache = tempdir()) -## -# iSEEindex ---- -## - dataset_fun <- function() { x <- yaml::read_yaml(system.file(package = "iSEEindex", "example.yaml")) x$datasets @@ -152,6 +147,54 @@ app <- iSEEindex(bfc, dataset_fun, initial_fun) if (interactive()) { shiny::runApp(app, port = 1234) } + +## Alternatively, with the example based on using runr calls + +dataset_fun_tonsils <- function() { + x <- yaml::read_yaml( + system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") + ) + x$datasets +} +initial_fun_tonsils <- function() { + x <- yaml::read_yaml( + system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") + ) + x$initial +} + +library("shiny") +header_tonsils <- fluidRow( + shinydashboard::box( + width = 12, collapsible = TRUE, collapsed = TRUE, + title = "How to explore the Tonsil Atlas datasets", + includeMarkdown( + system.file("tonsils_example", "header_tonsils.md", package = "iSEEindex") + ) + ) +) +footer_tonsils <- fluidRow( + shinydashboard::box( + width = 12, + includeMarkdown( + system.file("tonsils_example", "footer_tonsils.md", package = "iSEEindex") + ) + ) +) + +app_tonsils <- iSEEindex(bfc, + dataset_fun_tonsils, + initial_fun_tonsils, + default.add = TRUE, + default.position = "last", + app.title = "iSEE ❤️ Tonsil Data Atlas", + body.header = header_tonsils, + body.footer = footer_tonsils, + already_se_object = TRUE) + +if (interactive()) { + shiny::runApp(app_tonsils, port = 5678) +} } \author{ Kevin Rue-Albrecht diff --git a/tests/testthat/test-observers.R b/tests/testthat/test-observers.R index 4a3c337..8b04357 100644 --- a/tests/testthat/test-observers.R +++ b/tests/testthat/test-observers.R @@ -19,7 +19,7 @@ test_that(".create_launch_observers works", { pObjects <- new.env() FUN <- function(SE, INITIAL) invisible(NULL) - out <- iSEEindex:::.create_launch_observers(FUN, bfc, input, session = NULL, pObjects) + out <- iSEEindex:::.create_launch_observers(FUN, bfc, input, session = NULL, pObjects, already_se_object = FALSE) expect_null(out) }) diff --git a/tests/testthat/test-utils-datasets.R b/tests/testthat/test-utils-datasets.R index 134a791..3a3514c 100644 --- a/tests/testthat/test-utils-datasets.R +++ b/tests/testthat/test-utils-datasets.R @@ -10,7 +10,7 @@ test_that(".load_sce works", { ## Usage --- - out <- iSEEindex:::.load_sce(bfc, id, metadata) + out <- iSEEindex:::.load_sce(bfc, id, metadata, already_se_object = FALSE) expect_s4_class(out, "SummarizedExperiment") }) From dab973b4f579b47a44d607bf2c01cfd70075f5cc Mon Sep 17 00:00:00 2001 From: Federico Marini Date: Wed, 2 Oct 2024 21:59:52 +0200 Subject: [PATCH 2/7] going in with a simple heuristics to determine what should happen on the resource passed. path -> prefetch fully and load object -> just load Might be thinking of extra work to have an extra field in the resource class to define this more flexibly, but so far so good? --- R/utils-datasets.R | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/R/utils-datasets.R b/R/utils-datasets.R index 8eced35..cb39123 100644 --- a/R/utils-datasets.R +++ b/R/utils-datasets.R @@ -8,7 +8,6 @@ #' @param bfc A [BiocFileCache()] object. #' @param id A data set identifier as a character scalar. #' @param metadata Named list of metadata. See individual resource classes for required and optional metadata. -#' @param already_se_object Logical, TODO - shall we default this to FALSE? #' #' @return #' For `.load_sce()`, a [SingleCellExperiment()] object. @@ -29,18 +28,28 @@ #' #' ## Usage --- #' -#' iSEEindex:::.load_sce(bfc, id, metadata, already_se_object = FALSE) +#' iSEEindex:::.load_sce(bfc, id, metadata) #' #' ## Alternatively, using the runr approach #' id_tonsil <- "demo_load_sce_tonsil" -#' metadata <- list( +#' metadata_tonsil <- list( #' uri="runr://HCATonsilData::HCATonsilData(assayType = 'RNA', cellType = 'epithelial')" #' ) -#' iSEEindex:::.load_sce(bfc, id, metadata, already_se_object = TRUE) +#' iSEEindex:::.load_sce(bfc, id_tonsil, metadata_tonsil) .load_sce <- function(bfc, id, - metadata, - already_se_object) { + metadata) { + resource_obj <- .metadata_to_object(metadata) + if (is(resource_obj, "iSEEindexHttpsResource") | is(resource_obj, "iSEEindexLocalhostResource") | + is(resource_obj, "iSEEindexRcallResource") | is(resource_obj, "iSEEindexS3Resource")) { + already_se_object <- FALSE + } else if (is(resource_obj, "iSEEindexRunrResource")) { + already_se_object <- TRUE + } else { + # without knowing too much about it... + already_se_object <- FALSE + } + if (!already_se_object) { bfc_result <- bfcquery(bfc, id, field = "rname", exact = TRUE) # nocov start From 7aecda45e80e43e7d44b56d39e88935e10dbcdf5 Mon Sep 17 00:00:00 2001 From: Federico Marini Date: Wed, 2 Oct 2024 22:00:32 +0200 Subject: [PATCH 3/7] param `already_se_object` is not required anymore, replaced by the heuristics --- R/iSEEindex.R | 16 +++++----------- R/landing_page.R | 6 ++---- R/observers.R | 5 ++--- man/iSEEindex.Rd | 8 ++------ tests/testthat/test-observers.R | 2 +- tests/testthat/test-utils-datasets.R | 2 +- 6 files changed, 13 insertions(+), 26 deletions(-) diff --git a/R/iSEEindex.R b/R/iSEEindex.R index 597b3d2..547768e 100644 --- a/R/iSEEindex.R +++ b/R/iSEEindex.R @@ -96,7 +96,6 @@ #' info on the versions of the `iSEEindex` and `iSEE` packages. #' @param body.header UI element to display \emph{above} the main landing page body. #' @param body.footer UI element to display \emph{below} the main landing page body. -#' @param already_se_object TODO #' #' @return An [iSEE::iSEE()] app with a custom landing page using a [BiocFileCache()] to cache a selection of data sets. #' @@ -168,8 +167,7 @@ #' default.position = "last", #' app.title = "iSEE ❤️ Tonsil Data Atlas", #' body.header = header_tonsils, -#' body.footer = footer_tonsils, -#' already_se_object = TRUE) +#' body.footer = footer_tonsils) #' #' if (interactive()) { #' shiny::runApp(app_tonsils, port = 5678) @@ -181,8 +179,7 @@ iSEEindex <- function(bfc, default.position = c("first", "last"), app.title = NULL, body.header = NULL, - body.footer = NULL, - already_se_object = FALSE) { + body.footer = NULL) { stopifnot(is(bfc, "BiocFileCache")) if (is.null(FUN.initial)) { FUN.initial <- function() NULL @@ -201,8 +198,7 @@ iSEEindex <- function(bfc, default.add, default.position, body.header, - body.footer, - already_se_object = already_se_object + body.footer ), appTitle = app.title ) @@ -319,7 +315,6 @@ iSEEindex <- function(bfc, #' @param session The Shiny session object from the server function. #' @param pObjects An environment containing global parameters generated in the #' landing page. -#' @param already_se_object TODO propagated #' #' @return A `NULL` value is invisibly returned. #' @@ -331,7 +326,7 @@ iSEEindex <- function(bfc, #' @importFrom shinyjs enable #' #' @rdname INTERNAL_launch_isee -.launch_isee <- function(FUN, bfc, session, pObjects, already_se_object) { +.launch_isee <- function(FUN, bfc, session, pObjects) { # nocov start dataset_id <- pObjects[[.dataset_selected_id]] which_dataset <- which(pObjects$datasets_table[[.datasets_id]] == dataset_id) @@ -342,8 +337,7 @@ iSEEindex <- function(bfc, withProgress(message = sprintf("Loading '%s'", dataset_title), value = 0, max = 2, { incProgress(1, detail = "(Down)loading object") - se2 <- try(.load_sce(bfc, dataset_id, dataset_metadata, - already_se_object = already_se_object)) + se2 <- try(.load_sce(bfc, dataset_id, dataset_metadata)) incProgress(1, detail = "Launching iSEE app") if (is(se2, "try-error")) { showNotification("Invalid SummarizedExperiment supplied.", type="error") diff --git a/R/landing_page.R b/R/landing_page.R index a507561..d8260e9 100644 --- a/R/landing_page.R +++ b/R/landing_page.R @@ -11,7 +11,6 @@ #' in the Shiny `selectizeInput()`. #' @param body.header UI element to display \emph{above} the main landing page body. #' @param body.footer UI element to display \emph{below} the main landing page body. -#' @param already_se_object TODO to be propagated #' #' @return A `function` that defines UI elements and observers for the #' landing page of the app. @@ -31,8 +30,7 @@ default.add = TRUE, default.position = c("first", "last"), body.header = NULL, - body.footer = NULL, - already_se_object) { + body.footer = NULL) { default.position <- match.arg(default.position) # datasets datasets_available_list <- FUN.datasets() @@ -103,7 +101,7 @@ .create_observers(input, session, pObjects, rObjects, FUN.initial, default.add, default.position) - .create_launch_observers(FUN, bfc, input, session, pObjects, already_se_object = already_se_object) + .create_launch_observers(FUN, bfc, input, session, pObjects) .render_datasets_table(output, pObjects, rObjects) diff --git a/R/observers.R b/R/observers.R index 79e4f12..50db35b 100644 --- a/R/observers.R +++ b/R/observers.R @@ -71,16 +71,15 @@ #' @param input TODO #' @param session TODO #' @param pObjects TODO -#' @param already_se_object TODO #' #' @importFrom shiny observeEvent #' #' @rdname INTERNAL_create_observers -.create_launch_observers <- function(FUN, bfc, input, session, pObjects, already_se_object) { +.create_launch_observers <- function(FUN, bfc, input, session, pObjects) { # nocov start observeEvent(input[[.ui_launch_button]], { - .launch_isee(FUN, bfc, session, pObjects, already_se_object = already_se_object) + .launch_isee(FUN, bfc, session, pObjects) }, ignoreNULL=TRUE, ignoreInit=TRUE) # nocov end diff --git a/man/iSEEindex.Rd b/man/iSEEindex.Rd index f3842e3..cb10796 100644 --- a/man/iSEEindex.Rd +++ b/man/iSEEindex.Rd @@ -12,8 +12,7 @@ iSEEindex( default.position = c("first", "last"), app.title = NULL, body.header = NULL, - body.footer = NULL, - already_se_object = FALSE + body.footer = NULL ) } \arguments{ @@ -40,8 +39,6 @@ info on the versions of the \code{iSEEindex} and \code{iSEE} packages.} \item{body.header}{UI element to display \emph{above} the main landing page body.} \item{body.footer}{UI element to display \emph{below} the main landing page body.} - -\item{already_se_object}{TODO} } \value{ An \code{\link[iSEE:iSEE]{iSEE::iSEE()}} app with a custom landing page using a \code{\link[=BiocFileCache]{BiocFileCache()}} to cache a selection of data sets. @@ -189,8 +186,7 @@ app_tonsils <- iSEEindex(bfc, default.position = "last", app.title = "iSEE ❤️ Tonsil Data Atlas", body.header = header_tonsils, - body.footer = footer_tonsils, - already_se_object = TRUE) + body.footer = footer_tonsils) if (interactive()) { shiny::runApp(app_tonsils, port = 5678) diff --git a/tests/testthat/test-observers.R b/tests/testthat/test-observers.R index 8b04357..4a3c337 100644 --- a/tests/testthat/test-observers.R +++ b/tests/testthat/test-observers.R @@ -19,7 +19,7 @@ test_that(".create_launch_observers works", { pObjects <- new.env() FUN <- function(SE, INITIAL) invisible(NULL) - out <- iSEEindex:::.create_launch_observers(FUN, bfc, input, session = NULL, pObjects, already_se_object = FALSE) + out <- iSEEindex:::.create_launch_observers(FUN, bfc, input, session = NULL, pObjects) expect_null(out) }) diff --git a/tests/testthat/test-utils-datasets.R b/tests/testthat/test-utils-datasets.R index 3a3514c..134a791 100644 --- a/tests/testthat/test-utils-datasets.R +++ b/tests/testthat/test-utils-datasets.R @@ -10,7 +10,7 @@ test_that(".load_sce works", { ## Usage --- - out <- iSEEindex:::.load_sce(bfc, id, metadata, already_se_object = FALSE) + out <- iSEEindex:::.load_sce(bfc, id, metadata) expect_s4_class(out, "SummarizedExperiment") }) From ff5eb34ebfa7e15c6b6e5e35887cc694dde70903 Mon Sep 17 00:00:00 2001 From: Federico Marini Date: Wed, 2 Oct 2024 22:00:59 +0200 Subject: [PATCH 4/7] adding another yaml, "just for the fun" and for showing a proof of principle that this could simply work --- inst/tonsils_example/tonsil_and_mix.yml | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 inst/tonsils_example/tonsil_and_mix.yml diff --git a/inst/tonsils_example/tonsil_and_mix.yml b/inst/tonsils_example/tonsil_and_mix.yml new file mode 100644 index 0000000..a9e30fc --- /dev/null +++ b/inst/tonsils_example/tonsil_and_mix.yml @@ -0,0 +1,48 @@ +datasets: + - id: Tonsil_epithelial + title: Tonsil Data - Epithelial + uri: runr://HCATonsilData::HCATonsilData(assayType = "RNA", cellType = "epithelial") + description: | + Tonsil Data - Epithelial, 396 cells + +

+ +

+ - id: ReprocessedAllenData + title: ReprocessedAllenData + uri: https://zenodo.org/record/8076991/files/ReprocessedAllenData.rds + description: | + Reprocessed Allen Data. + - id: BuettnerESCData + title: BuettnerESCData + uri: https://zenodo.org/record/8076991/files/BuettnerESCData.rds + description: | + Reprocessed Allen Data (copy). +initial: + - id: Tonsil_epithelial_full5 + datasets: + - Tonsil_epithelial + title: Tonsil_epithelial configuration 1 (R call) + uri: rcall://system.file(package='iSEEindex','tonsils_example/hca_tonsil_epithelial_v2.R') + # uri: localhost:///Users/fede/Development/iSEEindex/hca_tonsil_epithelial_v2.R + # uri: rcall://system.file(package='iSEEindex','ReprocessedAllenData_config_01.R') + description: | + touring around, first go + - id: config01rcall + datasets: + - ReprocessedAllenData + title: Example configuration 1 (R call) + uri: rcall://system.file(package='iSEEindex','ReprocessedAllenData_config_01.R') + description: | + One `ReducedDimensionPlot` panel, one `ColumnDataTable` panel. + + File distributed with the `iSEEindex` package. + - id: config02rcall + datasets: + - ReprocessedAllenData + title: Example configuration 2 (R call) + uri: rcall://system.file(package='iSEEindex','ReprocessedAllenData_config_02.R') + description: | + One `RowDataTable` panel, one `ColumnDataTable` panel. + + File distributed with the `iSEEindex` package. From 08cd8fefa2594df9d092d87e761ba35503b56530 Mon Sep 17 00:00:00 2001 From: Federico Marini Date: Wed, 2 Oct 2024 23:40:42 +0200 Subject: [PATCH 5/7] general cleanup, and polishing a bit what is there so far --- R/iSEEindex.R | 233 ++++++------------------ R/iSEEindexResource-class.R | 122 ++++++++----- R/landing_page.R | 109 ++--------- R/observers.R | 39 ++-- R/outputs.R | 30 +-- R/utils-datasets.R | 58 +----- R/utils-initial.R | 26 ++- man/iSEEindex.Rd | 65 ++++--- man/iSEEindexHttpsResource-class.Rd | 16 +- man/iSEEindexLocalhostResource-class.Rd | 16 +- man/iSEEindexRcallResource-class.Rd | 15 +- man/iSEEindexResource-class.Rd | 12 +- man/iSEEindexResource-generics.Rd | 6 +- man/iSEEindexRunrResource-class.Rd | 13 +- man/iSEEindexS3Resource-class.Rd | 34 ++-- 15 files changed, 317 insertions(+), 477 deletions(-) diff --git a/R/iSEEindex.R b/R/iSEEindex.R index 547768e..edaba54 100644 --- a/R/iSEEindex.R +++ b/R/iSEEindex.R @@ -6,15 +6,19 @@ #' states prepared by the app maintainer. #' #' @section Data Sets: -#' The function passed to the argument `FUN.datasets` must return a `list` that contains metadata about the available data sets. +#' The function passed to the argument `FUN.datasets` must return a `list` that +#' contains metadata about the available data sets. #' #' For each data set, required metadata are: #' #' \describe{ #' \item{id}{A unique identifier for the data set.} -#' \item{title}{A short human-readable title for the data set, displayed in the 'Info' panel when the data set is selected.} -#' \item{uri}{A Uniform Resource Identifier (URI) that indicates the location of the data file that contains the data set.} -#' \item{description}{A more detailed description of the data set, displayed in the 'Info' panel when the data set is selected.} +#' \item{title}{A short human-readable title for the data set, displayed in the +#' 'Info' panel when the data set is selected.} +#' \item{uri}{A Uniform Resource Identifier (URI) that indicates the location of +#' the data file that contains the data set.} +#' \item{description}{A more detailed description of the data set, displayed in +#' the 'Info' panel when the data set is selected.} #' } #' #' Example: @@ -22,40 +26,54 @@ #' ``` #' list( #' list( -#' id = "dataset01", -#' title = "Dataset 01", -#' uri = "https://example.com/1.rds", -#' description = "My first data set." +#' id = "dataset01", +#' title = "Dataset 01", +#' uri = "https://example.com/1.rds", +#' description = "My first data set." #' ), #' list( -#' id = "dataset02", -#' title = "Dataset 02", -#' uri = "https://example.com/1.rds", -#' description = "My second data set." +#' id = "dataset02", +#' title = "Dataset 02", +#' uri = "https://example.com/1.rds", +#' description = "My second data set." #' ) #' ) #' ``` #' -#' The individual sub-lists may also contain optional named metadata specific to individual [`iSEEindexResource-class`] classes (refer to the help page of those classes for details). +#' The individual sub-lists may also contain optional named metadata specific to +#' individual [`iSEEindexResource-class`] classes (refer to the help page of +#' those classes for details). #' -#' **Important**: The `id` value is used to identify the data set file in the \pkg{BiocFileCache}. -#' Thus, we recommend using a dedicated `BiocFileCache()` for the app, using the `BiocFileCache(cache)` argument to specify an on-disk location (directory path) for the dedicated cache. +#' **Important**: The `id` value is used to identify the data set file in the +#' \pkg{BiocFileCache}. +#' Thus, we recommend using a dedicated `BiocFileCache()` for the app, using the +#' `BiocFileCache(cache)` argument to specify an on-disk location (directory +#' path) for the dedicated cache. #' #' @section Initial Configurations: -#' The function passed to the argument `FUN.initial` must return a `list` that contains metadata about the available initial configurations, or `NULL` in the absence of any custom initial configuration (default settings will be applied to all data sets.). +#' The function passed to the argument `FUN.initial` must return a `list` that +#' contains metadata about the available initial configurations, or `NULL` in +#' the absence of any custom initial configuration (default settings will be +#' applied to all data sets.). #' #' For each initial configuration, required metadata are: #' #' \describe{ #' \item{id}{A unique identifier for the initial configuration.} -#' \item{title}{A short human-readable title for the initial configuration, representing the initial configuration in the 'Initial settings' dropdown menu.} -#' \item{uri}{A Uniform Resource Identifier (URI) that indicates the location of the R script that contains the initial configuration.} -#' \item{description}{A more detailed description of the initial configuration, displayed in the 'Configure and launch' panel when the initial configuration is selected.} +#' \item{title}{A short human-readable title for the initial configuration, +#' representing the initial configuration in the 'Initial settings' dropdown menu.} +#' \item{uri}{A Uniform Resource Identifier (URI) that indicates the location of +#' the R script that contains the initial configuration.} +#' \item{description}{A more detailed description of the initial configuration, +#' displayed in the 'Configure and launch' panel when the initial configuration +#' is selected.} #' } #' #' For each initial configuration, optional metadata are: #' \describe{ -#' \item{datasets}{A series of data set identifiers for which the configuration should be made available. If missing, the configuration will be available for all data sets.} +#' \item{datasets}{A series of data set identifiers for which the configuration +#' should be made available. If missing, the configuration will be available for +#' all data sets.} #' } #' #' Example: @@ -78,7 +96,9 @@ #' ) #' ``` #' -#' The individual sub-lists may also contain additional optional named metadata specific to individual [`iSEEindexResource-class`] classes (refer to the help page of those classes for details). +#' The individual sub-lists may also contain additional optional named metadata +#' specific to individual [`iSEEindexResource-class`] classes (refer to the help +#' page of those classes for details). #' #' @param bfc An [BiocFileCache()] object. #' @param FUN.datasets A function that returns a `list` of metadata for @@ -97,7 +117,8 @@ #' @param body.header UI element to display \emph{above} the main landing page body. #' @param body.footer UI element to display \emph{below} the main landing page body. #' -#' @return An [iSEE::iSEE()] app with a custom landing page using a [BiocFileCache()] to cache a selection of data sets. +#' @return An [iSEE::iSEE()] app with a custom landing page using a +#' [BiocFileCache()] to cache a selection of data sets. #' #' @author Kevin Rue-Albrecht #' @@ -192,107 +213,19 @@ iSEEindex <- function(bfc, } iSEE( - landingPage = .landing_page(bfc, - FUN.datasets, - FUN.initial, - default.add, - default.position, - body.header, - body.footer + landingPage = .landing_page( + bfc, + FUN.datasets, + FUN.initial, + default.add, + default.position, + body.header, + body.footer ), appTitle = app.title ) } -#### #' @examples -#### #' ## -#### #' ## -#### #' -#### #' library(BiocFileCache) -#### #' bfc <- BiocFileCache(cache = tempdir()) -#### #' -#### #' ## -#### #' ## -#### #' -#### #' dataset_fun <- function() { -#### #' x <- yaml::read_yaml( -#### #' system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") -#### #' ) -#### #' x$datasets -#### #' } -#### #' -#### #' initial_fun <- function() { -#### #' x <- yaml::read_yaml( -#### #' system.file("tonsils_example", "tonsil_package.yml", package = "iSEEindex") -#### #' ) -#### #' x$initial -#### #' } -#### #' -#### #' library("shiny") -#### #' header_tonsils <- fluidRow( -#### #' shinydashboard::box( -#### #' width = 12, -#### #' collapsible = TRUE, -#### #' collapsed = TRUE, -#### #' title = "How to explore the Tonsil Atlas datasets", -#### #' includeMarkdown( -#### #' system.file("tonsils_example", "header_tonsils.md", package = "iSEEindex") -#### #' ) -#### #' ) -#### #' ) -#### #' -#### #' footer_tonsils <- fluidRow( -#### #' shinydashboard::box( -#### #' width = 12, -#### #' includeMarkdown( -#### #' system.file("tonsils_example", "footer_tonsils.md", package = "iSEEindex") -#### #' ) -#### #' ) -#### #' ) -#### #' -#### #' app <- iSEEindex_runr(bfc, dataset_fun, initial_fun, -#### #' default.add = TRUE, -#### #' default.position = "last", -#### #' app.title = "iSEE ❤️ Tonsil Data Atlas", -#### #' body.header = header_tonsils, -#### #' body.footer = footer_tonsils) -#### #' -#### #' if (interactive()) { -#### #' shiny::runApp(app, port = 1234) -#### #' } -#### # iSEEindex_runr <- function(bfc, -#### # FUN.datasets, -#### # FUN.initial = NULL, -#### # default.add = TRUE, -#### # default.position = c("first", "last"), -#### # app.title = NULL, -#### # body.header = NULL, -#### # body.footer = NULL) { -#### # stopifnot(is(bfc, "BiocFileCache")) -#### # if (is.null(FUN.initial)) { -#### # FUN.initial <- function() NULL -#### # } -#### # -#### # if (is.null(app.title)) { -#### # app.title <- sprintf("iSEEindex - v%s", -#### # packageVersion("iSEEindex")) -#### # } else { -#### # app.title <- app.title -#### # } -#### # -#### # iSEE( -#### # landingPage=.landing_page(bfc, -#### # FUN.datasets, -#### # FUN.initial, -#### # default.add, default.position, -#### # body.header, -#### # body.footer, -#### # already_se_object = TRUE), -#### # appTitle = app.title -#### # ) -#### # } - - #' Prepare and Launch the Main App. #' @@ -386,67 +319,3 @@ iSEEindex <- function(bfc, # nocov end } - - - - - -# .launch_isee_runr <- function(FUN, bfc, session, pObjects) { -# # nocov start -# dataset_id <- pObjects[[.dataset_selected_id]] -# which_dataset <- which(pObjects$datasets_table[[.datasets_id]] == dataset_id) -# # TODO: refactor as function that takes data set identifier and returns uri -# dataset_metadata <- as.list(pObjects$datasets_table[which_dataset, , drop=FALSE]) -# # TODO: refactor as function that takes data set identifier and returns title -# dataset_title <- pObjects$datasets_table[which_dataset, .datasets_title, drop=TRUE] -# withProgress(message = sprintf("Loading '%s'", dataset_title), -# value = 0, max = 2, { -# incProgress(1, detail = "(Down)loading object") -# se2 <- try(.load_sce(bfc, dataset_id, dataset_metadata, already_se_object = TRUE)) -# incProgress(1, detail = "Launching iSEE app") -# if (is(se2, "try-error")) { -# showNotification("Invalid SummarizedExperiment supplied.", type="error") -# } else { -# if (is.null(pObjects$initial_table)) { -# initial <- NULL -# tour <- NULL -# } else { -# initial_id <- pObjects[[.ui_initial]] -# which_initial <- which( -# pObjects$initial_table[[.initial_config_id]] == initial_id & -# pObjects$initial_table[[.initial_datasets_id]] == dataset_id -# ) -# initial_metadata <- as.list(pObjects$initial_table[which_initial, , drop = FALSE]) -# initial_message <- capture.output( -# init <- try(.parse_initial(bfc, dataset_id, initial_id, initial_metadata)), -# type = "message") -# initial <- init$initial -# tour <- init$tour -# } -# if (is(init, "try-error")) { -# showModal(modalDialog( -# title = "Invalid initial state", -# p("An error occured while evaluating the script:"), -# markdown(paste0(c("```", initial_message, "```"), collapse = "\n")), -# p("Contact the app maintainer for further help."), -# footer = NULL, -# size = "l", -# easyClose = TRUE -# )) -# return(NULL) -# } -# FUN(SE=se2, INITIAL=initial, TOUR=tour) -# shinyjs::enable(iSEE:::.generalOrganizePanels) # organize panels -# shinyjs::enable(iSEE:::.generalLinkGraph) # link graph -# shinyjs::enable(iSEE:::.generalExportOutput) # export content -# shinyjs::enable(iSEE:::.generalCodeTracker) # tracked code -# shinyjs::enable(iSEE:::.generalPanelSettings) # panel settings -# shinyjs::enable(iSEE:::.generalVignetteOpen) # open vignette -# shinyjs::enable(iSEE:::.generalSessionInfo) # session info -# shinyjs::enable(iSEE:::.generalCitationInfo) # citation info -# } -# }, session = session) -# -# invisible(NULL) -# # nocov end -# } diff --git a/R/iSEEindexResource-class.R b/R/iSEEindexResource-class.R index 2c7caf5..4371437 100644 --- a/R/iSEEindexResource-class.R +++ b/R/iSEEindexResource-class.R @@ -2,7 +2,8 @@ #' The iSEEindexResource class #' -#' The iSEEindexResource class is a virtual class from which classes of supported resource must be derived. +#' The iSEEindexResource class is a virtual class from which classes of +#' supported resource must be derived. #' #' @section Slot overview: #' \itemize{ @@ -10,11 +11,14 @@ #' } #' #' @section Supported methods: -#' In the following code snippets, \code{x} is an instance of a [`iSEEindexResource-class`] class. -#' Refer to the documentation for each method for more details on the remaining arguments. +#' In the following code snippets, \code{x} is an instance of a +#' [`iSEEindexResource-class`] class. +#' Refer to the documentation for each method for more details on the remaining +#' arguments. #' #' \itemize{ -#' \item \code{\link{precache}(x, bfc, id, ...)} throws an error, encouraging users to develop a method for derived classes that are not supported yet. +#' \item \code{\link{precache}(x, bfc, id, ...)} throws an error, encouraging +#' users to develop a method for derived classes that are not supported yet. #' } #' #' @author Kevin Rue-Albrecht @@ -58,7 +62,8 @@ setMethod("show", "iSEEindexResource", #' @param ... additional arguments passed to and from other methods. #' #' @section Preparing and caching resources: -#' `precache(x, bfc, id, ...)` retrieves and caches a resource from an URI, caches it, and returns the path to the cached file. +#' `precache(x, bfc, id, ...)` retrieves and caches a resource from an URI, +#' caches it, and returns the path to the cached file. #' #' @author Kevin Rue-Albrecht #' @@ -79,7 +84,8 @@ NULL #' @export #' @rdname iSEEindexResource-generics #' -#' @return `precache()` returns the file path to the cached copy of a resource fetched from a given URI. +#' @return `precache()` returns the file path to the cached copy of a resource +#' fetched from a given URI. setGeneric("precache", function(x, bfc, id, ...) { stopifnot(is(x, "iSEEindexResource"), length(x) == 1L) standardGeneric("precache") @@ -119,14 +125,19 @@ setMethod("precache", "iSEEindexResource", #' } #' #' @section Slot overview: -#' This class inherits all slots from its parent class \linkS4class{iSEEindexResource}. +#' This class inherits all slots from its parent class +#' \linkS4class{iSEEindexResource}. #' #' @section Supported methods: -#' In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexHttpsResource} class. -#' Refer to the documentation for each method for more details on the remaining arguments. +#' In the following code snippets, \code{x} is an instance of a +#' \linkS4class{iSEEindexHttpsResource} class. +#' Refer to the documentation for each method for more details on the remaining +#' arguments. #' #' \itemize{ -#' \item \code{\link{precache}(x, bfc, id, ...)} caches the resource located at the given URI using \pkg{BiocFileCache} and returns the file path to the cached file. +#' \item \code{\link{precache}(x, bfc, id, ...)} caches the resource located at +#' the given URI using \pkg{BiocFileCache} and returns the file path to the +#' cached file. #' } #' #' @author Kevin Rue-Albrecht @@ -148,7 +159,8 @@ setClass("iSEEindexHttpsResource", contains="iSEEindexResource") #' #' @param x List of metadata. See Details. #' -#' @return The constructor function `iSEEindexHttpsResource()` returns an object of object of class `iSEEindexHttpsResource`. +#' @return The constructor function `iSEEindexHttpsResource()` returns an object +#' of class `iSEEindexHttpsResource`. iSEEindexHttpsResource <- function(x) { new("iSEEindexHttpsResource", uri = x[[.datasets_uri]]) } @@ -183,11 +195,15 @@ setMethod("precache", "iSEEindexHttpsResource", #' This class inherits all slots from its parent class \linkS4class{iSEEindexResource}. #' #' @section Supported methods: -#' In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexLocalhostResource} class. -#' Refer to the documentation for each method for more details on the remaining arguments. +#' In the following code snippets, \code{x} is an instance of a +#' \linkS4class{iSEEindexLocalhostResource} class. +#' Refer to the documentation for each method for more details on the remaining +#' arguments. #' #' \itemize{ -#' \item \code{\link{precache}(x, ...)} trims the `localhost://` prefix, and caches a copy of the resource located at the resulting file path using \pkg{BiocFileCache}, before returning the file path to the cached file. +#' \item \code{\link{precache}(x, ...)} trims the `localhost://` prefix, and +#' caches a copy of the resource located at the resulting file path using +#' \pkg{BiocFileCache}, before returning the file path to the cached file. #' } #' #' @section Absolute and relative paths: @@ -195,7 +211,8 @@ setMethod("precache", "iSEEindexHttpsResource", #' Absolute and relative paths are both supported. #' #' Absolute paths require an additional `/` (forward slash) -#' following the double forward slash `//` separating the scheme component of the URI. +#' following the double forward slash `//` separating the scheme component of +#' the URI. #' #' For instance: #' @@ -225,7 +242,8 @@ setClass("iSEEindexLocalhostResource", contains="iSEEindexResource") #' #' @param x List of metadata. See Details. #' -#' @return The constructor function `iSEEindexLocalhostResource()` returns an object of object of class `iSEEindexLocalhostResource`. +#' @return The constructor function `iSEEindexLocalhostResource()` returns an +#' object of object of class `iSEEindexLocalhostResource`. iSEEindexLocalhostResource <- function(x) { new("iSEEindexLocalhostResource", uri = x[[.datasets_uri]]) } @@ -255,7 +273,8 @@ setMethod("precache", "iSEEindexLocalhostResource", #' Required metadata: #' #' \describe{ -#' \item{uri}{Character scalar. R call which, once evaluated, produces a character scalar that is the URI of the resource.} +#' \item{uri}{Character scalar. R call which, once evaluated, produces a +#' character scalar that is the URI of the resource.} #' } #' #' @section URI format: @@ -269,11 +288,14 @@ setMethod("precache", "iSEEindexLocalhostResource", #' ``` #' #' @section Slot overview: -#' This class inherits all slots from its parent class \linkS4class{iSEEindexResource}. +#' This class inherits all slots from its parent class +#' \linkS4class{iSEEindexResource}. #' #' @section Supported methods: -#' In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexRcallResource} class. -#' Refer to the documentation for each method for more details on the remaining arguments. +#' In the following code snippets, \code{x} is an instance of a +#' \linkS4class{iSEEindexRcallResource} class. +#' Refer to the documentation for each method for more details on the remaining +#' arguments. #' #' \itemize{ #' \item \code{\link{precache}(x, ...)} trims the `rcall://` prefix, @@ -303,7 +325,8 @@ setClass("iSEEindexRcallResource", contains="iSEEindexResource") #' #' @param x List of metadata. See Details. #' -#' @return The constructor function `iSEEindexRcallResource()` returns an object of object of class `iSEEindexRcallResource`. +#' @return The constructor function `iSEEindexRcallResource()` returns an object +#' of object of class `iSEEindexRcallResource`. iSEEindexRcallResource <- function(x) { new("iSEEindexRcallResource", uri = x[[.datasets_uri]]) } @@ -325,7 +348,6 @@ setMethod("precache", "iSEEindexRcallResource", }) - # iSEEindexRunrResource ---- #' The iSEEindexRunrResource class @@ -343,11 +365,15 @@ setMethod("precache", "iSEEindexRcallResource", #' } #' #' @section Supported methods: -#' In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexRunrResource} class. -#' Refer to the documentation for each method for more details on the remaining arguments. +#' In the following code snippets, \code{x} is an instance of a +#' \linkS4class{iSEEindexRunrResource} class. +#' Refer to the documentation for each method for more details on the remaining +#' arguments. #' #' \itemize{ -#' \item \code{\link{precache}(x, bfc, id, ...)} caches the resource located at the given URI using \pkg{BiocFileCache} and returns the file path to the cached file. +#' \item \code{\link{precache}(x, bfc, id, ...)} caches the resource located at +#' the given URI using \pkg{BiocFileCache} and returns the file path to the +#' cached file. #' } #' #' @name iSEEindexRunrResource-class @@ -369,7 +395,8 @@ setClass("iSEEindexRunrResource", contains="iSEEindexResource") #' #' @param x List of metadata. See Details. #' -#' @return The constructor function `iSEEindexRunrResource()` returns an object of object of class `iSEEindexRunrResource`. +#' @return The constructor function `iSEEindexRunrResource()` returns an object +#' of object of class `iSEEindexRunrResource`. iSEEindexRunrResource <- function(x) { new("iSEEindexRunrResource", uri = x[[.datasets_uri]]) } @@ -394,15 +421,6 @@ setMethod("precache", "iSEEindexRunrResource", - - - - - - - - - # iSEEindexS3Resource ---- #' The iSEEindexS3Resource class @@ -421,7 +439,8 @@ setMethod("precache", "iSEEindexRunrResource", #' } #' #' @section Slot overview: -#' This class inherits all slots from its parent class \linkS4class{iSEEindexResource}. +#' This class inherits all slots from its parent class +#' \linkS4class{iSEEindexResource}. #' #' Furthermore, this class defines the additional slot(s) below: #' \describe{ @@ -429,12 +448,14 @@ setMethod("precache", "iSEEindexRunrResource", #' } #' #' @section Supported methods: -#' In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexS3Resource} class. -#' Refer to the documentation for each method for more details on the remaining arguments. +#' In the following code snippets, \code{x} is an instance of a +#' \linkS4class{iSEEindexS3Resource} class. +#' Refer to the documentation for each method for more details on the remaining +#' arguments. #' #' \itemize{ -#' \item \code{\link{precache}(x, ..., temp_dir = tempdir())} trims the `s3://` prefix, -#' parses information encoded in the remainder of the URI, +#' \item \code{\link{precache}(x, ..., temp_dir = tempdir())} trims the `s3://` +#' prefix, parses information encoded in the remainder of the URI, #' downloads the resource from AWS S3 using that information, #' and caches a copy of the resource located at the resulting file path using #' \pkg{BiocFileCache}, before returning the file path to the cached file. @@ -465,7 +486,8 @@ setMethod("precache", "iSEEindexRunrResource", #' For detailed information, please consult the #' [paws R package documentation](https://github.com/paws-r/paws/blob/main/docs/credentials.md). #' -#' Currently, you must have the [AWS Command Line Interface](https://aws.amazon.com/cli/) installed to use AWS SSO with \pkg{paws.storage}. +#' Currently, you must have the [AWS Command Line Interface](https://aws.amazon.com/cli/) +#' installed to use AWS SSO with \pkg{paws.storage}. #' #' A default AWS region can be set in the file `~/.aws/config`. #' For instance: @@ -475,7 +497,8 @@ setMethod("precache", "iSEEindexRunrResource", #' region=eu-west-2 #' ``` #' -#' Optionally, a field named `region` can be added in the list of resource metadata to set the AWS S3 region for each individual resource, e.g. +#' Optionally, a field named `region` can be added in the list of resource +#' metadata to set the AWS S3 region for each individual resource, e.g. #' #' ``` #' - id: ID1 @@ -486,12 +509,16 @@ setMethod("precache", "iSEEindexRunrResource", #' region: eu-west-2 #' ``` #' -#' Regions set in individual resource metadata override the default AWS region set in `~/.aws/config` (if any). -#' The region metadata does not need to be set for resources that should use the default region, and resource classes that do not require region information. +#' Regions set in individual resource metadata override the default AWS region +#' set in `~/.aws/config` (if any). +#' The region metadata does not need to be set for resources that should use the +#' default region, and resource classes that do not require region information. #' -#' If a default region is NOT set in `~/.aws/config`, then the region MUST be set in the metadata. +#' If a default region is NOT set in `~/.aws/config`, then the region MUST be +#' set in the metadata. #' -#' Credentials for all services can be set in the AWS shared credentials file `~/.aws/credentials`. +#' Credentials for all services can be set in the AWS shared credentials file +#' `~/.aws/credentials`. #' For instance: #' #' ``` @@ -529,7 +556,8 @@ setClass("iSEEindexS3Resource", contains="iSEEindexResource", slots = c("region" #' #' @param x List of metadata. See Details. #' -#' @return The constructor function `iSEEindexS3Resource()` returns an object of object of class `iSEEindexS3Resource`. +#' @return The constructor function `iSEEindexS3Resource()` returns an object of +#' object of class `iSEEindexS3Resource`. iSEEindexS3Resource <- function(x) { region <- x[[.dataset_region]] if (is.null(region) || identical(nchar(region), 0L)) { diff --git a/R/landing_page.R b/R/landing_page.R index d8260e9..de2b95b 100644 --- a/R/landing_page.R +++ b/R/landing_page.R @@ -1,10 +1,13 @@ #' Landing page function #' #' @param bfc A [BiocFileCache()] object. -#' @param FUN.datasets A function that returns a `data.frame` of metadata for available data sets. -#' @param FUN.initial A function that returns a `data.frame` of metadata for initial configuration states. +#' @param FUN.datasets A function that returns a `data.frame` of metadata for +#' available data sets. +#' @param FUN.initial A function that returns a `data.frame` of metadata for +#' initial configuration states. #' @param default.add Logical scalar indicating whether a default -#' initial configuration should be added as a choice in the Shiny `selectizeInput()`. +#' initial configuration should be added as a choice in the Shiny +#' `selectizeInput()`. #' See [iSEEindex()]. #' @param default.position Character scalar indicating whether the default #' initial configuration should be added as the `"first"` or `"last"` option @@ -39,7 +42,8 @@ # initial configurations initial_available_list <- FUN.initial() .check_initial_list(initial_available_list) - initial_available_table <- .initial_to_dataframe(initial_available_list, datasets_available_table[[.datasets_id]]) + initial_available_table <- .initial_to_dataframe(initial_available_list, + datasets_available_table[[.datasets_id]]) # landing page function (return value) function (FUN, input, output, session) { # nocov start @@ -51,7 +55,8 @@ shinydashboard::box(title = "Available Data Sets", collapsible = FALSE, width = NULL, selectizeInput(.ui_dataset_columns, label = "Show columns:", - choices = setdiff(colnames(datasets_available_table), c(.datasets_id, .datasets_uri, .datasets_description)), + choices = setdiff(colnames(datasets_available_table), + c(.datasets_id, .datasets_uri, .datasets_description)), selected = c(.datasets_title), multiple = TRUE, options = list(plugins=list('remove_button', 'drag_drop'))), @@ -115,100 +120,14 @@ } - -# .landing_page_runr <- function(bfc, FUN.datasets, FUN.initial, default.add = TRUE, default.position = c("first", "last"), body.header = NULL, body.footer = NULL) { -# default.position <- match.arg(default.position) -# # datasets -# datasets_available_list <- FUN.datasets() -# .check_datasets_list(datasets_available_list) -# datasets_available_table <- .datasets_to_dataframe(datasets_available_list) -# # initial configurations -# initial_available_list <- FUN.initial() -# .check_initial_list(initial_available_list) -# initial_available_table <- .initial_to_dataframe(initial_available_list, datasets_available_table[[.datasets_id]]) -# # landing page function (return value) -# function (FUN, input, output, session) { -# # nocov start -# output$allPanels <- renderUI({ -# tagList( -# body.header, -# fluidRow( -# column(width = 7L, -# shinydashboard::box(title = "Available Data Sets", -# collapsible = FALSE, width = NULL, -# selectizeInput(.ui_dataset_columns, label = "Show columns:", -# choices = setdiff(colnames(datasets_available_table), c(.datasets_id, .datasets_uri, .datasets_description)), -# selected = c(.datasets_title), -# multiple = TRUE, -# options = list(plugins=list('remove_button', 'drag_drop'))), -# DTOutput(.ui_dataset_table) -# )), -# column(width = 5L, -# shinydashboard::tabBox(id = .ui_box_dataset, title = "Selected dataset", -# side = "left", -# width = NULL, -# tabPanel("Info", -# uiOutput(.ui_markdown_overview)), -# tabPanel("Configure and launch", -# fluidRow( -# column(width = 10L, -# selectizeInput(.ui_initial, label = "Initial settings:", -# choices = character(0))), -# column(width = 2L, -# br(), -# actionButton(.ui_launch_button, label="Launch!", -# style="color: #ffffff; background-color: #0092AC; border-color: #2e6da4")) -# ), -# uiOutput(.ui_initial_overview)) -# ) -# ) -# ), -# body.footer -# ) # tagList -# }) # renderUI -# -# ## Disable navbar buttons that are not linked to any observer yet -# shinyjs::disable(iSEE:::.generalOrganizePanels) # organize panels -# shinyjs::disable(iSEE:::.generalLinkGraph) # link graph -# shinyjs::disable(iSEE:::.generalExportOutput) # export content -# shinyjs::disable(iSEE:::.generalCodeTracker) # tracked code -# shinyjs::disable(iSEE:::.generalPanelSettings) # panel settings -# shinyjs::disable(iSEE:::.generalVignetteOpen) # open vignette -# shinyjs::disable(iSEE:::.generalSessionInfo) # session info -# shinyjs::disable(iSEE:::.generalCitationInfo) # citation info -# -# pObjects <- .create_persistent_objects( -# datasets_available_table, -# initial_available_table) -# rObjects <- reactiveValues( -# rerender_datasets=1L, -# rerender_overview=1L, -# rerender_initial=1L) -# -# .create_observers(input, session, pObjects, rObjects, FUN.initial, default.add, default.position) -# -# .create_launch_observers(FUN, bfc, input, session, pObjects, already_se_object = TRUE) -# -# .render_datasets_table(output, pObjects, rObjects) -# -# .render_markdown_overview(output, pObjects, rObjects) -# -# .render_initial_overview(output, pObjects, rObjects) -# -# invisible(NULL) -# # nocov end -# } -# } - - - - #' Create persistent objects #' #' @param datasets_table A `data.frame` of metadata for all available data sets. -#' @param initial_table A `data.frame` of metadata for all available initial configuration scripts. +#' @param initial_table A `data.frame` of metadata for all available initial +#' configuration scripts. #' -#' @return An environment containing several global variables for use throughout the application. +#' @return An environment containing several global variables for use throughout +#' the application. #' #' @author Kevin Rue-Albrecht #' diff --git a/R/observers.R b/R/observers.R index 50db35b..9731fd8 100644 --- a/R/observers.R +++ b/R/observers.R @@ -4,13 +4,16 @@ #' #' `.create_observers()` initialises observers for the \pkg{iSEEindex} landing page. #' -#' `.create_launch_observers()` initialises observers for launching the \pkg{iSEE} main app. +#' `.create_launch_observers()` initialises observers for launching the +#' \pkg{iSEE} main app. #' #' @param input The Shiny input object from the server function. #' @param session The Shiny session object from the server function. -#' @param pObjects An environment containing global parameters generated in the landing page. +#' @param pObjects An environment containing global parameters generated in the +#' landing page. #' @param rObjects A reactive list of values generated in the landing page. -#' @param FUN.initial A function that returns available scripts for initial configurations states for a given data set identifier. +#' @param FUN.initial A function that returns available scripts for initial +#' configurations states for a given data set identifier. #' @param default.add Logical scalar indicating whether a default #' initial configuration should be added as a choice in the Shiny `selectizeInput()`. #' See [iSEEindex()]. @@ -28,7 +31,13 @@ #' @importFrom rintrojs introjs #' #' @rdname INTERNAL_create_observers -.create_observers <- function(input, session, pObjects, rObjects, FUN.initial, default.add, default.position) { +.create_observers <- function(input, + session, + pObjects, + rObjects, + FUN.initial, + default.add, + default.position) { # nocov start observeEvent(input[[.dataset_selected_row]], { @@ -65,12 +74,12 @@ #' @param FUN A function to initialize the \pkg{iSEE} observer #' architecture. Refer to [iSEE::createLandingPage()] for more details. -#' #' @param bfc A [BiocFileCache()] object. #' landing page. -#' @param input TODO -#' @param session TODO -#' @param pObjects TODO +#' @param input The Shiny input object from the server function. +#' @param session The Shiny session object from the server function. +#' @param pObjects An environment containing global parameters generated in the +#' landing page. #' #' @importFrom shiny observeEvent #' @@ -85,17 +94,3 @@ invisible(NULL) } - - -# -# .create_launch_observers_runr <- function(FUN, bfc, input, session, pObjects) { -# -# # nocov start -# observeEvent(input[[.ui_launch_button]], { -# .launch_isee(FUN, bfc, session, pObjects, already_se_object = TRUE) -# }, ignoreNULL=TRUE, ignoreInit=TRUE) -# # nocov end -# -# invisible(NULL) -# } - diff --git a/R/outputs.R b/R/outputs.R index a102296..814fda9 100644 --- a/R/outputs.R +++ b/R/outputs.R @@ -1,14 +1,15 @@ #' Render Table of Available Data Sets #' #' @param output The Shiny output object from the server function. -#' @param pObjects An environment containing global parameters generated in the landing page. +#' @param pObjects An environment containing global parameters generated in the +#' landing page. #' @param rObjects A reactive list of values generated in the landing page. #' #' @return Adds a rendered [DT::datatable()] to `output`. #' A \code{NULL} value is invisibly returned. -#' +#' #' @author Kevin Rue-Albrecht -#' +#' #' @importFrom DT datatable renderDT #' #' @rdname INTERNAL_render_datasets_table @@ -32,17 +33,20 @@ } #' Render Overview of Selected Data Set -#' +#' #' @description -#' -#' `.render_markdown_overview()` renders an overview of the selected data set using Markdown. -#' -#' `.render_initial_overview()` renders an overview of the selected initial configuration using Markdown. +#' +#' `.render_markdown_overview()` renders an overview of the selected data set +#' using Markdown. +#' +#' `.render_initial_overview()` renders an overview of the selected initial +#' configuration using Markdown. #' #' @param output The Shiny output object from the server function. -#' @param pObjects An environment containing global parameters generated in the landing page. +#' @param pObjects An environment containing global parameters generated in the +#' landing page. #' @param rObjects A reactive list of values generated in the landing page. -#' +#' #' @details #' Currently, those functions expect a column named `uri` in the metadata table #' of available data sets, which it uses as the identifier for each data set. @@ -50,9 +54,9 @@ #' @return #' `.render_markdown_overview()` and `.render_initial_overview()` both #' add a rendered [shiny::markdown()] to `output`. -#' +#' #' In both cases, a \code{NULL} value is invisibly returned. -#' +#' #' @author Kevin Rue-Albrecht #' #' @importFrom shiny markdown renderUI @@ -97,7 +101,7 @@ initial_id <- pObjects[[.ui_initial]] dataset_id <- pObjects[[.dataset_selected_id]] which_initial <- which( - pObjects$initial_table[[.initial_config_id]] == initial_id & + pObjects$initial_table[[.initial_config_id]] == initial_id & pObjects$initial_table[[.initial_datasets_id]] == dataset_id ) initial_info <- pObjects$initial_table[which_initial, .initial_description, drop=TRUE] diff --git a/R/utils-datasets.R b/R/utils-datasets.R index cb39123..8496c40 100644 --- a/R/utils-datasets.R +++ b/R/utils-datasets.R @@ -7,7 +7,8 @@ #' #' @param bfc A [BiocFileCache()] object. #' @param id A data set identifier as a character scalar. -#' @param metadata Named list of metadata. See individual resource classes for required and optional metadata. +#' @param metadata Named list of metadata. See individual resource classes for +#' required and optional metadata. #' #' @return #' For `.load_sce()`, a [SingleCellExperiment()] object. @@ -40,8 +41,10 @@ id, metadata) { resource_obj <- .metadata_to_object(metadata) - if (is(resource_obj, "iSEEindexHttpsResource") | is(resource_obj, "iSEEindexLocalhostResource") | - is(resource_obj, "iSEEindexRcallResource") | is(resource_obj, "iSEEindexS3Resource")) { + if (is(resource_obj, "iSEEindexHttpsResource") | + is(resource_obj, "iSEEindexLocalhostResource") | + is(resource_obj, "iSEEindexRcallResource") | + is(resource_obj, "iSEEindexS3Resource")) { already_se_object <- FALSE } else if (is(resource_obj, "iSEEindexRunrResource")) { already_se_object <- TRUE @@ -74,50 +77,6 @@ - -### #' @examples -### #' -### #' library(BiocFileCache) -### #' bfc <- BiocFileCache(tempdir()) -### #' id <- "demo_load_sce_tonsil" -### #' metadata <- list(uri="runr://HCATonsilData::HCATonsilData(assayType = 'RNA', cellType = 'epithelial')") -### #' -### #' ## Usage --- -### #' -### #' iSEEindex:::.load_sce_runr(bfc, id, metadata) -# .load_sce_runr <- function(bfc, id, metadata) { -# bfc_result <- bfcquery(bfc, id, field = "rname", exact = TRUE) -# # nocov start -# # if (nrow(bfc_result) == 0) { -# # uri_object <- .metadata_to_object(metadata) -# # object_path <- precache(uri_object, bfc, id) -# # } else { -# # object_path <- bfc[[bfc_result$rid]] -# # } -# -# uri_object <- .metadata_to_object(metadata) -# -# object_call <- precache(uri_object, bfc, id) -# # if (nrow(bfc_result) == 0) { -# # uri_object <- .metadata_to_object(metadata) -# # object_path <- precache(uri_object, bfc, id) -# # } else { -# # object_path <- bfc[[bfc_result$rid]] -# # } -# -# -# # nocov end -# # object <- readRDS(object_path) -# -# object <- object_call -# -# object <- .convert_to_sce(object) -# object -# } - - - - #' @param x An object Coercible to SingleCellExperiment #' #' @return @@ -139,6 +98,7 @@ x } + #' Convert Metadata to Class #' #' @param x Named list of metadata. @@ -183,12 +143,12 @@ } - #' Check Validity of Data Sets Metadata #' #' @param x `list` of of lists of metadata. #' -#' @return Invisible `NULL` if the metadata table is valid. Otherwise, throw an error. +#' @return Invisible `NULL` if the metadata table is valid. Otherwise, throw an +#' error. #' #' @author Kevin Rue-Albrecht #' diff --git a/R/utils-initial.R b/R/utils-initial.R index 993aa5c..48161a2 100644 --- a/R/utils-initial.R +++ b/R/utils-initial.R @@ -18,10 +18,10 @@ #' added to the choices for all data sets. #' That default option launches an initial state that includes one panel of #' each type compatible with the information present in the data set. -#' +#' #' The default initial configuration is always added for data sets which are not #' associated with any custom initial configuration. -#' +#' #' The option `default.add` controls whether the default initial configuration #' is added to the choices for data sets associated with at least one custom #' initial configuration. @@ -32,13 +32,16 @@ #' @author Kevin Rue-Albrecht #' #' @rdname INTERNAL_initial_choices -.initial_choices <- function(id, available, default.add = TRUE, default.position = c("first", "last")) { +.initial_choices <- function(id, + available, + default.add = TRUE, + default.position = c("first", "last")) { default.position <- match.arg(default.position) which_initial <- available[[.initial_datasets_id]] == id config_subset_table <- available[which_initial, , drop=FALSE] initial_choices <- config_subset_table[[.initial_config_id]] names(initial_choices) <- config_subset_table[[.initial_title]] - + if (default.add) { default_choice <- c("Default" = .initial_default_choice) if (identical(default.position, "first")) { @@ -47,27 +50,29 @@ initial_choices <- c(initial_choices, default_choice) } } - + initial_choices } #' Parses an Initial Application State script -#' +#' #' @description #' Parses the selected initial application state script. #' This can be a custom R script or the default initial state that creates #' one panel of each class compatible with the contents of the data set. -#' +#' #' The same script may define two objects `initial` and `tour` (see 'Value'). #' #' @param bfc A [BiocFileCache()] object. #' @param dataset_id Character scalar. Identifier of the data set selected. #' @param config_id Character scalar. Identifier of the configuration file to load. -#' @param metadata Named list of metadata. See individual resource classes for required and optional metadata. +#' @param metadata Named list of metadata. See individual resource classes for +#' required and optional metadata. #' #' @return A `list` of two elements. #' \describe{ -#' \item{initial}{A list of [Panel-class] objects, representing an initial app state} +#' \item{initial}{A list of [Panel-class] objects, representing an initial app +#' state} #' \item{tour}{A `data.frame` representing an \pkg{rintrojs} interactive tour} #' } #' @@ -113,7 +118,8 @@ #' #' @param x `list` of lists of metadata. #' -#' @return Invisible `NULL` if the metadata table is valid. Otherwise, throw an error. +#' @return Invisible `NULL` if the metadata table is valid. Otherwise, throw an +#' error. #' #' @author Kevin Rue-Albrecht #' diff --git a/man/iSEEindex.Rd b/man/iSEEindex.Rd index cb10796..3dfaf4e 100644 --- a/man/iSEEindex.Rd +++ b/man/iSEEindex.Rd @@ -41,7 +41,8 @@ info on the versions of the \code{iSEEindex} and \code{iSEE} packages.} \item{body.footer}{UI element to display \emph{below} the main landing page body.} } \value{ -An \code{\link[iSEE:iSEE]{iSEE::iSEE()}} app with a custom landing page using a \code{\link[=BiocFileCache]{BiocFileCache()}} to cache a selection of data sets. +An \code{\link[iSEE:iSEE]{iSEE::iSEE()}} app with a custom landing page using a +\code{\link[=BiocFileCache]{BiocFileCache()}} to cache a selection of data sets. } \description{ Generate an \pkg{iSEE} app that includes a landing page enabling @@ -50,57 +51,75 @@ states prepared by the app maintainer. } \section{Data Sets}{ -The function passed to the argument \code{FUN.datasets} must return a \code{list} that contains metadata about the available data sets. +The function passed to the argument \code{FUN.datasets} must return a \code{list} that +contains metadata about the available data sets. For each data set, required metadata are: \describe{ \item{id}{A unique identifier for the data set.} -\item{title}{A short human-readable title for the data set, displayed in the 'Info' panel when the data set is selected.} -\item{uri}{A Uniform Resource Identifier (URI) that indicates the location of the data file that contains the data set.} -\item{description}{A more detailed description of the data set, displayed in the 'Info' panel when the data set is selected.} +\item{title}{A short human-readable title for the data set, displayed in the +'Info' panel when the data set is selected.} +\item{uri}{A Uniform Resource Identifier (URI) that indicates the location of +the data file that contains the data set.} +\item{description}{A more detailed description of the data set, displayed in +the 'Info' panel when the data set is selected.} } Example: \if{html}{\out{
}}\preformatted{list( list( - id = "dataset01", - title = "Dataset 01", - uri = "https://example.com/1.rds", - description = "My first data set." + id = "dataset01", + title = "Dataset 01", + uri = "https://example.com/1.rds", + description = "My first data set." ), list( - id = "dataset02", - title = "Dataset 02", - uri = "https://example.com/1.rds", - description = "My second data set." + id = "dataset02", + title = "Dataset 02", + uri = "https://example.com/1.rds", + description = "My second data set." ) ) }\if{html}{\out{
}} -The individual sub-lists may also contain optional named metadata specific to individual \code{\linkS4class{iSEEindexResource}} classes (refer to the help page of those classes for details). +The individual sub-lists may also contain optional named metadata specific to +individual \code{\linkS4class{iSEEindexResource}} classes (refer to the help page of +those classes for details). -\strong{Important}: The \code{id} value is used to identify the data set file in the \pkg{BiocFileCache}. -Thus, we recommend using a dedicated \code{BiocFileCache()} for the app, using the \code{BiocFileCache(cache)} argument to specify an on-disk location (directory path) for the dedicated cache. +\strong{Important}: The \code{id} value is used to identify the data set file in the +\pkg{BiocFileCache}. +Thus, we recommend using a dedicated \code{BiocFileCache()} for the app, using the +\code{BiocFileCache(cache)} argument to specify an on-disk location (directory +path) for the dedicated cache. } \section{Initial Configurations}{ -The function passed to the argument \code{FUN.initial} must return a \code{list} that contains metadata about the available initial configurations, or \code{NULL} in the absence of any custom initial configuration (default settings will be applied to all data sets.). +The function passed to the argument \code{FUN.initial} must return a \code{list} that +contains metadata about the available initial configurations, or \code{NULL} in +the absence of any custom initial configuration (default settings will be +applied to all data sets.). For each initial configuration, required metadata are: \describe{ \item{id}{A unique identifier for the initial configuration.} -\item{title}{A short human-readable title for the initial configuration, representing the initial configuration in the 'Initial settings' dropdown menu.} -\item{uri}{A Uniform Resource Identifier (URI) that indicates the location of the R script that contains the initial configuration.} -\item{description}{A more detailed description of the initial configuration, displayed in the 'Configure and launch' panel when the initial configuration is selected.} +\item{title}{A short human-readable title for the initial configuration, +representing the initial configuration in the 'Initial settings' dropdown menu.} +\item{uri}{A Uniform Resource Identifier (URI) that indicates the location of +the R script that contains the initial configuration.} +\item{description}{A more detailed description of the initial configuration, +displayed in the 'Configure and launch' panel when the initial configuration +is selected.} } For each initial configuration, optional metadata are: \describe{ -\item{datasets}{A series of data set identifiers for which the configuration should be made available. If missing, the configuration will be available for all data sets.} +\item{datasets}{A series of data set identifiers for which the configuration +should be made available. If missing, the configuration will be available for +all data sets.} } Example: @@ -122,7 +141,9 @@ Example: ) }\if{html}{\out{}} -The individual sub-lists may also contain additional optional named metadata specific to individual \code{\linkS4class{iSEEindexResource}} classes (refer to the help page of those classes for details). +The individual sub-lists may also contain additional optional named metadata +specific to individual \code{\linkS4class{iSEEindexResource}} classes (refer to the help +page of those classes for details). } \examples{ diff --git a/man/iSEEindexHttpsResource-class.Rd b/man/iSEEindexHttpsResource-class.Rd index d4f7b8a..2b99573 100644 --- a/man/iSEEindexHttpsResource-class.Rd +++ b/man/iSEEindexHttpsResource-class.Rd @@ -12,7 +12,8 @@ iSEEindexHttpsResource(x) \item{x}{List of metadata. See Details.} } \value{ -The constructor function \code{iSEEindexHttpsResource()} returns an object of object of class \code{iSEEindexHttpsResource}. +The constructor function \code{iSEEindexHttpsResource()} returns an object +of class \code{iSEEindexHttpsResource}. } \description{ The iSEEindexHttpsResource class represents a resource accessible through @@ -28,16 +29,21 @@ Required metadata: } \section{Slot overview}{ -This class inherits all slots from its parent class \linkS4class{iSEEindexResource}. +This class inherits all slots from its parent class +\linkS4class{iSEEindexResource}. } \section{Supported methods}{ -In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexHttpsResource} class. -Refer to the documentation for each method for more details on the remaining arguments. +In the following code snippets, \code{x} is an instance of a +\linkS4class{iSEEindexHttpsResource} class. +Refer to the documentation for each method for more details on the remaining +arguments. \itemize{ -\item \code{\link{precache}(x, bfc, id, ...)} caches the resource located at the given URI using \pkg{BiocFileCache} and returns the file path to the cached file. +\item \code{\link{precache}(x, bfc, id, ...)} caches the resource located at +the given URI using \pkg{BiocFileCache} and returns the file path to the +cached file. } } diff --git a/man/iSEEindexLocalhostResource-class.Rd b/man/iSEEindexLocalhostResource-class.Rd index ffe097b..154f3f3 100644 --- a/man/iSEEindexLocalhostResource-class.Rd +++ b/man/iSEEindexLocalhostResource-class.Rd @@ -12,7 +12,8 @@ iSEEindexLocalhostResource(x) \item{x}{List of metadata. See Details.} } \value{ -The constructor function \code{iSEEindexLocalhostResource()} returns an object of object of class \code{iSEEindexLocalhostResource}. +The constructor function \code{iSEEindexLocalhostResource()} returns an +object of object of class \code{iSEEindexLocalhostResource}. } \description{ The iSEEindexLocalhostResource class represents a resource accessible through @@ -33,11 +34,15 @@ This class inherits all slots from its parent class \linkS4class{iSEEindexResour \section{Supported methods}{ -In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexLocalhostResource} class. -Refer to the documentation for each method for more details on the remaining arguments. +In the following code snippets, \code{x} is an instance of a +\linkS4class{iSEEindexLocalhostResource} class. +Refer to the documentation for each method for more details on the remaining +arguments. \itemize{ -\item \code{\link{precache}(x, ...)} trims the \verb{localhost://} prefix, and caches a copy of the resource located at the resulting file path using \pkg{BiocFileCache}, before returning the file path to the cached file. +\item \code{\link{precache}(x, ...)} trims the \verb{localhost://} prefix, and +caches a copy of the resource located at the resulting file path using +\pkg{BiocFileCache}, before returning the file path to the cached file. } } @@ -47,7 +52,8 @@ Refer to the documentation for each method for more details on the remaining arg Absolute and relative paths are both supported. Absolute paths require an additional \code{/} (forward slash) -following the double forward slash \verb{//} separating the scheme component of the URI. +following the double forward slash \verb{//} separating the scheme component of +the URI. For instance: diff --git a/man/iSEEindexRcallResource-class.Rd b/man/iSEEindexRcallResource-class.Rd index d834044..cbf336f 100644 --- a/man/iSEEindexRcallResource-class.Rd +++ b/man/iSEEindexRcallResource-class.Rd @@ -12,7 +12,8 @@ iSEEindexRcallResource(x) \item{x}{List of metadata. See Details.} } \value{ -The constructor function \code{iSEEindexRcallResource()} returns an object of object of class \code{iSEEindexRcallResource}. +The constructor function \code{iSEEindexRcallResource()} returns an object +of object of class \code{iSEEindexRcallResource}. } \description{ The iSEEindexRcallResource class represents a resource accessible through @@ -23,7 +24,8 @@ A URI for this type of resource uses the prefix \dQuote{rcall://}. Required metadata: \describe{ -\item{uri}{Character scalar. R call which, once evaluated, produces a character scalar that is the URI of the resource.} +\item{uri}{Character scalar. R call which, once evaluated, produces a +character scalar that is the URI of the resource.} } } \section{URI format}{ @@ -39,13 +41,16 @@ For instance: \section{Slot overview}{ -This class inherits all slots from its parent class \linkS4class{iSEEindexResource}. +This class inherits all slots from its parent class +\linkS4class{iSEEindexResource}. } \section{Supported methods}{ -In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexRcallResource} class. -Refer to the documentation for each method for more details on the remaining arguments. +In the following code snippets, \code{x} is an instance of a +\linkS4class{iSEEindexRcallResource} class. +Refer to the documentation for each method for more details on the remaining +arguments. \itemize{ \item \code{\link{precache}(x, ...)} trims the \verb{rcall://} prefix, diff --git a/man/iSEEindexResource-class.Rd b/man/iSEEindexResource-class.Rd index bb2660b..ec2e099 100644 --- a/man/iSEEindexResource-class.Rd +++ b/man/iSEEindexResource-class.Rd @@ -27,7 +27,8 @@ \code{precache()} throws an error if no method is found for the derived class. } \description{ -The iSEEindexResource class is a virtual class from which classes of supported resource must be derived. +The iSEEindexResource class is a virtual class from which classes of +supported resource must be derived. } \section{Slot overview}{ @@ -38,11 +39,14 @@ The iSEEindexResource class is a virtual class from which classes of supported r \section{Supported methods}{ -In the following code snippets, \code{x} is an instance of a \code{\linkS4class{iSEEindexResource}} class. -Refer to the documentation for each method for more details on the remaining arguments. +In the following code snippets, \code{x} is an instance of a +\code{\linkS4class{iSEEindexResource}} class. +Refer to the documentation for each method for more details on the remaining +arguments. \itemize{ -\item \code{\link{precache}(x, bfc, id, ...)} throws an error, encouraging users to develop a method for derived classes that are not supported yet. +\item \code{\link{precache}(x, bfc, id, ...)} throws an error, encouraging +users to develop a method for derived classes that are not supported yet. } } diff --git a/man/iSEEindexResource-generics.Rd b/man/iSEEindexResource-generics.Rd index f20a9e7..774d84c 100644 --- a/man/iSEEindexResource-generics.Rd +++ b/man/iSEEindexResource-generics.Rd @@ -18,14 +18,16 @@ precache(x, bfc, id, ...) \item{...}{additional arguments passed to and from other methods.} } \value{ -\code{precache()} returns the file path to the cached copy of a resource fetched from a given URI. +\code{precache()} returns the file path to the cached copy of a resource +fetched from a given URI. } \description{ An overview of the generics for \code{iSEEindexResources} objects. } \section{Preparing and caching resources}{ -\code{precache(x, bfc, id, ...)} retrieves and caches a resource from an URI, caches it, and returns the path to the cached file. +\code{precache(x, bfc, id, ...)} retrieves and caches a resource from an URI, +caches it, and returns the path to the cached file. } \examples{ diff --git a/man/iSEEindexRunrResource-class.Rd b/man/iSEEindexRunrResource-class.Rd index fc0ad6d..ddb8e76 100644 --- a/man/iSEEindexRunrResource-class.Rd +++ b/man/iSEEindexRunrResource-class.Rd @@ -12,7 +12,8 @@ iSEEindexRunrResource(x) \item{x}{List of metadata. See Details.} } \value{ -The constructor function \code{iSEEindexRunrResource()} returns an object of object of class \code{iSEEindexRunrResource}. +The constructor function \code{iSEEindexRunrResource()} returns an object +of object of class \code{iSEEindexRunrResource}. } \description{ The iSEEindexRunrResource class represents an SE object, obtained directly @@ -29,11 +30,15 @@ Required metadata: } \section{Supported methods}{ -In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexRunrResource} class. -Refer to the documentation for each method for more details on the remaining arguments. +In the following code snippets, \code{x} is an instance of a +\linkS4class{iSEEindexRunrResource} class. +Refer to the documentation for each method for more details on the remaining +arguments. \itemize{ -\item \code{\link{precache}(x, bfc, id, ...)} caches the resource located at the given URI using \pkg{BiocFileCache} and returns the file path to the cached file. +\item \code{\link{precache}(x, bfc, id, ...)} caches the resource located at +the given URI using \pkg{BiocFileCache} and returns the file path to the +cached file. } } diff --git a/man/iSEEindexS3Resource-class.Rd b/man/iSEEindexS3Resource-class.Rd index a5686f6..3556fa7 100644 --- a/man/iSEEindexS3Resource-class.Rd +++ b/man/iSEEindexS3Resource-class.Rd @@ -12,7 +12,8 @@ iSEEindexS3Resource(x) \item{x}{List of metadata. See Details.} } \value{ -The constructor function \code{iSEEindexS3Resource()} returns an object of object of class \code{iSEEindexS3Resource}. +The constructor function \code{iSEEindexS3Resource()} returns an object of +object of class \code{iSEEindexS3Resource}. } \description{ The iSEEindexS3Resource class represents a cloud storage resource accessible @@ -30,7 +31,8 @@ Required metadata: } \section{Slot overview}{ -This class inherits all slots from its parent class \linkS4class{iSEEindexResource}. +This class inherits all slots from its parent class +\linkS4class{iSEEindexResource}. Furthermore, this class defines the additional slot(s) below: \describe{ @@ -40,12 +42,14 @@ Furthermore, this class defines the additional slot(s) below: \section{Supported methods}{ -In the following code snippets, \code{x} is an instance of a \linkS4class{iSEEindexS3Resource} class. -Refer to the documentation for each method for more details on the remaining arguments. +In the following code snippets, \code{x} is an instance of a +\linkS4class{iSEEindexS3Resource} class. +Refer to the documentation for each method for more details on the remaining +arguments. \itemize{ -\item \code{\link{precache}(x, ..., temp_dir = tempdir())} trims the \verb{s3://} prefix, -parses information encoded in the remainder of the URI, +\item \code{\link{precache}(x, ..., temp_dir = tempdir())} trims the \verb{s3://} +prefix, parses information encoded in the remainder of the URI, downloads the resource from AWS S3 using that information, and caches a copy of the resource located at the resulting file path using \pkg{BiocFileCache}, before returning the file path to the cached file. @@ -81,7 +85,8 @@ recursively if it doesn't already exist.} For detailed information, please consult the \href{https://github.com/paws-r/paws/blob/main/docs/credentials.md}{paws R package documentation}. -Currently, you must have the \href{https://aws.amazon.com/cli/}{AWS Command Line Interface} installed to use AWS SSO with \pkg{paws.storage}. +Currently, you must have the \href{https://aws.amazon.com/cli/}{AWS Command Line Interface} +installed to use AWS SSO with \pkg{paws.storage}. A default AWS region can be set in the file \verb{~/.aws/config}. For instance: @@ -90,7 +95,8 @@ For instance: region=eu-west-2 }\if{html}{\out{}} -Optionally, a field named \code{region} can be added in the list of resource metadata to set the AWS S3 region for each individual resource, e.g. +Optionally, a field named \code{region} can be added in the list of resource +metadata to set the AWS S3 region for each individual resource, e.g. \if{html}{\out{
}}\preformatted{- id: ID1 title: ReprocessedAllenData @@ -100,12 +106,16 @@ Optionally, a field named \code{region} can be added in the list of resource met region: eu-west-2 }\if{html}{\out{
}} -Regions set in individual resource metadata override the default AWS region set in \verb{~/.aws/config} (if any). -The region metadata does not need to be set for resources that should use the default region, and resource classes that do not require region information. +Regions set in individual resource metadata override the default AWS region +set in \verb{~/.aws/config} (if any). +The region metadata does not need to be set for resources that should use the +default region, and resource classes that do not require region information. -If a default region is NOT set in \verb{~/.aws/config}, then the region MUST be set in the metadata. +If a default region is NOT set in \verb{~/.aws/config}, then the region MUST be +set in the metadata. -Credentials for all services can be set in the AWS shared credentials file \verb{~/.aws/credentials}. +Credentials for all services can be set in the AWS shared credentials file +\verb{~/.aws/credentials}. For instance: \if{html}{\out{
}}\preformatted{[default] From cc9b964b01bb274f0b5b3a3cb4666f32f7546ee0 Mon Sep 17 00:00:00 2001 From: Federico Marini Date: Thu, 3 Oct 2024 00:07:32 +0200 Subject: [PATCH 6/7] expanding the test suite to cover the runr usage --- DESCRIPTION | 1 + .../testthat/test-iSEEindexResources-class.R | 89 ++++++++++++------- tests/testthat/test-utils-datasets.R | 9 ++ 3 files changed, 67 insertions(+), 32 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index aabef0f..3e67c5a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -48,6 +48,7 @@ Suggests: knitr, RefManageR, rmarkdown, + scRNAseq, sessioninfo, testthat (>= 3.0.0), yaml diff --git a/tests/testthat/test-iSEEindexResources-class.R b/tests/testthat/test-iSEEindexResources-class.R index dd22dbf..b8e4551 100644 --- a/tests/testthat/test-iSEEindexResources-class.R +++ b/tests/testthat/test-iSEEindexResources-class.R @@ -1,126 +1,151 @@ test_that("show(iSEEindexResource) works", { - + out <- new("iSEEindexResource", uri = "https://zenodo.org/record/7304331/files/ReprocessedAllenData.rds") expect_output(show(out), "class: iSEEindexResource") - + }) test_that("precache(iSEEindexResource) throws an error", { - + out <- new("iSEEindexResource", uri = "https://zenodo.org/record/7304331/files/ReprocessedAllenData.rds") expect_error(precache(out), "no 'precache' method defined for object of class") - + }) # iSEEindexHttpsResource ---- test_that("iSEEindexS3Resource constructor works", { - + out <- iSEEindexHttpsResource(list( uri = "https://zenodo.org/record/7304331/files/ReprocessedAllenData.rds")) - + expect_identical(out@uri, "https://zenodo.org/record/7304331/files/ReprocessedAllenData.rds") }) test_that("show(iSEEindexHttpsResource) works", { - + out <- new("iSEEindexHttpsResource", uri = "https://zenodo.org/record/7304331/files/ReprocessedAllenData.rds") expect_output(show(out), "class: iSEEindexHttpsResource") - + }) test_that("precache(iSEEindexHttpsResource) returns the original URI", { - + x <- new("iSEEindexHttpsResource", uri = "https://zenodo.org/record/7304331/files/ReprocessedAllenData_config_01.R?download=1") out <- precache(x, bfc, "DUMMY") expect_true(file.exists(out)) - + bfcremove(bfc, names(out)) }) # iSEEindexLocalhostResource ---- test_that("iSEEindexLocalhostResource constructor works", { - + tf <- tempfile() file.create(tf) - + out <- iSEEindexLocalhostResource(list( uri = sprintf("localhost://%s", tf))) - + expect_identical(out@uri, sprintf("localhost://%s", tf)) }) test_that("show(iSEEindexLocalhostResource) works", { - + out <- new("iSEEindexLocalhostResource", uri = "localhost://path/to/file") expect_output(show(out), "class: iSEEindexLocalhostResource") - + }) test_that("precache(iSEEindexLocalhostResource) workls", { - + tf <- tempfile() file.create(tf) - + x <- new("iSEEindexLocalhostResource", uri = sprintf("localhost://%s", tf)) out <- precache(x, bfc, "DUMMY") expect_true(file.exists(out)) - + bfcremove(bfc, names(out)) - + unlink(tf) }) # iSEEindexRcallResource ---- test_that("iSEEindexRcallResource constructor works", { - + out <- iSEEindexRcallResource (list( uri = "rcall://system.file(package='iSEEindex','ReprocessedAllenData_config_01.R')")) - + expect_identical(out@uri, "rcall://system.file(package='iSEEindex','ReprocessedAllenData_config_01.R')") }) test_that("show(iSEEindexRcallResource) works", { - + out <- new("iSEEindexRcallResource", uri = "rcall://system.file(package='iSEEindex','ReprocessedAllenData_config_01.R')") expect_output(show(out), "class: iSEEindexRcallResource") - + }) -test_that("precache(iSEEindexRcallResource) workls", { - +test_that("precache(iSEEindexRcallResource) works", { + x <- new("iSEEindexRcallResource", uri = "rcall://system.file(package='iSEEindex','ReprocessedAllenData_config_01.R')") out <- precache(x, bfc, "DUMMY") expect_true(file.exists(out)) - + bfcremove(bfc, names(out)) }) # iSEEindexS3Resource ---- test_that("iSEEindexS3Resource constructor works", { - + out <- iSEEindexS3Resource(list( uri = "s3://example/path/to/bucket")) - + expect_identical(out@uri, "s3://example/path/to/bucket") expect_identical(out@region, NA_character_) - + out <- iSEEindexS3Resource(list( uri = "s3://example/path/to/bucket", region = "eu-west-2")) - + expect_identical(out@uri, "s3://example/path/to/bucket") expect_identical(out@region, "eu-west-2") }) test_that("show(iSEEindexS3Resource) works", { - + x <- new("iSEEindexS3Resource", uri = "s3://bucket/file.R") expect_output(show(x), "class: iSEEindexS3Resource") - + +}) + + +# iSEEindexS3Resource ---- + +test_that("iSEEindexRunrResource constructor works", { + + out <- iSEEindexRunrResource(list( + uri = "runr://scRNAseq::ReprocessedAllenData()")) + + expect_identical(out@uri, "runr://scRNAseq::ReprocessedAllenData()") +}) + +test_that("show(iSEEindexRunrResource) works", { + + x <- new("iSEEindexRunrResource", uri = "runr://scRNAseq::ReprocessedAllenData()") + expect_output(show(x), "class: iSEEindexRunrResource") + +}) + +test_that("precache(iSEEindexRunrResource) works", { + + x <- new("iSEEindexRunrResource", uri = "runr://scRNAseq::ReprocessedAllenData()") + out <- precache(x, bfc, "DUMMY") + expect_true(is(out, "SingleCellExperiment")) }) diff --git a/tests/testthat/test-utils-datasets.R b/tests/testthat/test-utils-datasets.R index 134a791..79b3a1a 100644 --- a/tests/testthat/test-utils-datasets.R +++ b/tests/testthat/test-utils-datasets.R @@ -13,6 +13,15 @@ test_that(".load_sce works", { out <- iSEEindex:::.load_sce(bfc, id, metadata) expect_s4_class(out, "SummarizedExperiment") + + + # loading directly via runr + id_allen <- "demo_load_sce_tonsil" + metadata_allen <- list( + uri="runr://scRNAseq::ReprocessedAllenData()" + ) + out <- iSEEindex:::.load_sce(bfc, id_allen, metadata_allen) + expect_s4_class(out, "SummarizedExperiment") }) # .convert_to_sce ---- From 34080f9613574f72c67a866f83c08f296bfa2860 Mon Sep 17 00:00:00 2001 From: Federico Marini Date: Thu, 3 Oct 2024 00:07:54 +0200 Subject: [PATCH 7/7] Some general information on the runr implementation is provided also in the vignette --- vignettes/resources.Rmd | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/vignettes/resources.Rmd b/vignettes/resources.Rmd index caa1275..1a0f332 100644 --- a/vignettes/resources.Rmd +++ b/vignettes/resources.Rmd @@ -180,6 +180,29 @@ Now, while the scheme `s3` is recognised by the [AWS Command Line Interface][aws In this instance, the `precache()` function has the job to parse the URI for information that is passed to the `r BiocStyle::CRANpkg("paws.storage")` package to download the file, which is then cached using `r Biocpkg("BiocFileCache")`. +## iSEEindexRunrResource + +### Structure + +This type of resource is documented in `help("iSEEindexRunrResource-class")`. + +This class is used to represent directly objects that are generated via a call to arbitrary R code. + +The URI must use the custom scheme "runr", followed by the code itself to be run to obtain the object to explore. + +Example: + +```bash +runr://function_to_call(param1 = "value1", param2 = "value2") +``` + +### Caching + +As this class does not directly specify a path, but rather focus on the object itself, the classical `r Biocpkg("BiocFileCache")`-based caching will not work automatically. + +Nonetheless, since a typical use case would be to host a collection of datasets provided in a data package, chances are that these packages implement some form of `r Biocpkg("BiocFileCache")`-enabled caching. + + # Reproducibility The `r Biocpkg("iSEEindex")` package `r Citep(bib[["iSEEindex"]])` was made possible thanks to: