Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/no internet #4

Merged
merged 10 commits into from
Aug 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: SeuratData
Type: Package
Title: Install and Manage Seurat Datasets
Version: 0.1.0.9000
Version: 0.1.0.9001
Date: 2019-07-17
Authors@R: c(
person(given = 'Rahul', family = 'Satija', email = '[email protected]', role = 'aut', comment = c(ORCID = '0000-0001-9448-8833')),
Expand All @@ -21,6 +21,7 @@ RoxygenNote: 6.1.1
Imports:
cli,
crayon,
rappdirs,
stats,
utils
Collate:
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ importFrom(crayon,col_nchar)
importFrom(crayon,green)
importFrom(crayon,red)
importFrom(crayon,yellow)
importFrom(rappdirs,user_data_dir)
importFrom(stats,na.omit)
importFrom(utils,available.packages)
importFrom(utils,data)
Expand Down
23 changes: 21 additions & 2 deletions R/seurat_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,20 @@ AvailableData <- function() {
#'
InstallData <- function(ds, force.reinstall = FALSE, ...) {
UpdateManifest()
if (pkg.env$source != 'remote') {
stop(
"No access to remote SeuratData repository, unable to install new datasets",
call. = FALSE
)
}
pkgs <- NameToPackage(ds = ds)
if (!force.reinstall) {
installed <- intersect(x = pkgs, y = rownames(x = InstalledData()))
if (length(x = installed) > 0) {
warning(
"The following packages are already installed and will not be reinstalled: ",
paste(
gsub(pattern = '\\.SeuratData', replacement = '', x = installed),
gsub(pattern = pkg.key, replacement = '', x = installed),
collapse = ', '
),
call. = FALSE,
Expand All @@ -73,7 +79,12 @@ InstallData <- function(ds, force.reinstall = FALSE, ...) {
for (p in pkgs2[pkgs2 %in% search()]) {
detach(name = p, unload = TRUE, character.only = TRUE)
}
install.packages(pkgs = pkgs, repos = getOption(x = "SeuratData.repo.use"), type = 'source', ...)
install.packages(
pkgs = pkgs,
repos = getOption(x = "SeuratData.repo.use"),
type = 'source',
...
)
for (pkg in pkgs) {
attachNamespace(ns = pkg)
pkg.env$attached <- c(pkg.env$attached, pkg)
Expand Down Expand Up @@ -134,6 +145,7 @@ LoadData <- function(
graphs = NULL,
verbose = TRUE
) {
.NotYetImplemented()
installed <- InstalledData()
if (!NameToPackage(ds = ds) %in% rownames(x = installed)) {
stop("Cannot find dataset ", ds, call. = FALSE)
Expand Down Expand Up @@ -209,6 +221,13 @@ RemoveData <- function(ds, lib) {
#' }
#'
UpdateData <- function(ask = TRUE, lib.loc = NULL) {
UpdateManifest()
if (pkg.env$source != 'remote') {
stop(
"No access to remote SeuratData repository, unable to update datasets",
call. = FALSE
)
}
update.packages(lib.loc = lib.loc, repos = getOption(x = "SeuratData.repo.use"), ask = ask, type = 'source')
UpdateManifest()
invisible(x = NULL)
Expand Down
247 changes: 180 additions & 67 deletions R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@
#'
#' @section Package options:
#'
#' SeuratData uses the following [options()] to configure behaviour:
#' SeuratData uses the following options to control behaviour, users can configure
#' these with \code{\link[base]{options}}:
#'
#' \itemize{
#' \item `SeuratData.repo.use`: Set the location where the SeuratData datasets
#' are stored. Users generally should not modify.
#' \item `SeuratData.manifest.cache`: Cache the data manifest whenever we talk
#' to the data repository; note, setting to \code{FALSE} will simply prevent
#' SeuratData from caching the manifest, not from reading a previously cached
#' manifest
#' \item `SeuratData.roaming`: For Windows users, use a roaming profile directory
#' for domain users. See \url{https://en.wikipedia.org/wiki/Roaming_user_profile}
#' for a brief overview and Microsoft's documentation for greater detail
#' }
#'
#' @docType package
Expand All @@ -17,16 +25,23 @@
"_PACKAGE"

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Global variables and environment
# Global variables, default options, and package environment
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

default.options <- list(
SeuratData.repo.use = 'https://seurat.nygenome.org'
SeuratData.repo.use = 'http://seurat.nygenome.org/',
SeuratData.manifest.cache = TRUE,
SeuratData.roaming = FALSE
)

pkg.key <- '\\.SeuratData$'

pkg.env <- new.env()
pkg.env$manifest <- vector(mode = 'character')
pkg.env$manifest <- vector(mode = 'list')
pkg.env$source <- vector(mode = 'character')
pkg.env$update.call <- vector(mode = 'character')
pkg.env$attached <- vector(mode = 'character')
pkg.env$extdata.warn <- FALSE

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Internal functions
Expand Down Expand Up @@ -60,6 +75,28 @@ pkg.env$attached <- vector(mode = 'character')
}
}

#' Get an application data directory
#'
#' @inheritParams AttachData
#' @param author Author name for application
#'
#' @return A character vector with path to the application data dir
#'
#' @importFrom rappdirs user_data_dir
#'
#' @seealso \code{\link[rappdirs]{user_data_dir}}
#'
#' @keywords internal
#'
AppData <- function(pkgname = 'SeuratData', author = pkgname) {
return(user_data_dir(
appname = pkgname,
appauthor = author,
version = file.path('%p-platform', '%v'),
roaming = getOption(x = 'SeuratData.roaming', default = FALSE)
))
}

#' Attach datasets
#'
#' @param pkgname Name of package
Expand Down Expand Up @@ -264,77 +301,134 @@ NameToPackage <- function(ds) {
#' @keywords internal
#'
UpdateManifest <- function() {
avail.pkgs <- available.packages(
repos = getOption(x = "SeuratData.repo.use"),
type = 'source',
fields = c('Description', 'Title'),
ignore_repo_cache = TRUE
# Set some defaults
pkg.env$source <- 'remote'
cache.manifest <- file.path(
AppData(pkgname = 'SeuratData', author = 'Satija Lab'),
'manifest.Rds'
)
avail.pkgs <- as.data.frame(x = avail.pkgs, stringsAsFactors = FALSE)
avail.pkgs <- avail.pkgs[grepl(pattern = '\\.SeuratData$', x = avail.pkgs$Package), , drop = FALSE]
avail.pkgs <- apply(
X = avail.pkgs,
MARGIN = 1,
FUN = function(pkg) {
dataset <- gsub(
pattern = '\\.SeuratData$',
replacement = '',
x = pkg[['Package']]
)
desc <- unlist(x = strsplit(x = pkg[['Description']], split = '\n'))
desc <- sapply(
X = strsplit(x = desc, split = ':'),
FUN = function(x) {
name <- trimws(x = x[[1]])
val <- trimws(x = unlist(x = strsplit(x = x[[2]], split = ',')))
val <- paste(val, collapse = ', ')
names(x = val) <- name
return(val)
}
)
desc <- sapply(
X = desc,
FUN = function(x) {
x <- tryCatch(
expr = as.numeric(x = x),
warning = function(...) {
return(x)
}
)
if (!is.numeric(x = x) && !is.na(x = as.logical(x = x))) {
x <- as.logical(x = x)
}
return(x)
},
simplify = FALSE,
USE.NAMES = TRUE
)
desc <- c(
'Dataset' = dataset,
'Version' = pkg[['Version']],
'Summary' = pkg[['Title']],
desc
# Attempt to get the manifest from the remote server
avail.pkgs <- tryCatch(
expr = available.packages(
repos = getOption(x = "SeuratData.repo.use"),
type = 'source',
fields = c('Description', 'Title'),
ignore_repo_cache = TRUE
),
warning = function(...) {
pkg.env$source <- ifelse(
test = file.exists(cache.manifest),
yes = 'appdir',
no = 'extdata'
)
return(desc)
}
)
manifest.names <- unique(x = unlist(
x = lapply(X = avail.pkgs, FUN = names),
use.names = FALSE
))
for (pkg in names(x = avail.pkgs)) {
for (col in manifest.names) {
avail.pkgs[[pkg]][[col]] <- avail.pkgs[[pkg]][[col]] %||% NA
# Process the manifest
if (pkg.env$source == 'remote') {
# Lots of stuff to get the manifest modified from the available.packages format
# into something usable by SeuratData
pkg.env$extdata.warn <- FALSE
avail.pkgs <- as.data.frame(x = avail.pkgs, stringsAsFactors = FALSE)
# Ensure we only use datasets tagged with .SeuratData
avail.pkgs <- avail.pkgs[grepl(pattern = pkg.key, x = avail.pkgs$Package), , drop = FALSE]
# Filter down to dataset name, short summary from package title, and
# metadata contained in package description
avail.pkgs <- apply(
X = avail.pkgs,
MARGIN = 1,
FUN = function(pkg) {
# Get dataset name
dataset <- gsub(
pattern = pkg.key,
replacement = '',
x = pkg[['Package']]
)
# Process the description metadata
desc <- unlist(x = strsplit(x = pkg[['Description']], split = '\n'))
desc <- sapply(
X = strsplit(x = desc, split = ':'),
FUN = function(x) {
name <- trimws(x = x[[1]])
val <- trimws(x = unlist(x = strsplit(x = x[[2]], split = ',')))
val <- paste(val, collapse = ', ')
names(x = val) <- name
return(val)
}
)
desc <- sapply(
X = desc,
FUN = function(x) {
x <- tryCatch(
expr = as.numeric(x = x),
warning = function(...) {
return(x)
}
)
if (!is.numeric(x = x) && !is.na(x = as.logical(x = x))) {
x <- as.logical(x = x)
}
return(x)
},
simplify = FALSE,
USE.NAMES = TRUE
)
# Assemble the information
desc <- c(
'Dataset' = dataset,
'Version' = pkg[['Version']],
'Summary' = pkg[['Title']],
desc
)
return(desc)
}
)
# Pad missing metadata with NAs
manifest.names <- unique(x = unlist(
x = lapply(X = avail.pkgs, FUN = names),
use.names = FALSE
))
for (pkg in names(x = avail.pkgs)) {
for (col in manifest.names) {
avail.pkgs[[pkg]][[col]] <- avail.pkgs[[pkg]][[col]] %||% NA
}
}
# Convert each entry to a dataframe and bind everything together
avail.pkgs <- lapply(X = avail.pkgs, FUN = as.data.frame, stringsAsFactors = FALSE)
avail.pkgs <- do.call(what = 'rbind', args = avail.pkgs)
# Coerce version information to package_version
avail.pkgs$Version <- package_version(x = avail.pkgs$Version)
} else if (pkg.env$source == 'appdir') {
# Read cached manifest
pkg.env$extdata.warn <- FALSE
packageStartupMessage(
"Using cached data manifest, last updated at ",
file.info(cache.manifest)$ctime
)
avail.pkgs <- readRDS(file = cache.manifest)
} else if (pkg.env$source == 'extdata') {
# Read SeuratData-bundled manifest
if (!pkg.env$extdata.warn) {
warning(
"Using SeuratData-bundled data manifest. ",
"This may be out-of-date and not contain the latest datasets. ",
"This warning will be shown once per session or until we can read from a remote or cached data manifest",
call. = FALSE,
immediate. = TRUE
)
}
pkg.env$extdata.warn <- TRUE
avail.pkgs <- readRDS(file = system.file(
'extdata/manifest.Rds',
package = 'SeuratData',
mustWork = TRUE
))
}
avail.pkgs <- lapply(X = avail.pkgs, FUN = as.data.frame, stringsAsFactors = FALSE)
avail.pkgs <- do.call(what = 'rbind', args = avail.pkgs)
avail.pkgs$Version <- package_version(x = avail.pkgs$Version)
# Get dataset installation status
avail.pkgs$Installed <- vapply(
X = rownames(x = avail.pkgs),
FUN = requireNamespace,
FUN.VALUE = logical(length = 1L),
quietly = TRUE,
quietly = TRUE
)
avail.pkgs$InstalledVersion <- sapply(
X = rownames(x = avail.pkgs),
Expand All @@ -348,14 +442,33 @@ UpdateManifest <- function() {
return(as.character(x = pkg.version))
}
)
# Coerce version information to package_version
# Allow NAs to become effectively NA_pacakge_version_
avail.pkgs$InstalledVersion <- package_version(
x = avail.pkgs$InstalledVersion,
strict = FALSE
)
# TODO: remove these when we allow loading of processed datasets
ds.index <- which(x = colnames(x = avail.pkgs) %in% c('default.dataset', 'other.datasets'))
avail.pkgs <- avail.pkgs[, -ds.index]
cols.remove <- c('default.dataset', 'other.datasets')
if (any(cols.remove %in% colnames(x = avail.pkgs))) {
ds.index <- which(x = colnames(x = avail.pkgs) %in% cols.remove)
avail.pkgs <- avail.pkgs[, -ds.index]
}
pkg.env$manifest <- avail.pkgs
# Cache the manifest
if (getOption(x = 'SeuratData.manifest.cache', default = FALSE)) {
if (!dir.exists(paths = dirname(path = cache.manifest))) {
dir.create(path = dirname(path = cache.manifest), recursive = TRUE)
}
cached <- if (file.exists(cache.manifest)) {
readRDS(file = cache.manifest)
} else {
NULL
}
if (!isTRUE(x = all.equal(target = pkg.env$manifest, current = cached))) {
saveRDS(object = pkg.env$manifest, file = cache.manifest)
}
}
invisible(x = NULL)
}

Expand Down
Binary file added inst/extdata/manifest.Rds
Binary file not shown.
Loading