library(sf)
library(SFEData)
library(terra)
# From sf's examples
pts = st_sfc(st_point(c(.5,.5)), st_point(c(1.5, 1.5)), st_point(c(2.5, 2.5)))
pol = st_polygon(list(rbind(c(0,0), c(2,0), c(2,2), c(0,2), c(0,0))))
test_that("trivial, st_any_intersects", {
o <- st_any_intersects(pts, pol, sparse = FALSE)
expect_equal(o, c(TRUE, TRUE, FALSE))
o <- st_any_intersects(pts, pol, sparse = TRUE)
expect_equal(o, c(1L, 2L))
})
test_that("Swap x and y for st_intersects", {
o1 <- st_any_intersects(pts, pol, sparse = TRUE)
o2 <- st_any_intersects(pts, pol, sparse = TRUE, yx = TRUE)
expect_equal(o1, o2)
})
test_that("trivial, st_n_intersects", {
n1 <- st_n_intersects(pts, pol)
expect_equal(n1, c(1,1,0))
n2 <- st_n_intersects(pol, pts)
expect_equal(n2, 2)
})
# Crop============
sfe_visium <- readRDS(system.file("extdata/sfe_visium.rds",
package = "SpatialFeatureExperiment"
))
sfe_visium <- addVisiumSpotPoly(sfe_visium, 0.5)
bbox_use <- st_as_sfc(st_bbox(c(xmin = 1, xmax = 3, ymin = 1, ymax = 6),
crs = NA
))
bbox_use2 <- st_as_sfc(st_bbox(c(xmin = 1, xmax = 3, ymin = 5, ymax = 9)), crs = NA)
bbox_sf <- st_sf(geometry = bbox_use, sample_id = "sample01", crs = NA)
cg <- colGeometry(sfe_visium, sample_id = "sample01")
bbox_cg <- st_bbox(st_centroid(cg))
ag <- st_bbox(cg) |> st_as_sfc() |> st_buffer(dist = 0.3)
annotGeometry(sfe_visium, "box", sample_id = "sample01") <- st_sf(geometry = ag, sample_id = "sample01",
sf_column_name = "geometry",
crs = NA)
rg_bbox <- st_bbox(ag)
set.seed(29)
rg1 <- cbind(runif(20, rg_bbox["xmin"], rg_bbox["xmax"]),
runif(20, rg_bbox["ymin"], rg_bbox["ymax"]))
rg2 <- matrix(rnorm(30, mean = 3, sd = 3), ncol = 2)
rg_use <- st_sf(geometry = st_sfc(st_multipoint(rg1), st_multipoint(rg2)),
crs = NA)
rowGeometry(sfe_visium, "points", sample_id = "sample01", withDimnames = FALSE) <- rg_use
test_that("All spots in the cropped SFE objects indeed are covered by the bbox", {
sfe_cropped <- SpatialFeatureExperiment::crop(sfe_visium, bbox_use, sample_id = "all")
cg <- spotPoly(sfe_cropped, "all")
expect_true(all(st_any_pred(cg, bbox_use, pred = st_covered_by, sparse = FALSE)))
expect_true(st_geometry_type(cg, by_geometry = FALSE) == "POLYGON")
rg <- rowGeometry(sfe_cropped)
expect_true(all(st_any_pred(rg, bbox_use, pred = st_covered_by, sparse = FALSE)))
})
test_that("Only crop one sample out of two, with sf", {
expect_error(SpatialFeatureExperiment::crop(sfe_visium, y = bbox_sf, sample_id = "sample02"),
"No bounding boxes for samples specified.")
sfe_cropped2 <- SpatialFeatureExperiment::crop(sfe_visium, y = bbox_sf, sample_id = "sample01")
expect_true(all(st_any_pred(spotPoly(sfe_cropped2, "sample01"), bbox_use,
pred = st_covered_by, sparse = FALSE
)))
expect_false(all(st_any_pred(spotPoly(sfe_cropped2, "sample02"), bbox_use,
pred = st_covered_by, sparse = FALSE
)))
expect_equal(sum(st_any_intersects(
spotPoly(sfe_cropped2, "sample02"),
bbox_use
)), 2)
})
test_that("Using a bounding box to crop SFE objects, current way, expected errors", {
expect_error(SpatialFeatureExperiment::crop(sfe_visium, y = "foobar", sample_id = "sample01"),
"bbox must be a numeric vector or matrix.")
expect_error(SpatialFeatureExperiment::crop(sfe_visium, y = c(meow = 1, purr = 2), sample_id = "sample01"),
"must be a vector of length 4")
m <- matrix(1:8, ncol = 2)
expect_error(SpatialFeatureExperiment::crop(sfe_visium, y = m, sample_id = "sample01"),
"must have rownames xmin, xmax")
rownames(m) <- c("xmin", "ymin", "xmax", "ymax")
expect_error(SpatialFeatureExperiment::crop(sfe_visium, y = m, sample_id = "sample01"),
"must have colnames")
})
test_that("Using a bounding box to crop SFE objects, current way, one sample", {
# Sample ID for bbox doesn't match sample specified in crop function
m <- matrix(c(1, 3, 1, 6), ncol = 1,
dimnames = list(c("xmin", "xmax", "ymin", "ymax"),
"sample01"))
expect_error(SpatialFeatureExperiment::crop(sfe_visium, y = m, sample_id = "sample02"),
"No bounding boxes for samples specified.")
sfe_cropped <- SpatialFeatureExperiment::crop(sfe_visium, y = m)
expect_true(all(st_any_pred(spotPoly(sfe_cropped, "sample01"), bbox_use,
pred = st_covered_by, sparse = FALSE
)))
expect_false(all(st_any_pred(spotPoly(sfe_cropped, "sample02"), bbox_use,
pred = st_covered_by, sparse = FALSE
)))
expect_equal(sum(st_any_intersects(
spotPoly(sfe_cropped, "sample02"),
bbox_use
)), 2)
})
# I don't expect it to be common to use the same bbox to crop all samples,
# because the ROIs in different samples most likely have different bboxes
test_that("Using a bounding box to crop SFE objects, current way, all samples", {
m <- matrix(c(1, 3, 1, 6, 1, 3, 5, 9), ncol = 2,
dimnames = list(c("xmin", "xmax", "ymin", "ymax"),
c("sample01", "sample02")))
sfe_cropped <- SpatialFeatureExperiment::crop(sfe_visium, y = m)
expect_true(all(st_any_pred(spotPoly(sfe_cropped, "sample01"), bbox_use,
pred = st_covered_by, sparse = FALSE
)))
expect_true(all(st_any_pred(spotPoly(sfe_cropped, "sample02"), bbox_use2,
pred = st_covered_by, sparse = FALSE
)))
})
test_that("When a geometry is broken into multiple pieces", {
notch <- st_as_sfc(st_bbox(c(xmin = 0, xmax = 1.5, ymin = 1.7, ymax = 1.9)))
bbox_use3 <- st_difference(bbox_use, notch)
sfe_cropped3 <- SpatialFeatureExperiment::crop(sfe_visium, bbox_use3, sample_id = "sample01")
cg <- spotPoly(sfe_cropped3, "all")
expect_true(st_geometry_type(cg, by_geometry = FALSE) == "MULTIPOLYGON")
})
test_that("When a sample is removed by cropping", {
m <- matrix(c(1, 3, 1, 6, 6, 9, 10, 13), ncol = 2,
dimnames = list(c("xmin", "xmax", "ymin", "ymax"),
c("sample01", "sample02")))
expect_warning(sfe_cropped <- SpatialFeatureExperiment::crop(sfe_visium, m), "were removed")
expect_equal(sampleIDs(sfe_cropped), "sample01")
})
test_that("Keep whole colGeometry items", {
# In case you don't want small slivers or broken into multiple pieces
# rowGeometries, annotGeometries, and images should be cropped by the actual
# bbox of the remaining items of the colGeometry
sfe_cropped <- SpatialFeatureExperiment::crop(sfe_visium, bbox_cg, sample_id = "sample01",
keep_whole = "col")
cg2 <- colGeometry(sfe_cropped, sample_id = "sample01")
# colGeometry not cropped
expect_equal(cg, cg2)
# annotGeometry cropped
cg_bbox <- st_bbox(cg) |> st_as_sfc()
ag2 <- annotGeometry(sfe_cropped, sample_id = "sample01")
expect_true(st_equals(ag2, st_as_sfc(bbox_cg), sparse = FALSE))
# rowGeometry
rg_check <- rowGeometry(sfe_cropped, "points", sample_id = "sample01")
rg_bbox2 <- st_bbox(rg_check) |> st_as_sfc()
expect_true(st_covered_by(rg_bbox2, cg_bbox, sparse = FALSE))
})
test_that("Keep whole annotGeometry items", {
cg <- colGeometry(sfe_visium, sample_id = "sample01")
bbox_use <- st_bbox(st_centroid(cg))
set.seed(29)
ag_use <- cbind(runif(20, bbox_use["xmin"], bbox_use["xmax"]),
runif(20, bbox_use["ymin"], bbox_use["ymax"])) |>
as.data.frame()
names(ag_use) <- c("x", "y")
ag_use <- st_as_sf(ag_use, coords = c("x", "y"), crs = NA)
ag_use <- st_buffer(ag_use, 0.5)
ag_use$sample_id <- "sample01"
annotGeometry(sfe_visium, "circles", "sample01") <- ag_use
sfe_cropped <- SpatialFeatureExperiment::crop(sfe_visium, bbox_use, sample_id = "sample01",
keep_whole = "annot")
expect_true(st_covered_by(spotPoly(sfe_cropped, "sample01"), st_as_sfc(bbox_use),
sparse = FALSE) |> all())
expect_equal(ag_use, annotGeometry(sfe_cropped, "circles", "sample01")[,names(ag_use)])
})
test_that("Use st_difference for cropping, not cover", {
bbox_use <- c(xmin = 2.5, xmax = 3.5, ymin = 1.75, ymax = 2.5)
cg <- colGeometry(sfe_visium, sample_id = "sample01")
bbox1 <- st_bbox(st_centroid(cg))
set.seed(29)
ag_use <- cbind(runif(20, bbox1["xmin"], bbox1["xmax"]),
runif(20, bbox1["ymin"], bbox1["ymax"])) |>
as.data.frame()
names(ag_use) <- c("x", "y")
ag_use <- st_as_sf(ag_use, coords = c("x", "y"), crs = NA)
ag_use <- st_buffer(ag_use, 0.5)
ag_use$sample_id <- "sample01"
annotGeometry(sfe_visium, "circles", "sample01") <- ag_use
sfe_cropped <- SpatialFeatureExperiment::crop(sfe_visium, bbox_use, sample_id = "sample01",
op = st_difference)
cg2 <- spotPoly(sfe_cropped, "sample01")
ag2 <- annotGeometry(sfe_cropped, "circles", "sample01")
expect_false(any(st_overlaps(cg2, st_as_sfc(st_bbox(bbox_use)), sparse = FALSE)))
expect_false(any(st_covered_by(cg2, st_as_sfc(st_bbox(bbox_use)), sparse = FALSE)))
expect_false(any(st_overlaps(ag2, st_as_sfc(st_bbox(bbox_use)), sparse = FALSE)))
expect_false(any(st_covered_by(ag2, st_as_sfc(st_bbox(bbox_use)), sparse = FALSE)))
})
test_that("Use st_difference for cropping, cover", {
bbox_use <- c(xmin = 2.5, xmax = 3.5, ymin = 1.75, ymax = 2.5)
cg <- colGeometry(sfe_visium, sample_id = "sample01")
bbox1 <- st_bbox(st_centroid(cg)) |> st_as_sfc()
set.seed(29)
ag_use <- st_sample(bbox1, 20)
ag_use <- st_sf(geometry = ag_use, coords = c("x", "y"), crs = NA)
ag_use <- st_buffer(ag_use, 0.5)
ag_use$sample_id <- "sample01"
annotGeometry(sfe_visium, "circles", "sample01") <- ag_use
sfe_cropped <- SpatialFeatureExperiment::crop(sfe_visium, bbox_use, sample_id = "sample01",
op = st_difference, cover = TRUE,
keep_whole = c("col", "annot"))
cg2 <- spotPoly(sfe_cropped, "sample01")
ag2 <- annotGeometry(sfe_cropped, "circles", "sample01")
bbox_sf <- st_as_sfc(st_bbox(bbox_use))
expect_true(all(st_disjoint(cg2, bbox_sf, sparse = FALSE)))
expect_true(all(st_disjoint(ag2, bbox_sf, sparse = FALSE)))
})
test_that("Only cells/spots covered by y if keep whole", {
cg <- colGeometry(sfe_visium, sample_id = "sample01")
bbox1 <- st_bbox(st_centroid(cg))
bbox2 <- st_bbox(cg)
bbox_use <- c(bbox2[c("xmin", "xmax", "ymin")], bbox1["ymax"])
set.seed(29)
ag_use <- cbind(runif(20, bbox_use["xmin"], bbox_use["xmax"]),
runif(20, bbox_use["ymin"], bbox_use["ymax"])) |>
as.data.frame()
names(ag_use) <- c("x", "y")
ag_use <- st_as_sf(ag_use, coords = c("x", "y"), crs = NA)
ag_use <- st_buffer(ag_use, 0.5)
ag_use$sample_id <- "sample01"
annotGeometry(sfe_visium, "circles", "sample01") <- ag_use
sfe_cropped <- SpatialFeatureExperiment::crop(sfe_visium, bbox_use, sample_id = "sample01",
keep_whole = c("col", "annot"), cover = TRUE)
cg2 <- spotPoly(sfe_cropped, "sample01")
expect_true(all(st_covered_by(cg2, st_as_sfc(st_bbox(bbox_use)), sparse = FALSE)))
expect_true(all(lengths(st_equals(cg2, cg))))
ag2 <- annotGeometry(sfe_cropped, "circles", "sample01")
expect_true(all(st_covered_by(ag2, st_as_sfc(st_bbox(bbox_use)), sparse = FALSE)))
expect_true(all(lengths(st_equals(ag2, ag_use))))
})
test_that("Error when other spatial operations are specified", {
bbox_use <- c(xmin = 2.5, xmax = 3.5, ymin = 1.75, ymax = 2.5)
expect_error(SpatialFeatureExperiment::crop(sfe_visium, bbox_use, sample_id = "sample01",
op = st_sym_difference),
"op must be either st_intersection or st_difference")
})
test_that("Crop 3D geometry", {
fp <- tempfile()
dir_use <- CosMXOutput(file_path = fp)
sfe <- readCosMX(dir_use, z = "all", add_molecules = TRUE,
z_option = "3d")
bbox1 <- c(xmin = 171500, ymin = 11500, xmax = 172000, ymax = 12000)
sfe_cropped <- SpatialFeatureExperiment::crop(sfe, bbox1)
bbox_new <- bbox(sfe_cropped)
expect_true(st_covered_by(st_as_sfc(st_bbox(bbox_new)), st_as_sfc(st_bbox(bbox1)),
sparse = FALSE))
rg <- txSpots(sfe_cropped)
expect_true(st_covered_by(st_as_sfc(st_bbox(rg)), st_as_sfc(st_bbox(bbox_new)),
sparse = FALSE))
expect_equal(unclass(st_z_range(rg)), c(zmin = 0, zmax = 1),
ignore_attr = "crs")
unlink(dir_use, recursive = TRUE)
})
# annotPred and annotOp===========
annotGeometry(sfe_visium, "bbox", sample_id = "sample01") <- bbox_sf
test_that("annotPred", {
out <- annotPred(sfe_visium,
colGeometryName = "spotPoly",
annotGeometryName = "bbox", sample_id = "sample01"
)
expect_equal(
names(out),
colnames(sfe_visium)[colData(sfe_visium)$sample_id == "sample01"]
)
expect_true(all(out[c(1, 2, 5)]))
expect_false(any(out[3:4]))
})
test_that("annotOp", {
out <- annotOp(sfe_visium,
colGeometryName = "spotPoly",
annotGeometryName = "bbox", sample_id = "sample01"
)
expect_s3_class(out, "sf")
expect_equal(
rownames(out),
colnames(sfe_visium)[colData(sfe_visium)$sample_id == "sample01"]
)
p <- st_any_pred(out, bbox_use, st_covered_by, sparse = FALSE)
expect_true(all(p[c(1, 2, 5)]))
expect_false(any(p[3:4]))
})
# bbox=============
test_that("Find bbox of samples", {
cg1 <- spotPoly(sfe_visium, "sample01")
bbox1 <- bbox(sfe_visium, "sample01")
expect_equal(st_bbox(rowGeometry(sfe_visium)), bbox1,
ignore_attr = c("class", "crs")
)
bboxes <- bbox(sfe_visium, "all")
expect_true(is.matrix(bboxes))
expect_true(is.numeric(bboxes))
expect_equal(colnames(bboxes), c("sample01", "sample02"))
expect_equal(rownames(bboxes), c("xmin", "ymin", "xmax", "ymax"))
expect_true(all(!is.na(bboxes)))
})
test_that("bbox when 0 rows or columns", {
sfe0 <- sfe_visium[,logical(0)]
bbox0 <- bbox(sfe0)
expect_equal(names(bbox0), c("xmin", "ymin", "xmax", "ymax"))
expect_true(all(is.na(bbox0)))
})
test_that("Remove empty space", {
sfe_moved <- removeEmptySpace(sfe_visium, sample_id = "all")
bboxes <- int_metadata(sfe_moved)$orig_bbox
expect_true(is.matrix(bboxes))
expect_true(is.numeric(bboxes))
expect_equal(colnames(bboxes), c("sample01", "sample02"))
expect_equal(rownames(bboxes), c("xmin", "ymin", "xmax", "ymax"))
expect_true(all(!is.na(bboxes)))
new_bboxes <- bbox(sfe_moved, "all")
expect_true(all(abs(new_bboxes[
c("xmin", "ymin"),
c("sample01", "sample02")
]) < .Machine$double.eps))
# Make sure that spatialCoords are correctly moved
coord_diffs <- spatialCoords(sfe_visium) - spatialCoords(sfe_moved)
diff1 <- unname(coord_diffs[sfe_visium$sample_id == "sample01",][1,])
diff2 <- unname(coord_diffs[sfe_visium$sample_id == "sample02",][1,])
expect_equal(diff1, unname(bboxes[c("xmin", "ymin"), "sample01"]))
expect_equal(diff2, unname(bboxes[c("xmin", "ymin"), "sample02"]))
})
# removeEmptySpace===============
library(SFEData)
sfe1 <- McKellarMuscleData("small")
sfe2 <- McKellarMuscleData("small2")
sfe <- cbind(sfe1, sfe2)
# Toy example before removing empty space
bboxes <- bbox(sfe, sample_id = "all")
set.seed(29)
cg_toy1 <- data.frame(
x = runif(ncol(sfe1), bboxes["xmin", "Vis5A"], bboxes["xmax", "Vis5A"]),
y = runif(ncol(sfe1), bboxes["ymin", "Vis5A"], bboxes["ymax", "Vis5A"]),
sample_id = "Vis5A")
cg_toy1 <- df2sf(cg_toy1)
cg_toy2 <- data.frame(
x = runif(ncol(sfe2), bboxes["xmin", "sample02"], bboxes["xmax", "sample02"]),
y = runif(ncol(sfe2), bboxes["ymin", "sample02"], bboxes["ymax", "sample02"]),
sample_id = "sample02")
cg_toy2 <- df2sf(cg_toy2)
cg_toy <- rbind(cg_toy1, cg_toy2)
sfe <- sfe[rowSums(counts(sfe)) > 0,]
sfe_shifted <- removeEmptySpace(sfe)
bbox_new <- st_as_sfc(st_bbox(bbox(sfe_shifted, sample_id = "Vis5A")))
bbox_new2 <- st_as_sfc(st_bbox(bbox(sfe_shifted, sample_id = "sample02")))
bbox_old1 <- st_as_sfc(st_bbox(bbox(sfe, sample_id = "Vis5A")))
bbox_old2 <- st_as_sfc(st_bbox(bbox(sfe, sample_id = "sample02")))
test_that("colGeometry setter after removing empty space", {
# Two samples
colGeometry(sfe_shifted, "toy", sample_id = "all",
withDimnames = FALSE) <- cg_toy
cg <- colGeometry(sfe_shifted, "toy", sample_id = "all")
bb <- st_as_sfc(st_bbox(cg))
expect_true(st_covered_by(bb, bbox_new, sparse = FALSE))
# One of two samples
colGeometry(sfe_shifted, "toy2", sample_id = "sample02",
withDimnames = FALSE) <- cg_toy2
cg <- colGeometry(sfe_shifted, "toy2", sample_id = "sample02")
bb <- st_as_sfc(st_bbox(cg))
expect_true(st_covered_by(bb, bbox_new, sparse = FALSE))
# Use colGeometries setter
colGeometries(sfe_shifted, withDimnames = FALSE) <- list(foo = cg_toy)
cg <- colGeometry(sfe_shifted, "foo", sample_id = "all")
bb <- st_as_sfc(st_bbox(cg))
expect_true(st_covered_by(bb, bbox_new, sparse = FALSE))
# Not moved with translate = FALSE
colGeometry(sfe_shifted, "bar", sample_id = "all", translate = FALSE,
withDimnames = FALSE) <- cg_toy
cg1 <- colGeometry(sfe_shifted, "bar", sample_id = "Vis5A")
cg2 <- colGeometry(sfe_shifted, "bar", sample_id = "sample02")
bb1 <- st_as_sfc(st_bbox(cg1))
bb2 <- st_as_sfc(st_bbox(cg2))
expect_true(st_covered_by(bb1, bbox_old1, sparse = FALSE))
expect_true(st_covered_by(bb2, bbox_old2, sparse = FALSE))
})
test_that("annotGeometry setter after removing empty space", {
# One sample, that it shifted
sfe_shifted1 <- removeEmptySpace(sfe1)
ag <- annotGeometry(sfe_shifted1, "myofiber_simplified")
bb <- st_as_sfc(st_bbox(ag))
expect_true(st_covered_by(bb, bbox_new, sparse = FALSE))
# One sample setter
ag_old <- annotGeometry(sfe1, "myofiber_simplified")
annotGeometry(sfe_shifted1, "foo") <- ag_old
ag <- annotGeometry(sfe_shifted1, "foo")
bb <- st_as_sfc(st_bbox(ag))
expect_true(st_covered_by(bb, bbox_new, sparse = FALSE))
# Two samples
ag_old2 <- annotGeometry(sfe, "myofiber_simplified", sample_id = "all")
annotGeometry(sfe_shifted, "foo", sample_id = "all") <- ag_old2
ag <- annotGeometry(sfe_shifted, "foo", sample_id = "all")
bb <- st_as_sfc(st_bbox(ag))
expect_true(st_covered_by(bb, bbox_new, sparse = FALSE))
# One of two samples to modify existing annotGeometry
annotGeometry(sfe_shifted, "bar", sample_id = "Vis5A") <- ag_old
ag <- annotGeometry(sfe_shifted, "foo", sample_id = "Vis5A")
bb <- st_as_sfc(st_bbox(ag))
expect_true(st_covered_by(bb, bbox_new, sparse = FALSE))
# Use annotGeometries setter
annotGeometries(sfe_shifted) <- list(foobar = ag_old2)
ag <- annotGeometry(sfe_shifted, "foobar", sample_id = "all")
bb <- st_as_sfc(st_bbox(ag))
expect_true(st_covered_by(bb, bbox_new, sparse = FALSE))
# Not moved when translate = FALSE
annotGeometry(sfe_shifted, "baz", sample_id = "all", translate = FALSE) <-
ag_old2
bb1 <- st_as_sfc(st_bbox(annotGeometry(sfe_shifted, "baz", sample_id = "Vis5A")))
bb2 <- st_as_sfc(st_bbox(annotGeometry(sfe_shifted, "baz", sample_id = "sample02")))
expect_true(st_covered_by(bb1, bbox_old1, sparse = FALSE))
expect_true(st_covered_by(bb2, bbox_old2, sparse = FALSE))
})
set.seed(29)
rg1 <- st_sf(geometry = st_sample(bbox_old1, nrow(sfe)))
rg2 <- st_sf(geometry = st_sample(bbox_old2, nrow(sfe)))
rowGeometry(sfe, "foo", "Vis5A", withDimnames = FALSE) <- rg1
rowGeometry(sfe, "foo", "sample02", withDimnames = FALSE) <- rg2
test_that("rowGeometry removing empty space", {
sfe_shifted <- removeEmptySpace(sfe)
rg1_sh <- rowGeometry(sfe_shifted, "foo", "Vis5A")
rg2_sh <- rowGeometry(sfe_shifted, "foo", "sample02")
bb1 <- st_bbox(rg1_sh) |> st_as_sfc()
bb2 <- st_bbox(rg2_sh) |> st_as_sfc()
expect_true(st_covered_by(bb1, bbox_new, sparse = FALSE))
expect_true(st_covered_by(bb2, bbox_new2, sparse = FALSE))
})
test_that("rowGeometry setter after removing empty space", {
rowGeometry(sfe_shifted, "bar", "Vis5A", withDimnames = FALSE) <- rg1
rg_shifted <- rowGeometry(sfe_shifted, "bar", "Vis5A")
bb <- st_bbox(rg_shifted) |> st_as_sfc()
expect_true(st_covered_by(bb, bbox_new, sparse = FALSE))
})
test_that("Don't translate value if it's already translated", {
bb <- st_bbox(cg_toy)
cg_translated <- cg_toy
cg_translated$geometry <- cg_translated$geometry - bb[c("xmin", "ymin")]
bb2 <- st_as_sfc(st_bbox(cg_translated))
colGeometry(sfe_shifted, "cg_translated", sample_id = "all",
translate = TRUE, withDimnames = FALSE) <- cg_translated
cg_check <- colGeometry(sfe_shifted, "cg_translated", "all")
expect_true(all(st_covered_by(cg_check, bb2, sparse = FALSE)))
})
# annotSummary========
test_that("annotSummary", {
out <- annotSummary(sfe1, "spotPoly", "myofiber_simplified", "area")
expect_s3_class(out, "data.frame")
expect_equal(rownames(out), colnames(sfe1))
expect_equal(names(out), "area")
expect_true(is.numeric(out$area))
})
# Operations when there're images=================
# Need uncropped image
if (!dir.exists("ob")) dir.create(file.path("ob", "outs"), recursive = TRUE)
mat_fn <- file.path("ob", "outs", "filtered_feature_bc_matrix.h5")
if (!file.exists(mat_fn))
download.file("https://cf.10xgenomics.com/samples/spatial-exp/2.0.0/Visium_Mouse_Olfactory_Bulb/Visium_Mouse_Olfactory_Bulb_filtered_feature_bc_matrix.h5",
destfile = file.path("ob", "outs", "filtered_feature_bc_matrix.h5"),
mode = "wb")
if (!dir.exists(file.path("ob", "outs", "spatial"))) {
download.file("https://cf.10xgenomics.com/samples/spatial-exp/2.0.0/Visium_Mouse_Olfactory_Bulb/Visium_Mouse_Olfactory_Bulb_spatial.tar.gz",
destfile = file.path("ob", "outs", "spatial.tar.gz"))
untar(file.path("ob", "outs", "spatial.tar.gz"), exdir = file.path("ob", "outs"))
}
library(SpatialExperiment)
library(terra)
library(SingleCellExperiment)
library(S4Vectors)
sfe <- read10xVisiumSFE("ob")
test_that("bbox when images are included", {
bbox_tot <- bbox(sfe, include_image = TRUE) |> st_bbox() |> st_as_sfc()
bbox_img <- ext(getImg(sfe, image_id = "hires")) |>
st_bbox() |> st_as_sfc()
expect_true(st_equals(bbox_tot, bbox_img, sparse = FALSE))
})
sfe <- sfe[rowSums(counts(sfe)) > 0,]
bbox_use <- bbox(sfe) |> st_bbox() |> st_as_sfc()
set.seed(29)
ag <- st_sample(bbox_use, 20) |> st_buffer(dist = 100)
ag <- st_sf(geometry = ag, sample_id = "sample01")
rg <- st_sample(bbox_use, nrow(sfe))
rg <- st_sf(geometry = rg)
rownames(rg) <- rownames(sfe)
annotGeometry(sfe, "foo") <- ag
rowGeometry(sfe, "bar") <- rg
test_that("When no cells/spots left after cropping", {
bbox0 <- c(xmin = 3000, xmax = 4000, ymin = 2000, ymax = 3000)
expect_warning(sfe0 <- SpatialFeatureExperiment::crop(sfe, bbox0),
"No cells/spots left after cropping")
expect_equal(ncol(sfe0), 0)
expect_equal(nrow(sfe0), nrow(sfe))
expect_equal(nrow(spotPoly(sfe0)), 0)
expect_true(isEmpty(rowGeometries(sfe0)))
expect_equal(nrow(imgData(sfe0)), 0)
expect_equal(annotGeometryNames(sfe0), annotGeometryNames(sfe))
expect_equal(nrow(annotGeometry(sfe0, "foo")), 0)
})
test_that("Image is shifted after removing empty space", {
sfe2 <- removeEmptySpace(sfe)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- imgRaster(getImg(sfe2))
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
bbox_geom <- st_bbox(spotPoly(sfe2)) |> st_as_sfc()
bbox_img <- as.vector(ext(img)) |> st_bbox() |> st_as_sfc()
expect_true(st_covered_by(bbox_geom, bbox_img, sparse = FALSE))
expect_true(st_area(bbox_geom) / st_area(bbox_img) > 0.97)
})
test_that("Image is cropped after cropping SFE object", {
bc <- bbox(sfe)
bbox_use <- c(xmin = bc["xmin"], xmax = bc["xmin"] + 2000,
ymin = bc["ymin"], ymax = bc["ymin"] + 2000) |>
setNames(c("xmin", "xmax", "ymin", "ymax")) |>
st_bbox() |> st_as_sfc()
sfe2 <- SpatialFeatureExperiment::crop(sfe, bbox_use)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- imgRaster(getImg(sfe2, image_id = "hires"))
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean, use = "complete.obs")) > 0.4)
bbox_geom <- st_bbox(spotPoly(sfe2)) |> st_as_sfc()
bbox_img <- as.vector(ext(img)) |> st_bbox() |> st_as_sfc()
expect_true(st_covered_by(bbox_geom, bbox_img, sparse = FALSE))
expect_true(st_area(bbox_geom) / st_area(bbox_img) > 0.99)
})
# Affine transformations of the SFE object==============
test_that("Transpose SFE object with image", {
sfe2 <- transpose(sfe)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- imgRaster(getImg(sfe2))
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
bbox_cg <- st_bbox(spotPoly(sfe2)) |> st_as_sfc()
bbox_rg <- st_bbox(rowGeometry(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Transpose SFE object with image, after cropping image", {
sfe <- sfe[,sfe$in_tissue]
sfe2 <- transpose(sfe)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- imgRaster(getImg(sfe2, image_id = "hires"))
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
bbox_cg_orig <- st_bbox(spotPoly(sfe))
bbox_cg_orig_sf <- bbox_cg_orig |> st_as_sfc()
bbox_img_orig <- ext(getImg(sfe, image_id = "hires"))
bbox_img_orig_sf <- bbox_img_orig |> st_bbox() |> st_as_sfc()
bbox_cg <- st_bbox(spotPoly(sfe2))
bbox_cg_sf <- bbox_cg |> st_as_sfc()
bbox_img <- as.vector(ext(img))
bbox_img_sf <- bbox_img |> st_bbox() |> st_as_sfc()
expect_true(st_covered_by(bbox_cg_sf, bbox_img_sf, sparse = FALSE))
expect_equal(bbox_img_orig[["ymax"]] - bbox_cg_orig[["ymax"]],
bbox_cg[["xmin"]] - bbox_img[["xmin"]])
bbox_rg <- st_bbox(rowGeometry(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg_sf, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Mirror SFE object with image, vertical", {
sfe2 <- mirror(sfe, direction = "vertical")
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- imgRaster(getImg(sfe2))
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
bbox_cg <- st_bbox(spotPoly(sfe2)) |> st_as_sfc()
bbox_rg <- st_bbox(rowGeometry(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Mirror SFE object with image after cropping", {
sfe <- sfe[,sfe$in_tissue]
sfe2 <- mirror(sfe, direction = "vertical")
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- imgRaster(getImg(sfe2, image_id = "hires"))
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
bbox_cg_orig <- st_bbox(spotPoly(sfe))
bbox_cg_orig_sf <- bbox_cg_orig |> st_as_sfc()
bbox_img_orig <- ext(getImg(sfe, image_id = "hires"))
bbox_img_orig_sf <- bbox_img_orig |> st_bbox() |> st_as_sfc()
bbox_cg <- st_bbox(spotPoly(sfe2))
bbox_cg_sf <- bbox_cg |> st_as_sfc()
bbox_img <- as.vector(ext(img))
bbox_img_sf <- bbox_img |> st_bbox() |> st_as_sfc()
expect_true(st_covered_by(bbox_cg_sf, bbox_img_sf, sparse = FALSE))
expect_equal(bbox_img_orig[["ymax"]] - bbox_cg_orig[["ymax"]],
st_bbox(bbox_cg_sf)[["ymin"]] - bbox_img[["ymin"]])
bbox_rg <- st_bbox(rowGeometry(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg_sf, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Mirror SFE object with image, horizontal", {
sfe2 <- mirror(sfe, direction = "horizontal")
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- imgRaster(getImg(sfe2))
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
bbox_cg <- st_bbox(spotPoly(sfe2)) |> st_as_sfc()
bbox_rg <- st_bbox(rowGeometry(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Rotate SFE object with image", {
sfe2 <- SpatialFeatureExperiment::rotate(sfe, degrees = 45)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- getImg(sfe2) |> toSpatRasterImage(save_geotiff = FALSE) |> imgRaster()
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
# Also see if spotPoly is aligned
v2 <- terra::extract(terra::mean(img), vect(st_centroid(st_geometry(spotPoly(sfe2)))))
expect_true(abs(cor(nCounts, v2$mean)) > 0.4)
int1 <- st_intersects(rg, spotPoly(sfe))
int2 <- st_intersects(rowGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Rotate SFE object with image after cropping", {
sfe <- sfe[,sfe$in_tissue]
sfe2 <- SpatialFeatureExperiment::rotate(sfe, degrees = 45)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- getImg(sfe2) |> toSpatRasterImage(save_geotiff = FALSE) |> imgRaster()
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
# Also see if spotPoly is aligned
v2 <- terra::extract(terra::mean(img), vect(st_centroid(st_geometry(spotPoly(sfe2)))))
expect_true(abs(cor(nCounts, v2$mean)) > 0.4)
int1 <- st_intersects(rg, spotPoly(sfe))
int2 <- st_intersects(rowGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Scale SFE object with image", {
sfe2 <- SpatialFeatureExperiment::scale(sfe, factor = 1.5)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- getImg(sfe2) |> imgRaster()
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
# Also see if spotPoly is aligned
v2 <- terra::extract(terra::mean(img), vect(st_centroid(st_geometry(spotPoly(sfe2)))))
expect_true(abs(cor(nCounts, v2$mean)) > 0.4)
int1 <- st_intersects(rg, spotPoly(sfe))
int2 <- st_intersects(rowGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Scale SFE object with image after cropping", {
sfe <- sfe[,sfe$in_tissue]
sfe2 <- SpatialFeatureExperiment::scale(sfe, factor = 1.5)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- getImg(sfe2) |> imgRaster()
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
# Also see if spotPoly is aligned
v2 <- terra::extract(terra::mean(img), vect(st_centroid(st_geometry(spotPoly(sfe2)))))
expect_true(abs(cor(nCounts, v2$mean)) > 0.4)
int1 <- st_intersects(rg, spotPoly(sfe))
int2 <- st_intersects(rowGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("General affine transformation of SFE object with image", {
M <- matrix(c(0.6, -0.2, 0.2, 0.3), nrow = 2)
v <- c(0, 300)
sfe2 <- SpatialFeatureExperiment::affine(sfe, M = M, v = v)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- getImg(sfe2) |> toSpatRasterImage(save_geotiff = FALSE) |> imgRaster()
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
# Also see if spotPoly is aligned
v2 <- terra::extract(terra::mean(img), vect(st_centroid(st_geometry(spotPoly(sfe2)))))
expect_true(abs(cor(nCounts, v2$mean)) > 0.4)
int1 <- st_intersects(rg, spotPoly(sfe))
int2 <- st_intersects(rowGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Affine transformation of SFE object with image, after cropping", {
M <- matrix(c(0.6, -0.2, 0.2, 0.3), nrow = 2)
v <- c(0, 300)
sfe <- sfe[,sfe$in_tissue]
sfe2 <- SpatialFeatureExperiment::affine(sfe, M = M, v = v)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- getImg(sfe2) |> toSpatRasterImage(save_geotiff = FALSE) |> imgRaster()
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
# Also see if spotPoly is aligned
v2 <- terra::extract(terra::mean(img), vect(st_centroid(st_geometry(spotPoly(sfe2)))))
expect_true(abs(cor(nCounts, v2$mean)) > 0.4)
int1 <- st_intersects(rg, spotPoly(sfe))
int2 <- st_intersects(rowGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
test_that("Transformation when there's 3D geometry", {
fp <- tempfile()
dir_use <- CosMXOutput(file_path = fp)
sfe <- readCosMX(dir_use, z = "all", add_molecules = TRUE,
z_option = "3d")
sfe2 <- SpatialFeatureExperiment::rotate(sfe, degrees = 90)
ints <- st_intersects(cellSeg(sfe), txSpots(sfe))
ints2 <- st_intersects(cellSeg(sfe2), txSpots(sfe2))
expect_equal(ints, ints2)
rg <- txSpots(sfe2)
expect_equal(unclass(st_z_range(rg)), c(zmin = 0, zmax = 1),
ignore_attr = "crs")
unlink(dir_use, recursive = TRUE)
})
test_that("Translate SFE object with image", {
v <- c(100, 200)
sfe2 <- translate(sfe, v = v)
bbox_tr <- bbox(sfe2)
bbox_exp <- bbox(sfe)
bbox_exp[c("xmin", "xmax")] <- bbox_exp[c("xmin", "xmax")] + v[1]
bbox_exp[c("ymin", "ymax")] <- bbox_exp[c("ymin", "ymax")] + v[2]
expect_equal(bbox_tr, bbox_exp)
cg <- df2sf(spatialCoords(sfe2), spatialCoordsNames(sfe2))
img <- imgRaster(getImg(sfe2))
v <- terra::extract(terra::mean(img), cg)
nCounts <- Matrix::colSums(counts(sfe2))
expect_true(abs(cor(nCounts, v$mean)) > 0.4)
bbox_cg <- st_bbox(spotPoly(sfe2)) |> st_as_sfc()
bbox_rg <- st_bbox(rowGeometry(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, spotPoly(sfe))
int2 <- st_intersects(annotGeometry(sfe2), spotPoly(sfe2))
expect_equal(int1, int2)
})
# Affine transform of entire SFE object, for BioFormatsImage=========
library(RBioFormats)
library(EBImage)
fp <- tempfile()
xenium_path <- XeniumOutput(file_path = fp)
try(sfe <- readXenium(xenium_path))
sfe <- readXenium(xenium_path, add_molecules = TRUE)
set.seed(29)
annotGeometry(sfe, "foo") <- ag <-
st_sf(
geometry = st_sample(st_bbox(cellSeg(sfe)), 50) |>
st_buffer(30),
sample_id = "sample01")
test_that("Transpose SFE object with BioFormatsImage", {
sfe2 <- SpatialFeatureExperiment::transpose(sfe)
img <- toExtImage(getImg(sfe2), resolution = 1L)
# Create image mask
mask <- img > 500
spi <- ExtImage(mask, ext = ext(getImg(sfe2))) |> toSpatRasterImage(save_geotiff = FALSE)
# Due to the way XOA v1 segmentation works, the cell centroid is often
# outside the nucleus. So I use nuclei centroids
v <- terra::extract(spi, st_centroid(nucSeg(sfe2)$geometry) |> vect())
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9) # NA's from cells that don't have nuclei
cat("Actual mean: ", mean(v$lyr.1, na.rm = TRUE))
bbox_cg_orig <- st_bbox(cellSeg(sfe))
bbox_img_orig <- ext(getImg(sfe))
bbox_cg <- st_bbox(cellSeg(sfe2))
bbox_img <- ext(getImg(sfe2))
expect_equal(bbox_img_orig[["ymax"]] - bbox_cg_orig[["ymax"]],
bbox_cg[["xmin"]] - bbox_img[["xmin"]])
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("Mirror SFE object with BFI, vertical", {
sfe2 <- mirror(sfe, direction = "vertical")
img <- imgRaster(getImg(sfe2), resolution = 1L)
mask <- img > 500
spi <- ExtImage(mask, ext = ext(getImg(sfe2))) |> toSpatRasterImage(save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_cg_orig <- st_bbox(cellSeg(sfe))
bbox_img_orig <- ext(getImg(sfe))
bbox_cg <- st_bbox(cellSeg(sfe2))
bbox_img <- ext(getImg(sfe2))
expect_equal(bbox_img_orig[["ymax"]] - bbox_cg_orig[["ymax"]],
bbox_cg[["ymin"]] - bbox_img[["ymin"]])
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("Mirror SFE object with BFI, horizontal", {
sfe2 <- mirror(sfe, direction = "horizontal")
img <- imgRaster(getImg(sfe2), resolution = 1L)
mask <- img > 500
spi <- ExtImage(mask, ext = ext(getImg(sfe2))) |> toSpatRasterImage(save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_cg_orig <- st_bbox(cellSeg(sfe))
bbox_img_orig <- ext(getImg(sfe))
bbox_cg <- st_bbox(cellSeg(sfe2))
bbox_img <- ext(getImg(sfe2))
expect_equal(bbox_img_orig[["xmax"]] - bbox_cg_orig[["xmax"]],
bbox_cg[["xmin"]] - bbox_img[["xmin"]])
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("Rotate SFE object with BFI", {
sfe2 <- SpatialFeatureExperiment::rotate(sfe, degrees = 45)
img <- imgRaster(getImg(sfe2), resolution = 1L)
mask <- img > 500
spi <- ExtImage(mask, ext = ext(getImg(sfe2))) |> toSpatRasterImage(save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("Scale SFE object with BFI", {
sfe2 <- SpatialFeatureExperiment::scale(sfe, factor = 1.5)
img <- imgRaster(getImg(sfe2), resolution = 1L)
mask <- img > 500
spi <- ExtImage(mask, ext = ext(getImg(sfe2))) |> toSpatRasterImage(save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_cg_orig <- st_bbox(cellSeg(sfe))
bbox_img_orig <- ext(getImg(sfe))
bbox_cg <- st_bbox(cellSeg(sfe2))
bbox_img <- ext(getImg(sfe2))
expect_equal((bbox_cg_orig[["xmax"]] - bbox_img_orig[["xmax"]])*1.5,
bbox_cg[["xmax"]] - bbox_img[["xmax"]])
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("General affine transformation of SFE object with BFI", {
M <- matrix(c(0.6, -0.2, 0.2, 0.3), nrow = 2)
v <- c(0, 300)
sfe2 <- SpatialFeatureExperiment::affine(sfe, M = M, v = v)
img <- imgRaster(getImg(sfe2), resolution = 1L)
mask <- img > 500
spi <- ExtImage(mask, ext = ext(getImg(sfe2))) |> toSpatRasterImage(save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
# Affine transform of entire SFE object, for ExtImage=========
img <- toExtImage(getImg(sfe), resolution = 1L)
sfe <- addImg(sfe, img, image_id = "exi")
test_that("Transpose SFE object with ExtImage", {
sfe2 <- SpatialFeatureExperiment::transpose(sfe)
# Create image mask
mask <- getImg(sfe2, image_id = "exi") > 500
spi <- toSpatRasterImage(mask, save_geotiff = FALSE)
# Due to the way XOA v1 segmentation works, the cell centroid is often
# outside the nucleus. So I use nuclei centroids
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_cg_orig <- st_bbox(cellSeg(sfe))
bbox_img_orig <- ext(getImg(sfe))
bbox_cg <- st_bbox(cellSeg(sfe2))
bbox_img <- ext(getImg(sfe2))
expect_equal(bbox_img_orig[["ymax"]] - bbox_cg_orig[["ymax"]],
bbox_cg[["xmin"]] - bbox_img[["xmin"]])
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("Mirror SFE object with ExtImage, vertical", {
sfe2 <- mirror(sfe, direction = "vertical")
mask <- getImg(sfe2, image_id = "exi") > 500
spi <- toSpatRasterImage(mask, save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_cg_orig <- st_bbox(cellSeg(sfe))
bbox_img_orig <- ext(getImg(sfe))
bbox_cg <- st_bbox(cellSeg(sfe2))
bbox_img <- ext(getImg(sfe2))
expect_equal(bbox_img_orig[["ymax"]] - bbox_cg_orig[["ymax"]],
bbox_cg[["ymin"]] - bbox_img[["ymin"]])
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("Mirror SFE object with ExtImage, horizontal", {
sfe2 <- mirror(sfe, direction = "horizontal")
mask <- getImg(sfe2, image_id = "exi") > 500
spi <- toSpatRasterImage(mask, save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_cg_orig <- st_bbox(cellSeg(sfe))
bbox_img_orig <- ext(getImg(sfe))
bbox_cg <- st_bbox(cellSeg(sfe2))
bbox_img <- ext(getImg(sfe2))
expect_equal(bbox_img_orig[["xmax"]] - bbox_cg_orig[["xmax"]],
bbox_cg[["xmin"]] - bbox_img[["xmin"]])
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("Rotate SFE object with ExtImage", {
sfe2 <- SpatialFeatureExperiment::rotate(sfe, degrees = 45)
mask <- getImg(sfe2, image_id = "exi") > 500
spi <- toSpatRasterImage(mask, save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("Scale SFE object with ExtImage", {
sfe2 <- SpatialFeatureExperiment::scale(sfe, factor = 1.5)
mask <- getImg(sfe2, image_id = "exi") > 500
spi <- toSpatRasterImage(mask, save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_cg_orig <- st_bbox(cellSeg(sfe))
bbox_img_orig <- ext(getImg(sfe))
bbox_cg <- st_bbox(cellSeg(sfe2))
bbox_img <- ext(getImg(sfe2))
expect_equal((bbox_cg_orig[["xmax"]] - bbox_img_orig[["xmax"]])*1.5,
bbox_cg[["xmax"]] - bbox_img[["xmax"]])
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
test_that("General affine transformation of SFE object with ExtImage", {
M <- matrix(c(0.6, -0.2, 0.2, 0.3), nrow = 2)
v <- c(0, 300)
sfe2 <- SpatialFeatureExperiment::affine(sfe, M = M, v = v)
mask <- getImg(sfe2, image_id = "exi") > 500
spi <- toSpatRasterImage(mask, save_geotiff = FALSE)
v <- terra::extract(spi, vect(st_centroid(nucSeg(sfe2)$geometry)))
expect_true(mean(v$lyr.1, na.rm = TRUE) > 0.9)
bbox_rg <- st_bbox(txSpots(sfe2)) |> st_as_sfc()
bbox_cg <- st_bbox(cellSeg(sfe2)) |> st_as_sfc()
expect_true(st_covers(bbox_cg, bbox_rg, sparse = FALSE))
# For ag, can get indices of intersection
int1 <- st_intersects(ag, cellSeg(sfe))
int2 <- st_intersects(annotGeometry(sfe2), cellSeg(sfe2))
expect_equal(int1, int2)
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.