Skip to content

Commit 475a6f6

Browse files
authored
revise combine() to accept (named) list (#229)
Former-commit-id: 9a4cb77e78ee58fb7d918cf358f534a3bf81c900 Former-commit-id: 6080e4c6a547e0dedb8c09b1822e0ecdcdc990b5
1 parent 40c229e commit 475a6f6

3 files changed

Lines changed: 76 additions & 30 deletions

File tree

R/combine.R

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,43 +17,63 @@
1717
#' imageNames(y)
1818
#' region(table(y, 1))
1919
#' region(table(y, 2))
20+
#'
21+
#' y <- combine(list(Alpha=x, x, Omega=x))
22+
#' shapeNames(y)
23+
#'
24+
#' @importFrom BiocGenerics combine
2025
NULL
2126

22-
#' @export
23-
#' @rdname combine
24-
#' @importFrom BiocGenerics combine
25-
setMethod("combine", c("SpatialData", "SpatialData"), \(x, y, ...) {
26-
# ensure element names are unique across objects
27-
old <- list(unlist(colnames(x)), unlist(colnames(y)))
28-
idx <- rep.int(c(1, 2), lengths(old))
29-
new <- split(make.unique(unlist(old)), idx)
30-
for (i in c(1, 2)) {
31-
# get input element names
32-
z <- get(c("x", "y")[i])
33-
old_nms <- unlist(colnames(z)[.ls])
34-
35-
# find new names for these elements
27+
.combine <- \(xs, old, new) {
28+
for (i in seq_along(xs)) {
29+
x <- xs[[i]]
30+
# elements that might be referred to by tables (labels, shapes)
31+
old_nms <- unlist(colnames(x)[.ls])
3632
j <- match(old_nms, old[[i]])
3733
new_nms <- new[[i]][j]
38-
3934
# rename elements
4035
for (l in .ls) {
41-
j <- match(names(z[[l]]), old[[i]])
42-
names(z[[l]]) <- new[[i]][j]
36+
j <- match(names(x[[l]]), old[[i]])
37+
names(x[[l]]) <- new[[i]][j]
4338
}
4439
# sync tables
45-
z <- .sync_tables_sdattrs(z, old_nms, new_nms)
46-
40+
x <- .sync_tables_sdattrs(x, old_nms, new_nms)
4741
# rename tables themselves
48-
j <- match(tableNames(z), old[[i]])
49-
tableNames(z) <- new[[i]][j]
50-
51-
assign(c("x", "y")[i], z)
42+
j <- match(tableNames(x), old[[i]])
43+
tableNames(x) <- new[[i]][j]
44+
xs[[i]] <- x
5245
}
53-
SpatialData(
54-
images=c(x$images, y$images),
55-
labels=c(x$labels, y$labels),
56-
points=c(x$points, y$points),
57-
shapes=c(x$shapes, y$shapes),
58-
tables=c(x$tables, y$tables))
46+
names(ls) <- ls <- .LAYERS
47+
args <- lapply(ls, \(l) do.call(c, lapply(unname(xs), \(x) x[[l]])))
48+
do.call(SpatialData, args)
49+
}
50+
51+
#' @export
52+
#' @rdname combine
53+
setMethod("combine", c("list", "missing"), \(x, y, ...) {
54+
# validate input
55+
ok <- all(vapply(x, \(.) is(., "SpatialData"), logical(1)))
56+
if (!ok) stop("'x' should be a list of 'SpatialData' objects")
57+
# get current element names
58+
old <- lapply(x, \(z) unlist(colnames(z)))
59+
# get list names; if missing, use empty strings
60+
if (is.null(nms <- names(x)))
61+
nms <- character(length(x))
62+
# prepend list names to element names where available
63+
new <- lapply(seq_along(x), \(i) {
64+
if (nms[i] == "") return(old[[i]])
65+
paste(nms[i], old[[i]], sep=".")
66+
})
67+
# ensure global uniqueness
68+
new <- split(
69+
make.unique(unlist(new)),
70+
rep(seq_along(new), lengths(new)))
71+
.combine(x, old, new)
5972
})
73+
74+
#' @export
75+
#' @rdname combine
76+
setMethod("combine",
77+
c("SpatialData", "SpatialData"),
78+
\(x, y, ...) combine(list(x, y)))
79+

man/combine.Rd

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-combine.R

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ x <- file.path("extdata", "blobs.zarr")
22
x <- system.file(x, package="spatialdataR")
33
x <- readSpatialData(x)
44

5-
test_that("combine", {
5+
test_that("combine two SpatialData objects", {
66
# auto-fixed names
77
expect_no_message(y <- combine(x, x))
88
f <- \(.) unlist(colnames(.))
@@ -38,3 +38,22 @@ test_that("combine", {
3838
expect_identical(c[[.]][[2]], b[[.]][[1]])
3939
}
4040
})
41+
42+
test_that("combine length-2+ list of objects", {
43+
# partially named
44+
y <- combine(list(a=x, b=x, x))
45+
old <- unlist(colnames(x))
46+
new <- unlist(colnames(y))
47+
expect_true(all(old %in% new))
48+
expect_true(!any(duplicated(new)))
49+
expect_true(all(paste0("a.", old) %in% new))
50+
expect_true(all(paste0("b.", old) %in% new))
51+
expect_length(new, 3*length(unlist(colnames(x))))
52+
# unnamed
53+
y <- combine(list(x, x))
54+
new <- unlist(colnames(y))
55+
expect_true(all(old %in% new))
56+
expect_length(new, 2*length(old))
57+
expect_true(!any(duplicated(new)))
58+
expect_true(all(paste0(old, ".1") %in% new))
59+
})

0 commit comments

Comments
 (0)