Skip to content

Commit

Permalink
Merge pull request #64 from iSEE/runr_backpropagated_param
Browse files Browse the repository at this point in the history
Runr full implementation
  • Loading branch information
federicomarini authored Oct 2, 2024
2 parents 373b2ca + 247814e commit bd12c92
Show file tree
Hide file tree
Showing 20 changed files with 599 additions and 560 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Suggests:
knitr,
RefManageR,
rmarkdown,
scRNAseq,
sessioninfo,
testthat (>= 3.0.0),
yaml
Expand Down
264 changes: 89 additions & 175 deletions R/iSEEindex.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,56 +6,74 @@
#' 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:
#'
#' ```
#' 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:
Expand All @@ -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
Expand All @@ -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
#'
Expand All @@ -107,17 +128,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
Expand All @@ -133,63 +146,32 @@
#' 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
#' }
#'
#' 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,
Expand All @@ -199,48 +181,52 @@ 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)
#'
#' 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) {
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
),
appTitle = app.title
)
}



#' Prepare and Launch the Main App.
#'
#' Invokes a function that replaces the landing page by the \pkg{iSEE}
Expand All @@ -258,7 +244,7 @@ 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.
Expand Down Expand Up @@ -333,75 +319,3 @@ iSEEindex_runr <- 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_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
}
Loading

0 comments on commit bd12c92

Please sign in to comment.