Skip to content

Commit 95343c1

Browse files
authored
>2/3D array subsetting (#231)
* sda sub revision for >2/3 dims * crop multi-scale adjustment * divert badge to r-uni action * v0.99.42
1 parent cffa06f commit 95343c1

6 files changed

Lines changed: 76 additions & 39 deletions

File tree

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: spatialdataR
22
Title: Representation of Python's spatialdata in R
33
Depends: R (>= 4.6)
4-
Version: 0.99.41
4+
Version: 0.99.42
55
Description: R interface to Python/scverse's 'spatialdata' framework for
66
unified spatial omics data handling. Adheres to OME-NGFF standards,
77
providing lazy, on-disk representations for multiscale images and

R/crop.R

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,11 @@ NULL
155155

156156
#' @export
157157
#' @rdname crop
158+
#' @importFrom utils tail
158159
#' @importFrom methods is
159160
#' @importFrom sf st_bbox
160161
setMethod("crop", "SpatialDataArray", \(x, y, j=1, ...) {
162+
#x <- label(sd); y <- bb; j <- 1
161163
if (is.matrix(y)) {
162164
y <- .check_pol(y)
163165
y <- st_bbox(st_polygon(list(y)))
@@ -193,12 +195,28 @@ setMethod("crop", "SpatialDataArray", \(x, y, j=1, ...) {
193195
wh[[2]] <- wh[[2]][1] + c(z$ymin, z$ymax)
194196
}
195197
metadata(x)$wh <- wh
198+
# multi-scale adjustment
199+
t <- .get_multiscale_scale(x)
200+
tx <- tail(t, 1)
201+
ty <- tail(t, 2)[1]
202+
z$xmin <- floor(z$xmin/tx)
203+
z$ymin <- floor(z$ymin/ty)
204+
z$xmax <- ceiling(z$xmax/tx)
205+
z$ymax <- ceiling(z$ymax/ty)
196206
# subset array
197207
i <- seq(z$ymin+1, z$ymax)
198-
j <- seq(z$xmin+1, z$xmax)
199-
if (n == 3) x[, i, j] else x[i, j]
208+
j <- seq(z$xmin+1, z$xmax)
209+
ii <- is(x, "SpatialDataImage")
210+
if (ii) x[, i, j] else x[i, j]
200211
})
201212

213+
.get_multiscale_scale <- \(x) {
214+
ms <- multiscales(meta(x))[[1]]
215+
ds <- ms$datasets[[1]]
216+
ct <- ds$coordinateTransformations[[1]]
217+
return(unlist(ct$scale))
218+
}
219+
202220
#' @export
203221
#' @rdname crop
204222
#' @importFrom dplyr pull .data

R/sdArray.R

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ NULL
6363

6464
# new ----
6565

66+
.new_sda <- \(type, data=list(), meta=SpatialDataAttrs(), metadata=list(), ...) {
67+
if (is.array(data)) data <- list(data)
68+
x <- new(type, data=data, meta=meta, ...)
69+
metadata(x) <- metadata
70+
return(x)
71+
}
72+
73+
SpatialDataImage <- \(...) .new_sda("SpatialDataImage", ...)
74+
SpatialDataLabel <- \(...) .new_sda("SpatialDataLabel", ...)
75+
6676
#' @export
6777
#' @rdname SpatialDataArray
6878
#' @importFrom methods new
@@ -160,46 +170,53 @@ setMethod("channels", "SpatialDataElement", \(x, ...) stop("only 'images' have c
160170
)
161171
}
162172

173+
# https://github.com/Huber-group-EMBL/Rarr/blob/1795c676e2ac81a9ba2a592c7210cc59036544b6/R/utils.R#L74-L79
174+
.sub <- \(x, ix) rlang::inject(x[!!!ix, drop=FALSE])
175+
163176
#' @exportMethod [
164177
#' @rdname SpatialDataArray
165178
#' @importFrom utils head tail
179+
.sub_sda <- \(x, yx, z=list()) {
180+
#x <- label(sd); yx <- list(1:10, 1:10); z <- list()
181+
# yx: spatial; z: channels
182+
ls <- seq_along(data(x, NULL))
183+
data(x) <- lapply(ls, \(l) {
184+
sf <- 2^(l-1)
185+
rc <- tail(dim(data(x, l)), 2)
186+
# get spatial indices
187+
.yx <- lapply(seq_along(yx), \(a) {
188+
ix <- yx[[a]]
189+
if (isTRUE(ix)) return(seq_len(rc[a]))
190+
if (is.numeric(ix)) {
191+
return(seq(
192+
floor(head(ix, 1)/sf),
193+
min(ceiling(tail(ix, 1)/sf), rc[a])))
194+
}
195+
ix
196+
})
197+
# combine leading & spatial indices
198+
ix <- c(z, .yx)
199+
# (optional) prepend additional indices
200+
nd <- length(dim(data(x)))
201+
na <- nd-length(ix)
202+
if (na > 0) {
203+
na <- !logical(na)
204+
ix <- c(as.list(na), ix)
205+
}
206+
.sub(data(x, l), ix)
207+
})
208+
x
209+
}
210+
166211
setMethod("[", "SpatialDataImage", \(x, i, j, k, ..., drop=FALSE) {
167212
if (missing(i)) i <- TRUE
168213
if (missing(j)) j <- TRUE else if (isFALSE(j)) j <- 0 else .check_jk(j, "j")
169214
if (missing(k)) k <- TRUE else if (isFALSE(k)) k <- 0 else .check_jk(k, "k")
170-
ijk <- list(i, j, k)
171-
n <- length(data(x, NULL))
172-
d <- dim(data(x))
173-
data(x) <- lapply(seq_len(n), \(.) {
174-
j <- if (isTRUE(j)) seq_len(d[2]) else j
175-
k <- if (isTRUE(k)) seq_len(d[3]) else k
176-
jk <- lapply(list(j, k), \(jk) {
177-
fac <- 2^(.-1)
178-
seq(floor(head(jk, 1)/fac),
179-
ceiling(tail(jk, 1)/fac))
180-
})
181-
data(x, .)[i, jk[[1]], jk[[2]], drop=FALSE]
182-
})
183-
x
215+
.sub_sda(x, yx=list(j, k), z=list(i))
184216
})
185217

186-
#' @exportMethod [
187-
#' @rdname SpatialDataArray
188-
#' @importFrom utils head tail
189218
setMethod("[", "SpatialDataLabel", \(x, i, j, ..., drop=FALSE) {
190219
if (missing(i)) i <- TRUE else if (isFALSE(i)) i <- 0 else .check_jk(i, "i")
191220
if (missing(j)) j <- TRUE else if (isFALSE(j)) j <- 0 else .check_jk(j, "j")
192-
n <- length(data(x, NULL))
193-
d <- dim(data(x, 1))
194-
data(x) <- lapply(seq_len(n), \(.) {
195-
i <- if (isTRUE(i)) seq_len(d[1]) else i
196-
j <- if (isTRUE(j)) seq_len(d[2]) else j
197-
ij <- lapply(list(i, j), \(ij) {
198-
fac <- 2^(.-1)
199-
seq(floor(head(ij, 1)/fac),
200-
ceiling(tail(ij, 1)/fac))
201-
})
202-
data(x, .)[ij[[1]], ij[[2]], drop=FALSE]
203-
})
204-
x
221+
.sub_sda(x, yx=list(i, j), z=list())
205222
})

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SpatialData
22

3-
[![Bioc Check](https://github.com/HelenaLC/spatialdataR/actions/workflows/check-bioc.yml/badge.svg?branch=main&event=push)](https://github.com/HelenaLC/SpatialData/actions/workflows/check-bioc.yml)
3+
[![R-universe](https://github.com/HelenaLC/spatialdataR/actions/workflows/r-universe.yaml/badge.svg?branch=main&event=push)](https://github.com/HelenaLC/spatialdataR/actions/workflows/r-universe.yaml)
44

55
`spatialdataR` provides an R interface to Python's [spatialdata](https://spatialdata.scverse.org) framework.
66
It enables the representation, handling, and integration of diverse spatial omics datasets

inst/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
changes in version 0.99.42
2+
3+
- revised 'crop()' to adjust for array multiscales with scale factor != 1
4+
- revised subsetting to support >2/3D arrays (t & z dims. are protected)
5+
16
changes in version 0.99.41
27

38
- fix vignette to call 'spatialdataR::transform()' explicitly

man/SpatialDataArray.Rd

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

0 commit comments

Comments
 (0)