From 8f0b7d57ca0a85a8f44671fd42cab0554915b592 Mon Sep 17 00:00:00 2001 From: yun Date: Wed, 3 Jul 2024 23:02:24 +0800 Subject: [PATCH] remove seedform, code-generate codes and bump BPCells version to 0.2.0 --- .github/workflows/R-CMD-check.yaml | 1 + .github/workflows/pr-commands.yaml | 1 + DESCRIPTION | 11 +- NAMESPACE | 6 - R/BPCellsSeed.R | 13 ++ R/Class-BPCellsMatrix.R | 258 ++++++---------------- R/Class-Delayed.R | 82 +++---- R/IO-10xHDF5.R | 18 +- R/IO-Dir.R | 18 +- R/IO-HDF5.R | 19 +- R/IO-Mem.R | 8 +- R/Method-Arith.R | 59 ++--- R/Method-BindMatrix.R | 6 +- R/Method-Compare.R | 22 +- R/Method-Convert.R | 32 ++- R/Method-Mask.R | 38 ++-- R/Method-Math.R | 66 +++--- R/Method-Multiply.R | 74 ++++--- R/Method-RankTransform.R | 3 +- R/Method-RenameDims.R | 6 +- R/Method-Subassign.R | 151 +++++++------ R/Method-Subset.R | 17 +- R/Method-axis.R | 25 ++- R/Method-pmin.R | 82 ++++--- R/Seed-management.R | 110 --------- R/showtree.R | 23 +- R/utils-BPCells.R | 2 +- README.md | 172 ++++++++------- man/BPCells-Arithmetic.Rd | 6 - man/BPCells10xHDF5-IO.Rd | 13 +- man/BPCellsDir-IO.Rd | 8 +- man/BPCellsHDF5-IO.Rd | 8 +- man/BPCellsMatrix-class.Rd | 8 +- man/BPCellsMem-IO.Rd | 5 +- man/figures/README-unnamed-chunk-17-1.png | Bin 46744 -> 47728 bytes man/seedform.Rd | 70 ------ tests/testthat/setup.R | 15 +- tests/testthat/test-seedform.R | 24 -- vignettes/BPCellsArray.Rmd | 18 +- 39 files changed, 572 insertions(+), 926 deletions(-) delete mode 100644 R/Seed-management.R delete mode 100644 man/seedform.Rd delete mode 100644 tests/testthat/test-seedform.R diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index d78ee95..5292503 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -1,6 +1,7 @@ # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help on: + workflow_dispatch: push: branches: [main, master] pull_request: diff --git a/.github/workflows/pr-commands.yaml b/.github/workflows/pr-commands.yaml index 71f335b..36fcaf4 100644 --- a/.github/workflows/pr-commands.yaml +++ b/.github/workflows/pr-commands.yaml @@ -1,6 +1,7 @@ # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help on: + workflow_dispatch: issue_comment: types: [created] diff --git a/DESCRIPTION b/DESCRIPTION index 934abdf..77d91c0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -11,7 +11,7 @@ BugReports: https://github.com/Yunuuuu/BPCellsArray License: MIT + file LICENSE Imports: methods, - BPCells (>= 0.1.0), + BPCells (>= 0.2.0), DelayedArray (>= 0.28.0), SparseArray, Matrix, @@ -22,7 +22,7 @@ Imports: S4Vectors, BiocSingular Remotes: - bnprks/BPCells + bnprks/BPCells/r Suggests: SingleCellExperiment, BiocNeighbors, @@ -39,13 +39,11 @@ Suggests: Encoding: UTF-8 biocViews: Software, DataImport, DataRepresentation, Infrastructure Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.0 +RoxygenNote: 7.3.2 Collate: 'BPCellsSeed.R' - 'utils.R' - 'utils-BPCells.R' 'Class-Delayed.R' - 'Seed-management.R' + 'utils-BPCells.R' 'Class-BPCellsMatrix.R' 'Class-BPCellsSeed.R' 'Class-Transformed.R' @@ -77,6 +75,7 @@ Collate: 'showtree.R' 'utils-Rd.R' 'utils-check.R' + 'utils.R' 'zzz.R' Config/testthat/edition: 3 VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 5269a11..1484592 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -5,7 +5,6 @@ S3method(base::as.array,BPCellsMatrix) S3method(base::as.array,IterableMatrix) S3method(base::as.matrix,BPCellsDelayedOp) S3method(base::as.matrix,BPCellsMatrix) -export("seedform<-") export(BPCellsArray) export(BPCellsMatrix) export(BPCellsSeed) @@ -19,13 +18,11 @@ export(matrix_stats) export(pmin_by_col) export(pmin_by_row) export(pmin_scalar) -export(pow_slow) export(rank_transform) export(readBPCells10xHDF5Matrix) export(readBPCellsDirMatrix) export(readBPCellsHDF5Matrix) export(seedApply) -export(seedform) export(set_threads) export(showtree) export(storage_axis) @@ -51,7 +48,6 @@ exportMethods("[<-") exportMethods("colnames<-") exportMethods("dimnames<-") exportMethods("rownames<-") -exportMethods("seedform<-") exportMethods("type<-") exportMethods(Arith) exportMethods(BPCellsSeed) @@ -100,7 +96,6 @@ exportMethods(pmin2) exportMethods(pmin_by_col) exportMethods(pmin_by_row) exportMethods(pmin_scalar) -exportMethods(pow_slow) exportMethods(rank_transform) exportMethods(rbind) exportMethods(rbind2) @@ -111,7 +106,6 @@ exportMethods(rowSds) exportMethods(rowSums) exportMethods(rowVars) exportMethods(runSVD) -exportMethods(seedform) exportMethods(set_threads) exportMethods(show) exportMethods(storage_axis) diff --git a/R/BPCellsSeed.R b/R/BPCellsSeed.R index 5127d27..a6d5c80 100644 --- a/R/BPCellsSeed.R +++ b/R/BPCellsSeed.R @@ -89,3 +89,16 @@ coerce_into_dgCMatrix <- function(x) { } ) } + +# helper function used to extract the `IterableMatrix` from the user input, +# although user shouldn't provide `BPCellsDelayedOp` directly, but we also deal +# with it +extract_IterableMatrix <- function(x, seedform) { + if (is_BPCellsArray(x)) { + to_BPCells(x@seed) + } else if (methods::is(x, "BPCellsDelayedOp")) { + to_BPCells(x) + } else { + BPCellsSeed(x) + } +} diff --git a/R/Class-BPCellsMatrix.R b/R/Class-BPCellsMatrix.R index 51d1ac6..1d5dda6 100644 --- a/R/Class-BPCellsMatrix.R +++ b/R/Class-BPCellsMatrix.R @@ -4,7 +4,6 @@ #' [DelayedMatrix][DelayedArray::DelayedMatrix] class. #' #' @seealso -#' - [seedform]: Manage the seed form. #' - [bind][BPCells-bind]: Combine two Objects by Columns or Rows. #' - [%*%][BPCells-Multiplication]: Matrix Multiplication. #' - [crossprod][BPCells-crossprod]: Matrix Crossproduct. @@ -20,18 +19,13 @@ NULL #' @param x A `BPCellsMatrix` object. For `BPCellsArray` and `BPCellsMatrix` #' function, a `r rd_seed()` would also be okay. -#' @param seedform A string, `"BPCells"` or `"DelayedArray"`. If `NULL`, will -#' use the the default `seedform`. Details see [seedform]. #' @param object A `r rd_matrix()`. #' @return #' - `BPCellsArray` and `BPCellsMatrix`: A `r rd_matrix()`, since `BPCells` can #' only support 2-dim array. #' @export #' @rdname BPCellsMatrix-class -BPCellsArray <- function(x, seedform = NULL) { - lst <- extract_IterableMatrix_and_seedform(x, seedform) - with_seedform(lst$seedform, DelayedArray(lst$seed)) -} +BPCellsArray <- function(x) DelayedArray(x) #' @export #' @rdname BPCellsMatrix-class @@ -41,22 +35,14 @@ is_BPCellsArray <- function(x) { methods::is(x, "BPCellsArray") || methods::is(x, "BPCellsMatrix") } -#' @include Seed-management.R +#' @include utils-BPCells.R #' @export #' @rdname BPCellsMatrix-class -methods::setClass("BPCellsArray", - contains = "DelayedArray", - slots = list(SeedForm = "character"), - prototype = list(SeedForm = get_seedform()) -) +methods::setClass("BPCellsArray", contains = "DelayedArray") #' @export #' @rdname BPCellsMatrix-class -methods::setClass("BPCellsMatrix", - contains = "DelayedMatrix", - slots = list(SeedForm = "character"), - prototype = list(SeedForm = get_seedform()) -) +methods::setClass("BPCellsMatrix", contains = "DelayedMatrix") #' @return #' - `matrixClass`: A string, always be `"BPCellsMatrix"`. @@ -69,7 +55,6 @@ methods::setMethod("matrixClass", "BPCellsArray", function(x) { .validate_BPCellsArray <- function(object) { .validate_seed(object@seed, arg = "@seed") - .validate_seedform(object@SeedForm, arg = "@SeedForm") } methods::setValidity("BPCellsArray", .validate_BPCellsArray) @@ -82,15 +67,8 @@ methods::setValidity("BPCellsMatrix", .validate_BPCellsArray) #' @export #' @rdname BPCellsMatrix-class methods::setMethod("DelayedArray", "IterableMatrix", function(seed) { - # DelayedArray can only accept one argument, - # so we always use `with_seedform` with `DelayedArray` function and just - # assign the `seedform` value into the `BPCellsArray` object after creating - # `BPCellsArray` object - seedform <- get_seedform() - if (seedform == "DelayedArray") seed <- to_DelayedArray(seed) # styler: off - object <- DelayedArray::new_DelayedArray(seed, Class = "BPCellsArray") - object@SeedForm <- seedform - object + seed <- to_DelayedArray(seed) # styler: off + DelayedArray::new_DelayedArray(seed, Class = "BPCellsArray") }) # Although `BPCellsDelayedOp` shouldn't be touched by users (Just like the @@ -99,35 +77,9 @@ methods::setMethod("DelayedArray", "IterableMatrix", function(seed) { #' @include Class-Delayed.R #' @export #' @rdname internal-methods -methods::setMethod( - "DelayedArray", "BPCellsDelayedOp", - delayedop_call_BPCells_method(seed = ) -) - -############################################################## -#' @export -#' @rdname seedform -methods::setMethod("seedform", "BPCellsMatrix", function(x) { - x@SeedForm -}) - -#' @export -#' @rdname seedform -methods::setGeneric("seedform<-", function(x, ..., value) { - standardGeneric("seedform<-") -}) - -#' @param value A string, `"BPCells"` or `"DelayedArray"`. -#' @export -#' @rdname seedform -methods::setReplaceMethod("seedform", "BPCellsMatrix", function(x, value) { - value <- match_seedform(value) - if (value == x@SeedForm) { - msg <- "{.arg x@seed} is already in {.pkg {value}} format" - cli::cli_inform(paste(msg, "nothing to do", sep = ", ")) - return(x) - } - with_seedform(value, DelayedArray(x@seed)) +methods::setMethod("DelayedArray", "BPCellsDelayedOp", function(seed) { + seed <- to_BPCells(seed) + methods::callGeneric() }) ############################################################# @@ -144,7 +96,6 @@ methods::setMethod("BPCellsSeed", "BPCellsMatrix", function(x) { .show_internal <- function(object) { methods::callNextMethod() cat("\n") - cat(sprintf("Seed form: %s\n", seedform(object))) cat(sprintf("Storage Data type: %s\n", storage_mode(object))) cat(sprintf("Storage axis: %s major\n", storage_axis(object))) @@ -165,92 +116,6 @@ methods::setMethod("show", "BPCellsArray", .show_internal) #' @rdname BPCellsMatrix-class methods::setMethod("show", "BPCellsMatrix", .show_internal) -############################################################## -# helper function to re-dispath `DelayedArray` method -# should just used for `BPCellsMatrix` method -array_call_DelayedArray_method <- function(..., Array = NULL, type = "S4") { - method <- switch(type, - S4 = quote(methods::callNextMethod()), - S3 = quote(NextMethod()) - ) - args <- rlang::pairlist2(...) - Array <- rlang::sym(Array %||% names(args)[[1L]]) - # extract the seedform - seedform <- list( - substitute(seedform <- Array@SeedForm, list(Array = Array)) - ) - - after <- expression( - # for some method, it will return `DelayedArray` directly although - # `@seed` is compatible with `BPCellsMatrix`. - # here we just re-creating a BPCellsMatrix object when it could be. - if (!is_BPCellsArray(object)) { - seed <- object@seed - # we check if object can be converted into a `BPCellsMatrix` object, - # if not, we warn it - if (methods::is(seed, "BPCellsDelayedOp") || - methods::is(seed, "IterableMatrix")) { - object <- with_seedform(seedform, DelayedArray(seed)) - } else { - cli::cli_warn(c( - sprintf("{.fn %s} method return a {.cls {fclass(object)}} object", .Generic), # nolint - i = "Subsequent operation won't use {.pkg BPCells} methods" - )) - } - }, - object - ) - new_method(args, before = seedform, method = method, after = after) -} - -# hepler function to call BPCells method for `BPCellsArray` -# running order -# 1. before - (?convert: extract seedform) - to_BPCells - before2 -# 2. method -# 3. after - (?convert: DelayedArray) - after2 -#' @param Arrays The argument names which should be a BPCellsMatrix and -#' converted into `IterableMatrix`. The `seedform` will be extracted from the -#' first one. -#' @param convert A bool, whether should final object be converted into -#' BPCellsMatrix. -#' @include utils.R -#' @noRd -array_call_BPCells_method <- function(..., before = NULL, before2 = NULL, method = NULL, after = NULL, after2 = NULL, Arrays = NULL, convert = TRUE) { - method <- method %||% quote(methods::callGeneric()) - args <- rlang::pairlist2(...) - Arrays <- rlang::syms(Arrays %||% names(args)[[1L]]) - if (convert) { - # extract seedform, always respect the first Array - seedform <- list( - substitute(seedform <- Array@SeedForm, list(Array = Arrays[[1L]])) - ) - # transform IterableMatrix into BPCellsMatrix - converted <- quote(with_seedform(seedform, DelayedArray(object))) - if (is.null(after2)) { - after2 <- list(converted) - } else { - after2 <- c(list( - substitute(object <- converted, list(converted = converted)) - ), after2) - } - } else { - seedform <- NULL - } - before <- c( - before, seedform, - # transform all Arrays into BPCells object - lapply(Arrays, function(Array) { - substitute(Array <- to_BPCells(Array@seed), list(Array = Array)) - }), before2 - ) - after <- c(after, after2) - new_method(args, - before = before, - method = method, - after = after - ) -} - ########################################################### #' @export methods::setAs("BPCellsMatrix", "dgCMatrix", function(from) { @@ -260,15 +125,37 @@ methods::setAs("BPCellsMatrix", "dgCMatrix", function(from) { # Default drop use `as.array` and `aperm` methods ### S3/S4 combo for aperm.BPCellsMatrix # list_methods("DelayedAperm") -aperm.BPCellsMatrix <- array_call_DelayedArray_method( - a = , perm = , ... = , type = "S3" -) +aperm.BPCellsMatrix <- function(a, perm, ...) { + object <- NextMethod() + return_BPCellsMatrix(object, .Generic) # nolint +} #' @importFrom BiocGenerics aperm -methods::setMethod( - "aperm", "BPCellsMatrix", - array_call_DelayedArray_method(a = , perm = , ... = ) -) +methods::setMethod("aperm", "BPCellsMatrix", function(a, perm, ...) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint +}) + +# when necessary, we restore the BPCellsMatrix, instead of returning the +# DelayedArray object. +return_BPCellsMatrix <- function(object, fn_name) { + if (!is_BPCellsArray(object)) { + seed <- object@seed + if (methods::is(seed, "BPCellsDelayedOp") || + methods::is(seed, "IterableMatrix")) { + return(DelayedArray(seed)) + } else { + cli::cli_warn(c( + sprintf( + "{.fn %s} method return a {.cls {fclass(object)}} object", + fn_name + ), + i = "Subsequent operation won't use {.pkg BPCells} methods" + )) + } + } + object +} #' @return #' - `as.matrix`: A dense matrix. @@ -318,10 +205,11 @@ NULL #' @export #' @aliases t #' @rdname BPCellsMatrix-class -methods::setMethod( - "t", "BPCellsMatrix", - array_call_BPCells_method(x = ) -) +methods::setMethod("t", "BPCellsMatrix", function(x) { + x <- to_BPCells(x@seed) + ans <- methods::callGeneric() + DelayedArray(ans) +}) #' @param value #' - `type<-`: See the mode argument in [convert_mode]. @@ -338,44 +226,44 @@ methods::setMethod("type<-", "BPCellsMatrix", function(x, value) { #' @export #' @rdname BPCellsMatrix-class -methods::setMethod( - "is.na", "BPCellsMatrix", - array_call_DelayedArray_method(x = ) -) +methods::setMethod("is.na", "BPCellsMatrix", function(x) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint +}) #' @export #' @rdname BPCellsMatrix-class -methods::setMethod( - "is.finite", "BPCellsMatrix", - array_call_DelayedArray_method(x = ) -) +methods::setMethod("is.finite", "BPCellsMatrix", function(x) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint +}) #' @export #' @rdname BPCellsMatrix-class -methods::setMethod( - "is.infinite", "BPCellsMatrix", - array_call_DelayedArray_method(x = ) -) +methods::setMethod("is.infinite", "BPCellsMatrix", function(x) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint +}) #' @export #' @rdname BPCellsMatrix-class -methods::setMethod( - "is.nan", "BPCellsMatrix", - array_call_DelayedArray_method(x = ) -) +methods::setMethod("is.nan", "BPCellsMatrix", function(x) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint +}) #' @importFrom methods Ops -methods::setMethod( - "Ops", c("BPCellsArray", "vector"), - array_call_DelayedArray_method(e1 = , e2 = ) -) - -methods::setMethod( - "Ops", c("vector", "BPCellsArray"), - array_call_DelayedArray_method(e1 = , e2 = , Array = "e2") -) - -methods::setMethod( - "Ops", c("BPCellsArray", "BPCellsArray"), - array_call_DelayedArray_method(e1 = , e2 = ) -) +methods::setMethod("Ops", c("BPCellsArray", "vector"), function(e1, e2) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint +}) + +methods::setMethod("Ops", c("vector", "BPCellsArray"), function(e1, e2) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint +}) + +methods::setMethod("Ops", c("BPCellsArray", "BPCellsArray"), function(e1, e2) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint +}) diff --git a/R/Class-Delayed.R b/R/Class-Delayed.R index b2cabdd..74a0793 100644 --- a/R/Class-Delayed.R +++ b/R/Class-Delayed.R @@ -14,7 +14,7 @@ ################################################################### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# the `@<-` function will check slot class. +# the `@<-` function will check slot class. # For `IterableMatrix` object, `@matrix` must be a `IterableMatrix` object, but # for `DelayedOp` object `@seed` is a signature "ANY". # So when define `to_BPCells`, we must run `to_BPCells` firstly with `@seed` @@ -75,25 +75,6 @@ to_DelayedUnaryOp <- function(object, Class) { object } -####################################################################### -# helper function to re-dispath `BPCells` method -# should used for `BPCellsDelayedOp` object -# This will not convert the final object into `DelayedArray` object so should be -# used for function return another class, usually the seed contract methods -#' @include utils.R utils-BPCells.R -delayedop_call_BPCells_method <- function(..., before = NULL, after = NULL, Array = NULL) { - args <- rlang::pairlist2(...) - Array <- rlang::sym(Array %||% names(args)[[1L]]) - before <- c(before, list( - substitute(Array <- to_BPCells(Array), list(Array = Array)) - )) - new_method(args, - before = before, - method = quote(methods::callGeneric()), - after = after - ) -} - ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # https://developer.r-project.org/howMethodsWork.pdf # The current implementation (as of version 2.4.0 of R) works as follows. The @@ -156,10 +137,10 @@ methods::setAs("BPCellsDelayedOp", "dgCMatrix", function(from) { #' @export #' @rdname BPCellsDelayedOp-class -methods::setMethod( - "type", "BPCellsDelayedOp", - delayedop_call_BPCells_method(x = ) -) +methods::setMethod("type", "BPCellsDelayedOp", function(x) { + x <- to_BPCells(x) + methods::callGeneric() +}) #' @export #' @rdname BPCellsDelayedOp-class @@ -167,53 +148,58 @@ methods::setMethod("is_sparse", "BPCellsDelayedOp", function(x) TRUE) #' @export #' @rdname BPCellsDelayedOp-class -methods::setMethod( - "extract_array", "BPCellsDelayedOp", - delayedop_call_BPCells_method(x = , index = ) -) +methods::setMethod("extract_array", "BPCellsDelayedOp", function(x, index) { + x <- to_BPCells(x) + methods::callGeneric() +}) #' @export #' @rdname BPCellsDelayedOp-class methods::setMethod( "OLD_extract_sparse_array", "BPCellsDelayedOp", - delayedop_call_BPCells_method(x = , index = ) + function(x, index) { + x <- to_BPCells(x) + methods::callGeneric() + } ) #' @export #' @rdname BPCellsDelayedOp-class methods::setMethod( "extract_sparse_array", "BPCellsDelayedOp", - delayedop_call_BPCells_method(x = , index = ) + function(x, index) { + x <- to_BPCells(x) + methods::callGeneric() + } ) #' @export #' @rdname BPCellsDelayedOp-class -methods::setMethod( - "dim", "BPCellsDelayedOp", - delayedop_call_BPCells_method(x = ) -) +methods::setMethod("dim", "BPCellsDelayedOp", function(x) { + x <- to_BPCells(x) + methods::callGeneric() +}) #' @export #' @rdname BPCellsDelayedOp-class -methods::setMethod( - "dimnames", "BPCellsDelayedOp", - delayedop_call_BPCells_method(x = ) -) +methods::setMethod("dimnames", "BPCellsDelayedOp", function(x) { + x <- to_BPCells(x) + methods::callGeneric() +}) #' @importMethodsFrom BPCells t #' @export #' @rdname BPCellsDelayedOp-class -methods::setMethod( - "t", "BPCellsDelayedOp", - delayedop_call_BPCells_method( - x = , after = expression(to_DelayedArray(object)) - ) -) +methods::setMethod("t", "BPCellsDelayedOp", function(x) { + x <- to_BPCells(x) + ans <- methods::callGeneric() + to_DelayedArray(ans) +}) #' @importFrom DelayedArray chunkdim #' @export #' @rdname BPCellsDelayedOp-class -methods::setMethod( - "chunkdim", "BPCellsDelayedOp", - delayedop_call_BPCells_method(x = ) -) +methods::setMethod("chunkdim", "BPCellsDelayedOp", function(x) { + x <- to_BPCells(x) + methods::callGeneric() +}) diff --git a/R/IO-10xHDF5.R b/R/IO-10xHDF5.R index f66b410..79a7fe3 100644 --- a/R/IO-10xHDF5.R +++ b/R/IO-10xHDF5.R @@ -13,14 +13,14 @@ methods::setMethod("summary", "10xMatrixH5", summary.10xMatrixH5) #' @param path A string path of the `10x HDF5` file to read or save data into. #' @export #' @name BPCells10xHDF5-IO -readBPCells10xHDF5Matrix <- function(path, feature_type = NULL, buffer_size = 16384L, seedform = NULL) { +readBPCells10xHDF5Matrix <- function(path, feature_type = NULL, + buffer_size = 16384L) { assert_string(path, empty_ok = FALSE) - seedform <- match_seedform(seedform) - obj <- BPCells::open_matrix_10x_hdf5( + ans <- BPCells::open_matrix_10x_hdf5( path = path, feature_type = feature_type, buffer_size = as.integer(buffer_size) ) - with_seedform(seedform, DelayedArray(obj)) + DelayedArray(ans) } #' @export @@ -40,12 +40,10 @@ methods::setGeneric( feature_metadata = list(), buffer_size = 16384L, chunk_size = 1024L, - gzip = 0L, - seedform = NULL) { + gzip = 0L) { assert_string(path, empty_ok = FALSE) if (file.exists(path)) cli::cli_abort("{.arg path} requested is exist") - lst <- extract_IterableMatrix_and_seedform(x, seedform) - seed <- lst$seed + seed <- extract_IterableMatrix(x) mode <- storage_mode(seed) if (mode != "uint32_t") { cli::cli_warn(paste( @@ -53,7 +51,7 @@ methods::setGeneric( "but you provided a {.field {mode}}" )) } - obj <- BPCells::write_matrix_10x_hdf5( + ans <- BPCells::write_matrix_10x_hdf5( mat = seed, path = path, barcodes = barcodes, @@ -66,7 +64,7 @@ methods::setGeneric( gzip_level = as.integer(gzip), type = mode ) - with_seedform(lst$seedform, DelayedArray(obj)) + DelayedArray(ans) } #' @inherit BPCells::write_matrix_10x_hdf5 details diff --git a/R/IO-Dir.R b/R/IO-Dir.R index 8ec1d21..ccab6e9 100644 --- a/R/IO-Dir.R +++ b/R/IO-Dir.R @@ -17,14 +17,13 @@ methods::setMethod("summary", "MatrixDir", summary.MatrixDir) #' @inheritParams BPCells::open_matrix_dir #' @export #' @name BPCellsDir-IO -readBPCellsDirMatrix <- function(path, buffer_size = 8192L, seedform = NULL) { +readBPCellsDirMatrix <- function(path, buffer_size = 8192L) { assert_string(path, empty_ok = FALSE) - seedform <- match_seedform(seedform) - obj <- BPCells::open_matrix_dir( + ans <- BPCells::open_matrix_dir( dir = path, buffer_size = as.integer(buffer_size) ) - with_seedform(seedform, DelayedArray(obj)) + DelayedArray(ans) } #' @inherit BPCells::write_matrix_dir details @@ -49,19 +48,18 @@ methods::setGeneric( .writeBPCellsDirMatrix <- function( x, path = NULL, bitpacking = TRUE, buffer_size = 8192L, - overwrite = FALSE, - seedform = NULL) { + overwrite = FALSE) { assert_bool(bitpacking) assert_bool(overwrite) - lst <- extract_IterableMatrix_and_seedform(x, seedform) + seed <- extract_IterableMatrix(x) path <- path %||% tempfile("BPCellsDirMatrix") - obj <- BPCells::write_matrix_dir( - mat = lst$seed, + ans <- BPCells::write_matrix_dir( + mat = seed, dir = path, compress = bitpacking, buffer_size = as.integer(buffer_size), overwrite = overwrite ) - with_seedform(lst$seedform, DelayedArray(obj)) + DelayedArray(ans) } #' @export diff --git a/R/IO-HDF5.R b/R/IO-HDF5.R index cf37cb5..8bdb7ca 100644 --- a/R/IO-HDF5.R +++ b/R/IO-HDF5.R @@ -15,14 +15,13 @@ methods::setMethod("summary", "MatrixH5", summary.MatrixH5) #' @param path A string path of the `HDF5` file to read or save data into. #' @export #' @name BPCellsHDF5-IO -readBPCellsHDF5Matrix <- function(path, group, buffer_size = 8192L, seedform = NULL) { +readBPCellsHDF5Matrix <- function(path, group, buffer_size = 8192L) { assert_string(path, empty_ok = FALSE) - seedform <- match_seedform(seedform) - obj <- BPCells::open_matrix_hdf5( + ans <- BPCells::open_matrix_hdf5( path = path, group = group, buffer_size = as.integer(buffer_size) ) - with_seedform(seedform, DelayedArray(obj)) + DelayedArray(ans) } #' @export @@ -33,24 +32,26 @@ methods::setGeneric( function(x, ...) standardGeneric("writeBPCellsHDF5Matrix") ) -.writeBPCellsHDF5Matrix <- function(x, path, group, bitpacking = TRUE, buffer_size = 8192L, chunk_size = 1024L, overwrite = FALSE, gzip = 0L, seedform = NULL) { +.writeBPCellsHDF5Matrix <- function(x, path, group, bitpacking = TRUE, + buffer_size = 8192L, chunk_size = 1024L, + overwrite = FALSE, gzip = 0L) { assert_bool(bitpacking) assert_bool(overwrite) - lst <- extract_IterableMatrix_and_seedform(x, seedform) + seed <- extract_IterableMatrix(x) if (bitpacking) { gzip <- 0L } else { gzip <- as.integer(gzip) } - obj <- BPCells::write_matrix_hdf5( - mat = lst$seed, + ans <- BPCells::write_matrix_hdf5( + mat = seed, path = path, group = group, compress = bitpacking, buffer_size = as.integer(buffer_size), chunk_size = as.integer(chunk_size), overwrite = overwrite, gzip_level = gzip ) - with_seedform(lst$seedform, DelayedArray(obj)) + DelayedArray(ans) } diff --git a/R/IO-Mem.R b/R/IO-Mem.R index 7a32dda..ebcb213 100644 --- a/R/IO-Mem.R +++ b/R/IO-Mem.R @@ -29,10 +29,10 @@ methods::setGeneric( function(x, ...) standardGeneric("writeBPCellsMemMatrix") ) -.writeBPCellsMemMatrix <- function(x, compress = TRUE, seedform = NULL) { - lst <- extract_IterableMatrix_and_seedform(x, seedform) - obj <- BPCells::write_matrix_memory(mat = lst$seed, compress = compress) - with_seedform(seedform = lst$seedform, DelayedArray(obj)) +.writeBPCellsMemMatrix <- function(x, compress = TRUE) { + seed <- extract_IterableMatrix(x) + ans <- BPCells::write_matrix_memory(mat = seed, compress = compress) + DelayedArray(ans) } #' @inheritParams BPCellsDir-IO diff --git a/R/Method-Arith.R b/R/Method-Arith.R index cfb69b8..7cad52f 100644 --- a/R/Method-Arith.R +++ b/R/Method-Arith.R @@ -41,14 +41,22 @@ NULL #' @rdname BPCells-Arithmetic methods::setMethod( "Arith", c(e1 = "BPCellsMatrix", e2 = "numeric"), - array_call_BPCells_method(e1 = , e2 = ) + function(e1, e2) { + e1 <- to_BPCells(e1@seed) + ans <- methods::callGeneric() + DelayedArray(ans) + } ) #' @export #' @rdname BPCells-Arithmetic methods::setMethod( "Arith", c(e1 = "numeric", e2 = "BPCellsMatrix"), - array_call_BPCells_method(e1 = , e2 = , Arrays = "e2") + function(e1, e2) { + e2 <- to_BPCells(e2@seed) + ans <- methods::callGeneric() + DelayedArray(ans) + } ) #' @inheritParams BPCells-Arithmetic @@ -57,7 +65,10 @@ methods::setMethod( methods::setMethod( "/", c(e1 = "numeric", e2 = "BPCellsMatrix"), function(e1, e2) { - cli::cli_abort("Cannot dicided by a sparce {.cls BPCellsMatrix}, since too many zeros") + cli::cli_abort(paste( + "Cannot dicided by a Sparse {.cls BPCellsMatrix},", + "since too many zeros" + )) } ) @@ -66,48 +77,38 @@ methods::setMethod( #' @rdname internal-methods methods::setMethod( "%%", c(e1 = "numeric", e2 = "BPCellsMatrix"), - array_call_DelayedArray_method(e1 = , e2 = , Array = "e2") + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) #' @export #' @rdname internal-methods methods::setMethod( "%%", c(e1 = "BPCellsMatrix", e2 = "numeric"), - array_call_DelayedArray_method(e1 = , e2 = ) + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) #' @export #' @rdname internal-methods methods::setMethod( "%/%", c(e1 = "numeric", e2 = "BPCellsMatrix"), - array_call_DelayedArray_method(e1 = , e2 = , Array = "e2") + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) #' @export #' @rdname internal-methods methods::setMethod( "%/%", c(e1 = "BPCellsMatrix", e2 = "numeric"), - array_call_DelayedArray_method(e1 = , e2 = ) -) - -####################################################################### -# TransformPowSlow -methods::setClass("BPCellsDelayedTransformPowSlow", - contains = "BPCellsDelayedTransformed" -) - -#' @export -#' @rdname BPCells-Arithmetic -methods::setGeneric("pow_slow", function(e1, e2) { - standardGeneric("pow_slow") -}) - -#' @export -#' @rdname BPCells-Arithmetic -methods::setMethod( - "pow_slow", "BPCellsMatrix", - array_call_BPCells_method( - e1 = , e2 = , - method = quote(BPCells::pow_slow(x = e1, exponent = e2)) - ) + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) diff --git a/R/Method-BindMatrix.R b/R/Method-BindMatrix.R index 6dcea3b..c75c0db 100644 --- a/R/Method-BindMatrix.R +++ b/R/Method-BindMatrix.R @@ -109,9 +109,9 @@ methods::setGeneric("set_threads", function(object, ...) { methods::setMethod( "set_threads", "BPCellsMatrix", function(object, threads = 0L) { - seedform <- object@SeedForm object <- object@seed - with_seedform(seedform, DelayedArray(methods::callGeneric())) + ans <- methods::callGeneric() + DelayedArray(ans) } ) @@ -363,7 +363,7 @@ combine_matrices <- function(.fn, mode, matrices, ...) { } }, mode = mode) seed <- Reduce(function(x, y) fn(x = x, y = y, ...), seeds) - with_seedform(matrices[[1L]]@SeedForm, DelayedArray(seed)) + DelayedArray(seed) } pack_BPCellsMatrices <- function(..., call = rlang::caller_env()) { diff --git a/R/Method-Compare.R b/R/Method-Compare.R index 3c05793..6de6ca1 100644 --- a/R/Method-Compare.R +++ b/R/Method-Compare.R @@ -21,13 +21,11 @@ methods::setGeneric("binarize", function(object, ...) { #' @inheritDotParams BPCells::binarize -mat #' @export #' @rdname BPCells-Compare -methods::setMethod( - "binarize", "BPCellsMatrix", - array_call_BPCells_method( - object = , ... = , - method = quote(BPCells::binarize(mat = object, ...)) - ) -) +methods::setMethod("binarize", "BPCellsMatrix", function(object, ...) { + object <- to_BPCells(object@seed) + ans <- BPCells::binarize(mat = object, ...) + DelayedArray(ans) +}) #' @export #' @rdname internal-methods @@ -83,12 +81,18 @@ methods::setMethod( #' @rdname internal-methods methods::setMethod( "Compare", c(e1 = "BPCellsMatrix", e2 = "ANY"), - array_call_DelayedArray_method(e1 = , e2 = ) + function(e1, e2) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint + } ) #' @export #' @rdname internal-methods methods::setMethod( "Compare", c(e1 = "ANY", e2 = "BPCellsMatrix"), - array_call_DelayedArray_method(e1 = , e2 = , Array = "e2") + function(e1, e2) { + object <- methods::callNextMethod() + return_BPCellsMatrix(object, .Generic) # nolint + } ) diff --git a/R/Method-Convert.R b/R/Method-Convert.R index 3451346..fc5ca8b 100644 --- a/R/Method-Convert.R +++ b/R/Method-Convert.R @@ -70,16 +70,12 @@ methods::setGeneric( #' @importFrom DelayedArray DelayedArray #' @export #' @rdname convert_mode -methods::setMethod( - "convert_mode", "BPCellsMatrix", - array_call_BPCells_method( - object = , mode = , - method = quote(BPCells::convert_matrix_type( - matrix = object, type = mode - )), - before = expression(mode <- match.arg(mode, BPCells_MODE)) - ) -) +methods::setMethod("convert_mode", "BPCellsMatrix", function(object, mode) { + mode <- match.arg(mode, BPCells_MODE) + object <- to_BPCells(object@seed) + ans <- BPCells::convert_matrix_type(matrix = object, type = mode) + DelayedArray(ans) +}) #' @inheritParams convert_mode #' @export @@ -99,17 +95,17 @@ methods::setGeneric( #' @export #' @rdname convert_mode -methods::setMethod( - "storage_mode", "BPCellsMatrix", - array_call_BPCells_method(object = , convert = FALSE) -) +methods::setMethod("storage_mode", "BPCellsMatrix", function(object) { + object <- to_BPCells(object@seed) + methods::callGeneric() +}) #' @export #' @rdname convert_mode -methods::setMethod( - "storage_mode", "BPCellsDelayedOp", - delayedop_call_BPCells_method(object = ) -) +methods::setMethod("storage_mode", "BPCellsDelayedOp", function(object) { + object <- to_BPCells(object) + methods::callGeneric() +}) #' @export #' @rdname convert_mode diff --git a/R/Method-Mask.R b/R/Method-Mask.R index ec88c57..05abffe 100644 --- a/R/Method-Mask.R +++ b/R/Method-Mask.R @@ -96,34 +96,30 @@ methods::setGeneric( #' @rdname mask_matrix methods::setMethod( "mask_matrix", c(object = "BPCellsMatrix", mask = "BPCellsMatrix"), - array_call_BPCells_method( - object = , mask = , invert = FALSE, - method = quote( - BPCells:::mask_matrix( - mat = object, - mask = mask, - invert = invert - ) - ), - Arrays = c("object", "mask") - ) + function(object, mask, invert = FALSE) { + object <- to_BPCells(object@seed) + mask <- to_BPCells(mask@seed) + ans <- BPCells:::mask_matrix( + mat = object, mask = mask, + invert = invert + ) + DelayedArray(ans) + } ) #' @export #' @rdname mask_matrix methods::setMethod( "mask_matrix", c(object = "BPCellsMatrix", mask = "ANY"), - array_call_BPCells_method( - object = , mask = , invert = FALSE, - before2 = expression(mask <- BPCellsSeed(mask)), - method = quote( - BPCells:::mask_matrix( - mat = object, - mask = mask, - invert = invert - ) + function(object, mask, invert = FALSE) { + object <- to_BPCells(object@seed) + mask <- BPCellsSeed(mask) + ans <- BPCells:::mask_matrix( + mat = object, mask = mask, + invert = invert ) - ) + DelayedArray(ans) + } ) #' @inheritParams mask_matrix diff --git a/R/Method-Math.R b/R/Method-Math.R index 534483c..17a58a6 100644 --- a/R/Method-Math.R +++ b/R/Method-Math.R @@ -22,10 +22,11 @@ methods::setGeneric("expm1_slow", function(x) { #' @export #' @rdname BPCells-Math -methods::setMethod( - "expm1_slow", "BPCellsMatrix", - array_call_BPCells_method(x = , method = quote(BPCells::expm1_slow(x))) -) +methods::setMethod("expm1_slow", "BPCellsMatrix", function(x) { + x <- to_BPCells(x@seed) + ans <- BPCells::expm1_slow(x) + DelayedArray(ans) +}) #' @export #' @rdname internal-methods @@ -44,10 +45,11 @@ methods::setClass("BPCellsDelayedTransformExpm1", #' @export #' @aliases expm1 #' @rdname BPCells-Math -methods::setMethod( - "expm1", "BPCellsMatrix", - array_call_BPCells_method(x = ) -) +methods::setMethod("expm1", "BPCellsMatrix", function(x) { + x <- to_BPCells(x@seed) + ans <- methods::callGeneric() + DelayedArray(ans) +}) #################################################################### # TransformLog1pSlow @@ -62,10 +64,11 @@ methods::setClass("BPCellsDelayedTransformLog1pSlow", #' @export #' @aliases log1p #' @rdname BPCells-Math -methods::setMethod( - "log1p", "BPCellsMatrix", - array_call_BPCells_method(x = , method = quote(BPCells::log1p_slow(x))) -) +methods::setMethod("log1p", "BPCellsMatrix", function(x) { + x <- to_BPCells(x@seed) + ans <- BPCells::log1p_slow(x) + DelayedArray(ans) +}) #################################################################### # TransformLog1p @@ -82,10 +85,11 @@ methods::setGeneric("log1p_single", function(x) { #' @export #' @rdname BPCells-Math -methods::setMethod( - "log1p_single", "BPCellsMatrix", - array_call_BPCells_method(x = , method = quote(log1p(x))) -) +methods::setMethod("log1p_single", "BPCellsMatrix", function(x) { + x <- to_BPCells(x@seed) + ans <- log1p(x) + DelayedArray(ans) +}) #################################################################### # TransformRound @@ -99,28 +103,32 @@ methods::setClass("BPCellsDelayedTransformRound", #' @export #' @aliases round #' @rdname BPCells-Math -methods::setMethod( - "round", "BPCellsMatrix", - array_call_BPCells_method(x = , digits = 0) -) +methods::setMethod("round", "BPCellsMatrix", function(x, digits = 0) { + x <- to_BPCells(x@seed) + ans <- methods::callGeneric() + DelayedArray(ans) +}) # override methods of DelayedArray #' @export #' @rdname internal-methods -methods::setMethod("log", "BPCellsMatrix", array_call_DelayedArray_method(x = )) +methods::setMethod("log", "BPCellsMatrix", function(x) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint +}) #' @importFrom methods Math #' @export #' @rdname internal-methods -methods::setMethod( - "Math", "BPCellsArray", - array_call_DelayedArray_method(x = ) -) +methods::setMethod("Math", "BPCellsArray", function(x) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint +}) #' @importFrom methods Math2 #' @export #' @rdname internal-methods -methods::setMethod( - "Math2", "BPCellsArray", - array_call_DelayedArray_method(x = ) -) +methods::setMethod("Math2", "BPCellsArray", function(x) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint +}) diff --git a/R/Method-Multiply.R b/R/Method-Multiply.R index 16b9303..ca931fc 100644 --- a/R/Method-Multiply.R +++ b/R/Method-Multiply.R @@ -93,34 +93,36 @@ NULL #' @rdname BPCells-Multiplication methods::setMethod( "%*%", c(x = "BPCellsMatrix", y = "BPCellsMatrix"), - array_call_BPCells_method( - x = , y = , - method = quote(.multiply_BPCells(x, y)), - Arrays = c("x", "y") - ) + function(x, y) { + x <- to_BPCells(x@seed) + y <- to_BPCells(y@seed) + ans <- .multiply_BPCells(x, y) + DelayedArray(ans) + } ) #' @export #' @rdname BPCells-Multiplication methods::setMethod( "%*%", c(x = "BPCellsMatrix", y = "ANY"), - array_call_BPCells_method( - x = , y = , - before = expression(y <- BPCellsSeed(y)), - method = quote(.multiply_BPCells(x, y)) - ) + function(x, y) { + y <- BPCellsSeed(y) + x <- to_BPCells(x@seed) + ans <- .multiply_BPCells(x, y) + DelayedArray(ans) + } ) #' @export #' @rdname BPCells-Multiplication methods::setMethod( "%*%", c(x = "ANY", y = "BPCellsMatrix"), - array_call_BPCells_method( - x = , y = , - before = expression(x <- BPCellsSeed(x)), - method = quote(.multiply_BPCells(x, y)), - Arrays = "y" - ) + function(x, y) { + x <- BPCellsSeed(x) + y <- to_BPCells(y@seed) + ans <- .multiply_BPCells(x, y) + DelayedArray(ans) + } ) #################### Matrix multiplication ######################## @@ -129,42 +131,42 @@ methods::setMethod( #' @rdname BPCells-Multiplication methods::setMethod( "%*%", c(x = "BPCellsMatrix", y = "matrix"), - array_call_BPCells_method( - x = , y = , - before = expression(y <- matrix_to_double(y)), - Arrays = "x", convert = FALSE - ) + function(x, y) { + y <- matrix_to_double(y) + x <- to_BPCells(x@seed) + methods::callGeneric() + } ) #' @export #' @rdname BPCells-Multiplication methods::setMethod( "%*%", c(x = "matrix", y = "BPCellsMatrix"), - array_call_BPCells_method( - x = , y = , - before = expression(x <- matrix_to_double(x)), - Arrays = "y", convert = FALSE - ) + function(x, y) { + x <- matrix_to_double(x) + y <- to_BPCells(y@seed) + methods::callGeneric() + } ) #' @export #' @rdname BPCells-Multiplication methods::setMethod( "%*%", c(x = "BPCellsMatrix", y = "numeric"), - array_call_BPCells_method( - x = , y = , - before = expression(y <- matrix_to_double(y)), - Arrays = "x", convert = FALSE - ) + function(x, y) { + y <- matrix_to_double(y) + x <- to_BPCells(x@seed) + methods::callGeneric() + } ) #' @export #' @rdname BPCells-Multiplication methods::setMethod( "%*%", c(x = "numeric", y = "BPCellsMatrix"), - array_call_BPCells_method( - x = , y = , - before = expression(x <- matrix_to_double(x)), - Arrays = "y", convert = FALSE - ) + function(x, y) { + x <- matrix_to_double(x) + y <- to_BPCells(y@seed) + methods::callGeneric() + } ) diff --git a/R/Method-RankTransform.R b/R/Method-RankTransform.R index 7810318..b2ecc67 100644 --- a/R/Method-RankTransform.R +++ b/R/Method-RankTransform.R @@ -72,7 +72,6 @@ methods::setMethod( "rank_transform", "BPCellsMatrix", function(object, axis = NULL, offset = TRUE, ...) { assert_bool(offset) - seedform <- object@SeedForm object <- to_BPCells(object@seed) main_axis <- storage_axis(object) if (is.null(axis)) { @@ -118,7 +117,7 @@ methods::setMethod( seed <- t(t(seed) + rank_offsets) } } - with_seedform(seedform, DelayedArray(seed)) + DelayedArray(seed) } ) diff --git a/R/Method-RenameDims.R b/R/Method-RenameDims.R index 1a93618..9c76dae 100644 --- a/R/Method-RenameDims.R +++ b/R/Method-RenameDims.R @@ -44,7 +44,11 @@ methods::setClassUnion("ListOrNULL", c("list", "NULL")) #' @rdname BPCellsMatrix-class methods::setMethod( "dimnames<-", c(x = "BPCellsMatrix", value = "ListOrNULL"), - array_call_BPCells_method(x = , value = ) + function(x, value) { + x <- to_BPCells(x@seed) + ans <- methods::callGeneric() + DelayedArray(ans) + } ) #' @return diff --git a/R/Method-Subassign.R b/R/Method-Subassign.R index 471d439..70d7ef5 100644 --- a/R/Method-Subassign.R +++ b/R/Method-Subassign.R @@ -18,31 +18,30 @@ methods::setMethod( #' @rdname BPCellsMatrix-class methods::setMethod( "[<-", c("BPCellsMatrix", "ANY", "ANY", "IterableMatrix"), - array_call_BPCells_method( - x = , i = , j = , ... = , value = , - before2 = expression( - # keep consistent storage mode - x_mode <- storage_mode(x), - value_mode <- storage_mode(value), - if (x_mode != value_mode) { - cli::cli_warn(incompatible_mode_msg("x", "value", x_mode)) - value <- BPCells::convert_matrix_type( - matrix = value, type = x_mode - ) - }, - # keep consistent storage axis - if (x@transpose != value@transpose) { - cli::cli_warn(c( - "!" = paste( - "Incompatible storage axis between", - "{.arg x} and {.arg value}" - ), - i = "transposing the storage axis of {.arg value}" - )) - value <- BPCells::transpose_storage_order(matrix = value, ...) - } - ) - ) + function(x, i, j, ..., value) { + x <- to_BPCells(x@seed) + x_mode <- storage_mode(x) + value_mode <- storage_mode(value) + if (x_mode != value_mode) { + cli::cli_warn(incompatible_mode_msg("x", "value", x_mode)) + value <- BPCells::convert_matrix_type( + matrix = value, + type = x_mode + ) + } + if (x@transpose != value@transpose) { + cli::cli_warn(c(`!` = paste( + "Incompatible storage axis between", + "{.arg x} and {.arg value}" + ), i = "transposing the storage axis of {.arg value}")) + value <- BPCells::transpose_storage_order( + matrix = value, + ... + ) + } + ans <- methods::callGeneric() + DelayedArray(ans) + } ) #' @export @@ -62,24 +61,25 @@ methods::setMethod( #' @rdname internal-methods methods::setMethod( "[<-", c("BPCellsMatrix", "ANY", "ANY", "dgCMatrix"), - array_call_BPCells_method( - x = , i = , j = , value = , - before2 = expression( - x_mode <- storage_mode(x), - if (x@transpose) { - value <- t(value) - value <- t(BPCellsSeed(value)) - } else { - value <- BPCellsSeed(value) - }, - if (x_mode != "double") { - cli::cli_warn(incompatible_mode_msg("x", "value", x_mode)) - value <- BPCells::convert_matrix_type( - matrix = value, type = x_mode - ) - } - ) - ) + function(x, i, j, value) { + x <- to_BPCells(x@seed) + x_mode <- storage_mode(x) + if (x@transpose) { + value <- t(value) + value <- t(BPCellsSeed(value)) + } else { + value <- BPCellsSeed(value) + } + if (x_mode != "double") { + cli::cli_warn(incompatible_mode_msg("x", "value", x_mode)) + value <- BPCells::convert_matrix_type( + matrix = value, + type = x_mode + ) + } + ans <- methods::callGeneric() + DelayedArray(ans) + } ) # respect matrix storage.mode @@ -87,37 +87,36 @@ methods::setMethod( #' @rdname internal-methods methods::setMethod( "[<-", c("BPCellsMatrix", "ANY", "ANY", "matrix"), - array_call_BPCells_method( - x = , i = , j = , value = , - before2 = expression( - x_mode <- storage_mode(x), - value_mode <- storage_mode(value), - # convert `value` into a `IterableMatrix` object - # I don't need BPCellsSeed to take care of the storage mode of - # `value`, since we'll do it special - value <- methods::as(value, "dgCMatrix"), - if (x@transpose) { - value <- t(value) - value <- t(BPCellsSeed(value)) - } else { - value <- BPCellsSeed(value) - }, - # convert the storage mode of `value` when necessary - if (x_mode == "uint32_t" && value_mode != "uint32_t") { - cli::cli_warn(incompatible_mode_msg("x", "value", x_mode)) - value <- BPCells::convert_matrix_type( - matrix = value, type = "uint32_t" - ) - } else if (x_mode != "uint32_t" && value_mode == "uint32_t") { - cli::cli_warn(incompatible_mode_msg("x", "value", x_mode)) - value <- BPCells::convert_matrix_type( - matrix = value, type = x_mode - ) - } else { - value <- BPCells::convert_matrix_type( - matrix = value, type = x_mode - ) - } - ) - ) + function(x, i, j, value) { + x <- to_BPCells(x@seed) + x_mode <- storage_mode(x) + value_mode <- storage_mode(value) + value <- methods::as(value, "dgCMatrix") + if (x@transpose) { + value <- t(value) + value <- t(BPCellsSeed(value)) + } else { + value <- BPCellsSeed(value) + } + if (x_mode == "uint32_t" && value_mode != "uint32_t") { + cli::cli_warn(incompatible_mode_msg("x", "value", x_mode)) + value <- BPCells::convert_matrix_type( + matrix = value, + type = "uint32_t" + ) + } else if (x_mode != "uint32_t" && value_mode == "uint32_t") { + cli::cli_warn(incompatible_mode_msg("x", "value", x_mode)) + value <- BPCells::convert_matrix_type( + matrix = value, + type = x_mode + ) + } else { + value <- BPCells::convert_matrix_type( + matrix = value, + type = x_mode + ) + } + ans <- methods::callGeneric() + DelayedArray(ans) + } ) diff --git a/R/Method-Subset.R b/R/Method-Subset.R index 0e9397b..2736877 100644 --- a/R/Method-Subset.R +++ b/R/Method-Subset.R @@ -65,10 +65,13 @@ methods::setMethod("summary", "MatrixSubset", summary.BPCellsDelayedSubset) #' - `[`: A `BPCellsMatrix` object or an atomic vector. #' @export #' @rdname BPCellsMatrix-class -methods::setMethod( - "[", "BPCellsMatrix", - array_call_BPCells_method( - x = , i = , j = , drop = TRUE, - after2 = expression(if (drop) drop(object) else object) - ) -) +methods::setMethod("[", "BPCellsMatrix", function(x, i, j, drop = TRUE) { + x <- to_BPCells(x@seed) + ans <- methods::callGeneric() + ans <- DelayedArray(ans) + if (drop) { + drop(ans) + } else { + ans + } +}) diff --git a/R/Method-axis.R b/R/Method-axis.R index 744a19b..c652241 100644 --- a/R/Method-axis.R +++ b/R/Method-axis.R @@ -18,10 +18,11 @@ methods::setGeneric("transpose_axis", function(object, ...) { methods::setMethod( "transpose_axis", "BPCellsMatrix", # `transpose_storage_order` always return a `MatrixDir` object - array_call_BPCells_method( - object = , ... = , - method = quote(BPCells::transpose_storage_order(matrix = object, ...)) - ) + function(object, ...) { + object <- to_BPCells(object@seed) + ans <- BPCells::transpose_storage_order(matrix = object, ...) + DelayedArray(ans) + } ) #' @inheritParams transpose_axis @@ -50,17 +51,17 @@ methods::setGeneric("storage_axis", function(object) { #' @export #' @rdname transpose_axis -methods::setMethod( - "storage_axis", "BPCellsMatrix", - array_call_BPCells_method(object = , convert = FALSE) -) +methods::setMethod("storage_axis", "BPCellsMatrix", function(object) { + object <- to_BPCells(object@seed) + methods::callGeneric() +}) #' @export #' @rdname transpose_axis -methods::setMethod( - "storage_axis", "BPCellsDelayedOp", - delayedop_call_BPCells_method(object = ) -) +methods::setMethod("storage_axis", "BPCellsDelayedOp", function(object) { + object <- to_BPCells(object) + methods::callGeneric() +}) #' @export #' @rdname transpose_axis diff --git a/R/Method-pmin.R b/R/Method-pmin.R index 6a2a440..b866f1d 100644 --- a/R/Method-pmin.R +++ b/R/Method-pmin.R @@ -20,13 +20,11 @@ methods::setGeneric("pmin_by_col", function(object, values) { #' - `pmin_by_col`: Take the minimum with a per-col constant #' @export #' @rdname pmin2 -methods::setMethod( - "pmin_by_col", "BPCellsMatrix", - array_call_BPCells_method( - object = , values = , - method = quote(BPCells::min_by_col(mat = object, vals = values)) - ) -) +methods::setMethod("pmin_by_col", "BPCellsMatrix", function(object, values) { + object <- to_BPCells(object@seed) + ans <- BPCells::min_by_col(mat = object, vals = values) + DelayedArray(ans) +}) #################################################################### # TransformMinByRow @@ -44,13 +42,11 @@ methods::setGeneric("pmin_by_row", function(object, values) { #' - `pmin_by_row`: Take the minimum with a per-row constant #' @export #' @rdname pmin2 -methods::setMethod( - "pmin_by_row", "BPCellsMatrix", - array_call_BPCells_method( - object = , values = , - method = quote(BPCells::min_by_row(mat = object, vals = values)) - ) -) +methods::setMethod("pmin_by_row", "BPCellsMatrix", function(object, values) { + object <- to_BPCells(object@seed) + ans <- BPCells::min_by_row(mat = object, vals = values) + DelayedArray(ans) +}) #################################################################### # TransformMin @@ -69,13 +65,11 @@ methods::setGeneric("pmin_scalar", function(object, value) { #' - `pmin_scalar`: Take minumum with a global constant #' @export #' @rdname pmin2 -methods::setMethod( - "pmin_scalar", "BPCellsMatrix", - array_call_BPCells_method( - object = , value = , - method = quote(BPCells::min_scalar(mat = object, val = value)) - ) -) +methods::setMethod("pmin_scalar", "BPCellsMatrix", function(object, value) { + object <- to_BPCells(object@seed) + ans <- BPCells::min_scalar(mat = object, val = value) + DelayedArray(ans) +}) .pmin2_internal <- function( e1, e2, @@ -114,30 +108,36 @@ methods::setMethod("pmin2", c("numeric", "BPCellsMatrix"), function(e1, e2) { #' @export #' @rdname internal-methods -methods::setMethod( - "pmin2", c("BPCellsMatrix", "vector"), - array_call_DelayedArray_method(e1 = , e2 = ) -) +methods::setMethod("pmin2", c("BPCellsMatrix", "vector"), function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint +}) #' @export #' @rdname internal-methods -methods::setMethod( - "pmin2", c("vector", "BPCellsMatrix"), - array_call_DelayedArray_method(e1 = , e2 = , Array = "e2") -) +methods::setMethod("pmin2", c("vector", "BPCellsMatrix"), function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint +}) #' @export #' @rdname internal-methods methods::setMethod( "pmin2", c("BPCellsMatrix", "DelayedArray"), - array_call_DelayedArray_method(e1 = , e2 = ) + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) #' @export #' @rdname internal-methods methods::setMethod( "pmin2", c("DelayedArray", "BPCellsMatrix"), - array_call_DelayedArray_method(e1 = , e2 = , Array = "e2") + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) ###################################################################### @@ -146,26 +146,38 @@ methods::setMethod( #' @rdname internal-methods methods::setMethod( "pmax2", c("BPCellsMatrix", "vector"), - array_call_DelayedArray_method(e1 = , e2 = ) + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) #' @export #' @rdname internal-methods methods::setMethod( "pmax2", c("vector", "BPCellsMatrix"), - array_call_DelayedArray_method(e1 = , e2 = , Array = "e2") + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) #' @export #' @rdname internal-methods methods::setMethod( "pmax2", c("BPCellsMatrix", "DelayedArray"), - array_call_DelayedArray_method(e1 = , e2 = ) + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) #' @export #' @rdname internal-methods methods::setMethod( "pmax2", c("DelayedArray", "BPCellsMatrix"), - array_call_DelayedArray_method(e1 = , e2 = , Array = "e2") + function(e1, e2) { + ans <- methods::callNextMethod() + return_BPCellsMatrix(ans, .Generic) # nolint + } ) diff --git a/R/Seed-management.R b/R/Seed-management.R deleted file mode 100644 index 6b469fe..0000000 --- a/R/Seed-management.R +++ /dev/null @@ -1,110 +0,0 @@ -#' BPCellsArray seed management -#' -#' @description -#' `BPCellsArray` offers two seed form to use BPCells Matrix as the DelayedArray -#' seed: -#' - `BPCells`: use the `IterableMatrix` of BPCells as the seed directly. -#' - `DelayedArray`: convert `IterableMatrix` into a parallel -#' [DelayedOp][DelayedArray::DelayedOp-class] object -#' (See [BPCellsDelayedOp][BPCellsDelayedOp-class] object). -#' -#' Both methods are generally effective for most operations. However, choosing -#' `seedform=DelayedArray` ensures better compatibility with DelayedArray -#' package. It should be noted that some methods from DelayedArray do not -#' function well when `seedform=BPCells`, but executing operations with -#' `seedform=BPCells` is expected to be a little faster due to the absence of -#' the need to convert between `IterableMatrix` and -#' [BPCellsDelayedOp][BPCellsDelayedOp-class] object. For compatible with all -#' DelayedArray operations, `seedform=DelayedArray` is set as the default -#' method. -#' -#' @section Default seedform: All function in `BPCellsArray` will use the global -#' `seedform` value as the default seedform (use `seedform()` to check), except -#' for `BPCellsMatrix` object, in which the default will be extracted from the -#' object directly (use `seedform(object)` to check). -#' -#' @param ... Additional argumentds passed into specific methods. -#' @return -#' - `missing`: Get current global `seedform` value. -#' - `character`: Change the global `seedform` value and return the original -#' global `seedform` value invisiblely. -#' - `BPCellsMatrix`: -#' * For `seedform` method: Get the seedform of [BPCellsMatrix] object. -#' * For `seedform<-` method: Change the `seedform` value of a -#' [BPCellsMatrix] object. -#' @export -methods::setGeneric("seedform", function(x) { - standardGeneric("seedform") -}) - -#' @param x See `Value` section -#' @export -#' @rdname seedform -methods::setMethod("seedform", "missing", function(x) { - get_seedform() -}) - -#' @export -#' @rdname seedform -methods::setMethod("seedform", "character", function(x) { - x <- match_seedform(x) - old <- get_seedform() - set_seedform(x) - invisible(old) -}) - -with_seedform <- function(seedform, code) { - old <- get_seedform() - set_seedform(seedform) - on.exit(set_seedform(old)) - force(code) -} - -get_seedform <- function() GlobalOptions$SeedForm - -set_seedform <- function(seedform) GlobalOptions$SeedForm <- seedform - -match_seedform <- function(seedform, default = get_seedform()) { - if (is.null(seedform)) default else match.arg(seedform, SupportedSeedForm) -} - -# Global options control whether use `to_DelayedArray` to convert -# BPCells matrix into a `DelayedOp` object -GlobalOptions <- new.env(parent = emptyenv()) -SupportedSeedForm <- c("BPCells", "DelayedArray") -# set Global default `seedform` -set_seedform("DelayedArray") - -# helper function used to extract the `IterableMatrix` and seedform from the -# user input, although user shouldn't provide `BPCellsDelayedOp` directly, -# but we also deal with it, and always use "DelayedArray" as the default -# `seedform` -extract_IterableMatrix_and_seedform <- function(x, seedform) { - if (is_BPCellsArray(x)) { - seed <- to_BPCells(x@seed) - default <- x@SeedForm - } else if (methods::is(x, "BPCellsDelayedOp")) { - seed <- to_BPCells(x) - default <- get_seedform() - } else { - seed <- BPCellsSeed(x) - default <- get_seedform() - } - seedform <- match_seedform(seedform, default) - list(seed = seed, seedform = seedform) -} - -.validate_seedform <- function(seedform, arg = rlang::caller_arg(seedform)) { - msg <- paste( - style_arg(arg), "must be a single string of", - oxford_comma(style_val(SupportedSeedForm), sep = " ", final = "or") - ) - if (length(seedform) != 1L) { - cli::cli_abort( - c(msg, i = "You have provided a length {length(seedform)}") - ) - } else if (is.na(seedform) || !any(seedform == SupportedSeedForm)) { - cli::cli_abort(c(msg, i = "{.val {seedform}} is not allowed")) - } - TRUE -} diff --git a/R/showtree.R b/R/showtree.R index 98852d0..5fdafef 100644 --- a/R/showtree.R +++ b/R/showtree.R @@ -123,9 +123,6 @@ methods::setMethod("seed", "BPCellsMatrix", function(x) seed(x@seed)) #' @importFrom DelayedArray seed<- methods::setReplaceMethod("seed", "BPCellsMatrix", function(x, value) { x@seed <- methods::callGeneric(x = x@seed, value = value) - # No need to use `DelayedArray`, the `@SeedForm` won't change - # and we have ensure the class of `value` is the same with `@seed` - # with_seedform(x@SeedForm, DelayedArray(seed)) x }) @@ -266,17 +263,6 @@ abort_nary_path <- function(call = rlang::caller_env()) { ans } -no_DelayedArray <- function(object) { - if (is_BPCellsArray(object)) { - if (object@SeedForm == "BPCells") { - return(TRUE) - } - } else if (methods::is(object, "IterableMatrix")) { - return(TRUE) - } - return(FALSE) -} - .rec_showtree <- function(x, indent = "", last.child = NA, prefix = "", show.node.dim = TRUE) { if (is.list(x) && !is_array(x)) { nchildren <- length(x) @@ -293,12 +279,6 @@ no_DelayedArray <- function(object) { prefix = nms[[i]] ) } - } else if (no_DelayedArray(x)) { - .rec_show_BPCells( - x = x, indent = indent, - last.child = last.child, prefix = prefix, - show.node.dim = show.node.dim - ) } else { DelayedArray:::.rec_showtree( x = x, indent = indent, @@ -310,8 +290,7 @@ no_DelayedArray <- function(object) { ### 'last.child' can be NA, TRUE, or FALSE. NA means 'x' is the root of the ### tree. -#' @param x A `IterableMatrix` or `BPCellsMatrix` object with `@@SeedForm` equal -#' to "BPCells". +#' @param x A `IterableMatrix` or `BPCellsMatrix` object. #' @noRd .rec_show_BPCells <- function(x, indent = "", last.child = NA, prefix = "", show.node.dim = TRUE) { ## Display summary line. diff --git a/R/utils-BPCells.R b/R/utils-BPCells.R index 65154c8..b67ecbf 100644 --- a/R/utils-BPCells.R +++ b/R/utils-BPCells.R @@ -20,7 +20,7 @@ BPCells_Transform_classes <- c( TransformExpm1Slow = "expm1_slow", TransformSquare = NULL, TransformPow = "^", - TransformPowSlow = "pow_slow", + # TransformPowSlow = "pow_slow", # has been removed from BPCells TransformMin = "min_scalar", TransformMinByRow = "min_by_row", TransformMinByCol = "min_by_col", diff --git a/README.md b/README.md index 78e96b6..98686af 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Installation -To install from Bioconductor (waitting...), use the following code: +To install from Bioconductor, use the following code: ``` r if (!requireNamespace("BiocManager", quietly = TRUE)) { @@ -50,7 +50,7 @@ these methods to use the optimized methods in BPCells. Here is a summarized delayed operations in BPCells: | Operations | BPCells | BPCellsArray | -| ---------------------------------------- | --------------------------- | -------------------------------------- | +|------------------------------------------|-----------------------------|----------------------------------------| | Combine by row | rbind2 | rbind2,rbind,arbind,bindROWS | | Combine by column | cbind2 | cbind2,cbind,acbind,bindCOLS | | transpose matrix | t | t | @@ -61,12 +61,12 @@ Here is a summarized delayed operations in BPCells: | Matrix product transpose | | tcrossprod | | Arithmetic | `+`,`-`,`*`,`/` | `+`,`-`,`*`,`/` | | Relational Operators | Binary (`<`,`>`,`<=`, `>=`) | Binary (`<`,`>`,`<=`, `>=`) | -| Storage mode | convert\_matrix\_type | convert\_mode | -| Rank-transform | rank\_transform | `rank_transform`,`rowRanks`,`colRanks` | -| Mask matrix entries to zero | mask\_matrix | mask\_matrix | -| Take minumum with a global constant | min\_scalar | pmin\_scalar | -| Take the minimum with a per-col constant | min\_by\_col | pmin\_by\_col | -| Take the minimum with a per-row constant | min\_by\_row | pmin\_by\_row | +| Storage mode | convert_matrix_type | convert_mode | +| Rank-transform | rank_transform | `rank_transform`,`rowRanks`,`colRanks` | +| Mask matrix entries to zero | mask_matrix | mask_matrix | +| Take minumum with a global constant | min_scalar | pmin_scalar | +| Take the minimum with a per-col constant | min_by_col | pmin_by_col | +| Take the minimum with a per-row constant | min_by_row | pmin_by_row | | Round number | round | round | | `exp(x) - 1` | `expm1_slow`,`expm1` | `expm1_slow`,`expm1` | | `log(1+x)` | `log1p`,`log1p_slow` | `log1p_single`,`log1p` | @@ -74,31 +74,31 @@ Here is a summarized delayed operations in BPCells: Other non-lazied operations: -| Operations | BPCells | BPCellsArray | Note | -| ------------------------ | ---------------- | ------------------------------- | ---------------- | -| row/col summarize | matrix\_stats | matrix\_stats | | -| row summarize | rowSums,rowMeans | rowSums,rowMeans,rowVars,rowSds | | -| col summarize | colSums,colMeans | colSums,colMeans,colVars,colSds | | -| Multiplication | %\*% | %\*% | For some methods | -| Crossproduct | | crossprod | For some methods | -| Matrix product transpose | | tcrossprod | For some methods | -| svd | svds | `runSVD`+`SpectraParam` | | +| Operations | BPCells | BPCellsArray | Note | +|--------------------------|--------------------------|---------------------------------|------------------| +| row/col summarize | matrix_stats | matrix_stats | | +| row summarize | rowSums,rowMeans,rowVars | rowSums,rowMeans,rowVars,rowSds | | +| col summarize | colSums,colMeans,colVars | colSums,colMeans,colVars,colSds | | +| Multiplication | %\*% | %\*% | For some methods | +| Crossproduct | | crossprod | For some methods | +| Matrix product transpose | | tcrossprod | For some methods | +| svd | svds | `runSVD`+`SpectraParam` | | ## Matrix Storage Format BPCells provide following formats: 1. Directory of files - - read: `readBPCellsDirMatrix` - - write: `writeBPCellsDirMatrix` + - read: `readBPCellsDirMatrix` + - write: `writeBPCellsDirMatrix` 2. HDF5 file - - read: `readBPCellsHDF5Matrix` - - write: `writeBPCellsHDF5Matrix` + - read: `readBPCellsHDF5Matrix` + - write: `writeBPCellsHDF5Matrix` 3. 10x HDF5 file - - read: `readBPCells10xHDF5Matrix` - - write: `writeBPCells10xHDF5Matrix` + - read: `readBPCells10xHDF5Matrix` + - write: `writeBPCells10xHDF5Matrix` 4. in memory - - write: `writeBPCellsMemMatrix` + - write: `writeBPCellsMemMatrix` Matrices can be stored in a directory on disk, in memory, or in an HDF5 file. Saving in a directory on disk is a good default for local @@ -156,8 +156,8 @@ library(SingleCellExperiment) #> colnames, dirname, do.call, duplicated, eval, evalq, Filter, Find, #> get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply, #> match, mget, order, paste, pmax, pmax.int, pmin, pmin.int, -#> Position, rank, rbind, Reduce, rownames, sapply, setdiff, sort, -#> table, tapply, union, unique, unsplit, which.max, which.min +#> Position, rank, rbind, Reduce, rownames, sapply, setdiff, table, +#> tapply, union, unique, unsplit, which.max, which.min #> Loading required package: S4Vectors #> #> Attaching package: 'S4Vectors' @@ -204,6 +204,9 @@ bitpacking_mat <- writeBPCellsDirMatrix(counts_mat, path = path) #> Warning: Matrix compression performs poorly with non-integers. #> • Consider calling convert_matrix_type if a compressed integer matrix is intended. #> This message is displayed once every 8 hours. +``` + +``` r format(object.size(bitpacking_mat), "MB") #> [1] "0.3 Mb" ``` @@ -233,12 +236,11 @@ bitpacking_mat #> Gene_2999 217 1774 369 . 173 1415 #> Gene_3000 3014 215 1219 . 137 300 #> -#> Seed form: DelayedArray #> Storage Data type: double #> Storage axis: col major #> #> Queued Operations: -#> 3000x2000 double, sparse: [seed] Load compressed matrix from directory +#> 3000x2000 double, sparse: [seed] MatrixDir object ``` You can coerce it into a dense matrix or `dgCMatrix` to get the actual @@ -259,13 +261,15 @@ bitpacking_mat[1:10, 1:10] #> Gene_0009 464 494 21 . 135 167 #> Gene_0010 52 142 1 . 454 157 #> -#> Seed form: DelayedArray #> Storage Data type: double #> Storage axis: col major #> #> Queued Operations: #> 10x10 double, sparse: Subset matrix #> └─ 3000x2000 double, sparse: [seed] MatrixDir object +``` + +``` r as.matrix(bitpacking_mat[1:10, 1:10]) #> Cell_001 Cell_002 Cell_003 Cell_004 Cell_005 Cell_006 Cell_007 #> Gene_0001 0 0 0 0 51 0 16 @@ -289,6 +293,9 @@ as.matrix(bitpacking_mat[1:10, 1:10]) #> Gene_0008 244 146 74 #> Gene_0009 1578 135 167 #> Gene_0010 335 454 157 +``` + +``` r as(bitpacking_mat[1:10, 1:10], "dgCMatrix") #> 10 x 10 sparse Matrix of class "dgCMatrix" #> [[ suppressing 10 column names 'Cell_001', 'Cell_002', 'Cell_003' ... ]] @@ -313,13 +320,16 @@ pacakge for more supported matrix statisticals. ``` r identical(rowMins(bitpacking_mat), rowMins(counts_mat, useNames = TRUE)) #> [1] TRUE +``` + +``` r identical(rowMaxs(bitpacking_mat), rowMaxs(counts_mat, useNames = TRUE)) #> [1] TRUE ``` Again, no real work is performed on the matrix until the result needs to -be returned as an R object or written to disk. Attention the `Queued -Operations` information. +be returned as an R object or written to disk. Attention the +`Queued Operations` information. ``` r assay(sce, "counts") <- bitpacking_mat @@ -339,7 +349,6 @@ assay(sce, "logcounts") #> Gene_2999 7.744385 10.867509 8.500775 . 7.485524 10.469749 #> Gene_3000 11.534041 7.828500 10.222001 . 7.151042 8.235757 #> -#> Seed form: DelayedArray #> Storage Data type: double #> Storage axis: col major #> @@ -425,9 +434,9 @@ scater::plotReducedDim( ``` r sessionInfo() -#> R version 4.3.1 (2023-06-16) -#> Platform: x86_64-pc-linux-gnu (64-bit) -#> Running under: Ubuntu 22.04.3 LTS +#> R version 4.4.0 (2024-04-24) +#> Platform: x86_64-pc-linux-gnu +#> Running under: Ubuntu 24.04 LTS #> #> Matrix products: default #> BLAS/LAPACK: /usr/lib/x86_64-linux-gnu/libmkl_rt.so; LAPACK version 3.8.0 @@ -446,53 +455,54 @@ sessionInfo() #> [8] base #> #> other attached packages: -#> [1] SingleCellExperiment_1.22.0 SummarizedExperiment_1.30.2 -#> [3] Biobase_2.60.0 GenomicRanges_1.52.0 -#> [5] GenomeInfoDb_1.36.1 IRanges_2.34.1 -#> [7] S4Vectors_0.38.1 BiocGenerics_0.46.0 -#> [9] MatrixGenerics_1.12.3 matrixStats_1.2.0 +#> [1] SingleCellExperiment_1.26.0 SummarizedExperiment_1.34.0 +#> [3] Biobase_2.64.0 GenomicRanges_1.56.1 +#> [5] GenomeInfoDb_1.40.1 IRanges_2.38.0 +#> [7] S4Vectors_0.42.0 BiocGenerics_0.50.0 +#> [9] MatrixGenerics_1.16.0 matrixStats_1.3.0 #> [11] BPCellsArray_0.0.0.9000 #> #> loaded via a namespace (and not attached): -#> [1] tidyselect_1.2.0 viridisLite_0.4.2 -#> [3] farver_2.1.1 dplyr_1.1.4 -#> [5] vipor_0.4.5 viridis_0.6.4 -#> [7] bitops_1.0-7 fastmap_1.1.1 -#> [9] RCurl_1.98-1.12 bluster_1.11.4 -#> [11] digest_0.6.33 rsvd_1.0.5 -#> [13] lifecycle_1.0.4 cluster_2.1.4 -#> [15] statmod_1.5.0 magrittr_2.0.3 -#> [17] compiler_4.3.1 rlang_1.1.2 -#> [19] tools_4.3.1 igraph_1.5.0.1 -#> [21] utf8_1.2.4 yaml_2.3.8 -#> [23] knitr_1.45 labeling_0.4.3 -#> [25] S4Arrays_1.3.2 dqrng_0.3.0 -#> [27] DelayedArray_0.29.0 abind_1.4-5 -#> [29] BiocParallel_1.34.2 withr_2.5.2 -#> [31] grid_4.3.1 fansi_1.0.6 -#> [33] beachmat_2.16.0 colorspace_2.1-0 -#> [35] edgeR_3.42.4 ggplot2_3.4.4 -#> [37] scales_1.3.0 cli_3.6.2 -#> [39] rmarkdown_2.25 crayon_1.5.2 -#> [41] generics_0.1.3 metapod_1.8.0 -#> [43] RSpectra_0.16-1 DelayedMatrixStats_1.22.1 -#> [45] scuttle_1.10.1 ggbeeswarm_0.7.2 -#> [47] zlibbioc_1.46.0 parallel_4.3.1 -#> [49] XVector_0.40.0 BPCells_0.1.0 -#> [51] vctrs_0.6.5 Matrix_1.6-4 -#> [53] BiocSingular_1.16.0 BiocNeighbors_1.18.0 -#> [55] ggrepel_0.9.3 irlba_2.3.5.1 -#> [57] beeswarm_0.4.0 scater_1.31.1 -#> [59] locfit_1.5-9.8 limma_3.56.2 -#> [61] glue_1.6.2 codetools_0.2-19 -#> [63] cowplot_1.1.1 uwot_0.1.16 -#> [65] gtable_0.3.4 ScaledMatrix_1.8.1 -#> [67] munsell_0.5.0 tibble_3.2.1 -#> [69] pillar_1.9.0 htmltools_0.5.7 -#> [71] GenomeInfoDbData_1.2.10 R6_2.5.1 -#> [73] sparseMatrixStats_1.12.2 evaluate_0.23 -#> [75] lattice_0.22-5 highr_0.10 -#> [77] scran_1.28.2 Rcpp_1.0.11 -#> [79] gridExtra_2.3 SparseArray_1.3.3 -#> [81] xfun_0.41 pkgconfig_2.0.3 +#> [1] tidyselect_1.2.1 viridisLite_0.4.2 +#> [3] farver_2.1.2 dplyr_1.1.4 +#> [5] vipor_0.4.7 viridis_0.6.5 +#> [7] fastmap_1.2.0 bluster_1.14.0 +#> [9] digest_0.6.36 rsvd_1.0.5 +#> [11] lifecycle_1.0.4 cluster_2.1.6 +#> [13] statmod_1.5.0 magrittr_2.0.3 +#> [15] compiler_4.4.0 rlang_1.1.4 +#> [17] tools_4.4.0 igraph_2.0.3 +#> [19] utf8_1.2.4 yaml_2.3.8 +#> [21] knitr_1.47 labeling_0.4.3 +#> [23] S4Arrays_1.4.1 dqrng_0.4.1 +#> [25] DelayedArray_0.30.1 abind_1.4-5 +#> [27] BiocParallel_1.38.0 withr_3.0.0 +#> [29] grid_4.4.0 fansi_1.0.6 +#> [31] beachmat_2.20.0 colorspace_2.1-0 +#> [33] edgeR_4.2.0 ggplot2_3.5.1 +#> [35] scales_1.3.0 cli_3.6.3 +#> [37] rmarkdown_2.27 crayon_1.5.3 +#> [39] generics_0.1.3 metapod_1.12.0 +#> [41] RSpectra_0.16-1 httr_1.4.7 +#> [43] DelayedMatrixStats_1.26.0 scuttle_1.14.0 +#> [45] ggbeeswarm_0.7.2 zlibbioc_1.50.0 +#> [47] parallel_4.4.0 XVector_0.44.0 +#> [49] BPCells_0.2.0 vctrs_0.6.5 +#> [51] Matrix_1.7-0 jsonlite_1.8.8 +#> [53] BiocSingular_1.20.0 BiocNeighbors_1.22.0 +#> [55] ggrepel_0.9.5 irlba_2.3.5.1 +#> [57] beeswarm_0.4.0 scater_1.32.0 +#> [59] locfit_1.5-9.10 limma_3.60.3 +#> [61] glue_1.7.0 codetools_0.2-20 +#> [63] cowplot_1.1.3 uwot_0.2.2 +#> [65] gtable_0.3.5 UCSC.utils_1.0.0 +#> [67] ScaledMatrix_1.12.0 munsell_0.5.1 +#> [69] tibble_3.2.1 pillar_1.9.0 +#> [71] htmltools_0.5.8.1 GenomeInfoDbData_1.2.12 +#> [73] R6_2.5.1 sparseMatrixStats_1.16.0 +#> [75] evaluate_0.24.0 lattice_0.22-6 +#> [77] highr_0.11 scran_1.32.0 +#> [79] Rcpp_1.0.12 gridExtra_2.3 +#> [81] SparseArray_1.4.8 xfun_0.45 +#> [83] pkgconfig_2.0.3 ``` diff --git a/man/BPCells-Arithmetic.Rd b/man/BPCells-Arithmetic.Rd index 6d505bd..660d9c2 100644 --- a/man/BPCells-Arithmetic.Rd +++ b/man/BPCells-Arithmetic.Rd @@ -5,17 +5,11 @@ \alias{BPCells-Arith} \alias{Arith,BPCellsMatrix,numeric-method} \alias{Arith,numeric,BPCellsMatrix-method} -\alias{pow_slow} -\alias{pow_slow,BPCellsMatrix-method} \title{Arithmetic operators for BPCellsMatrix} \usage{ \S4method{Arith}{BPCellsMatrix,numeric}(e1, e2) \S4method{Arith}{numeric,BPCellsMatrix}(e1, e2) - -pow_slow(e1, e2) - -\S4method{pow_slow}{BPCellsMatrix}(e1, e2) } \arguments{ \item{e1, e2}{One of \code{x} or \code{y} must be a \link[=BPCellsMatrix-class]{BPCellsMatrix} object, and the another can diff --git a/man/BPCells10xHDF5-IO.Rd b/man/BPCells10xHDF5-IO.Rd index 9e32288..8360c55 100644 --- a/man/BPCells10xHDF5-IO.Rd +++ b/man/BPCells10xHDF5-IO.Rd @@ -7,12 +7,7 @@ \alias{writeBPCells10xHDF5Matrix,ANY-method} \title{Read/write sparse matrices from (or into) 10x feature matrix} \usage{ -readBPCells10xHDF5Matrix( - path, - feature_type = NULL, - buffer_size = 16384L, - seedform = NULL -) +readBPCells10xHDF5Matrix(path, feature_type = NULL, buffer_size = 16384L) writeBPCells10xHDF5Matrix(x, ...) @@ -26,8 +21,7 @@ writeBPCells10xHDF5Matrix(x, ...) feature_metadata = list(), buffer_size = 16384L, chunk_size = 1024L, - gzip = 0L, - seedform = NULL + gzip = 0L ) } \arguments{ @@ -40,9 +34,6 @@ only compatible with files from cellranger 3.0 and newer.} \item{buffer_size}{For performance tuning only. The number of items to be buffered in memory before calling writes to disk.} -\item{seedform}{A string, \code{"BPCells"} or \code{"DelayedArray"}. If \code{NULL}, will -use the the default \code{seedform}. Details see \link{seedform}.} - \item{x}{A \link[=BPCellsMatrix-class]{BPCellsMatrix} object or a matrix-like object which can be coerced into \link[Matrix:dgCMatrix-class]{dgCMatrix} object.} \item{...}{Additional arguments passed into specific methods.} diff --git a/man/BPCellsDir-IO.Rd b/man/BPCellsDir-IO.Rd index 4adaaa8..1d4fbe8 100644 --- a/man/BPCellsDir-IO.Rd +++ b/man/BPCellsDir-IO.Rd @@ -7,7 +7,7 @@ \alias{writeBPCellsDirMatrix,ANY-method} \title{Read/write sparse matrices from (or into) directory on disk} \usage{ -readBPCellsDirMatrix(path, buffer_size = 8192L, seedform = NULL) +readBPCellsDirMatrix(path, buffer_size = 8192L) writeBPCellsDirMatrix(x, ...) @@ -16,8 +16,7 @@ writeBPCellsDirMatrix(x, ...) path = NULL, bitpacking = TRUE, buffer_size = 8192L, - overwrite = FALSE, - seedform = NULL + overwrite = FALSE ) } \arguments{ @@ -28,9 +27,6 @@ directory.} \item{buffer_size}{For performance tuning only. The number of items to be buffered in memory before calling writes to disk.} -\item{seedform}{A string, \code{"BPCells"} or \code{"DelayedArray"}. If \code{NULL}, will -use the the default \code{seedform}. Details see \link{seedform}.} - \item{x}{A \link[=BPCellsMatrix-class]{BPCellsMatrix} object or a matrix-like object which can be coerced into \link[Matrix:dgCMatrix-class]{dgCMatrix} object.} \item{...}{Additional arguments passed into specific methods.} diff --git a/man/BPCellsHDF5-IO.Rd b/man/BPCellsHDF5-IO.Rd index 79b947d..8dac806 100644 --- a/man/BPCellsHDF5-IO.Rd +++ b/man/BPCellsHDF5-IO.Rd @@ -7,7 +7,7 @@ \alias{writeBPCellsHDF5Matrix,ANY-method} \title{Read/write sparse matrices from (or into) HDF5 file} \usage{ -readBPCellsHDF5Matrix(path, group, buffer_size = 8192L, seedform = NULL) +readBPCellsHDF5Matrix(path, group, buffer_size = 8192L) writeBPCellsHDF5Matrix(x, ...) @@ -19,8 +19,7 @@ writeBPCellsHDF5Matrix(x, ...) buffer_size = 8192L, chunk_size = 1024L, overwrite = FALSE, - gzip = 0L, - seedform = NULL + gzip = 0L ) } \arguments{ @@ -32,9 +31,6 @@ to an existing hdf5 file this group must not already be in use} \item{buffer_size}{For performance tuning only. The number of items to be buffered in memory before calling writes to disk.} -\item{seedform}{A string, \code{"BPCells"} or \code{"DelayedArray"}. If \code{NULL}, will -use the the default \code{seedform}. Details see \link{seedform}.} - \item{x}{A \link[=BPCellsMatrix-class]{BPCellsMatrix} object or a matrix-like object which can be coerced into \link[Matrix:dgCMatrix-class]{dgCMatrix} object.} \item{...}{Additional arguments passed into specific methods.} diff --git a/man/BPCellsMatrix-class.Rd b/man/BPCellsMatrix-class.Rd index d6d79fe..a2ac3ec 100644 --- a/man/BPCellsMatrix-class.Rd +++ b/man/BPCellsMatrix-class.Rd @@ -39,9 +39,9 @@ \S4method{show}{BPCellsMatrix}(object) -BPCellsArray(x, seedform = NULL) +BPCellsArray(x) -BPCellsMatrix(x, seedform = NULL) +BPCellsMatrix(x) \S4method{matrixClass}{BPCellsArray}(x) @@ -87,9 +87,6 @@ BPCellsMatrix(x, seedform = NULL) \item{x}{A \code{BPCellsMatrix} object. For \code{BPCellsArray} and \code{BPCellsMatrix} function, a matrix-like object which can be coerced into \link[Matrix:dgCMatrix-class]{dgCMatrix} object would also be okay.} -\item{seedform}{A string, \code{"BPCells"} or \code{"DelayedArray"}. If \code{NULL}, will -use the the default \code{seedform}. Details see \link{seedform}.} - \item{seed}{A \link[=BPCellsSeed-class]{IterableMatrix} object.} \item{drop}{A bool, if \code{TRUE}, any extents of length one will be removed and @@ -164,7 +161,6 @@ The \code{BPCellsMatrix} class just inherits from the } \seealso{ \itemize{ -\item \link{seedform}: Manage the seed form. \item \link[=BPCells-bind]{bind}: Combine two Objects by Columns or Rows. \item \link[=BPCells-Multiplication]{\%*\%}: Matrix Multiplication. \item \link[=BPCells-crossprod]{crossprod}: Matrix Crossproduct. diff --git a/man/BPCellsMem-IO.Rd b/man/BPCellsMem-IO.Rd index 0b8dbd0..becef3d 100644 --- a/man/BPCellsMem-IO.Rd +++ b/man/BPCellsMem-IO.Rd @@ -8,7 +8,7 @@ \usage{ writeBPCellsMemMatrix(x, ...) -\S4method{writeBPCellsMemMatrix}{ANY}(x, compress = TRUE, seedform = NULL) +\S4method{writeBPCellsMemMatrix}{ANY}(x, compress = TRUE) } \arguments{ \item{x}{A \link[=BPCellsMatrix-class]{BPCellsMatrix} object or a matrix-like object which can be coerced into \link[Matrix:dgCMatrix-class]{dgCMatrix} object.} @@ -16,9 +16,6 @@ writeBPCellsMemMatrix(x, ...) \item{...}{Additional arguments passed into specific methods.} \item{compress}{Whether or not to compress the data.} - -\item{seedform}{A string, \code{"BPCells"} or \code{"DelayedArray"}. If \code{NULL}, will -use the the default \code{seedform}. Details see \link{seedform}.} } \value{ A \link[=BPCellsMatrix-class]{BPCellsMatrix} object. diff --git a/man/figures/README-unnamed-chunk-17-1.png b/man/figures/README-unnamed-chunk-17-1.png index 7b61e2195b9e514515974c866444c52adc00be34..fca334796b1d625c68e2df1c3ae735e19beb7968 100644 GIT binary patch literal 47728 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 ?+rEDqgh^f{Jnho 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 literal 46744 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 diff --git a/man/seedform.Rd b/man/seedform.Rd deleted file mode 100644 index 5adc29f..0000000 --- a/man/seedform.Rd +++ /dev/null @@ -1,70 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/Seed-management.R, R/Class-BPCellsMatrix.R -\name{seedform} -\alias{seedform} -\alias{seedform,missing-method} -\alias{seedform,character-method} -\alias{seedform,BPCellsMatrix-method} -\alias{seedform<-} -\alias{seedform<-,BPCellsMatrix-method} -\title{BPCellsArray seed management} -\usage{ -seedform(x) - -\S4method{seedform}{missing}(x) - -\S4method{seedform}{character}(x) - -\S4method{seedform}{BPCellsMatrix}(x) - -seedform(x, ...) <- value - -\S4method{seedform}{BPCellsMatrix}(x) <- value -} -\arguments{ -\item{x}{See \code{Value} section} - -\item{...}{Additional argumentds passed into specific methods.} - -\item{value}{A string, \code{"BPCells"} or \code{"DelayedArray"}.} -} -\value{ -\itemize{ -\item \code{missing}: Get current global \code{seedform} value. -\item \code{character}: Change the global \code{seedform} value and return the original -global \code{seedform} value invisiblely. -\item \code{BPCellsMatrix}: -\itemize{ -\item For \code{seedform} method: Get the seedform of \link{BPCellsMatrix} object. -\item For \verb{seedform<-} method: Change the \code{seedform} value of a -\link{BPCellsMatrix} object. -} -} -} -\description{ -\code{BPCellsArray} offers two seed form to use BPCells Matrix as the DelayedArray -seed: -\itemize{ -\item \code{BPCells}: use the \code{IterableMatrix} of BPCells as the seed directly. -\item \code{DelayedArray}: convert \code{IterableMatrix} into a parallel -\link[DelayedArray:DelayedOp-class]{DelayedOp} object -(See \link[=BPCellsDelayedOp-class]{BPCellsDelayedOp} object). -} - -Both methods are generally effective for most operations. However, choosing -\code{seedform=DelayedArray} ensures better compatibility with DelayedArray -package. It should be noted that some methods from DelayedArray do not -function well when \code{seedform=BPCells}, but executing operations with -\code{seedform=BPCells} is expected to be a little faster due to the absence of -the need to convert between \code{IterableMatrix} and -\link[=BPCellsDelayedOp-class]{BPCellsDelayedOp} object. For compatible with all -DelayedArray operations, \code{seedform=DelayedArray} is set as the default -method. -} -\section{Default seedform}{ - All function in \code{BPCellsArray} will use the global -\code{seedform} value as the default seedform (use \code{seedform()} to check), except -for \code{BPCellsMatrix} object, in which the default will be extracted from the -object directly (use \code{seedform(object)} to check). -} - diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index ec077b8..60bde30 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -3,18 +3,7 @@ tmpdir <- testthat::test_path("_TEMP") if (!dir.exists(tmpdir)) dir.create(tmpdir) tmpdir <- normalizePath(tmpdir, mustWork = TRUE) -test_methods <- function(obj, ..., name) { - with_seedform( - "BPCells", - methods_test(obj = obj, ..., name = sprintf("%s (BPCells)", name)) - ) - with_seedform( - "DelayedArray", - methods_test(obj = obj, ..., name = sprintf("%s (DelayedArray)", name)) - ) -} - -methods_test <- function( +test_methods <- function( obj, ..., mode = NULL, mat = NULL, name, skip_multiplication = FALSE) { mode <- mode %||% storage_mode(obj) @@ -511,5 +500,3 @@ methods_test <- function( } ) } - - diff --git a/tests/testthat/test-seedform.R b/tests/testthat/test-seedform.R deleted file mode 100644 index 3a47145..0000000 --- a/tests/testthat/test-seedform.R +++ /dev/null @@ -1,24 +0,0 @@ -testthat::test_that("`with_seedform()` works well", { - old_seedform <- get_seedform() - testthat::expect_identical( - with_seedform("DelayedArray", seedform()), "DelayedArray" - ) - testthat::expect_identical(seedform(), old_seedform) -}) - -testthat::test_that("`seedform()` works well for string argument", { - # BPCells - old_seedform <- get_seedform() - testthat::expect_identical(seedform("BPCells"), old_seedform) - testthat::expect_identical(get_seedform(), "BPCells") - - # DelayedArray - old_seedform <- get_seedform() - testthat::expect_identical(seedform("DelayedArray"), old_seedform) - testthat::expect_identical(get_seedform(), "DelayedArray") - - # error for un-supported seedform - testthat::expect_error(seedform("UnSupportedSeedForm")) - # error for multiple items - testthat::expect_error(seedform(letters)) -}) diff --git a/vignettes/BPCellsArray.Rmd b/vignettes/BPCellsArray.Rmd index 6d320ee..6a70f03 100644 --- a/vignettes/BPCellsArray.Rmd +++ b/vignettes/BPCellsArray.Rmd @@ -83,15 +83,15 @@ Here is a summarized delayed operations in BPCells: Other non-lazied operations: -| Operations | BPCells | BPCellsArray | Note | -| ------------------------ | ---------------- | ------------------------------- | ---------------- | -| row/col summarize | matrix_stats | matrix_stats | | -| row summarize | rowSums,rowMeans | rowSums,rowMeans,rowVars,rowSds | | -| col summarize | colSums,colMeans | colSums,colMeans,colVars,colSds | | -| Multiplication | %*% | %*% | For some methods | -| Crossproduct | | crossprod | For some methods | -| Matrix product transpose | | tcrossprod | For some methods | -| svd | svds | `runSVD`+`SpectraParam` | | +| Operations | BPCells | BPCellsArray | Note | +| ------------------------ | ------------------------ | ------------------------------- | ---------------- | +| row/col summarize | matrix_stats | matrix_stats | | +| row summarize | rowSums,rowMeans,rowVars | rowSums,rowMeans,rowVars,rowSds | | +| col summarize | colSums,colMeans,colVars | colSums,colMeans,colVars,colSds | | +| Multiplication | %*% | %*% | For some methods | +| Crossproduct | | crossprod | For some methods | +| Matrix product transpose | | tcrossprod | For some methods | +| svd | svds | `runSVD`+`SpectraParam` | | ## Matrix Storage Format BPCells provide following formats: