Nothing
makeCompressedMatrix <- function(x, dims, byrow=TRUE)
# Coerces a NULL, scalar, vector or matrix to a compressed matrix,
# Determines whether the rows or columns are intended to be
# repeated, and stores this in the attributes.
#
# written by Aaron Lun
# created 24 September 2016
# last modified 9 July 2017
{
repeat.row <- repeat.col <- FALSE
if (is.matrix(x)) {
if (inherits(x, "CompressedMatrix")) {
return(x)
}
dims <- dim(x)
} else if (length(x)==1L) {
repeat.row <- repeat.col <- TRUE
x <- matrix(x)
} else {
if (!byrow) {
if (dims[1]!=length(x)) {
stop("'dims[1]' should equal length of 'x'")
}
x <- cbind(x)
repeat.col <- TRUE
} else {
x <- rbind(x)
if (dims[2]!=length(x)) {
stop("'dims[2]' should equal length of 'x'")
}
repeat.row <- TRUE
}
}
dimnames(x) <- NULL
class(x) <- "CompressedMatrix"
attr(x, "Dims") <- as.integer(dims)
attr(x, "repeat.row") <- repeat.row
attr(x, "repeat.col") <- repeat.col
return(x)
}
.strip_to_matrix <- function(x) {
dims <- attr(x, "dim")
attributes(x) <- NULL
attr(x, "dim") <- dims
return(x)
}
dim.CompressedMatrix <- function(x)
# Getting dimensions.
#
# written by Aaron Lun
# created 21 June 2017
{
attr(x, "Dims")
}
length.CompressedMatrix <- function(x)
# Getting length.
#
# written by Aaron Lun
# created 25 January 2018
# last modified 1 March 2018
{
prod(attr(x,"Dims"))
}
`[.CompressedMatrix` <- function(x, i, j, drop=TRUE)
# Subsetting for CompressedMatrix objects.
#
# written by Aaron Lun
# created 24 September 2016
# last modified 21 June 2017
{
Nargs <- nargs() - !(missing(drop))
if (Nargs<3L) {
return(as.matrix(x)[i])
}
raw.mat <- .strip_to_matrix(x)
row.status <- attr(x, "repeat.row")
col.status <- attr(x, "repeat.col")
if (!row.status && !missing(i)) {
raw.mat <- raw.mat[i,,drop=FALSE]
}
if (!col.status && !missing(j)) {
raw.mat <- raw.mat[,j,drop=FALSE]
}
nr <- nrow(x)
if (!missing(i)) {
ref <- seq_len(nr)
nr <- length(ref[i])
}
nc <- ncol(x)
if (!missing(j)) {
ref <- seq_len(nc)
nc <- length(ref[j])
}
class(raw.mat) <- class(x)
attr(raw.mat, "Dims") <- c(nr, nc)
attr(raw.mat, "repeat.row") <- row.status
attr(raw.mat, "repeat.col") <- col.status
if (drop &&
((!missing(i) && length(i)==1L) ||
(!missing(j) && length(j)==1L))) {
raw.mat <- as.vector(as.matrix(raw.mat))
}
return(raw.mat)
}
`[<-.CompressedMatrix` <- function(x, i, j, value)
# Subset assignment for CompressedMatrix objects.
#
# written by Aaron Lun
# created 25 January 2018
{
ref <- as.matrix(x)
if (is(value, "CompressedMatrix")) {
value <- as.matrix(value)
}
if (nargs() < 4L) {
ref[i] <- value
} else {
ref[i,j] <- value
}
makeCompressedMatrix(ref, attr(x, "Dims"), TRUE)
}
as.matrix.CompressedMatrix <- function(x, ...)
# Expanding it to a full matrix.
#
# written by Aaron Lun
# created 26 September 2016
# last modified 21 June 2017
{
raw.mat <- .strip_to_matrix(x)
row.status <- attr(x, "repeat.row")
col.status <- attr(x, "repeat.col")
if (row.status) {
raw.mat <- matrix(raw.mat, nrow(x), ncol(x), byrow=TRUE)
} else if (col.status) {
raw.mat <- matrix(raw.mat, nrow(x), ncol(x))
} else {
raw.mat <- as.matrix(raw.mat)
}
return(raw.mat)
}
rbind.CompressedMatrix <- function(...)
# Rbinding things together.
#
# written by Aaron Lun
# created 21 June 2017
{
everything <- list(...)
nobjects <- length(everything)
if (nobjects==1) {
return(everything[[1]])
}
all.nr <- sum(unlist(lapply(everything, nrow)))
col.rep <- logical(nobjects)
row.rep <- logical(nobjects)
for (i in seq_along(everything)) {
x <- everything[[i]]
col.rep[i] <- attr(x, "repeat.col")
row.rep[i] <- attr(x, "repeat.row")
}
# If everything is column repeats, we can do a naive concatenation.
if (all(col.rep)) {
collected.vals <- vector("list", nobjects)
all.nc <- ncol(everything[[1]])
for (i in seq_along(everything)) {
current <- everything[[i]]
if (!identical(all.nc, ncol(current))) {
stop("cannot combine CompressedMatrix objects with different number of columns")
}
collected.vals[[i]] <- rep(.strip_to_matrix(current), length.out=nrow(current))
}
return(makeCompressedMatrix(unlist(collected.vals), dims=c(all.nr, all.nc), byrow=FALSE))
}
# If everything is row repeats AND values are all equal, we can just modify the nr.
if (all(row.rep)) {
okay <- TRUE
ref <- .strip_to_matrix(everything[[1]])
for (i in 2:length(everything)) {
current <- .strip_to_matrix(everything[[i]])
if (!isTRUE(all.equal(everything[[i]], ref))) {
okay <- FALSE
break
}
}
if (okay) {
current <- everything[[1]]
attr(current, "Dims")[1] <- all.nr
return(current)
}
}
# Otherwise, expanding each element and rbinding them.
for (i in seq_along(everything)) {
everything[[i]] <- as.matrix(everything[[i]])
}
return(makeCompressedMatrix(do.call(rbind, everything)))
}
cbind.CompressedMatrix <- function(...)
# Cbinding things together.
#
# written by Aaron Lun
# created 21 June 2017
{
everything <- list(...)
nobjects <- length(everything)
if (nobjects==1) {
return(everything[[1]])
}
all.nc <- sum(unlist(lapply(everything, ncol)))
col.rep <- logical(nobjects)
row.rep <- logical(nobjects)
for (i in seq_along(everything)) {
x <- everything[[i]]
col.rep[i] <- attr(x, "repeat.col")
row.rep[i] <- attr(x, "repeat.row")
}
# If everything is row repeats, we can do a naive concatenation.
if (all(row.rep)) {
collected.vals <- vector("list", nobjects)
all.nr <- nrow(everything[[1]])
for (i in seq_along(everything)) {
current <- everything[[i]]
if (!identical(all.nr, nrow(current))) {
stop("cannot combine CompressedMatrix objects with different number of rows")
}
collected.vals[[i]] <- rep(.strip_to_matrix(current), length.out=ncol(current))
}
return(makeCompressedMatrix(unlist(collected.vals), dims=c(all.nr, all.nc), byrow=TRUE))
}
# If everything is column repeats AND values are all equal, we can just modify the nc.
if (all(col.rep)) {
okay <- TRUE
ref <- .strip_to_matrix(everything[[1]])
for (i in 2:length(everything)) {
current <- .strip_to_matrix(everything[[i]])
if (!isTRUE(all.equal(everything[[i]], ref))) {
okay <- FALSE
break
}
}
if (okay) {
current <- everything[[1]]
attr(current, "Dims")[2] <- all.nc
return(current)
}
}
# Otherwise, expanding each element and rbinding them.
for (i in seq_along(everything)) {
everything[[i]] <- as.matrix(everything[[i]])
}
return(makeCompressedMatrix(do.call(cbind, everything)))
}
Ops.CompressedMatrix <- function(e1, e2)
# A function that performs some binary operation on two CompressedMatrix objects,
# in a manner that best preserves memory usage.
#
# written by Aaron Lun
# created 26 September 2016
# last modified 30 June 2017
{
if (!inherits(e1, "CompressedMatrix")) {
e1 <- makeCompressedMatrix(e1, dim(e2), byrow=FALSE) # Promoted to column-major CompressedMatrix
}
if (!inherits(e2, "CompressedMatrix")) {
e2 <- makeCompressedMatrix(e2, dim(e1), byrow=FALSE)
}
if (!identical(dim(e1), dim(e2))) {
stop("CompressedMatrix dimensions should be equal for binary operations")
}
row.rep <- attr(e1, "repeat.row") && attr(e2, "repeat.row")
col.rep <- attr(e1, "repeat.col") && attr(e2, "repeat.col")
if (row.rep || col.rep) {
new.dim <- dim(e1)
e1 <- as.vector(.strip_to_matrix(e1))
e2 <- as.vector(.strip_to_matrix(e2))
outcome <- NextMethod(.Generic)
outcome <- makeCompressedMatrix(outcome, new.dim, byrow=row.rep)
} else {
e1 <- as.matrix(e1)
e2 <- as.matrix(e2)
outcome <- NextMethod(.Generic)
outcome <- makeCompressedMatrix(outcome)
}
return(outcome)
}
.compressOffsets <- function(y, offset, lib.size=NULL)
# A convenience function to avoid repeatedly having to write the code below.
# If provided, offsets take precedence over the library size.
# If neither are provided, library sizes are automatically computed
# as the sum of counts in the count matrix 'y'.
# A prefunctory check for finite values is performed in the C++ code.
# If 'offset' is already of the CompressedMatrix class, then
# we assume it's already gone through this once so we don't do it again.
{
if (inherits(offset, "CompressedMatrix")) {
return(offset)
}
if (is.null(offset)) {
if (is.null(lib.size)) lib.size <- colSums(y)
offset <- log(lib.size)
}
if (!is.double(offset)) storage.mode(offset) <- "double"
offset <- makeCompressedMatrix(offset, dim(y), byrow=TRUE)
check.range <- suppressWarnings(range(offset))
if (any(!is.finite(check.range))) {
stop("offsets must be finite values")
}
return(offset)
}
.compressWeights <- function(y, weights=NULL)
# A convenience function to avoid repeatedly having to write the code below.
# All weights default to 1 if not specified.
# A prefunctory check for finite, positive values is performed in the C++ code.
# If 'weights' is already a CompressedMatrix, then we assume it's
# already gone through this and don't do it again.
{
if (inherits(weights, "CompressedMatrix")) {
return(weights)
}
if (is.null(weights)) weights <- 1
if (!is.double(weights)) storage.mode(weights) <- "double"
weights <- makeCompressedMatrix(weights, dim(y), byrow=TRUE)
check.range <- suppressWarnings(range(weights))
if (any(is.na(check.range)) || check.range[1] <= 0) {
stop("weights must be finite positive values")
}
return(weights)
}
.compressPrior <- function(y, prior.count)
# Again for the prior counts, checking for non-negative finite values.
# Skipping the check if it's already a CompressedMatrix object.
{
if (inherits(prior.count, "CompressedMatrix")) {
return(prior.count)
}
if(!is.double(prior.count)) storage.mode(prior.count) <- "double"
prior.count <- makeCompressedMatrix(prior.count, dim(y), byrow=FALSE)
check.range <- suppressWarnings(range(prior.count))
if (any(is.na(check.range)) || check.range[1] < 0) {
stop("prior counts must be finite non-negative values")
}
return(prior.count)
}
.compressDispersions <- function(y, dispersion)
# Again for the dispersions, checking for non-negative finite values.
# Skipping the check if it's already a CompressedMatrix object.
{
if (inherits(dispersion, "CompressedMatrix")) {
return(dispersion)
}
if(!is.double(dispersion)) storage.mode(dispersion) <- "double"
dispersion <- makeCompressedMatrix(dispersion, dim(y), byrow=FALSE)
check.range <- suppressWarnings(range(dispersion))
if (any(is.na(check.range)) || check.range[1] < 0) {
stop("dispersions must be finite non-negative values")
}
return(dispersion)
}
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.