Binary files /tmp/tmp86arxl31/9HX8KBCsXg/r-bioc-singlecellexperiment-1.14.1+ds1/build/vignette.rds and /tmp/tmp86arxl31/BICvWzB_UA/r-bioc-singlecellexperiment-1.16.0+ds/build/vignette.rds differ diff -Nru r-bioc-singlecellexperiment-1.14.1+ds1/debian/changelog r-bioc-singlecellexperiment-1.16.0+ds/debian/changelog --- r-bioc-singlecellexperiment-1.14.1+ds1/debian/changelog 2021-09-06 16:44:15.000000000 +0000 +++ r-bioc-singlecellexperiment-1.16.0+ds/debian/changelog 2021-11-25 11:18:19.000000000 +0000 @@ -1,3 +1,10 @@ +r-bioc-singlecellexperiment (1.16.0+ds-1) unstable; urgency=medium + + * Team upload. + * New upstream version 1.16.0+ds + + -- Nilesh Patra Thu, 25 Nov 2021 16:48:19 +0530 + r-bioc-singlecellexperiment (1.14.1+ds1-1) unstable; urgency=medium * Drop another doc with compressed JS diff -Nru r-bioc-singlecellexperiment-1.14.1+ds1/DESCRIPTION r-bioc-singlecellexperiment-1.16.0+ds/DESCRIPTION --- r-bioc-singlecellexperiment-1.14.1+ds1/DESCRIPTION 2021-05-21 23:34:27.000000000 +0000 +++ r-bioc-singlecellexperiment-1.16.0+ds/DESCRIPTION 2021-10-26 22:50:24.000000000 +0000 @@ -1,6 +1,6 @@ Package: SingleCellExperiment -Version: 1.14.1 -Date: 2021-05-20 +Version: 1.16.0 +Date: 2021-08-21 Title: S4 Classes for Single Cell Data Authors@R: c( person("Aaron", "Lun", role=c("aut", "cph"), email="infinite.monkeys.with.keyboards@gmail.com"), @@ -23,12 +23,12 @@ VignetteBuilder: knitr RoxygenNote: 7.1.1 git_url: https://git.bioconductor.org/packages/SingleCellExperiment -git_branch: RELEASE_3_13 -git_last_commit: 5357eff -git_last_commit_date: 2021-05-21 -Date/Publication: 2021-05-21 +git_branch: RELEASE_3_14 +git_last_commit: bb27609 +git_last_commit_date: 2021-10-26 +Date/Publication: 2021-10-26 NeedsCompilation: no -Packaged: 2021-05-21 23:34:27 UTC; biocbuild +Packaged: 2021-10-26 22:50:24 UTC; biocbuild Author: Aaron Lun [aut, cph], Davide Risso [aut, cre, cph], Keegan Korthauer [ctb], diff -Nru r-bioc-singlecellexperiment-1.14.1+ds1/man/combine.Rd r-bioc-singlecellexperiment-1.16.0+ds/man/combine.Rd --- r-bioc-singlecellexperiment-1.14.1+ds1/man/combine.Rd 2021-05-19 19:15:32.000000000 +0000 +++ r-bioc-singlecellexperiment-1.16.0+ds/man/combine.Rd 2021-10-26 19:19:47.000000000 +0000 @@ -5,6 +5,7 @@ \alias{SCE-combine} \alias{cbind,SingleCellExperiment-method} \alias{rbind,SingleCellExperiment-method} +\alias{combineCols,SingleCellExperiment-method} \alias{[,SingleCellExperiment,ANY-method} \alias{[,SingleCellExperiment,ANY,ANY-method} \alias{[,SingleCellExperiment,ANY,ANY,ANY-method} @@ -47,6 +48,30 @@ Refer to \code{?\link[base]{cbind}} for the interpretation of \code{deparse.level}. } } + +In the following code snippets, \code{x} is a SingleCellExperiment and \code{...} contains multiple SingleCellExperiment objects. +\describe{ +\item{\code{combineCols(x, ..., delayed=TRUE, fill=NA, use.names=TRUE)}:}{ +Returns a SingleCellExperiment where all objects are flexibly combined by column. +The assays and \code{\link{colData}} are combined as described in \code{?"\link{combineCols,SummarizedExperiment-method}"}, +where assays or DataFrame columns missing in any given object are filled in with missing values before combining. + +Entries of the \code{\link{reducedDims}} with the same name across objects are combined by row. +If a dimensionality reduction result is not present for a particular SingleCellExperiment, it is represented by a matrix of \code{NA} values instead. +If corresponding \code{\link{reducedDim}} entries cannot be combined, e.g., due to inconsistent dimensions, they are omitted from the \code{\link{reducedDims}} of the output object with a warning. + +Entries of the \code{\link{altExps}} with the same name across objects are combined by column using the relevant \code{\link{combineCols}} method. +If a named entry is not present for a particular SingleCellExperiment, it is represented by a SummarizedExperiment with a single assay full of \code{fill} values. +If entries cannot be combined, e.g., due to inconsistent dimensions, they are omitted from the \code{\link{altExps}} of the output object with a warning. + +Entries of the \code{\link{colPairs}} with the same name across objects are concatenated together after adjusting the indices for each column's new position in the combined object. +If a named entry is not present for a particular SingleCellExperiments, it is assumed to contribute no column pairings and is ignored. + +Entries of the \code{\link{rowPairs}} with the same name should be identical across objects if \code{use.names=FALSE}. +If \code{use.names=TRUE}, we attempt to merge together entries with the same name by taking the union of all column pairings. +However, if the same cell has a different set of pairings across objects, a warning is raised and we fall back to the \code{\link{rowPair}} entry from the first object. +} +} } \section{Subsetting}{ diff -Nru r-bioc-singlecellexperiment-1.14.1+ds1/NAMESPACE r-bioc-singlecellexperiment-1.16.0+ds/NAMESPACE --- r-bioc-singlecellexperiment-1.14.1+ds1/NAMESPACE 2021-05-19 19:15:32.000000000 +0000 +++ r-bioc-singlecellexperiment-1.16.0+ds/NAMESPACE 2021-10-26 19:19:47.000000000 +0000 @@ -112,6 +112,7 @@ exportMethods(colPair) exportMethods(colPairNames) exportMethods(colPairs) +exportMethods(combineCols) exportMethods(counts) exportMethods(cpm) exportMethods(dim) @@ -171,6 +172,9 @@ importFrom(S4Vectors,I) importFrom(S4Vectors,SelfHits) importFrom(S4Vectors,SimpleList) +importFrom(S4Vectors,combineCols) +importFrom(S4Vectors,combineRows) +importFrom(S4Vectors,combineUniqueCols) importFrom(S4Vectors,coolcat) importFrom(S4Vectors,endoapply) importFrom(S4Vectors,findMatches) diff -Nru r-bioc-singlecellexperiment-1.14.1+ds1/R/combine.R r-bioc-singlecellexperiment-1.16.0+ds/R/combine.R --- r-bioc-singlecellexperiment-1.14.1+ds1/R/combine.R 2021-05-19 19:15:32.000000000 +0000 +++ r-bioc-singlecellexperiment-1.16.0+ds/R/combine.R 2021-10-26 19:19:47.000000000 +0000 @@ -37,6 +37,30 @@ #' } #' } #' +#' In the following code snippets, \code{x} is a SingleCellExperiment and \code{...} contains multiple SingleCellExperiment objects. +#' \describe{ +#' \item{\code{combineCols(x, ..., delayed=TRUE, fill=NA, use.names=TRUE)}:}{ +#' Returns a SingleCellExperiment where all objects are flexibly combined by column. +#' The assays and \code{\link{colData}} are combined as described in \code{?"\link{combineCols,SummarizedExperiment-method}"}, +#' where assays or DataFrame columns missing in any given object are filled in with missing values before combining. +#' +#' Entries of the \code{\link{reducedDims}} with the same name across objects are combined by row. +#' If a dimensionality reduction result is not present for a particular SingleCellExperiment, it is represented by a matrix of \code{NA} values instead. +#' If corresponding \code{\link{reducedDim}} entries cannot be combined, e.g., due to inconsistent dimensions, they are omitted from the \code{\link{reducedDims}} of the output object with a warning. +#' +#' Entries of the \code{\link{altExps}} with the same name across objects are combined by column using the relevant \code{\link{combineCols}} method. +#' If a named entry is not present for a particular SingleCellExperiment, it is represented by a SummarizedExperiment with a single assay full of \code{fill} values. +#' If entries cannot be combined, e.g., due to inconsistent dimensions, they are omitted from the \code{\link{altExps}} of the output object with a warning. +#' +#' Entries of the \code{\link{colPairs}} with the same name across objects are concatenated together after adjusting the indices for each column's new position in the combined object. +#' If a named entry is not present for a particular SingleCellExperiments, it is assumed to contribute no column pairings and is ignored. +#' +#' Entries of the \code{\link{rowPairs}} with the same name should be identical across objects if \code{use.names=FALSE}. +#' If \code{use.names=TRUE}, we attempt to merge together entries with the same name by taking the union of all column pairings. +#' However, if the same cell has a different set of pairings across objects, a warning is raised and we fall back to the \code{\link{rowPair}} entry from the first object. +#' } +#' } +#' #' @section Subsetting: #' In the following code snippets, \code{x} is a \linkS4class{SingleCellExperiment} object. #' \describe{ @@ -92,6 +116,7 @@ #' @aliases #' cbind,SingleCellExperiment-method #' rbind,SingleCellExperiment-method +#' combineCols,SingleCellExperiment-method #' [,SingleCellExperiment,ANY-method #' [,SingleCellExperiment,ANY,ANY-method #' [,SingleCellExperiment,ANY,ANY,ANY-method @@ -187,3 +212,151 @@ SummarizedExperiment(rowData=int_elementMetadata(x)) } +#' @export +#' @importFrom DelayedArray ConstantArray +#' @importFrom S4Vectors combineCols combineRows combineUniqueCols +setMethod("combineCols", "SingleCellExperiment", function(x, ..., delayed=TRUE, fill=NA, use.names=TRUE) { + old <- S4Vectors:::disableValidity() + if (!isTRUE(old)) { + S4Vectors:::disableValidity(TRUE) + on.exit(S4Vectors:::disableValidity(old)) + } + ans <- callNextMethod() + + args <- list(x, ...) + args <- lapply(args, updateObject) + new.int_m <- do.call(c, unname(lapply(args, int_metadata))) + + # Merging everything but the alternative experiments and reduced dimensions. + all.int_cd <- all.int_ed <- all.altexp <- all.reddim <- all.colp <- all.rowp <- vector("list", length(args)) + for (i in seq_along(all.int_cd)) { + current.int_cd <- int_colData(args[[i]]) + current.int_ed <- int_elementMetadata(args[[i]]) + + all.altexp[i] <- list(current.int_cd[[.alt_key]]) + all.reddim[i] <- list(current.int_cd[[.red_key]]) + all.colp[i] <- list(current.int_cd[[.colp_key]]) + all.rowp[i] <- list(current.int_ed[[.rowp_key]]) + + current.int_cd[[.alt_key]] <- NULL + current.int_cd[[.red_key]] <- NULL + current.int_cd[[.colp_key]] <- NULL + current.int_ed[[.rowp_key]] <- NULL + + all.int_cd[[i]] <- current.int_cd + all.int_ed[[i]] <- current.int_ed + } + + new.int_cd <- do.call(combineRows, all.int_cd) + + # Reduced dimensions need a bit more care. + all.reddim.names <- Reduce(union, lapply(all.reddim, colnames)) + new.reddim <- new.int_cd[,0] + + for (i in all.reddim.names) { + collated <- vector("list", length(all.reddim)) + first <- NULL + + for (j in seq_along(collated)) { + if (i %in% names(all.reddim[[j]])) { + collated[[j]] <- all.reddim[[j]][[i]] + if (is.null(first)) { + first <- collated[[j]] + } + } + } + + for (j in seq_along(collated)) { + if (is.null(collated[[j]])) { + collated[[j]] <- matrix(NA_real_, ncol(args[[j]]), ncol(first)) + } + } + + tryCatch({ + new.reddim[[i]] <- do.call(rbind, collated) + }, error=function(e) { + warning("failed to combine '", i, "' in 'reducedDims(<", class(ans), ">)':\n ", conditionMessage(e)) + }) + } + + new.int_cd[[.red_key]] <- new.reddim + + # Alternative experiments need a bit more care. + all.altexp.names <- Reduce(union, lapply(all.altexp, colnames)) + new.altexps <- new.int_cd[,0] + + for (i in all.altexp.names) { + collated <- vector("list", length(all.altexp)) + first <- NULL + + for (j in seq_along(collated)) { + if (i %in% names(all.altexp[[j]])) { + collated[[j]] <- all.altexp[[j]][[i]]@se + if (is.null(first)) { + first <- collated[[j]] + } + } + } + + for (j in seq_along(collated)) { + if (is.null(collated[[j]])) { + dummy.assay <- assays(first)[1] + dummy.assay[[1]] <- ConstantArray(c(nrow(first), ncol(args[[j]])), fill) + dummy <- SummarizedExperiment(dummy.assay, rowData=rowData(first)[,0], colData=colData(args[[j]])[,0]) + collated[[j]] <- as(dummy, class(first)) # probably not the best placeholder, but whatever. + } + } + + tryCatch({ + new.altexps[[i]] <- SummarizedExperimentByColumn(do.call(combineCols, c(collated, list(use.names=use.names)))) + }, error=function(e) { + warning("failed to combine '", i, "' in 'altExps(<", class(ans), ">)':\n ", conditionMessage(e)) + }) + } + + new.int_cd[[.alt_key]] <- new.altexps + + # As do the colPairs. + all.colp.names <- Reduce(union, lapply(all.colp, colnames)) + new.colp <- new.int_cd[,0] + + for (i in all.colp.names) { + collated <- vector("list", length(all.colp)) + first <- NULL + + for (j in seq_along(collated)) { + if (i %in% names(all.colp[[j]])) { + collated[[j]] <- all.colp[[j]][[i]] + } + } + + for (j in seq_along(collated)) { + if (is.null(collated[[j]])) { + collated[[j]] <- DualSubset(SelfHits(integer(0), integer(0), nnode=ncol(args[[j]]))) + } + } + + tryCatch({ + new.colp[[i]] <- do.call(c, collated) + }, error=function(e) { + warning("failed to combine '", i, "' in 'colPairs(<", class(ans), ">)':\n ", conditionMessage(e)) + }) + } + + new.int_cd[[.colp_key]] <- new.colp + + # As do the rowPairs. + for (i in seq_along(all.rowp)) { + rn <- rownames(args[[i]]) + rownames(all.int_ed[[i]]) <- rn + rownames(all.rowp[[i]]) <- rn + } + new.rowp <- do.call(combineUniqueCols, c(all.rowp, list(use.names=use.names))) + new.int_ed <- do.call(combineUniqueCols, c(all.int_ed, list(use.names=use.names))) + rownames(new.rowp) <- rownames(new.int_ed) <- NULL + new.int_ed[[.rowp_key]] <- new.rowp + + ans <- as(ans, "SingleCellExperiment") + BiocGenerics:::replaceSlots(ans, int_colData=new.int_cd, int_elementMetadata=new.int_ed, + int_metadata=new.int_m, check=FALSE) +}) diff -Nru r-bioc-singlecellexperiment-1.14.1+ds1/R/DualSubset-methods.R r-bioc-singlecellexperiment-1.16.0+ds/R/DualSubset-methods.R --- r-bioc-singlecellexperiment-1.14.1+ds1/R/DualSubset-methods.R 2021-05-19 19:15:32.000000000 +0000 +++ r-bioc-singlecellexperiment-1.16.0+ds/R/DualSubset-methods.R 2021-10-26 19:19:47.000000000 +0000 @@ -12,7 +12,12 @@ #' SelfHits normalizeSingleBracketSubscript setMethod("[", "DualSubset", function(x, i, j, ..., drop=FALSE) { p <- .get_hits(x) - i <- normalizeSingleBracketSubscript(i, x) + + if (anyNA(i) && is.numeric(i)) { + i <- as.integer(i) + } else { + i <- normalizeSingleBracketSubscript(i, x) + } mq <- findMatches(i, queryHits(p)) ms <- findMatches(i, subjectHits(p)) diff -Nru r-bioc-singlecellexperiment-1.14.1+ds1/R/unsplitAltExps.R r-bioc-singlecellexperiment-1.16.0+ds/R/unsplitAltExps.R --- r-bioc-singlecellexperiment-1.14.1+ds1/R/unsplitAltExps.R 2021-05-19 19:15:32.000000000 +0000 +++ r-bioc-singlecellexperiment-1.16.0+ds/R/unsplitAltExps.R 2021-10-26 19:19:47.000000000 +0000 @@ -74,17 +74,17 @@ #' @importFrom BiocGenerics rbind #' @importFrom SummarizedExperiment assayNames assay .unsplit_assays <- function(all.se, delayed) { - all.assays <- unique(unlist(lapply(all.se, assayNames))) - combined <- vector("list", length(all.assays)) - names(combined) <- all.assays + all_assay_names <- unique(unlist(lapply(all.se, assayNames))) + combined <- vector("list", length(all_assay_names)) + names(combined) <- all_assay_names - for (a in all.assays) { + for (assay_name in all_assay_names) { current <- vector("list", length(all.se)) for (s in seq_along(all.se)) { cur.se <- all.se[[s]] - if (a %in% assayNames(cur.se)) { - mat <- assay(cur.se, a, withDimnames=FALSE) + if (assay_name %in% assayNames(cur.se)) { + mat <- assay(cur.se, assay_name, withDimnames=FALSE) if (delayed) { mat <- DelayedArray(mat) } @@ -97,7 +97,9 @@ current[[s]] <- mat } } - combined[[a]] <- do.call(rbind, current) + a <- do.call(rbind, current) + rownames(a) <- NULL + combined[[assay_name]] <- a } combined diff -Nru r-bioc-singlecellexperiment-1.14.1+ds1/tests/testthat/test-more-combine.R r-bioc-singlecellexperiment-1.16.0+ds/tests/testthat/test-more-combine.R --- r-bioc-singlecellexperiment-1.14.1+ds1/tests/testthat/test-more-combine.R 1970-01-01 00:00:00.000000000 +0000 +++ r-bioc-singlecellexperiment-1.16.0+ds/tests/testthat/test-more-combine.R 2021-10-26 19:19:47.000000000 +0000 @@ -0,0 +1,110 @@ +# Checks the combining methods. +# library(SingleCellExperiment); library(testthat); source("setup.R"); source("test-more-combine.R") + +sce <- loaded +sce2 <- loaded[,1:50] + +test_that("basic combineCols works correctly", { + copy <- sce2 + logcounts(copy) <- NULL + + out <- combineCols(sce, copy, use.names=FALSE) + expect_identical(ncol(out), ncol(sce) + ncol(copy)) + expect_identical(as.matrix(logcounts(out)[,1:ncol(sce)]), as.matrix(logcounts(sce))) + expect_true(all(is.na(as.matrix(logcounts(out)[,ncol(sce) + 1:ncol(copy)])))) + + rownames(sce2) <- rownames(sce) <- sprintf("GENE_%i", seq_len(nrow(sce))) + copy <- sce2[10:20,] + out <- combineCols(sce, copy, use.names=TRUE) + expect_identical(ncol(out), ncol(sce) + ncol(copy)) + expect_identical(as.matrix(counts(out)[,1:ncol(sce)]), as.matrix(counts(sce))) + expect_identical(as.matrix(counts(out)[10:20,ncol(sce) + 1:ncol(copy)]), as.matrix(counts(copy))) + expect_true(all(is.na(counts(out)[-(10:20),ncol(sce) + 1:ncol(copy)]))) +}) + +test_that("combineCols works correctly with reducedDims", { + # Handles absent entries. + copy <- sce2 + reducedDim(copy, "PCA") <- NULL + reducedDim(copy, "TSNE") <- reducedDim(copy, "TSNE") * 2 + out <- combineCols(sce, copy, use.names=FALSE) + + expect_identical(reducedDim(out, "TSNE"), rbind(reducedDim(sce, "TSNE"), reducedDim(copy, "TSNE"))) + expect_identical(reducedDim(out, "PCA")[1:ncol(sce),], reducedDim(sce, "PCA")) + expect_true(all(is.na(reducedDim(out, "PCA")[ncol(sce) + 1:ncol(copy),]))) + + # Robust to incompatible dimensions. + copy <- sce2 + reducedDim(copy, "PCA") <- reducedDim(copy, "PCA")[,1:2] + expect_warning(out <- combineCols(sce, copy, use.names=FALSE), "PCA") + expect_false("PCA" %in% reducedDimNames(out)) + expect_identical(reducedDim(out, "TSNE"), rbind(reducedDim(sce, "TSNE"), reducedDim(copy, "TSNE"))) +}) + +test_that("combineCols works correctly with altExps", { + # Handles absent entries. + copy1 <- sce + altExp(copy1, "Protein") <- NULL + copy2 <- sce2 + assay(altExp(copy2, "Spike"), "counts") <- NULL + out <- combineCols(copy1, copy2, use.names=FALSE) + + prot <- altExp(out, "Protein") + expect_true(all(is.na(as.matrix(assay(prot, "logcounts")[,1:ncol(copy1)])))) + expect_identical(as.matrix(assay(prot, "logcounts")[,ncol(copy1) + 1:ncol(copy2)]), as.matrix(assay(altExp(copy2, "Protein"), "logcounts"))) + + spike <- altExp(out, "Spike") + expect_identical(as.matrix(assay(spike, "counts")[,1:ncol(copy1)]), as.matrix(assay(altExp(copy1, "Spike"), "counts"))) + expect_true(all(is.na(as.matrix(assay(spike, "counts")[,ncol(copy1) + 1:ncol(copy2)])))) + + # Robust to incompatible dimensions. + copy1 <- sce + altExp(copy1, "Protein") <- altExp(copy1, "Protein")[1:2,] + expect_warning(out <- combineCols(copy1, copy2, use.names=FALSE), "Protein") + expect_false("Protein" %in% altExpNames(out)) + + # Use.names=TRUE propagates. + rownames(copy1) <- rownames(copy2) <- sprintf("GENE_%i", seq_len(nrow(copy1))) + out <- combineCols(copy1, copy2) + prot <- altExp(out, "Protein") + vals <- assay(prot, "counts") + expect_identical(as.matrix(vals[1:2,1:ncol(copy1)]), as.matrix(assay(altExp(copy1, "Protein"), "counts"))) + expect_true(all(is.na(vals[-(1:2),1:ncol(copy1)]))) +}) + +test_that("combineCols works correctly with colPairs", { + # Handles absent entries. + copy1 <- sce + colPairs(copy1) <- NULL + + out <- combineCols(copy1, sce2, use.names=FALSE) + expect_identical(as.matrix(colPair(out)) - ncol(copy1), as.matrix(colPair(sce2))) + + out <- combineCols(sce, copy1, use.names=FALSE) + expect_identical(as.data.frame(colPair(out)), as.data.frame(colPair(sce))) +}) + +test_that("combineCols works correctly with rowPairs", { + # Handles absent entries. + copy1 <- sce + rowPairs(copy1) <- NULL + out <- combineCols(copy1, sce2, use.names=FALSE) + expect_identical(rowPairs(out), rowPairs(sce2)) + + # Handles mismatching entries. + copy1 <- sce + mcols(rowPair(copy1))$value <- runif(100) + expect_warning(out <- combineCols(copy1, sce2, use.names=FALSE), "unnamed1") + expect_identical(rowPairs(out), rowPairs(copy1)) + + # Merges non-contradictory entries. + copy1 <- sce + copy2 <- sce2 + rownames(copy1) <- rownames(copy2) <- sprintf("GENE_%i", seq_len(nrow(copy1))) + copy1 <- copy1[1:(nrow(sce)/2),] + copy2 <- copy2[nrow(sce)/2+1:(nrow(sce)/2),] + + expect_warning(out <- combineCols(copy1, copy2), NA) + expect_true(length(rowPair(out)) > 0) + expect_true(length(rowPair(out)) < length(rowPair(sce))) # as links spanning the split are lost. +})