Skip to content

Commit 5633f35

Browse files
committed
doc: finish vignettes for xenium data with giotto
1 parent 25d176c commit 5633f35

File tree

10 files changed

+396
-210
lines changed

10 files changed

+396
-210
lines changed

DESCRIPTION

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ Imports:
2828
Suggests:
2929
ComplexHeatmap,
3030
Seurat (>= 5.0.0),
31+
data.table,
32+
methods,
3133
ggalluvial,
3234
ggforce,
3335
gglogger,

Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ test:
1313
Rscript <(echo "devtools::test()")
1414

1515
notebooks:
16-
jupyter nbconvert --to html notebooks/spatial/*.ipynb --output-dir=pkgdown/assets
16+
jupyter nbconvert -y --to html notebooks/spatial/*.ipynb --output-dir=pkgdown/assets
1717

1818
notebook: notebooks
19+
nb: notebooks
1920

20-
.PHONY: readme docs install test notebooks notebook
21+
.PHONY: readme docs install test notebooks notebook nb

NAMESPACE

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ importFrom(plotthis,RidgePlot)
105105
importFrom(plotthis,RingPlot)
106106
importFrom(plotthis,SankeyPlot)
107107
importFrom(plotthis,ScatterPlot)
108-
importFrom(plotthis,SpatialImagePlot)
109-
importFrom(plotthis,SpatialMasksPlot)
110-
importFrom(plotthis,SpatialPointsPlot)
111-
importFrom(plotthis,SpatialShapesPlot)
108+
importFrom(plotthis,SpatImagePlot)
109+
importFrom(plotthis,SpatMasksPlot)
110+
importFrom(plotthis,SpatPointsPlot)
111+
importFrom(plotthis,SpatShapesPlot)
112112
importFrom(plotthis,SpiderPlot)
113113
importFrom(plotthis,TrendPlot)
114114
importFrom(plotthis,UpsetPlot)

R/spatialplot.R

Lines changed: 106 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,3 @@
1-
#' Convert a data.frame to a terra SpatVector polygon
2-
#' @keywords internal
3-
.df_to_polygon_spatvector <- function(
4-
df, id, x, y,
5-
attrs = NULL
6-
) {
7-
shapes <- split(df[, c(x, y), drop = FALSE], df[[id]])
8-
sv <- terra::vect(lapply(shapes, as.matrix), type = "polygons")
9-
if (!is.null(attrs)) {
10-
for (attr in attrs) {
11-
# only get the first value of each polygon
12-
sv[[attr]] <- sapply(split(df[[attr]], df[[id]]), function(x) x[1])
13-
}
14-
}
15-
sv
16-
}
17-
181
#' Process points layer for Seurat spatial plots
192
#' @keywords internal
203
.seurat_points_layer <- function(
@@ -103,7 +86,7 @@
10386
points_args$legend.direction <- legend.direction
10487
points_args$flip_y <- points_args$flip_y
10588
points_args$return_layer <- TRUE
106-
player <- do.call(SpatialPointsPlot, points_args)
89+
player <- do.call(SpatPointsPlot, points_args)
10790

10891
list(player = player, facet_by = facet_by)
10992
}
@@ -133,13 +116,13 @@
133116
#' @param ... Additional arguments passed to the plotting functions.
134117
#' @return A ggplot object
135118
#' @keywords internal
136-
#' @rdname SpatialPlot
119+
#' @rdname SpatPlot
137120
SpatPlot <- function(object, ...) {
138121
UseMethod("SpatPlot", object)
139122
}
140123

141124
#' @keywords internal
142-
#' @rdname SpatialPlot
125+
#' @rdname SpatPlot
143126
SpatPlot.Seurat <- function(object, image = NULL, ...) {
144127
first_image <- Seurat::Images(object)[1]
145128
if (is.null(first_image)) {
@@ -161,8 +144,8 @@ SpatPlot.Seurat <- function(object, image = NULL, ...) {
161144
}
162145

163146
#' @keywords internal
164-
#' @rdname SpatialPlot
165-
#' @importFrom plotthis SpatialImagePlot SpatialMasksPlot SpatialShapesPlot SpatialPointsPlot
147+
#' @rdname SpatPlot
148+
#' @importFrom plotthis SpatImagePlot SpatMasksPlot SpatShapesPlot SpatPointsPlot
166149
SpatPlot.Seurat.Visium <- function(
167150
object, image = NULL, masks = NULL, shapes = NULL, points = NULL, ext = NULL, points_x = "x", points_y = "y",
168151
image_scale = NULL, crop = TRUE, group_by = NULL, features = NULL, layer = "data", scale_factor = NULL,
@@ -235,7 +218,7 @@ SpatPlot.Seurat.Visium <- function(
235218
image_args$flip_y <- flip_y
236219
image_args$return_layer <- TRUE
237220
image_args$ext <- if (!is.null(ext_unscaled)) ext_unscaled * the_scale_factor
238-
player <- do.call(SpatialImagePlot, image_args)
221+
player <- do.call(SpatImagePlot, image_args)
239222
scales_reused <- intersect(scales_used, attr(player, "scales"))
240223
players <- c(players, list(player))
241224
scales_used <- unique(c(scales_used, attr(player, "scales")))
@@ -302,7 +285,7 @@ SpatPlot.Seurat.Visium <- function(
302285
}
303286

304287
#' @keywords internal
305-
#' @rdname SpatialPlot
288+
#' @rdname SpatPlot
306289
SpatPlot.Seurat.SlideSeq <- function(
307290
object, image = NULL, masks = NULL, shapes = NULL, points = NULL, ext = NULL,
308291
image_scale = NULL, crop = TRUE, group_by = NULL, features = NULL, layer = "data",
@@ -425,8 +408,8 @@ SpatPlot.Seurat.SlideSeq <- function(
425408
}
426409

427410
#' @keywords internal
428-
#' @rdname SpatialPlot
429-
#' @importFrom plotthis SpatialImagePlot SpatialMasksPlot SpatialShapesPlot SpatialPointsPlot
411+
#' @rdname SpatPlot
412+
#' @importFrom plotthis SpatImagePlot SpatMasksPlot SpatShapesPlot SpatPointsPlot
430413
SpatPlot.Seurat.FOV <- function(
431414
object, image = NULL, masks = NULL, shapes = NULL, points = NULL, ext = NULL, points_x = "x", points_y = "y",
432415
image_scale = NULL, crop = TRUE, group_by = NULL, features = NULL, layer = "data", scale_factor = NULL,
@@ -499,7 +482,7 @@ SpatPlot.Seurat.FOV <- function(
499482
image_args$flip_y <- flip_y
500483
image_args$return_layer <- TRUE
501484
image_args$ext <- if (!is.null(ext_unscaled)) ext_unscaled * the_scale_factor
502-
player <- do.call(SpatialImagePlot, image_args)
485+
player <- do.call(SpatImagePlot, image_args)
503486
scales_reused <- intersect(scales_used, attr(player, "scales"))
504487
players <- c(players, list(player))
505488
scales_used <- unique(c(scales_used, attr(player, "scales")))
@@ -566,18 +549,19 @@ SpatPlot.Seurat.FOV <- function(
566549
}
567550

568551
#' @keywords internal
569-
#' @rdname SpatialPlot
552+
#' @rdname SpatPlot
570553
SpatPlot.giotto <- function(
571554
object,
572555
image = NULL,
573556
masks = NULL,
574557
shapes = NULL,
575558
points = NULL,
559+
graph = NULL,
576560
ext = NULL,
577561
layer = c("normalized", "scaled", "custom", "raw"),
578562
layers = NULL,
579563
flip_y = FALSE,
580-
group_by = "shapes",
564+
group_by = NULL,
581565
feat_type = "rna",
582566
features = NULL,
583567
nmols = 1000,
@@ -625,6 +609,9 @@ SpatPlot.giotto <- function(
625609
if (isTRUE(image)) {
626610
image <- names(object@images)[1]
627611
}
612+
if (is.null(points) && !is.null(graph)) {
613+
points <- TRUE
614+
}
628615
points <- points %||% TRUE
629616
shapes <- shapes %||% (if(identical(group_by, "shapes") || !is.null(shapes_fill_by)) TRUE)
630617
layers <- intersect(
@@ -645,20 +632,37 @@ SpatPlot.giotto <- function(
645632
shapes_alpha <- shapes_alpha %||% ifelse("image" %in% layers, 0.5, 1)
646633
for (element in layers) {
647634
if (element == "image") {
648-
image_obj <- GiottoClass::getGiottoImage(gobject = object, name = image)
649-
ext <- ext %||% as.vector(terra::ext(image_obj))
650-
image_args <- args[startsWith(names(args), "image_")]
651-
names(image_args) <- sub("^image_", "", names(image_args))
652-
image_args$data <- image_obj@raster_object
653-
image_args$flip_y <- flip_y
654-
image_args$return_layer <- TRUE
655-
image_args$ext <- ext
656-
image_colors <- attr(image_obj, "colors")
657-
if (!is.null(image_colors)) { image_args$palcolor <- image_colors }
658-
player <- do.call(SpatialImagePlot, image_args)
659-
scales_reused <- intersect(scales_used, attr(player, "scales"))
660-
players <- c(players, .new_scale_layers(scales_reused), list(player))
661-
scales_used <- unique(c(scales_used, attr(player, "scales")))
635+
if (image %in% names(object@images)) {
636+
image_obj <- GiottoClass::getGiottoImage(gobject = object, name = image)
637+
ext <- ext %||% as.vector(terra::ext(image_obj))
638+
image_args <- args[startsWith(names(args), "image_")]
639+
names(image_args) <- sub("^image_", "", names(image_args))
640+
image_args$data <- image_obj@raster_object
641+
image_args$flip_y <- flip_y
642+
image_args$return_layer <- TRUE
643+
image_args$ext <- ext
644+
image_colors <- attr(image_obj, "colors")
645+
if (!is.null(image_colors)) { image_args$palcolor <- image_colors }
646+
player <- do.call(SpatImagePlot, image_args)
647+
scales_reused <- intersect(scales_used, attr(player, "scales"))
648+
players <- c(players, .new_scale_layers(scales_reused), list(player))
649+
scales_used <- unique(c(scales_used, attr(player, "scales")))
650+
} else {
651+
# use as a color to plot a background rect
652+
image_args <- args[startsWith(names(args), "image_")]
653+
names(image_args) <- sub("^image_", "", names(image_args))
654+
image_args$data = data.frame(x = 0, y = 0) # dummy data
655+
image_args$xmin = -Inf
656+
image_args$xmax = Inf
657+
image_args$ymin = -Inf
658+
image_args$ymax = Inf
659+
image_args$fill <- image
660+
image_args$color <- NA
661+
player <- do.call(ggplot2::geom_rect, image_args)
662+
scales_reused <- intersect(scales_used, "fill")
663+
players <- c(players, .new_scale_layers(scales_reused), list(player))
664+
scales_used <- unique(c(scales_used, attr(player, "scales")))
665+
}
662666
} else if (element == "masks") {
663667
stop("[SpatPlot] 'masks' is not supported for Giotto objects yet.")
664668
} else if (element == "shapes") {
@@ -693,32 +697,39 @@ SpatPlot.giotto <- function(
693697
shapes_args <- args[startsWith(names(args), "shapes_")]
694698
names(shapes_args) <- sub("^shapes_", "", names(shapes_args))
695699

700+
shapes_args$x <- "x"
701+
shapes_args$y <- "y"
702+
shapes_args$group <- "cell_ID"
703+
696704
if (!is.null(shapes_fill_by)) {
697-
shapes_dt <- merge(
698-
shapes_dt,
699-
suppressMessages(GiottoClass::spatValues(
700-
object,
701-
feats = shapes_fill_by,
702-
spat_unit = shapes_feat_type,
703-
feat_type = feat_type,
704-
spat_enr_name = spat_enr_names
705-
)),
706-
by = "cell_ID",
707-
all.x = TRUE,
708-
suffixes = c(".x", "")
709-
)
710-
shapes_args$data <- .df_to_polygon_spatvector(shapes_dt, "cell_ID", "x", "y", attrs = shapes_fill_by)
705+
# It should be a color name
706+
if (length(shapes_fill_by) > 1 || shapes_fill_by %in% GiottoClass::featIDs(object, feat_type = shapes_feat_type)) {
707+
shapes_dt <- merge(
708+
shapes_dt,
709+
suppressMessages(GiottoClass::spatValues(
710+
object,
711+
feats = shapes_fill_by,
712+
spat_unit = shapes_feat_type,
713+
feat_type = feat_type,
714+
spat_enr_name = spat_enr_names
715+
)),
716+
by = "cell_ID",
717+
all.x = TRUE,
718+
suffixes = c(".x", "")
719+
)
720+
}
721+
shapes_args$data <- shapes_dt
711722
shapes_args$fill_by <- shapes_fill_by
712723
shapes_args$legend.position <- shapes_args$legend.position %||% "right"
713724
shapes_args$legend.direction <- shapes_args$legend.direction %||% "vertical"
714725
} else {
715-
shapes_args$data <- .df_to_polygon_spatvector(shapes_dt, "cell_ID", "x", "y")
726+
shapes_args$data <- shapes_dt
716727
}
717728
shapes_args$flip_y <- flip_y
718729
shapes_args$return_layer <- TRUE
719730
shapes_args$alpha <- shapes_alpha
720-
shapes_args$ext <- ext %||% as.vector(terra::ext(shapes_args$data))
721-
player <- do.call(SpatialShapesPlot, shapes_args)
731+
shapes_args$ext <- ext %||% c(range(shapes_dt$x, na.rm = TRUE), range(shapes_dt$y, na.rm = TRUE))
732+
player <- do.call(SpatShapesPlot, shapes_args)
722733
scales_reused <- intersect(scales_used, attr(player, "scales"))
723734
players <- c(players, .new_scale_layers(scales_reused), list(player))
724735
scales_used <- unique(c(scales_used, attr(player, "scales")))
@@ -759,6 +770,13 @@ SpatPlot.giotto <- function(
759770
points_args$data <- data.table::rbindlist(points_args$data, fill = TRUE)
760771
} else if (!is.null(group_by)) {
761772
# prepare the cell metadata
773+
points_args$data <- GiottoClass::combineCellData(
774+
gobject = object,
775+
feat_type = feat_type,
776+
spat_loc_name = spat_loc_name,
777+
spat_enr_name = spat_enr_names,
778+
include_spat_locs = FALSE
779+
)[[feat_type]]
762780
} else { # expression or just locations
763781
points_args$data <- GiottoClass::getSpatialLocations(
764782
gobject = object,
@@ -768,6 +786,21 @@ SpatPlot.giotto <- function(
768786
)
769787
}
770788

789+
if (!is.null(graph)) {
790+
points_args$graph <- GiottoClass::getSpatialNetwork(
791+
gobject = object,
792+
spat_unit = spat_unit,
793+
name = if(!isTRUE(graph)) graph,
794+
output = "networkDT",
795+
verbose = FALSE
796+
)
797+
points_args$graph_x <- "sdimx_begin"
798+
points_args$graph_y <- "sdimy_begin"
799+
points_args$graph_xend <- "sdimx_end"
800+
points_args$graph_yend <- "sdimy_end"
801+
points_args$graph_value <- "weight"
802+
}
803+
771804
if (identical(group_by, "shapes")) {
772805
points_args$label <- FALSE
773806
} else if (identical(group_by, "molecules")) {
@@ -812,11 +845,16 @@ SpatPlot.giotto <- function(
812845
}
813846
points_args$legend.position <- points_args$legend.position %||% "right"
814847
points_args$legend.direction <- points_args$legend.direction %||% "vertical"
848+
} else if (!is.null(group_by)) {
849+
points_args$color_by <- group_by
850+
points_args$color_name <- points_args$color_name %||% group_by
851+
points_args$legend.position <- points_args$legend.position %||% "right"
852+
points_args$legend.direction <- points_args$legend.direction %||% "vertical"
815853
}
816854
points_args$flip_y <- flip_y
817855
points_args$return_layer <- TRUE
818856
points_args$ext <- ext
819-
player <- do.call(SpatialPointsPlot, points_args)
857+
player <- do.call(SpatPointsPlot, points_args)
820858
scales_reused <- intersect(scales_used, attr(player, "scales"))
821859
players <- c(players, .new_scale_layers(scales_reused), list(player))
822860
scales_used <- unique(c(scales_used, attr(player, "scales")))
@@ -854,19 +892,19 @@ SpatPlot.giotto <- function(
854892
#' @param object A Seurat object or a Giotto object.
855893
#' @return A ggplot object
856894
#' @export
857-
#' @rdname SpatialPlot
895+
#' @rdname SpatPlot
858896
SpatFeaturePlot <- function(object, ...) {
859897
UseMethod("SpatFeaturePlot", object)
860898
}
861899

862900
#' @export
863-
#' @rdname SpatialPlot
901+
#' @rdname SpatPlot
864902
SpatFeaturePlot.Seurat <- function(object, image = NULL, ...) {
865903
SpatPlot(object, image = image, ...)
866904
}
867905

868906
#' @export
869-
#' @rdname SpatialPlot
907+
#' @rdname SpatPlot
870908
SpatFeaturePlot.giotto <- function(object, image = NULL, group_by = NULL, ...) {
871909
stopifnot(
872910
"[SpatFeaturePlot] 'group_by' is not supported for Giotto objects. Use 'SpatDimPlot' instead." =
@@ -880,13 +918,13 @@ SpatFeaturePlot.giotto <- function(object, image = NULL, group_by = NULL, ...) {
880918
#' @param object A Seurat object or a Giotto object.
881919
#' @return A ggplot object
882920
#' @export
883-
#' @rdname SpatialPlot
921+
#' @rdname SpatPlot
884922
SpatDimPlot <- function(object, ...) {
885923
UseMethod("SpatDimPlot", object)
886924
}
887925

888926
#' @export
889-
#' @rdname SpatialPlot
927+
#' @rdname SpatPlot
890928
SpatDimPlot.Seurat <- function(object, image = NULL, group_by = NULL, ...) {
891929
if (is.null(group_by)) {
892930
group_by <- "Identity"
@@ -896,8 +934,8 @@ SpatDimPlot.Seurat <- function(object, image = NULL, group_by = NULL, ...) {
896934
}
897935

898936
#' @export
899-
#' @rdname SpatialPlot
937+
#' @rdname SpatPlot
900938
SpatDimPlot.giotto <- function(object, image = NULL, group_by = NULL, ...) {
901-
group_by <- group_by %||% "shapes"
939+
group_by <- group_by %||% "molecules"
902940
SpatPlot.giotto(object, image = image, group_by = group_by, ...)
903941
}

_pkgdown.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ navbar:
1212
menu:
1313
- text: "Visualizing 10x Visum data prepared with Seurat"
1414
href: Seurat.10x_Visium.html
15+
- text: "Visualizing Visium HD data prepared with Seurat"
16+
href: Seurat.10x_VisiumHD.html
1517
- text: "Visualizing SlideSeq data prepared with Seurat"
1618
href: Seurat.SlideSeq.html
19+
- text: "Visualizing Xenium data prepared with Giotto"
20+
href: Giotto.XeniumInsitu.html
1721
reference:
1822
- title: scRNA-seq
1923
desc: Functions for plotting single cell RNA-seq data
@@ -43,8 +47,8 @@ reference:
4347
- title: Spatial data visualization
4448
desc: Functions for plotting spatial data
4549
contents:
46-
- SpatialDimPlot
47-
- SpatialFeaturePlot
50+
- SpatDimPlot
51+
- SpatFeaturePlot
4852
- title: Visualizing using LLMs
4953
desc: Functions/Classes for visualizing using LLMs
5054
contents:

0 commit comments

Comments
 (0)