Nothing
# Get internal UUIDs for proxy
get_inital_uuids <- function(arrays) {
return(vapply(arrays, function(a) { a$.uuid }, "", USE.NAMES = FALSE))
}
# Get output UUIDs for proxy
get_uuids <- function(arrays) {
return(vapply(arrays, function(a) { a$uuid() }, "", USE.NAMES = FALSE))
}
#' @rdname filearray
#' @export
FileArrayProxy <- setRefClass(
Class = "FileArrayProxy",
contains = "FileArray",
fields = list(
.uuid = "character",
.ops = "list",
.linked = "list",
persist = "logical"
),
methods = list(
.mature = function(env, data, verbose = FALSE) {
# make sure the elements of .linked are matured
lapply(.self$.linked, function(arr) {
arr$.mature(env = env, data = data, verbose = verbose)
})
lapply(.self$.ops, function(op) {
op$op_func(env = env, data = data, verbose = verbose)
return(NULL)
})
return(invisible())
},
initialize = function() {
# callNextMethod()
if(length(.self$.filebase) == 1) {
.self$.uuid <- sprintf("0000-%s", .self$.filebase)
} else {
.self$.uuid <- new_uuid()
}
},
uuid = function() {
if(length(.self$.ops)) {
return(.self$.ops[[length(.self$.ops)]]$uuid)
}
return(.self$.uuid)
},
get_all_uuids = function() {
return(c(.self$.uuid, vapply(.self$.ops, "[[", "uuid", FUN.VALUE = "")))
},
# Only get unique arrays
linked_arrays = function(exclude_uuids = NULL) {
re <- list()
if(!.self$.uuid %in% exclude_uuids) {
re[[.self$.uuid]] <- .self
exclude_uuids <- c(exclude_uuids, .self$get_all_uuids())
}
for(proxy in .self$.linked) {
linked_subs <- proxy$linked_arrays(exclude_uuids = exclude_uuids)
if(length(linked_subs)) {
uuids <- get_inital_uuids(linked_subs)
uuids <- uuids[!uuids %in% exclude_uuids]
re[uuids] <- linked_subs[uuids]
}
}
return(re)
},
link_proxy = function(x) {
.self$.linked[[x$uuid()]] <- x
return(invisible())
},
add_operator = function(
operator, context = "element_wise", label = "Unknown operator",
out_type = c("double", "complex", "float", "integer", "raw", "logical")
) {
out_type <- match.arg(out_type)
op_idx <- length(.self$.ops) + 1L
output_uuid <- new_uuid(op_idx)
out_mode <- ifelse(out_type == "float", "double", out_type)
.self$.ops[[op_idx]] <- list(
uuid = output_uuid,
label = label,
# Output type
output_type = out_type,
# operation type
context = context,
# operation function
op_func = function(env, data, verbose = FALSE) {
if(is.null(env[[ output_uuid ]])) {
if( verbose ) {
message(label)
}
tmp <- operator(env, data)
if(!identical(typeof(tmp), out_mode)) {
storage.mode(tmp) <- out_mode
}
env[[ output_uuid ]] <- tmp
}
}
)
},
collapse = function(
keep, method = c('mean', 'sum'),
transform = c('asis', '10log10', 'square', 'sqrt', 'normalize'),
na.rm = FALSE
) {
# TODO This is a quick fix
method <- match.arg(method)
transform <- match.arg(transform)
fa_eval_ops(.self)$collapse(
keep = keep, method = method,
transform = transform,
na.rm = na.rm
)
},
expand = function(n) {
stop("Cannot expand a proxy array. Please mature the array first before expanding.")
},
show = function(){
if(.self$valid()){
cat('Reference class object of class "FileArrayProxy"\n')
cat('Mode:', .self$.mode, "\n")
tryCatch({
cat(sprintf("UUID: %s (depth=%d)\n", .self$uuid(), length(.self$.ops)))
cat("Dimension:", paste(.self$dimension(), collapse = "x"), "\n")
cat("Partition count:", nrow(.self$.partition_info), "\n")
cat("Partition size:", .self$partition_size(), "\n")
cat("Data type:", typeof(.self), "\n")
cat("Internal type:", .self$type(), "\n")
}, error = function(e){
quiet_warning("Partition information is unavailable: might be broken or improperly set.", immediate. = FALSE)
})
cat("Location:", .self$.filebase, "\n")
} else {
if(.self$.valid){
cat("The FileArray is invalid (it has not been initialized).")
} else {
cat("The FileArray is invalid (unable to locate the array in the file system).")
}
}
},
mature = function(...) {
return(fa_eval_ops(.self, ...))
}
)
)
#' @rdname filearray
#' @export
as_filearrayproxy <- function(x, ...) {
UseMethod("as_filearrayproxy")
}
#' @export
as_filearrayproxy.FileArray <- function(x, ...) {
proxy <- new("FileArrayProxy")
proxy$load(x$.filebase)
if(length(x$.filebase) == 1) {
proxy$.uuid <- sprintf("0000-%s", x$.filebase)
}
return(proxy)
}
#' @export
as_filearrayproxy.FileArrayProxy <- function(x, ...) {
proxy <- x$copy()
proxy$.uuid <- x$.uuid
return(proxy)
}
#' @export
as_filearrayproxy.default <- function(x, ...) {
return(as_filearrayproxy.FileArray(
as_filearray(x, ...)
))
}
fa_pairwise_operator <- function(e1, e2, op, out_type = NULL, label = NULL) {
stopifnot(is_filearray(e1) || is_filearray(e2))
if(is.null(out_type)) {
out_type <- operation_output_type(typeof(e1), typeof(e2))
}
if(is.null(label)) {
if(is.character(op)) {
label <- sprintf("e1 %s e2", op)
} else {
label <- deparse1(op)
}
}
# check if e1 is scalar
if(length(e1) == 1) {
e2 <- as_filearrayproxy(e2)
uuid2 <- e2$uuid()
op_func <- function(v, ...) {
# v is an env with names: uuids
return(do.call(op, list(e1, v[[ uuid2 ]])))
}
e2$add_operator( op_func, out_type = out_type, context = "scalar", label = label )
return(e2)
}
# check if e2 is scalar
if(length(e2) == 1) {
e1 <- as_filearrayproxy(e1)
uuid1 <- e1$uuid()
op_func <- function(v, ...) {
# v is an env with names: uuids
return(do.call(op, list(v[[ uuid1 ]], e2)))
return(v[[ uuid1 ]] + e2)
}
e1$add_operator( op_func, out_type = out_type, context = "scalar", label = label )
return(e1)
}
# check if e1 or e2 is numerical
if(!is_filearray(e1)) {
if(!is_same_dim(e1, e2)) {
stop("non-conformable arrays")
}
e1 <- as_filearray(e1, dimension = dim(e2))
}
if(!is_filearray(e2)) {
if(!is_same_dim(e2, e1)) {
stop("non-conformable arrays")
}
e2 <- as_filearray(e2, dimension = dim(e1))
}
# e1 and e2 must be filearray or filearray proxy
if(!is_same_dim(e1, e2)) {
stop("non-conformable arrays")
}
e1 <- as_filearrayproxy(e1)
e2 <- as_filearrayproxy(e2)
uuid1 <- e1$uuid()
uuid2 <- e2$uuid()
e1$link_proxy( e2 )
op_func <- function(v, ...) {
return(do.call(op, list(v[[ uuid1 ]], v[[ uuid2 ]])))
}
e1$add_operator( op_func, out_type = out_type, context = "array", label = label )
return( e1 )
}
fa_operator <- function(x, op, ..., out_type = NULL, label = NULL) {
stopifnot(is_filearray(x))
if(is.null(out_type)) {
out_type <- typeof(x)
}
if(is.null(label)) {
if(is.null(label)) {
if(is.character(op)) {
label <- sprintf("%s(x)", op)
} else {
label <- deparse1(op)
}
}
}
x <- as_filearrayproxy(x)
uuid <- x$uuid()
v <- NULL
args <- list(quote(v[[ uuid ]]), ...)
op_func <- function(v, ...) {
# v is an env with names: uuids
return(do.call(op, args))
}
x$add_operator( op_func, out_type = out_type, context = "scalar", label = label )
return(x)
}
# Be careful when using addon, must be deterministic, or signature will be invalid
fa_eval_ops <- function(
x, addon = NULL, verbose = FALSE, input_size = NA_integer_,
filebase = NULL, use_cache = is.null(filebase)) {
# DIPSAUS DEBUG START
# verbose <- TRUE
# addon <- NULL
# input_size <- NA
# filebase <- NULL
# z = filearray_create(tempfile(), c(2,3,4))
# z[] <- 1:24
# y <- (z + 1 + (z - 1))
# x <- y + (1+y)
# result <- fa_eval_ops(x, verbose = TRUE)
# print(result[])
has_addon <- is.function(addon)
if( has_addon ) {
fml <- formals(addon)
if(length(fml) < 3 && !"..." %in% names(fml)) {
stop("`fa_eval_ops`: addon function must take 3 parameters (environment, list of data, output UUID)")
}
}
if(!inherits(x, "FileArrayProxy") ) {
if( has_addon ) {
x <- as_filearrayproxy(x)
} else {
return(x)
}
}
if(!length(x$.ops) && !has_addon) { return(x) }
if( !has_addon ) {
addon_func <- function(...) {}
} else {
addon_func <- addon
}
arrays <- x$linked_arrays()
# the first uuid is x's
uuids <- get_inital_uuids(arrays)
is_unique <- !duplicated(uuids)
uuids <- uuids[is_unique]
arrays <- arrays[is_unique]
uuid_x <- x$uuid()
dm_x <- dim(x)
verbose <- as.logical(verbose)
signature <- digest::digest(list(
x$.uuid,
x$get_all_uuids(),
addon = addon
))
if(length(filebase) != 1 || !is.character(filebase) || is.na(filebase)) {
fbase <- file.path(tempdir(check = TRUE), sprintf("filearrayproxy_%s", signature))
} else {
fbase <- filebase
}
if(verbose) {
message("Results will be saved to: ", fbase)
}
re <- filearray_load_or_create(
filebase = fbase, mode = "readwrite",
dimension = dm_x,
type = typeof(x),
partition_size = x$partition_size(),
signature = signature,
verbose = verbose,
initialize = FALSE,
on_missing = function(arr) {
headers <- x$.header
arr$.header <- headers[!names(headers) %in% RESERVED_HEADERS]
arr$.header$dimnames <- x$.header$dimnames
# x header might have matured, force unset
arr$.header$matured <- FALSE
}
)
if(!use_cache || !isTRUE(re$get_header("matured")) || has_addon) {
if( length(input_size) == 1 && !is.na(input_size) ) {
nruns <- length(x) / input_size
if(!isTRUE(nruns == round(nruns))) {
input_size <- NULL
}
}
if( length(input_size) != 1 || is.na(input_size) ) {
input_size <- guess_fmap_buffer_size(dim(x), x$element_size())
}
matured <- tryCatch({
fmap_element_wise_internal(arrays, function(data) {
env <- new.env(parent = emptyenv(), hash = TRUE)
lapply(seq_along(uuids), function(i) {
env[[ uuids[[i]] ]] <- data[[ i ]]
return(NULL)
})
x$.mature(env, data = data, verbose = verbose)
# tmp <- as.list(env)
# print(tmp[order(names(tmp))])
if(has_addon) {
addon_func(env, data, uuid_x)
}
env[[ uuid_x ]]
}, .y = re, .input_size = input_size)
TRUE
}, error = function(e) {
stop(e)
FALSE
})
re$set_header(key = "matured", value = matured, save = TRUE)
}
re$.mode <- "readonly"
return(re)
}
# DIPSAUS DEBUG START
# z = filearray_create(tempfile(), c(2,3,4), type = "integer")
# z[] <- 1:24
# e1 = as_filearrayproxy(z)
# e1$.ops |> length()
# e2 <- fa_add_scalar(e1,1)
# e2$.ops |> length()
# x = fa_add_filearray(e1, e2)
# #x <- e2
# x$.ops |> length()
# .self = x
# exclude_uuids=NULL
# data <- list(1:24)
# op = .self$.ops[[1]]
# verbose <- TRUE
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.