Browse code

Modify SCE2AnnData() to return dgRMatix assays

Luke Zappia authored on 10/04/2025 17:01:41
Showing 4 changed files

... ...
@@ -2,9 +2,11 @@
2 2
 
3 3
 * Bioconductor 3.21, May 2025
4 4
 
5
-## zellkonverter 1.17.4
5
+## zellkonverter 1.17.4 (2025-04-10)
6 6
 
7 7
 * Add tests for **anndata** v0.10.9
8
+* Modify `SCE2AnnData()` to covert sparse matrices to `dgRMatrix` when they are
9
+  transposed (mostly assays) (Fixes #132)
8 10
 
9 11
 ## zellkonverter 1.17.3 (2025-04-08)
10 12
 
... ...
@@ -268,14 +268,18 @@ SCE2AnnData <- function(sce, X_name = NULL, assays = TRUE, colData = TRUE,
268 268
 #' @importClassesFrom Matrix CsparseMatrix
269 269
 #' @importFrom DelayedArray is_sparse
270 270
 #' @importFrom Matrix t
271
+# Original code from Charlotte Soneson in kevinrue/velociraptor
271 272
 .makeNumpyFriendly <- function(x, transpose = TRUE) {
272 273
     if (transpose) {
273 274
         x <- t(x)
274 275
     }
275 276
 
276
-    # Code from Charlotte Soneson in kevinrue/velociraptor.
277 277
     if (is_sparse(x)) {
278
-        as(x, "CsparseMatrix")
278
+        x <- as(x, "CsparseMatrix")
279
+        if (transpose) {
280
+            x <- as(x, "RsparseMatrix")
281
+        }
282
+        x
279 283
     } else {
280 284
         as.matrix(x)
281 285
     }
282 286
new file mode 100644
... ...
@@ -0,0 +1,38 @@
1
+test_that(".makeNumpyFriendly() works correctly", {
2
+    mat <- matrix(1:50, nrow = 10, ncol = 5)
3
+
4
+    friendly_mat <- .makeNumpyFriendly(mat, transpose = TRUE)
5
+    expect_identical(friendly_mat, t(mat))
6
+    expect_identical(dim(friendly_mat), rev(dim(mat)))
7
+
8
+    friendly_mat <- .makeNumpyFriendly(mat, transpose = FALSE)
9
+    expect_identical(friendly_mat, mat)
10
+    expect_identical(dim(friendly_mat), dim(mat))
11
+
12
+    sparse_mat <- Matrix::Matrix(mat, sparse = TRUE)
13
+    friendly_sparse_mat <- .makeNumpyFriendly(sparse_mat, transpose = TRUE)
14
+    expect_s4_class(friendly_sparse_mat, "dgRMatrix")
15
+    expect_identical(dim(friendly_sparse_mat), rev(dim(sparse_mat)))
16
+
17
+    friendly_sparse_mat <- .makeNumpyFriendly(sparse_mat, transpose = FALSE)
18
+    expect_s4_class(friendly_sparse_mat, "dgCMatrix")
19
+    expect_identical(dim(friendly_sparse_mat), dim(sparse_mat))
20
+
21
+    delayed_mat <- DelayedArray::DelayedArray(mat)
22
+    friendly_delayed_mat <- .makeNumpyFriendly(delayed_mat, transpose = TRUE)
23
+    expect_identical(friendly_delayed_mat, t(mat))
24
+    expect_identical(dim(friendly_delayed_mat), rev(dim(mat)))
25
+
26
+    friendly_delayed_mat <- .makeNumpyFriendly(delayed_mat, transpose = FALSE)
27
+    expect_identical(friendly_delayed_mat, mat)
28
+    expect_identical(dim(friendly_delayed_mat), dim(mat))
29
+
30
+    sparse_delayed_mat <- DelayedArray::DelayedArray(sparse_mat)
31
+    friendly_sparse_delayed_mat <- .makeNumpyFriendly(sparse_delayed_mat, transpose = TRUE)
32
+    expect_s4_class(friendly_sparse_delayed_mat, "dgRMatrix")
33
+    expect_identical(dim(friendly_sparse_delayed_mat), rev(dim(sparse_delayed_mat)))
34
+
35
+    friendly_sparse_delayed_mat <- .makeNumpyFriendly(sparse_delayed_mat, transpose = FALSE)
36
+    expect_s4_class(friendly_sparse_delayed_mat, "dgCMatrix")
37
+    expect_identical(dim(friendly_sparse_delayed_mat), dim(sparse_delayed_mat))
38
+})
... ...
@@ -35,6 +35,37 @@ test_that("writeH5AD works as expected", {
35 35
     expect_identical(col_data, colData(sce))
36 36
 })
37 37
 
38
+test_that("writeH5AD works as expected with version 0.10.9", {
39
+    temp <- tempfile(fileext = ".h5ad")
40
+    writeH5AD(sce, temp, version = "0.10.9")
41
+    expect_true(file.exists(temp))
42
+
43
+    # Reading it back out again. Hopefully we didn't lose anything important.
44
+    out <- readH5AD(temp, version = "0.10.9")
45
+
46
+    expect_identical(dimnames(out), dimnames(sce))
47
+    expect_equal(assay(out), assay(sce))
48
+    expect_identical(reducedDims(out), reducedDims(sce))
49
+
50
+    # Need to coerce the factors back to strings.
51
+    row_data <- rowData(out)
52
+    for (i in seq_len(ncol(row_data))) {
53
+        if (is.factor(row_data[[i]])) {
54
+            row_data[[i]] <- as.character(row_data[[i]])
55
+        }
56
+    }
57
+    expect_identical(row_data, rowData(sce))
58
+
59
+    col_data <- colData(out)
60
+    for (i in seq_len(ncol(col_data))) {
61
+        if (is.factor(col_data[[i]])) {
62
+            col_data[[i]] <- as.character(col_data[[i]])
63
+        }
64
+    }
65
+    names(col_data) <- names(colData(sce))
66
+    expect_identical(col_data, colData(sce))
67
+})
68
+
38 69
 test_that("writeH5AD works as expected with version 0.10.6", {
39 70
     temp <- tempfile(fileext = ".h5ad")
40 71
     writeH5AD(sce, temp, version = "0.10.6")